diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml
index 1a9949f1..d60fc74e 100644
--- a/.github/workflows/conda.yml
+++ b/.github/workflows/conda.yml
@@ -11,7 +11,7 @@ jobs:
fail-fast: false
matrix:
os: ${{ fromJSON(vars.BUILD_OS)}}
- python-version: ${{ fromJSON(vars.PYTHON_VERSIONS)}}
+ python-version: ${{ fromJSON(vars.PYTHON_VERSIONS) }}
steps:
- uses: conda-incubator/setup-miniconda@v3
with:
@@ -27,10 +27,14 @@ jobs:
ANACONDA_API_TOKEN: ${{ secrets.ANACONDA_TOKEN }}
shell: bash -l {0}
run: |
+ conda config --env --add channels conda-forge
+ conda config --env --add channels loop3d
+ conda config --env --set channel_priority strict
conda install -c conda-forge conda-build scikit-build-core numpy anaconda-client conda-libmamba-solver -y
- conda build -c conda-forge -c loop3d --output-folder conda conda --python ${{matrix.python-version}}
+ conda config --set solver libmamba
+ conda build --output-folder conda conda --python ${{matrix.python-version}}
anaconda upload --label main conda/*/*.tar.bz2
-
+
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
diff --git a/.github/workflows/linting_and_testing.yml b/.github/workflows/linting_and_testing.yml
index a7ea3a0c..482fcf86 100644
--- a/.github/workflows/linting_and_testing.yml
+++ b/.github/workflows/linting_and_testing.yml
@@ -1,7 +1,20 @@
name: Linting and Testing
on:
- [push]
+ push:
+ branches:
+ - master
+ paths:
+ - '**.py'
+ - .github/workflows/linting_and_testing.yml
+
+ pull_request:
+ branches:
+ - master
+ paths:
+ - '**.py'
+ - .github/workflows/linting_and_testing.yml
+ workflow_dispatch:
jobs:
linting:
@@ -18,17 +31,23 @@ jobs:
- uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "style: style fixes by ruff and autoformatting by black"
-
+
+
testing:
- name: Testing
- runs-on: ubuntu-24.04
+ name: Testing${{ matrix.os }} python ${{ matrix.python-version }}
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: ${{ fromJSON(vars.BUILD_OS)}}
+ python-version: ${{ fromJSON(vars.PYTHON_VERSIONS)}}
steps:
- uses: actions/checkout@v4
- - name: Install GDAL
- run: |
- sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable
- sudo apt-get update
- sudo apt-get install -y libgdal-dev gdal-bin
+ - uses: conda-incubator/setup-miniconda@v3
+ with:
+ python-version: ${{ matrix.python }}
+ conda-remove-defaults: "true"
+
- name: Install dependencies
run: |
diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml
index 50e8d505..a2f47d5c 100644
--- a/.github/workflows/pypi.yml
+++ b/.github/workflows/pypi.yml
@@ -6,7 +6,7 @@ jobs:
sdist:
name: Build sdist
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -23,7 +23,7 @@ jobs:
publish:
name: Publish wheels to pypi
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-latest
permissions:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1f73031b..144739cd 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "3.2.0"
+ ".": "3.2.2"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 016d06e0..a78587db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## [3.2.2](https://github.com/Loop3D/map2loop/compare/v3.2.1...v3.2.2) (2025-01-13)
+
+
+### Bug Fixes
+
+* add featureId when parsing fault_orientations ([#177](https://github.com/Loop3D/map2loop/issues/177)) ([924c2cf](https://github.com/Loop3D/map2loop/commit/924c2cf696688abe3dc1c8579753daeb2f1b45e4))
+
+## [3.2.1](https://github.com/Loop3D/map2loop/compare/v3.2.0...v3.2.1) (2025-01-12)
+
+
+### Bug Fixes
+
+* include dependencies in site-packages - issue [#169](https://github.com/Loop3D/map2loop/issues/169) ([#170](https://github.com/Loop3D/map2loop/issues/170)) ([b33532b](https://github.com/Loop3D/map2loop/commit/b33532b56473148433fd192e182aadee028dc875))
+
## [3.2.0](https://github.com/Loop3D/map2loop/compare/v3.1.13...v3.2.0) (2024-12-16)
diff --git a/MANIFEST.in b/MANIFEST.in
index 67577e81..02b24a35 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,8 +1,3 @@
-include LICENSE
-include README.md
-
include map2loop/_datasets/clut_files/*.csv
include map2loop/_datasets/config_files/*.json
-include map2loop/_datasets/geodata_files/hamersley/*
-
-recursive-include tests *.py
\ No newline at end of file
+include map2loop/_datasets/geodata_files/hamersley/*
\ No newline at end of file
diff --git a/README.md b/README.md
index 144bc856..35a6909e 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,13 @@

+[](https://doi.org/10.5194/gmd-14-5063-2021)



[](https://github.com/Loop3D/map2loop/actions/workflows/linting_and_testing.yml)
[](https://github.com/Loop3D/map2loop/actions/workflows/documentation.yml)
-# Map2Loop 3.1
+
+# Map2Loop 3.2
Generate 3D geological model inputs from geological maps — a high-level implementation and extension of the original map2loop code developed by Prof. Mark Jessell at UWA. To see an example interactive model built with map2loop and LoopStructural, follow this link:
@@ -13,88 +15,56 @@ Generate 3D geological model inputs from geological maps — a high-level implem
## Install
-You will need some flavour of conda (a Python package manager, [see here](https://docs.anaconda.com/anaconda/install/index.html)), as well as Python ≥ 3.8.
+#### Option 1: Install with Anaconda
-### Adding ```conda-forge``` to Anaconda channels
-map2loop installation may run smoother if ```conda-forge``` is added to the channels.
-To check for that, run
+This is the simplest and recommended installation process, with:
```bash
-conda config --show channels
+conda install -c loop3d -c conda-forge map2loop
```
-if conda-forge is not in the output, the channel can be added with:
+#### Option 2: Install with pip
+Installation with pip will require that GDAL is installed on your system prior to map2loop installation.
+This is because GDAL cannot be installed via pip (at least not with one line of code), and the GDAL installation process will vary depending on your OS.
+
+For more information on installing gdal, see GDAL's Pypi page.
+
+Once GDAL is available on your system, map2loop can be installed with:
```bash
-conda config --add channels conda-forge
+pip install map2loop
```
-### Run
-
-To just use map2loop, issue the following. *
+#### Option 3: From source
```bash
git clone https://github.com/Loop3D/map2loop.git
cd map2loop
-conda install -c loop3d --file dependencies.txt
+conda install gdal
+
+conda install -c loop3d -c conda-forge --file dependencies.txt
pip install .
```
-
* We're actively working towards a better approach - stay tuned!
-
-### Documentation
-
-If you can call it that, is available here
-
-### Development
-
-If you want to tinker yourself/contribute, clone the source code with
-
+#### Option 4: From source & developer mode:
```bash
git clone https://github.com/Loop3D/map2loop.git
-```
-Or get the source + example notebooks with
+cd map2loop
-```bash
-git clone https://github.com/Loop3D/map2loop.git
-git clone https://github.com/Loop3D/map2loop-3-notebooks
-```
+conda install gdal
-Navigate into map2loop, and issue the following to install map2loop and its dependencies. _Note_: The 'develop' flag makes your source changes take effect on saving, so you only need to run this once
+conda install -c loop3d -c conda-forge --file dependencies.txt
-```bash
-conda install -c loop3d --file dependencies.txt
pip install -e .
```
-## Building with Docker
-
-Fair warning, we recommend conda to almost everyone. With great software development power comes great environment setup inconvenience. You'll need to download and install the [docker containerisation software](https://docs.docker.com/get-docker/), and the docker and docker-compose CLI.
-
-### Development
-
-1. Clone this repo and navigate inside as per above
-2. Run the following and click on the Jupyter server forwarded link to access and edit the notebooks
-
- ```bash
- docker-compose up --build
- ```
-
-3. To hop into a bash shell in a running container, open a terminal and issue
-
- ```bash
- docker ps
- ```
+### Documentation
- Find the container name or ID and then run
+Map2loop's documentation is available here
- ```bash
- docker exec -it bash
- # Probably -> docker exec -it map2loop_dev_1 bash
- ```
## Usage
@@ -118,8 +88,6 @@ bbox_3d = {
}
```
-
-
Then, specify: the state, directory for the output, the bounding box and projection from above - and hit go! That's it.
```python
diff --git a/conda/bld.bat b/conda/bld.bat
new file mode 100644
index 00000000..79ddb243
--- /dev/null
+++ b/conda/bld.bat
@@ -0,0 +1,5 @@
+mkdir %SP_DIR%\map2loop
+copy %RECIPE_DIR%\..\LICENSE %SP_DIR%\map2loop\
+copy %RECIPE_DIR%\..\README.md %SP_DIR%\map2loop\
+copy %RECIPE_DIR%\..\dependencies.txt %SP_DIR%\map2loop\
+%PYTHON% -m pip install .
\ No newline at end of file
diff --git a/conda/build.sh b/conda/build.sh
new file mode 100644
index 00000000..ca06369b
--- /dev/null
+++ b/conda/build.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+mkdir -p $SP_DIR/map2loop
+cp $RECIPE_DIR/../dependencies.txt $SP_DIR/map2loop/
+cp $RECIPE_DIR/../LICENSE $SP_DIR/map2loop/
+cp $RECIPE_DIR/../README.md $SP_DIR/map2loop/
+$PYTHON -m pip install .
\ No newline at end of file
diff --git a/conda/conda-build.py b/conda/conda-build.py
deleted file mode 100644
index e56347e3..00000000
--- a/conda/conda-build.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from subprocess import Popen, PIPE
-from concurrent.futures import ThreadPoolExecutor
-import tqdm
-import sys
-import os
-
-
-def process(python_version):
- try:
-
- command = 'conda build --py {} .'.format(
- python_version)
- p = Popen(
- command.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
- except Exception as e:
- return e
-
- output, err = p.communicate()
- return str(err.decode('ascii'))
-
-
-def build(packages):
- for dirname in packages:
- if not os.path.exists(dirname):
- sys.exit(
- "Make sure each package directory is at the same level as this script.")
-
- python_versions = [3.9, 3.10, 3.11, 3.12]
- print("Building " + " ".join(packages),
- "for python versions {}".format(python_versions))
-
- with ThreadPoolExecutor(15) as executor:
- output = list(
- tqdm.tqdm(executor.map(process, python_versions), total=len(packages)))
-
- for message in output:
- lines = message.split('\\n')
- for line in lines:
- print(line)
-
-
-def upload(root_buildpath):
-
- # Create OSX packages from linux versions
- output = ''
- command = "conda convert -p osx-64 {}*tar.bz2 -o {} -f".format(
- root_buildpath + 'linux-64/', root_buildpath)
- p = Popen(
- command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- output += p.communicate()[0].decode('ascii')
- output += p.communicate()[1].decode('ascii')
- command = "conda convert -p win-64 {}*tar.bz2 -o {} -f".format(
- root_buildpath + 'linux-64/', root_buildpath)
- p = Popen(
- command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- output += p.communicate()[0].decode('ascii')
- output += p.communicate()[1].decode('ascii')
-
- command = "anaconda upload {} {} {} --force".format(
- root_buildpath + 'linux-64/*.tar.bz2',
- root_buildpath + 'osx-64/*.tar.bz2',
- root_buildpath + 'win-64/*tar.bz2',
- )
- p = Popen(
- command, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
- output += p.communicate()[0].decode('ascii')
- output += p.communicate()[1].decode('ascii')
- print(output)
-
-
-if __name__ == "__main__":
-
- packages = [
- '.'
- ]
-
- command = 'which conda'
- p = Popen(
- command.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
- std, err = p.communicate()
- root_buildpath = "/".join(std.decode('ascii').split('/')
- [:-2]) + '/conda-bld/'
-
- build(packages)
- # upload(root_buildpath)
diff --git a/conda/conda_build_config.yaml b/conda/conda_build_config.yaml
deleted file mode 100644
index d7d85008..00000000
--- a/conda/conda_build_config.yaml
+++ /dev/null
@@ -1,6 +0,0 @@
-python:
- - 3.8
- - 3.9
- - 3.10
- - 3.11
- - 3.12
diff --git a/conda/meta.yaml b/conda/meta.yaml
index 4da8e118..4abf63a8 100644
--- a/conda/meta.yaml
+++ b/conda/meta.yaml
@@ -7,10 +7,8 @@ package:
source:
git_url: https://github.com/Loop3D/map2loop
-
build:
number: 0
- script: "{{ PYTHON }} -m pip install . --no-deps"
requirements:
host:
@@ -20,17 +18,17 @@ requirements:
run:
- loopprojectfile ==0.2.2
- gdal
- - map2model
- - beartype
- python
- numpy
- - pandas
+ - scipy
- geopandas
- shapely
- - tqdm
- networkx
- owslib
-
+ - map2model
+ - beartype
+ - pytest
+ - scikit-learn
about:
home: "https://github.com/Loop3D/map2loop"
diff --git a/dependencies.txt b/dependencies.txt
index 57a2f246..7a1d95e7 100644
--- a/dependencies.txt
+++ b/dependencies.txt
@@ -1,4 +1,3 @@
-
numpy
scipy
geopandas
diff --git a/map2loop/__init__.py b/map2loop/__init__.py
index 17428522..d7ccac11 100644
--- a/map2loop/__init__.py
+++ b/map2loop/__init__.py
@@ -30,7 +30,7 @@ class DependencyChecker:
def __init__(self, package_name, dependency_file="dependencies.txt"):
self.package_name = package_name
- self.dependency_file = pathlib.Path(__file__).parent.parent / dependency_file
+ self.dependency_file = pathlib.Path(__file__).parent / dependency_file
self.required_version = self.get_required_version()
self.installed_version = self.get_installed_version()
@@ -93,7 +93,7 @@ def check_version(self):
def check_all_dependencies(dependency_file="dependencies.txt"):
- dependencies_path = pathlib.Path(__file__).parent.parent / dependency_file
+ dependencies_path = pathlib.Path(__file__).parent / dependency_file
try:
with dependencies_path.open("r") as file:
for line in file:
@@ -108,6 +108,7 @@ def check_all_dependencies(dependency_file="dependencies.txt"):
checker = DependencyChecker(package_name, dependency_file=dependency_file)
checker.check_version()
+
except FileNotFoundError:
warnings.warn(
f"{dependency_file} not found. No dependencies checked for map2loop.",
diff --git a/map2loop/mapdata.py b/map2loop/mapdata.py
index 4ef0be89..6948d3c3 100644
--- a/map2loop/mapdata.py
+++ b/map2loop/mapdata.py
@@ -567,7 +567,7 @@ def __retrieve_tif(self, filename: str):
if filename.lower() == "aus" or filename.lower() == "au":
logger.info('Using Geoscience Australia DEM')
- url = "http://services.ga.gov.au/gis/services/DEM_SRTM_1Second_over_Bathymetry_Topography/MapServer/WCSServer?"
+ url = "https://services.ga.gov.au/gis/services/Bathymetry_Topography/MapServer/WCSServer?"
wcs = WebCoverageService(url, version="1.0.0")
coverage = wcs.getCoverage(
@@ -730,7 +730,7 @@ def parse_fault_orientations(self) -> tuple:
# Parse dip direction and dip columns
if config["dipdir_column"] in self.raw_data[Datatype.FAULT_ORIENTATION]:
if config["orientation_type"] == "strike":
- fault_orientations["DIPDIR"] = self.raw_data[Datatype.STRUCTURE].apply(
+ fault_orientations["DIPDIR"] = self.raw_data[Datatype.FAULT_ORIENTATION].apply(
lambda row: (row[config["dipdir_column"]] + 90.0) % 360.0, axis=1
)
else:
@@ -763,6 +763,14 @@ def parse_fault_orientations(self) -> tuple:
else:
fault_orientations["ID"] = numpy.arange(len(fault_orientations))
self.data[Datatype.FAULT_ORIENTATION] = fault_orientations
+
+ if config["featureid_column"] in self.raw_data[Datatype.FAULT_ORIENTATION]:
+ fault_orientations["featureId"] = self.raw_data[Datatype.FAULT_ORIENTATION][
+ config["featureid_column"]
+ ]
+ else:
+ fault_orientations["featureId"] = numpy.arange(len(fault_orientations))
+
return (False, "")
@beartype.beartype
diff --git a/map2loop/version.py b/map2loop/version.py
index 11731085..1e3bed4c 100644
--- a/map2loop/version.py
+++ b/map2loop/version.py
@@ -1 +1 @@
-__version__ = "3.2.0"
+__version__ = "3.2.2"
diff --git a/pyproject.toml b/pyproject.toml
index c5d1b68a..4ecb4207 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -38,7 +38,11 @@ version = { attr = "map2loop.version.__version__" }
[tool.setuptools.packages.find]
include = ['map2loop', 'map2loop.*']
-
+[tool.setuptools.package-data]
+map2loop = [
+ "dependencies.txt",
+ "_datasets/geodata_files/hamersley/*"
+]
[tool.black]
line-length = 100
diff --git a/setup.py b/setup.py
index 7cea5025..21383418 100644
--- a/setup.py
+++ b/setup.py
@@ -1,28 +1,49 @@
-"""See pyproject.toml for project metadata."""
+from setuptools.command.sdist import sdist as _sdist
+import shutil
+from setuptools import setup, find_packages
+from pathlib import Path
-import os
-from setuptools import setup
-
-package_root = os.path.abspath(os.path.dirname(__file__))
+# Resolve the absolute path to the directory containing this file:
+package_root = Path(__file__).resolve().parent
# Get the version from the version.py file
version = {}
-with open(os.path.join(package_root, "map2loop/version.py")) as fp:
+version_file = package_root / "map2loop" / "version.py"
+with version_file.open() as fp:
exec(fp.read(), version)
-version = version["__version__"]
# Read dependencies from dependencies.txt
-requirements_file = os.path.join(package_root, "dependencies.txt")
-with open(requirements_file, 'r') as f:
+requirements_file = package_root / "dependencies.txt"
+with requirements_file.open("r") as f:
install_requires = [line.strip() for line in f if line.strip()]
+
+class CustomSDist(_sdist):
+
+ def make_release_tree(self, base_dir, files):
+ # 1) Let the normal sdist process run first.
+ super().make_release_tree(base_dir, files)
+ map2loop_dir = Path(base_dir) / "map2loop"
+
+ # 2) Specify which files to move from the root to map2loop/.
+ top_level_files = ["dependencies.txt", "LICENSE", "README.md"]
+
+ for filename in top_level_files:
+ src = Path(base_dir) / filename
+ dst = map2loop_dir / filename
+
+ # If the source file exists in base_dir, move it to map2loop/.
+ if src.exists():
+ shutil.copy(str(src), str(dst))
+
setup(
name="map2loop",
- install_requires=install_requires,
- version=version,
+ install_requires=install_requires,
+ packages=find_packages(exclude=["tests", "tests.*"]),
+ package_data={"": ['dependencies.txt']},
+ include_package_data=True,
license="MIT",
- package_data={
- # Include test files:
- '': ['tests/*.py'],
+ cmdclass={
+ "sdist": CustomSDist,
},
-)
\ No newline at end of file
+)