From aeb66c89e5921bbc04187914843701c6f147342e Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 25 Jun 2025 15:21:51 -0700 Subject: [PATCH 1/9] Initial migration of files --- .../py-3.10-linux-64-dev.conda.lock.yml | 19 +- environments/py-3.10-linux-64.conda.lock.yml | 19 +- .../py-3.10-win-64-dev.conda.lock.yml | 11 +- environments/py-3.10-win-64.conda.lock.yml | 11 +- .../py-3.11-linux-64-dev.conda.lock.yml | 19 +- environments/py-3.11-linux-64.conda.lock.yml | 19 +- .../py-3.11-win-64-dev.conda.lock.yml | 11 +- environments/py-3.11-win-64.conda.lock.yml | 11 +- .../py-3.12-linux-64-dev.conda.lock.yml | 19 +- environments/py-3.12-linux-64.conda.lock.yml | 19 +- .../py-3.12-win-64-dev.conda.lock.yml | 11 +- environments/py-3.12-win-64.conda.lock.yml | 11 +- py-3.10.conda-lock.yml | 146 +++++++-- py-3.11.conda-lock.yml | 146 +++++++-- py-3.12.conda-lock.yml | 146 +++++++-- pyproject.toml | 2 + simpeg_drivers/plate_simulation/__init__.py | 23 ++ simpeg_drivers/plate_simulation/driver.py | 307 ++++++++++++++++++ simpeg_drivers/plate_simulation/logger.py | 32 ++ .../plate_simulation/mesh/__init__.py | 9 + .../plate_simulation/mesh/options.py | 73 +++++ .../plate_simulation/models/__init__.py | 11 + .../plate_simulation/models/events.py | 184 +++++++++++ .../plate_simulation/models/options.py | 157 +++++++++ .../plate_simulation/models/parametric.py | 247 ++++++++++++++ .../plate_simulation/models/series.py | 229 +++++++++++++ simpeg_drivers/plate_simulation/options.py | 100 ++++++ simpeg_drivers/plate_simulation/utils.py | 56 ++++ 28 files changed, 1880 insertions(+), 168 deletions(-) create mode 100644 simpeg_drivers/plate_simulation/__init__.py create mode 100644 simpeg_drivers/plate_simulation/driver.py create mode 100644 simpeg_drivers/plate_simulation/logger.py create mode 100644 simpeg_drivers/plate_simulation/mesh/__init__.py create mode 100644 simpeg_drivers/plate_simulation/mesh/options.py create mode 100644 simpeg_drivers/plate_simulation/models/__init__.py create mode 100644 simpeg_drivers/plate_simulation/models/events.py create mode 100644 simpeg_drivers/plate_simulation/models/options.py create mode 100644 simpeg_drivers/plate_simulation/models/parametric.py create mode 100644 simpeg_drivers/plate_simulation/models/series.py create mode 100644 simpeg_drivers/plate_simulation/options.py create mode 100644 simpeg_drivers/plate_simulation/utils.py diff --git a/environments/py-3.10-linux-64-dev.conda.lock.yml b/environments/py-3.10-linux-64-dev.conda.lock.yml index 33cd49b6..d5faa705 100644 --- a/environments/py-3.10-linux-64-dev.conda.lock.yml +++ b/environments/py-3.10-linux-64-dev.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: linux-64 -# input_hash: d20cb4f62773f79495ca5432e662a34453afa41e6084f06c349fbb84600a44bb +# input_hash: 0f54a26695792bef9ae71d11e72896171987869d09020c611e73c9a0622596d6 channels: - conda-forge @@ -125,10 +125,10 @@ dependencies: - libffi=3.4.6=h2dba641_1 - libfreetype=2.13.3=ha770c72_1 - libfreetype6=2.13.3=h48d6fc4_1 - - libgcc=15.1.0=h767d61c_2 - - libgcc-ng=15.1.0=h69a702a_2 - - libgfortran=15.1.0=h69a702a_2 - - libgfortran5=15.1.0=hcea5267_2 + - libgcc=15.1.0=h767d61c_3 + - libgcc-ng=15.1.0=h69a702a_3 + - libgfortran=15.1.0=h69a702a_3 + - libgfortran5=15.1.0=hcea5267_3 - libhwloc=2.11.2=default_h0d58e46_1001 - libiconv=1.18=h4ce23a2_1 - libjpeg-turbo=3.1.0=hb9d3cd8_0 @@ -139,10 +139,11 @@ dependencies: - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 - libsodium=1.0.20=h4ab18f5_0 + - libspatialindex=2.0.0=he02047a_0 - libsqlite=3.50.1=h6cd9bfd_6 - libssh2=1.11.1=hcf80075_0 - - libstdcxx=15.1.0=h8f9b012_2 - - libstdcxx-ng=15.1.0=h4852527_2 + - libstdcxx=15.1.0=h8f9b012_3 + - libstdcxx-ng=15.1.0=h4852527_3 - libtiff=4.7.0=hf01ce69_5 - libuuid=2.38.1=h0b41bf4_0 - libwebp-base=1.5.0=h851e524_0 @@ -233,6 +234,7 @@ dependencies: - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 - rpds-py=0.25.1=py310hbcd0ec0_0 + - rtree=1.2.0=py310haf1e407_1 - scikit-learn=1.4.2=py310h981052a_1 - scipy=1.14.1=py310hfcf56fc_2 - send2trash=1.8.3=pyh0d859eb_1 @@ -275,6 +277,7 @@ dependencies: - tornado=6.5.1=py310ha75aee5_0 - tqdm=4.67.1=pyhd8ed1ab_1 - traitlets=5.14.3=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - types-python-dateutil=2.9.0.20250516=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 @@ -302,7 +305,7 @@ dependencies: - zstandard=0.23.0=py310ha75aee5_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.10-linux-64.conda.lock.yml b/environments/py-3.10-linux-64.conda.lock.yml index 5fc2b5e9..611d51ab 100644 --- a/environments/py-3.10-linux-64.conda.lock.yml +++ b/environments/py-3.10-linux-64.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: linux-64 -# input_hash: d20cb4f62773f79495ca5432e662a34453afa41e6084f06c349fbb84600a44bb +# input_hash: 0f54a26695792bef9ae71d11e72896171987869d09020c611e73c9a0622596d6 channels: - conda-forge @@ -64,10 +64,10 @@ dependencies: - libffi=3.4.6=h2dba641_1 - libfreetype=2.13.3=ha770c72_1 - libfreetype6=2.13.3=h48d6fc4_1 - - libgcc=15.1.0=h767d61c_2 - - libgcc-ng=15.1.0=h69a702a_2 - - libgfortran=15.1.0=h69a702a_2 - - libgfortran5=15.1.0=hcea5267_2 + - libgcc=15.1.0=h767d61c_3 + - libgcc-ng=15.1.0=h69a702a_3 + - libgfortran=15.1.0=h69a702a_3 + - libgfortran5=15.1.0=hcea5267_3 - libhwloc=2.11.2=default_h0d58e46_1001 - libiconv=1.18=h4ce23a2_1 - libjpeg-turbo=3.1.0=hb9d3cd8_0 @@ -77,10 +77,11 @@ dependencies: - libnsl=2.0.1=hb9d3cd8_1 - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 + - libspatialindex=2.0.0=he02047a_0 - libsqlite=3.50.1=h6cd9bfd_6 - libssh2=1.11.1=hcf80075_0 - - libstdcxx=15.1.0=h8f9b012_2 - - libstdcxx-ng=15.1.0=h4852527_2 + - libstdcxx=15.1.0=h8f9b012_3 + - libstdcxx-ng=15.1.0=h4852527_3 - libtiff=4.7.0=hf01ce69_5 - libuuid=2.38.1=h0b41bf4_0 - libwebp-base=1.5.0=h851e524_0 @@ -125,6 +126,7 @@ dependencies: - pytz=2025.2=pyhd8ed1ab_0 - pyyaml=6.0.2=py310h89163eb_2 - readline=8.2=h8c095d6_2 + - rtree=1.2.0=py310haf1e407_1 - scikit-learn=1.4.2=py310h981052a_1 - scipy=1.14.1=py310hfcf56fc_2 - setuptools=80.9.0=pyhff2d567_0 @@ -137,6 +139,7 @@ dependencies: - toolz=1.0.0=pyhd8ed1ab_1 - tornado=6.5.1=py310ha75aee5_0 - tqdm=4.67.1=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 - typing_extensions=4.14.0=pyhe01879c_0 @@ -154,7 +157,7 @@ dependencies: - zstandard=0.23.0=py310ha75aee5_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.10-win-64-dev.conda.lock.yml b/environments/py-3.10-win-64-dev.conda.lock.yml index c379b4a8..375bbae8 100644 --- a/environments/py-3.10-win-64-dev.conda.lock.yml +++ b/environments/py-3.10-win-64-dev.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: eaae335cf36adc80372dc46b8513b3371068cb4b78164f9bf33218ae884e5a43 +# input_hash: fe9bea64dc53fd535084a0a107d7688e8632e51eeb8084b72468b0a651a364b6 channels: - conda-forge @@ -121,8 +121,8 @@ dependencies: - libffi=3.4.6=h537db12_1 - libfreetype=2.13.3=h57928b3_1 - libfreetype6=2.13.3=h0b5ce68_1 - - libgcc=15.1.0=h1383e82_2 - - libgomp=15.1.0=h1383e82_2 + - libgcc=15.1.0=h1383e82_3 + - libgomp=15.1.0=h1383e82_3 - libhwloc=2.11.2=default_ha69328c_1001 - libiconv=1.18=h135ad9c_1 - libjpeg-turbo=3.1.0=h2466b09_0 @@ -130,6 +130,7 @@ dependencies: - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 - libsodium=1.0.20=hc70643c_0 + - libspatialindex=2.0.0=h5a68840_0 - libsqlite=3.50.1=hf5d6505_6 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 @@ -217,6 +218,7 @@ dependencies: - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 - rpds-py=0.25.1=py310hed05c55_0 + - rtree=1.2.0=py310h08d5ad2_1 - scikit-learn=1.4.2=py310hf2a6c47_1 - scipy=1.14.1=py310hbd0dde3_2 - send2trash=1.8.3=pyh5737063_1 @@ -259,6 +261,7 @@ dependencies: - tornado=6.5.1=py310ha8f682b_0 - tqdm=4.67.1=pyhd8ed1ab_1 - traitlets=5.14.3=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - types-python-dateutil=2.9.0.20250516=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 @@ -292,7 +295,7 @@ dependencies: - zstandard=0.23.0=py310ha8f682b_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.10-win-64.conda.lock.yml b/environments/py-3.10-win-64.conda.lock.yml index d3c226fb..9b20d542 100644 --- a/environments/py-3.10-win-64.conda.lock.yml +++ b/environments/py-3.10-win-64.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: eaae335cf36adc80372dc46b8513b3371068cb4b78164f9bf33218ae884e5a43 +# input_hash: fe9bea64dc53fd535084a0a107d7688e8632e51eeb8084b72468b0a651a364b6 channels: - conda-forge @@ -59,14 +59,15 @@ dependencies: - libffi=3.4.6=h537db12_1 - libfreetype=2.13.3=h57928b3_1 - libfreetype6=2.13.3=h0b5ce68_1 - - libgcc=15.1.0=h1383e82_2 - - libgomp=15.1.0=h1383e82_2 + - libgcc=15.1.0=h1383e82_3 + - libgomp=15.1.0=h1383e82_3 - libhwloc=2.11.2=default_ha69328c_1001 - libiconv=1.18=h135ad9c_1 - libjpeg-turbo=3.1.0=h2466b09_0 - liblapack=3.9.0=32_h1aa476e_mkl - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 + - libspatialindex=2.0.0=h5a68840_0 - libsqlite=3.50.1=hf5d6505_6 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 @@ -108,6 +109,7 @@ dependencies: - python_abi=3.10=7_cp310 - pytz=2025.2=pyhd8ed1ab_0 - pyyaml=6.0.2=py310h38315fa_2 + - rtree=1.2.0=py310h08d5ad2_1 - scikit-learn=1.4.2=py310hf2a6c47_1 - scipy=1.14.1=py310hbd0dde3_2 - setuptools=80.9.0=pyhff2d567_0 @@ -120,6 +122,7 @@ dependencies: - toolz=1.0.0=pyhd8ed1ab_1 - tornado=6.5.1=py310ha8f682b_0 - tqdm=4.67.1=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 - typing_extensions=4.14.0=pyhe01879c_0 @@ -142,7 +145,7 @@ dependencies: - zstandard=0.23.0=py310ha8f682b_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-linux-64-dev.conda.lock.yml b/environments/py-3.11-linux-64-dev.conda.lock.yml index b9cac7c0..164bc451 100644 --- a/environments/py-3.11-linux-64-dev.conda.lock.yml +++ b/environments/py-3.11-linux-64-dev.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: linux-64 -# input_hash: c83206a2eacb4c3e0efe0aa15f924d81adc9fe1f02d077a12434b468bb2045e6 +# input_hash: c9dba1cefe5fafa1d6916df23312dff6e683994e65910cb3e402d7568b87973d channels: - conda-forge @@ -127,10 +127,10 @@ dependencies: - libffi=3.4.6=h2dba641_1 - libfreetype=2.13.3=ha770c72_1 - libfreetype6=2.13.3=h48d6fc4_1 - - libgcc=15.1.0=h767d61c_2 - - libgcc-ng=15.1.0=h69a702a_2 - - libgfortran=15.1.0=h69a702a_2 - - libgfortran5=15.1.0=hcea5267_2 + - libgcc=15.1.0=h767d61c_3 + - libgcc-ng=15.1.0=h69a702a_3 + - libgfortran=15.1.0=h69a702a_3 + - libgfortran5=15.1.0=hcea5267_3 - libhwloc=2.11.2=default_h0d58e46_1001 - libiconv=1.18=h4ce23a2_1 - libjpeg-turbo=3.1.0=hb9d3cd8_0 @@ -141,10 +141,11 @@ dependencies: - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 - libsodium=1.0.20=h4ab18f5_0 + - libspatialindex=2.0.0=he02047a_0 - libsqlite=3.50.1=h6cd9bfd_6 - libssh2=1.11.1=hcf80075_0 - - libstdcxx=15.1.0=h8f9b012_2 - - libstdcxx-ng=15.1.0=h4852527_2 + - libstdcxx=15.1.0=h8f9b012_3 + - libstdcxx-ng=15.1.0=h4852527_3 - libtiff=4.7.0=hf01ce69_5 - libuuid=2.38.1=h0b41bf4_0 - libwebp-base=1.5.0=h851e524_0 @@ -235,6 +236,7 @@ dependencies: - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 - rpds-py=0.25.1=py311hdae7d1d_0 + - rtree=1.2.0=py311ha1603b9_1 - scikit-learn=1.4.2=py311he08f58d_1 - scipy=1.14.1=py311he9a78e4_2 - send2trash=1.8.3=pyh0d859eb_1 @@ -277,6 +279,7 @@ dependencies: - tornado=6.5.1=py311h9ecbd09_0 - tqdm=4.67.1=pyhd8ed1ab_1 - traitlets=5.14.3=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - types-python-dateutil=2.9.0.20250516=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 @@ -305,7 +308,7 @@ dependencies: - zstandard=0.23.0=py311h9ecbd09_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-linux-64.conda.lock.yml b/environments/py-3.11-linux-64.conda.lock.yml index 6cd3518c..50dc8edc 100644 --- a/environments/py-3.11-linux-64.conda.lock.yml +++ b/environments/py-3.11-linux-64.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: linux-64 -# input_hash: c83206a2eacb4c3e0efe0aa15f924d81adc9fe1f02d077a12434b468bb2045e6 +# input_hash: c9dba1cefe5fafa1d6916df23312dff6e683994e65910cb3e402d7568b87973d channels: - conda-forge @@ -65,10 +65,10 @@ dependencies: - libffi=3.4.6=h2dba641_1 - libfreetype=2.13.3=ha770c72_1 - libfreetype6=2.13.3=h48d6fc4_1 - - libgcc=15.1.0=h767d61c_2 - - libgcc-ng=15.1.0=h69a702a_2 - - libgfortran=15.1.0=h69a702a_2 - - libgfortran5=15.1.0=hcea5267_2 + - libgcc=15.1.0=h767d61c_3 + - libgcc-ng=15.1.0=h69a702a_3 + - libgfortran=15.1.0=h69a702a_3 + - libgfortran5=15.1.0=hcea5267_3 - libhwloc=2.11.2=default_h0d58e46_1001 - libiconv=1.18=h4ce23a2_1 - libjpeg-turbo=3.1.0=hb9d3cd8_0 @@ -78,10 +78,11 @@ dependencies: - libnsl=2.0.1=hb9d3cd8_1 - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 + - libspatialindex=2.0.0=he02047a_0 - libsqlite=3.50.1=h6cd9bfd_6 - libssh2=1.11.1=hcf80075_0 - - libstdcxx=15.1.0=h8f9b012_2 - - libstdcxx-ng=15.1.0=h4852527_2 + - libstdcxx=15.1.0=h8f9b012_3 + - libstdcxx-ng=15.1.0=h4852527_3 - libtiff=4.7.0=hf01ce69_5 - libuuid=2.38.1=h0b41bf4_0 - libwebp-base=1.5.0=h851e524_0 @@ -126,6 +127,7 @@ dependencies: - pytz=2025.2=pyhd8ed1ab_0 - pyyaml=6.0.2=py311h2dc5d0c_2 - readline=8.2=h8c095d6_2 + - rtree=1.2.0=py311ha1603b9_1 - scikit-learn=1.4.2=py311he08f58d_1 - scipy=1.14.1=py311he9a78e4_2 - setuptools=80.9.0=pyhff2d567_0 @@ -138,6 +140,7 @@ dependencies: - toolz=1.0.0=pyhd8ed1ab_1 - tornado=6.5.1=py311h9ecbd09_0 - tqdm=4.67.1=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 - typing_extensions=4.14.0=pyhe01879c_0 @@ -156,7 +159,7 @@ dependencies: - zstandard=0.23.0=py311h9ecbd09_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-win-64-dev.conda.lock.yml b/environments/py-3.11-win-64-dev.conda.lock.yml index 1c432fc6..c7dd9846 100644 --- a/environments/py-3.11-win-64-dev.conda.lock.yml +++ b/environments/py-3.11-win-64-dev.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: 2d7c4e988ae2df2fbd8349e86ba264f7eb281505021cebbdb8d9a2d3b0dda7ad +# input_hash: b9f574bd52f02e9a0d8648f478d484cd228f132f708933856414eed155f61a30 channels: - conda-forge @@ -123,8 +123,8 @@ dependencies: - libffi=3.4.6=h537db12_1 - libfreetype=2.13.3=h57928b3_1 - libfreetype6=2.13.3=h0b5ce68_1 - - libgcc=15.1.0=h1383e82_2 - - libgomp=15.1.0=h1383e82_2 + - libgcc=15.1.0=h1383e82_3 + - libgomp=15.1.0=h1383e82_3 - libhwloc=2.11.2=default_ha69328c_1001 - libiconv=1.18=h135ad9c_1 - libjpeg-turbo=3.1.0=h2466b09_0 @@ -132,6 +132,7 @@ dependencies: - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 - libsodium=1.0.20=hc70643c_0 + - libspatialindex=2.0.0=h5a68840_0 - libsqlite=3.50.1=hf5d6505_6 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 @@ -219,6 +220,7 @@ dependencies: - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 - rpds-py=0.25.1=py311hc4022dc_0 + - rtree=1.2.0=py311h44d53c4_1 - scikit-learn=1.4.2=py311hdcb8d17_1 - scipy=1.14.1=py311hf16d85f_2 - send2trash=1.8.3=pyh5737063_1 @@ -261,6 +263,7 @@ dependencies: - tornado=6.5.1=py311he736701_0 - tqdm=4.67.1=pyhd8ed1ab_1 - traitlets=5.14.3=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - types-python-dateutil=2.9.0.20250516=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 @@ -295,7 +298,7 @@ dependencies: - zstandard=0.23.0=py311he736701_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-win-64.conda.lock.yml b/environments/py-3.11-win-64.conda.lock.yml index c8bba703..1a7b224a 100644 --- a/environments/py-3.11-win-64.conda.lock.yml +++ b/environments/py-3.11-win-64.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: 2d7c4e988ae2df2fbd8349e86ba264f7eb281505021cebbdb8d9a2d3b0dda7ad +# input_hash: b9f574bd52f02e9a0d8648f478d484cd228f132f708933856414eed155f61a30 channels: - conda-forge @@ -60,14 +60,15 @@ dependencies: - libffi=3.4.6=h537db12_1 - libfreetype=2.13.3=h57928b3_1 - libfreetype6=2.13.3=h0b5ce68_1 - - libgcc=15.1.0=h1383e82_2 - - libgomp=15.1.0=h1383e82_2 + - libgcc=15.1.0=h1383e82_3 + - libgomp=15.1.0=h1383e82_3 - libhwloc=2.11.2=default_ha69328c_1001 - libiconv=1.18=h135ad9c_1 - libjpeg-turbo=3.1.0=h2466b09_0 - liblapack=3.9.0=32_h1aa476e_mkl - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 + - libspatialindex=2.0.0=h5a68840_0 - libsqlite=3.50.1=hf5d6505_6 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 @@ -109,6 +110,7 @@ dependencies: - python_abi=3.11=7_cp311 - pytz=2025.2=pyhd8ed1ab_0 - pyyaml=6.0.2=py311h5082efb_2 + - rtree=1.2.0=py311h44d53c4_1 - scikit-learn=1.4.2=py311hdcb8d17_1 - scipy=1.14.1=py311hf16d85f_2 - setuptools=80.9.0=pyhff2d567_0 @@ -121,6 +123,7 @@ dependencies: - toolz=1.0.0=pyhd8ed1ab_1 - tornado=6.5.1=py311he736701_0 - tqdm=4.67.1=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 - typing_extensions=4.14.0=pyhe01879c_0 @@ -144,7 +147,7 @@ dependencies: - zstandard=0.23.0=py311he736701_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-linux-64-dev.conda.lock.yml b/environments/py-3.12-linux-64-dev.conda.lock.yml index f4ed79fa..6b90380b 100644 --- a/environments/py-3.12-linux-64-dev.conda.lock.yml +++ b/environments/py-3.12-linux-64-dev.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: linux-64 -# input_hash: 86d8c36c4b440eac7a217d19ba6775b033719c3606e19d205f30e9bf039ae01e +# input_hash: 986de85ed6e6464ef1d28bc0bd68959524a00d49b9d9e57fda77fdcf3447934a channels: - conda-forge @@ -127,10 +127,10 @@ dependencies: - libffi=3.4.6=h2dba641_1 - libfreetype=2.13.3=ha770c72_1 - libfreetype6=2.13.3=h48d6fc4_1 - - libgcc=15.1.0=h767d61c_2 - - libgcc-ng=15.1.0=h69a702a_2 - - libgfortran=15.1.0=h69a702a_2 - - libgfortran5=15.1.0=hcea5267_2 + - libgcc=15.1.0=h767d61c_3 + - libgcc-ng=15.1.0=h69a702a_3 + - libgfortran=15.1.0=h69a702a_3 + - libgfortran5=15.1.0=hcea5267_3 - libhwloc=2.11.2=default_h0d58e46_1001 - libiconv=1.18=h4ce23a2_1 - libjpeg-turbo=3.1.0=hb9d3cd8_0 @@ -141,10 +141,11 @@ dependencies: - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 - libsodium=1.0.20=h4ab18f5_0 + - libspatialindex=2.0.0=he02047a_0 - libsqlite=3.50.1=h6cd9bfd_6 - libssh2=1.11.1=hcf80075_0 - - libstdcxx=15.1.0=h8f9b012_2 - - libstdcxx-ng=15.1.0=h4852527_2 + - libstdcxx=15.1.0=h8f9b012_3 + - libstdcxx-ng=15.1.0=h4852527_3 - libtiff=4.7.0=hf01ce69_5 - libuuid=2.38.1=h0b41bf4_0 - libwebp-base=1.5.0=h851e524_0 @@ -235,6 +236,7 @@ dependencies: - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 - rpds-py=0.25.1=py312h680f630_0 + - rtree=1.2.0=py312h3ed4c40_1 - scikit-learn=1.4.2=py312h1fcc3ea_1 - scipy=1.14.1=py312h62794b6_2 - send2trash=1.8.3=pyh0d859eb_1 @@ -277,6 +279,7 @@ dependencies: - tornado=6.5.1=py312h66e93f0_0 - tqdm=4.67.1=pyhd8ed1ab_1 - traitlets=5.14.3=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - types-python-dateutil=2.9.0.20250516=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 @@ -305,7 +308,7 @@ dependencies: - zstandard=0.23.0=py312h66e93f0_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-linux-64.conda.lock.yml b/environments/py-3.12-linux-64.conda.lock.yml index 1ce584ee..43604127 100644 --- a/environments/py-3.12-linux-64.conda.lock.yml +++ b/environments/py-3.12-linux-64.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: linux-64 -# input_hash: 86d8c36c4b440eac7a217d19ba6775b033719c3606e19d205f30e9bf039ae01e +# input_hash: 986de85ed6e6464ef1d28bc0bd68959524a00d49b9d9e57fda77fdcf3447934a channels: - conda-forge @@ -65,10 +65,10 @@ dependencies: - libffi=3.4.6=h2dba641_1 - libfreetype=2.13.3=ha770c72_1 - libfreetype6=2.13.3=h48d6fc4_1 - - libgcc=15.1.0=h767d61c_2 - - libgcc-ng=15.1.0=h69a702a_2 - - libgfortran=15.1.0=h69a702a_2 - - libgfortran5=15.1.0=hcea5267_2 + - libgcc=15.1.0=h767d61c_3 + - libgcc-ng=15.1.0=h69a702a_3 + - libgfortran=15.1.0=h69a702a_3 + - libgfortran5=15.1.0=hcea5267_3 - libhwloc=2.11.2=default_h0d58e46_1001 - libiconv=1.18=h4ce23a2_1 - libjpeg-turbo=3.1.0=hb9d3cd8_0 @@ -78,10 +78,11 @@ dependencies: - libnsl=2.0.1=hb9d3cd8_1 - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 + - libspatialindex=2.0.0=he02047a_0 - libsqlite=3.50.1=h6cd9bfd_6 - libssh2=1.11.1=hcf80075_0 - - libstdcxx=15.1.0=h8f9b012_2 - - libstdcxx-ng=15.1.0=h4852527_2 + - libstdcxx=15.1.0=h8f9b012_3 + - libstdcxx-ng=15.1.0=h4852527_3 - libtiff=4.7.0=hf01ce69_5 - libuuid=2.38.1=h0b41bf4_0 - libwebp-base=1.5.0=h851e524_0 @@ -126,6 +127,7 @@ dependencies: - pytz=2025.2=pyhd8ed1ab_0 - pyyaml=6.0.2=py312h178313f_2 - readline=8.2=h8c095d6_2 + - rtree=1.2.0=py312h3ed4c40_1 - scikit-learn=1.4.2=py312h1fcc3ea_1 - scipy=1.14.1=py312h62794b6_2 - setuptools=80.9.0=pyhff2d567_0 @@ -138,6 +140,7 @@ dependencies: - toolz=1.0.0=pyhd8ed1ab_1 - tornado=6.5.1=py312h66e93f0_0 - tqdm=4.67.1=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 - typing_extensions=4.14.0=pyhe01879c_0 @@ -156,7 +159,7 @@ dependencies: - zstandard=0.23.0=py312h66e93f0_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-win-64-dev.conda.lock.yml b/environments/py-3.12-win-64-dev.conda.lock.yml index 177e42fc..8c60a2ed 100644 --- a/environments/py-3.12-win-64-dev.conda.lock.yml +++ b/environments/py-3.12-win-64-dev.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: dd5f3d6403d5db52a5e41fb35b60dce2df1a615f984bba47e191a2a14a68dd3c +# input_hash: 8ac7e9b31d0a8968577d04b18bfae4e5b55625cc38cfb3a62f6b8f87f8a156f9 channels: - conda-forge @@ -123,8 +123,8 @@ dependencies: - libffi=3.4.6=h537db12_1 - libfreetype=2.13.3=h57928b3_1 - libfreetype6=2.13.3=h0b5ce68_1 - - libgcc=15.1.0=h1383e82_2 - - libgomp=15.1.0=h1383e82_2 + - libgcc=15.1.0=h1383e82_3 + - libgomp=15.1.0=h1383e82_3 - libhwloc=2.11.2=default_ha69328c_1001 - libiconv=1.18=h135ad9c_1 - libjpeg-turbo=3.1.0=h2466b09_0 @@ -132,6 +132,7 @@ dependencies: - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 - libsodium=1.0.20=hc70643c_0 + - libspatialindex=2.0.0=h5a68840_0 - libsqlite=3.50.1=hf5d6505_6 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 @@ -219,6 +220,7 @@ dependencies: - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 - rpds-py=0.25.1=py312h8422cdd_0 + - rtree=1.2.0=py312h50e5f8f_1 - scikit-learn=1.4.2=py312h816cc57_1 - scipy=1.14.1=py312h337df96_2 - send2trash=1.8.3=pyh5737063_1 @@ -261,6 +263,7 @@ dependencies: - tornado=6.5.1=py312h4389bb4_0 - tqdm=4.67.1=pyhd8ed1ab_1 - traitlets=5.14.3=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - types-python-dateutil=2.9.0.20250516=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 @@ -295,7 +298,7 @@ dependencies: - zstandard=0.23.0=py312h4389bb4_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-win-64.conda.lock.yml b/environments/py-3.12-win-64.conda.lock.yml index 877a4883..d952148e 100644 --- a/environments/py-3.12-win-64.conda.lock.yml +++ b/environments/py-3.12-win-64.conda.lock.yml @@ -1,6 +1,6 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: dd5f3d6403d5db52a5e41fb35b60dce2df1a615f984bba47e191a2a14a68dd3c +# input_hash: 8ac7e9b31d0a8968577d04b18bfae4e5b55625cc38cfb3a62f6b8f87f8a156f9 channels: - conda-forge @@ -60,14 +60,15 @@ dependencies: - libffi=3.4.6=h537db12_1 - libfreetype=2.13.3=h57928b3_1 - libfreetype6=2.13.3=h0b5ce68_1 - - libgcc=15.1.0=h1383e82_2 - - libgomp=15.1.0=h1383e82_2 + - libgcc=15.1.0=h1383e82_3 + - libgomp=15.1.0=h1383e82_3 - libhwloc=2.11.2=default_ha69328c_1001 - libiconv=1.18=h135ad9c_1 - libjpeg-turbo=3.1.0=h2466b09_0 - liblapack=3.9.0=32_h1aa476e_mkl - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 + - libspatialindex=2.0.0=h5a68840_0 - libsqlite=3.50.1=hf5d6505_6 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 @@ -109,6 +110,7 @@ dependencies: - python_abi=3.12=7_cp312 - pytz=2025.2=pyhd8ed1ab_0 - pyyaml=6.0.2=py312h31fea79_2 + - rtree=1.2.0=py312h50e5f8f_1 - scikit-learn=1.4.2=py312h816cc57_1 - scipy=1.14.1=py312h337df96_2 - setuptools=80.9.0=pyhff2d567_0 @@ -121,6 +123,7 @@ dependencies: - toolz=1.0.0=pyhd8ed1ab_1 - tornado=6.5.1=py312h4389bb4_0 - tqdm=4.67.1=pyhd8ed1ab_1 + - trimesh=4.1.8=pyhd8ed1ab_0 - typing-extensions=4.14.0=h32cad80_0 - typing-inspection=0.4.1=pyhd8ed1ab_0 - typing_extensions=4.14.0=pyhe01879c_0 @@ -144,7 +147,7 @@ dependencies: - zstandard=0.23.0=py312h4389bb4_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/py-3.10.conda-lock.yml b/py-3.10.conda-lock.yml index 7f4e3781..acd6aa64 100644 --- a/py-3.10.conda-lock.yml +++ b/py-3.10.conda-lock.yml @@ -15,8 +15,8 @@ version: 1 metadata: content_hash: - win-64: eaae335cf36adc80372dc46b8513b3371068cb4b78164f9bf33218ae884e5a43 - linux-64: d20cb4f62773f79495ca5432e662a34453afa41e6084f06c349fbb84600a44bb + win-64: fe9bea64dc53fd535084a0a107d7688e8632e51eeb8084b72468b0a651a364b6 + linux-64: 0f54a26695792bef9ae71d11e72896171987869d09020c611e73c9a0622596d6 channels: - url: conda-forge used_env_vars: [] @@ -3518,10 +3518,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' _openmp_mutex: '>=4.5' - url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-15.1.0-h767d61c_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda hash: - md5: ea8ac52380885ed41c1baa8f1d6d2b93 - sha256: 0024f9ab34c09629621aefd8603ef77bf9d708129b0dd79029e502c39ffc2195 + md5: 9e60c55e725c20d23125a5f0dd69af5d + sha256: 59a87161212abe8acc57d318b0cc8636eb834cdfdfddcf1f588b5493644b39a3 category: main optional: false - name: libgcc @@ -3531,10 +3531,10 @@ package: dependencies: _openmp_mutex: '>=4.5' libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' - url: https://repo.prefix.dev/conda-forge/win-64/libgcc-15.1.0-h1383e82_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/libgcc-15.1.0-h1383e82_3.conda hash: - md5: 9bedb24480136bfeb81ebc81d4285e70 - sha256: c0288596ac58366d96a56c57e4088fe1c6dd4194fdcaeacf5862f47fb1e1e5be + md5: d8314be93c803e2e2b430f6389d6ce6a + sha256: 05978c4e8c826dd3b727884e009a19ceee75b0a530c18fc14f0ba56b090f2ea3 category: main optional: false - name: libgcc-ng @@ -3543,10 +3543,10 @@ package: platform: linux-64 dependencies: libgcc: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_3.conda hash: - md5: ddca86c7040dd0e73b2b69bd7833d225 - sha256: 0ab5421a89f090f3aa33841036bb3af4ed85e1f91315b528a9d75fab9aad51ae + md5: e66f2b8ad787e7beb0f846e4bd7e8493 + sha256: b0b0a5ee6ce645a09578fc1cb70c180723346f8a45fdb6d23b3520591c6d6996 category: main optional: false - name: libgfortran @@ -3555,10 +3555,10 @@ package: platform: linux-64 dependencies: libgfortran5: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_3.conda hash: - md5: f92e6e0a3c0c0c85561ef61aa59d555d - sha256: 914daa4f632b786827ea71b5e07cd00d25fc6e67789db2f830dc481eec660342 + md5: bfbca721fd33188ef923dfe9ba172f29 + sha256: 77dd1f1efd327e6991e87f09c7c97c4ae1cfbe59d9485c41d339d6391ac9c183 category: main optional: false - name: libgfortran5 @@ -3568,10 +3568,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: '>=15.1.0' - url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda hash: - md5: 01de444988ed960031dbe84cf4f9b1fc - sha256: be23750f3ca1a5cb3ada858c4f633effe777487d1ea35fddca04c0965c073350 + md5: 530566b68c3b8ce7eec4cd047eae19fe + sha256: eea6c3cf22ad739c279b4d665e6cf20f8081f483b26a96ddd67d4df3c88dfa0a category: main optional: false - name: libgomp @@ -3580,10 +3580,10 @@ package: platform: win-64 dependencies: libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' - url: https://repo.prefix.dev/conda-forge/win-64/libgomp-15.1.0-h1383e82_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/libgomp-15.1.0-h1383e82_3.conda hash: - md5: 5fbacaa9b41e294a6966602205b99747 - sha256: 4316316097ce5fde2608b6fccd18709cf647dce52e230f5ac66f5c524dfad791 + md5: 94545e52b3d21a7ab89961f7bda3da0d + sha256: 2e6e286c817d2274b109c448f63d804dcc85610c5abf97e183440aa2d84b8c72 category: main optional: false - name: libhwloc @@ -3826,6 +3826,34 @@ package: sha256: 7bcb3edccea30f711b6be9601e083ecf4f435b9407d70fc48fbcf9e5d69a0fc6 category: dev optional: true +- name: libspatialindex + version: 2.0.0 + manager: conda + platform: linux-64 + dependencies: + __glibc: '>=2.17,<3.0.a0' + libgcc-ng: '>=12' + libstdcxx-ng: '>=12' + url: https://repo.prefix.dev/conda-forge/linux-64/libspatialindex-2.0.0-he02047a_0.conda + hash: + md5: e7d2dcd1a058149ff9731a8dca39566e + sha256: 997a4fa13864dcb35ac9dfe87ed70fb3e9509dd071fa1951ac7f184e7ffcde5d + category: main + optional: false +- name: libspatialindex + version: 2.0.0 + manager: conda + platform: win-64 + dependencies: + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vc14_runtime: '>=14.29.30139' + url: https://repo.prefix.dev/conda-forge/win-64/libspatialindex-2.0.0-h5a68840_0.conda + hash: + md5: 667559340fdf805ee1652de7b73e2b59 + sha256: 7802e6c51d59bc7e062841c525d772656708cdc44e42b6556493d345f08d7e50 + category: main + optional: false - name: libsqlite version: 3.50.1 manager: conda @@ -3892,10 +3920,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda hash: - md5: 1cb1c67961f6dd257eae9e9691b341aa - sha256: 6ae3d153e78f6069d503d9309f2cac6de5b93d067fc6433160a4c05226a5dad4 + md5: 6d11a5edae89fe413c0569f16d308f5a + sha256: 7650837344b7850b62fdba02155da0b159cf472b9ab59eb7b472f7bd01dff241 category: main optional: false - name: libstdcxx-ng @@ -3904,10 +3932,10 @@ package: platform: linux-64 dependencies: libstdcxx: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_3.conda hash: - md5: 9d2072af184b5caa29492bf2344597bb - sha256: 11bea86e11de7d6bce87589197a383344df3fa0a3552dab7e931785ff1159a5b + md5: 57541755b5a51691955012b8e197c06c + sha256: bbaea1ecf973a7836f92b8ebecc94d3c758414f4de39d2cc6818a3d10cb3216b category: main optional: false - name: libtiff @@ -6541,6 +6569,34 @@ package: sha256: ef0525e1c1cda25d4455d2ab8935673a71b49b9a2d5c152cdbfc765ad091dd53 category: dev optional: true +- name: rtree + version: 1.2.0 + manager: conda + platform: linux-64 + dependencies: + libspatialindex: '>=2.0.0,<2.0.1.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* + url: https://repo.prefix.dev/conda-forge/linux-64/rtree-1.2.0-py310haf1e407_1.conda + hash: + md5: aab35e5bbaac5bc7057effffe2b55df8 + sha256: 6eb76990124941e5303eb739b2ab8684112f829b6bfafc81b43bd722c3c91616 + category: main + optional: false +- name: rtree + version: 1.2.0 + manager: conda + platform: win-64 + dependencies: + libspatialindex: '>=2.0.0,<2.0.1.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* + url: https://repo.prefix.dev/conda-forge/win-64/rtree-1.2.0-py310h08d5ad2_1.conda + hash: + md5: ffc97287567416c807a69aeeee794678 + sha256: 5c1dbc4390adc6a75e2c648761b9e5e2a70ec1fab4e4055fed64bb3852604ace + category: main + optional: false - name: scikit-learn version: 1.4.2 manager: conda @@ -7714,6 +7770,32 @@ package: sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 category: dev optional: true +- name: trimesh + version: 4.1.8 + manager: conda + platform: linux-64 + dependencies: + numpy: '' + python: '>=2.7' + url: https://repo.prefix.dev/conda-forge/noarch/trimesh-4.1.8-pyhd8ed1ab_0.conda + hash: + md5: 78302527eb6c9d18b07a91e6a72ef957 + sha256: 021110c37eca2f0fca85ba6ac4576c509d23079758f63942e2f9a6954282f2ce + category: main + optional: false +- name: trimesh + version: 4.1.8 + manager: conda + platform: win-64 + dependencies: + numpy: '' + python: '>=2.7' + url: https://repo.prefix.dev/conda-forge/noarch/trimesh-4.1.8-pyhd8ed1ab_0.conda + hash: + md5: 78302527eb6c9d18b07a91e6a72ef957 + sha256: 021110c37eca2f0fca85ba6ac4576c509d23079758f63942e2f9a6954282f2ce + category: main + optional: false - name: types-python-dateutil version: 2.9.0.20250516 manager: conda @@ -8473,12 +8555,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 hash: - sha256: 91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 category: main optional: false - name: geoapps-utils @@ -8490,12 +8572,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 hash: - sha256: 91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 category: main optional: false - name: geoh5py diff --git a/py-3.11.conda-lock.yml b/py-3.11.conda-lock.yml index dd9f3462..0a480c17 100644 --- a/py-3.11.conda-lock.yml +++ b/py-3.11.conda-lock.yml @@ -15,8 +15,8 @@ version: 1 metadata: content_hash: - win-64: 2d7c4e988ae2df2fbd8349e86ba264f7eb281505021cebbdb8d9a2d3b0dda7ad - linux-64: c83206a2eacb4c3e0efe0aa15f924d81adc9fe1f02d077a12434b468bb2045e6 + win-64: b9f574bd52f02e9a0d8648f478d484cd228f132f708933856414eed155f61a30 + linux-64: c9dba1cefe5fafa1d6916df23312dff6e683994e65910cb3e402d7568b87973d channels: - url: conda-forge used_env_vars: [] @@ -3570,10 +3570,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' _openmp_mutex: '>=4.5' - url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-15.1.0-h767d61c_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda hash: - md5: ea8ac52380885ed41c1baa8f1d6d2b93 - sha256: 0024f9ab34c09629621aefd8603ef77bf9d708129b0dd79029e502c39ffc2195 + md5: 9e60c55e725c20d23125a5f0dd69af5d + sha256: 59a87161212abe8acc57d318b0cc8636eb834cdfdfddcf1f588b5493644b39a3 category: main optional: false - name: libgcc @@ -3583,10 +3583,10 @@ package: dependencies: _openmp_mutex: '>=4.5' libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' - url: https://repo.prefix.dev/conda-forge/win-64/libgcc-15.1.0-h1383e82_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/libgcc-15.1.0-h1383e82_3.conda hash: - md5: 9bedb24480136bfeb81ebc81d4285e70 - sha256: c0288596ac58366d96a56c57e4088fe1c6dd4194fdcaeacf5862f47fb1e1e5be + md5: d8314be93c803e2e2b430f6389d6ce6a + sha256: 05978c4e8c826dd3b727884e009a19ceee75b0a530c18fc14f0ba56b090f2ea3 category: main optional: false - name: libgcc-ng @@ -3595,10 +3595,10 @@ package: platform: linux-64 dependencies: libgcc: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_3.conda hash: - md5: ddca86c7040dd0e73b2b69bd7833d225 - sha256: 0ab5421a89f090f3aa33841036bb3af4ed85e1f91315b528a9d75fab9aad51ae + md5: e66f2b8ad787e7beb0f846e4bd7e8493 + sha256: b0b0a5ee6ce645a09578fc1cb70c180723346f8a45fdb6d23b3520591c6d6996 category: main optional: false - name: libgfortran @@ -3607,10 +3607,10 @@ package: platform: linux-64 dependencies: libgfortran5: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_3.conda hash: - md5: f92e6e0a3c0c0c85561ef61aa59d555d - sha256: 914daa4f632b786827ea71b5e07cd00d25fc6e67789db2f830dc481eec660342 + md5: bfbca721fd33188ef923dfe9ba172f29 + sha256: 77dd1f1efd327e6991e87f09c7c97c4ae1cfbe59d9485c41d339d6391ac9c183 category: main optional: false - name: libgfortran5 @@ -3620,10 +3620,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: '>=15.1.0' - url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda hash: - md5: 01de444988ed960031dbe84cf4f9b1fc - sha256: be23750f3ca1a5cb3ada858c4f633effe777487d1ea35fddca04c0965c073350 + md5: 530566b68c3b8ce7eec4cd047eae19fe + sha256: eea6c3cf22ad739c279b4d665e6cf20f8081f483b26a96ddd67d4df3c88dfa0a category: main optional: false - name: libgomp @@ -3632,10 +3632,10 @@ package: platform: win-64 dependencies: libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' - url: https://repo.prefix.dev/conda-forge/win-64/libgomp-15.1.0-h1383e82_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/libgomp-15.1.0-h1383e82_3.conda hash: - md5: 5fbacaa9b41e294a6966602205b99747 - sha256: 4316316097ce5fde2608b6fccd18709cf647dce52e230f5ac66f5c524dfad791 + md5: 94545e52b3d21a7ab89961f7bda3da0d + sha256: 2e6e286c817d2274b109c448f63d804dcc85610c5abf97e183440aa2d84b8c72 category: main optional: false - name: libhwloc @@ -3878,6 +3878,34 @@ package: sha256: 7bcb3edccea30f711b6be9601e083ecf4f435b9407d70fc48fbcf9e5d69a0fc6 category: dev optional: true +- name: libspatialindex + version: 2.0.0 + manager: conda + platform: linux-64 + dependencies: + __glibc: '>=2.17,<3.0.a0' + libgcc-ng: '>=12' + libstdcxx-ng: '>=12' + url: https://repo.prefix.dev/conda-forge/linux-64/libspatialindex-2.0.0-he02047a_0.conda + hash: + md5: e7d2dcd1a058149ff9731a8dca39566e + sha256: 997a4fa13864dcb35ac9dfe87ed70fb3e9509dd071fa1951ac7f184e7ffcde5d + category: main + optional: false +- name: libspatialindex + version: 2.0.0 + manager: conda + platform: win-64 + dependencies: + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vc14_runtime: '>=14.29.30139' + url: https://repo.prefix.dev/conda-forge/win-64/libspatialindex-2.0.0-h5a68840_0.conda + hash: + md5: 667559340fdf805ee1652de7b73e2b59 + sha256: 7802e6c51d59bc7e062841c525d772656708cdc44e42b6556493d345f08d7e50 + category: main + optional: false - name: libsqlite version: 3.50.1 manager: conda @@ -3944,10 +3972,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda hash: - md5: 1cb1c67961f6dd257eae9e9691b341aa - sha256: 6ae3d153e78f6069d503d9309f2cac6de5b93d067fc6433160a4c05226a5dad4 + md5: 6d11a5edae89fe413c0569f16d308f5a + sha256: 7650837344b7850b62fdba02155da0b159cf472b9ab59eb7b472f7bd01dff241 category: main optional: false - name: libstdcxx-ng @@ -3956,10 +3984,10 @@ package: platform: linux-64 dependencies: libstdcxx: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_3.conda hash: - md5: 9d2072af184b5caa29492bf2344597bb - sha256: 11bea86e11de7d6bce87589197a383344df3fa0a3552dab7e931785ff1159a5b + md5: 57541755b5a51691955012b8e197c06c + sha256: bbaea1ecf973a7836f92b8ebecc94d3c758414f4de39d2cc6818a3d10cb3216b category: main optional: false - name: libtiff @@ -6595,6 +6623,34 @@ package: sha256: 3a76edb8f446351f36eb43a215e0df0b444f73b0f22453c0966611653b05c06f category: dev optional: true +- name: rtree + version: 1.2.0 + manager: conda + platform: linux-64 + dependencies: + libspatialindex: '>=2.0.0,<2.0.1.0a0' + python: '>=3.11,<3.12.0a0' + python_abi: 3.11.* + url: https://repo.prefix.dev/conda-forge/linux-64/rtree-1.2.0-py311ha1603b9_1.conda + hash: + md5: 0737315cc9761f4060f9d52d12cea92e + sha256: 9b9d5be1924ced85110f635331379354ba57d44c5416c5709070ddb111048ef6 + category: main + optional: false +- name: rtree + version: 1.2.0 + manager: conda + platform: win-64 + dependencies: + libspatialindex: '>=2.0.0,<2.0.1.0a0' + python: '>=3.11,<3.12.0a0' + python_abi: 3.11.* + url: https://repo.prefix.dev/conda-forge/win-64/rtree-1.2.0-py311h44d53c4_1.conda + hash: + md5: a182e3a376af719a275136bfdbc3a70e + sha256: 78fecaad4f4b25ba60dc55af7fb5326d1b3512b8ed240eb45aabc1e86e50e77e + category: main + optional: false - name: scikit-learn version: 1.4.2 manager: conda @@ -7768,6 +7824,32 @@ package: sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 category: dev optional: true +- name: trimesh + version: 4.1.8 + manager: conda + platform: linux-64 + dependencies: + numpy: '' + python: '>=2.7' + url: https://repo.prefix.dev/conda-forge/noarch/trimesh-4.1.8-pyhd8ed1ab_0.conda + hash: + md5: 78302527eb6c9d18b07a91e6a72ef957 + sha256: 021110c37eca2f0fca85ba6ac4576c509d23079758f63942e2f9a6954282f2ce + category: main + optional: false +- name: trimesh + version: 4.1.8 + manager: conda + platform: win-64 + dependencies: + numpy: '' + python: '>=2.7' + url: https://repo.prefix.dev/conda-forge/noarch/trimesh-4.1.8-pyhd8ed1ab_0.conda + hash: + md5: 78302527eb6c9d18b07a91e6a72ef957 + sha256: 021110c37eca2f0fca85ba6ac4576c509d23079758f63942e2f9a6954282f2ce + category: main + optional: false - name: types-python-dateutil version: 2.9.0.20250516 manager: conda @@ -8558,12 +8640,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 hash: - sha256: 91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 category: main optional: false - name: geoapps-utils @@ -8575,12 +8657,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 hash: - sha256: 91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 category: main optional: false - name: geoh5py diff --git a/py-3.12.conda-lock.yml b/py-3.12.conda-lock.yml index 981080e8..d01d78c4 100644 --- a/py-3.12.conda-lock.yml +++ b/py-3.12.conda-lock.yml @@ -15,8 +15,8 @@ version: 1 metadata: content_hash: - win-64: dd5f3d6403d5db52a5e41fb35b60dce2df1a615f984bba47e191a2a14a68dd3c - linux-64: 86d8c36c4b440eac7a217d19ba6775b033719c3606e19d205f30e9bf039ae01e + win-64: 8ac7e9b31d0a8968577d04b18bfae4e5b55625cc38cfb3a62f6b8f87f8a156f9 + linux-64: 986de85ed6e6464ef1d28bc0bd68959524a00d49b9d9e57fda77fdcf3447934a channels: - url: conda-forge used_env_vars: [] @@ -3570,10 +3570,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' _openmp_mutex: '>=4.5' - url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-15.1.0-h767d61c_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-15.1.0-h767d61c_3.conda hash: - md5: ea8ac52380885ed41c1baa8f1d6d2b93 - sha256: 0024f9ab34c09629621aefd8603ef77bf9d708129b0dd79029e502c39ffc2195 + md5: 9e60c55e725c20d23125a5f0dd69af5d + sha256: 59a87161212abe8acc57d318b0cc8636eb834cdfdfddcf1f588b5493644b39a3 category: main optional: false - name: libgcc @@ -3583,10 +3583,10 @@ package: dependencies: _openmp_mutex: '>=4.5' libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' - url: https://repo.prefix.dev/conda-forge/win-64/libgcc-15.1.0-h1383e82_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/libgcc-15.1.0-h1383e82_3.conda hash: - md5: 9bedb24480136bfeb81ebc81d4285e70 - sha256: c0288596ac58366d96a56c57e4088fe1c6dd4194fdcaeacf5862f47fb1e1e5be + md5: d8314be93c803e2e2b430f6389d6ce6a + sha256: 05978c4e8c826dd3b727884e009a19ceee75b0a530c18fc14f0ba56b090f2ea3 category: main optional: false - name: libgcc-ng @@ -3595,10 +3595,10 @@ package: platform: linux-64 dependencies: libgcc: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgcc-ng-15.1.0-h69a702a_3.conda hash: - md5: ddca86c7040dd0e73b2b69bd7833d225 - sha256: 0ab5421a89f090f3aa33841036bb3af4ed85e1f91315b528a9d75fab9aad51ae + md5: e66f2b8ad787e7beb0f846e4bd7e8493 + sha256: b0b0a5ee6ce645a09578fc1cb70c180723346f8a45fdb6d23b3520591c6d6996 category: main optional: false - name: libgfortran @@ -3607,10 +3607,10 @@ package: platform: linux-64 dependencies: libgfortran5: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran-15.1.0-h69a702a_3.conda hash: - md5: f92e6e0a3c0c0c85561ef61aa59d555d - sha256: 914daa4f632b786827ea71b5e07cd00d25fc6e67789db2f830dc481eec660342 + md5: bfbca721fd33188ef923dfe9ba172f29 + sha256: 77dd1f1efd327e6991e87f09c7c97c4ae1cfbe59d9485c41d339d6391ac9c183 category: main optional: false - name: libgfortran5 @@ -3620,10 +3620,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: '>=15.1.0' - url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libgfortran5-15.1.0-hcea5267_3.conda hash: - md5: 01de444988ed960031dbe84cf4f9b1fc - sha256: be23750f3ca1a5cb3ada858c4f633effe777487d1ea35fddca04c0965c073350 + md5: 530566b68c3b8ce7eec4cd047eae19fe + sha256: eea6c3cf22ad739c279b4d665e6cf20f8081f483b26a96ddd67d4df3c88dfa0a category: main optional: false - name: libgomp @@ -3632,10 +3632,10 @@ package: platform: win-64 dependencies: libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' - url: https://repo.prefix.dev/conda-forge/win-64/libgomp-15.1.0-h1383e82_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/libgomp-15.1.0-h1383e82_3.conda hash: - md5: 5fbacaa9b41e294a6966602205b99747 - sha256: 4316316097ce5fde2608b6fccd18709cf647dce52e230f5ac66f5c524dfad791 + md5: 94545e52b3d21a7ab89961f7bda3da0d + sha256: 2e6e286c817d2274b109c448f63d804dcc85610c5abf97e183440aa2d84b8c72 category: main optional: false - name: libhwloc @@ -3878,6 +3878,34 @@ package: sha256: 7bcb3edccea30f711b6be9601e083ecf4f435b9407d70fc48fbcf9e5d69a0fc6 category: dev optional: true +- name: libspatialindex + version: 2.0.0 + manager: conda + platform: linux-64 + dependencies: + __glibc: '>=2.17,<3.0.a0' + libgcc-ng: '>=12' + libstdcxx-ng: '>=12' + url: https://repo.prefix.dev/conda-forge/linux-64/libspatialindex-2.0.0-he02047a_0.conda + hash: + md5: e7d2dcd1a058149ff9731a8dca39566e + sha256: 997a4fa13864dcb35ac9dfe87ed70fb3e9509dd071fa1951ac7f184e7ffcde5d + category: main + optional: false +- name: libspatialindex + version: 2.0.0 + manager: conda + platform: win-64 + dependencies: + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vc14_runtime: '>=14.29.30139' + url: https://repo.prefix.dev/conda-forge/win-64/libspatialindex-2.0.0-h5a68840_0.conda + hash: + md5: 667559340fdf805ee1652de7b73e2b59 + sha256: 7802e6c51d59bc7e062841c525d772656708cdc44e42b6556493d345f08d7e50 + category: main + optional: false - name: libsqlite version: 3.50.1 manager: conda @@ -3944,10 +3972,10 @@ package: dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-15.1.0-h8f9b012_3.conda hash: - md5: 1cb1c67961f6dd257eae9e9691b341aa - sha256: 6ae3d153e78f6069d503d9309f2cac6de5b93d067fc6433160a4c05226a5dad4 + md5: 6d11a5edae89fe413c0569f16d308f5a + sha256: 7650837344b7850b62fdba02155da0b159cf472b9ab59eb7b472f7bd01dff241 category: main optional: false - name: libstdcxx-ng @@ -3956,10 +3984,10 @@ package: platform: linux-64 dependencies: libstdcxx: 15.1.0 - url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libstdcxx-ng-15.1.0-h4852527_3.conda hash: - md5: 9d2072af184b5caa29492bf2344597bb - sha256: 11bea86e11de7d6bce87589197a383344df3fa0a3552dab7e931785ff1159a5b + md5: 57541755b5a51691955012b8e197c06c + sha256: bbaea1ecf973a7836f92b8ebecc94d3c758414f4de39d2cc6818a3d10cb3216b category: main optional: false - name: libtiff @@ -6595,6 +6623,34 @@ package: sha256: dfea71a35d7d5eb348893e24136ce6fb1004fc9402eaafae441fa61887638764 category: dev optional: true +- name: rtree + version: 1.2.0 + manager: conda + platform: linux-64 + dependencies: + libspatialindex: '>=2.0.0,<2.0.1.0a0' + python: '>=3.12,<3.13.0a0' + python_abi: 3.12.* + url: https://repo.prefix.dev/conda-forge/linux-64/rtree-1.2.0-py312h3ed4c40_1.conda + hash: + md5: 99780d5aa94447bc17298a22565ad592 + sha256: 2936fc466bac7dd43b80072440b2daaa1e76db504e2218b76a4e3b7528acb196 + category: main + optional: false +- name: rtree + version: 1.2.0 + manager: conda + platform: win-64 + dependencies: + libspatialindex: '>=2.0.0,<2.0.1.0a0' + python: '>=3.12,<3.13.0a0' + python_abi: 3.12.* + url: https://repo.prefix.dev/conda-forge/win-64/rtree-1.2.0-py312h50e5f8f_1.conda + hash: + md5: bf074df5a51c193b2d14d13c1bf404a3 + sha256: c0cdbd6ede905c2ff0c6c86277bac5f8967da373185649d47984bb4ee21f72fb + category: main + optional: false - name: scikit-learn version: 1.4.2 manager: conda @@ -7768,6 +7824,32 @@ package: sha256: f39a5620c6e8e9e98357507262a7869de2ae8cc07da8b7f84e517c9fd6c2b959 category: dev optional: true +- name: trimesh + version: 4.1.8 + manager: conda + platform: linux-64 + dependencies: + numpy: '' + python: '>=2.7' + url: https://repo.prefix.dev/conda-forge/noarch/trimesh-4.1.8-pyhd8ed1ab_0.conda + hash: + md5: 78302527eb6c9d18b07a91e6a72ef957 + sha256: 021110c37eca2f0fca85ba6ac4576c509d23079758f63942e2f9a6954282f2ce + category: main + optional: false +- name: trimesh + version: 4.1.8 + manager: conda + platform: win-64 + dependencies: + numpy: '' + python: '>=2.7' + url: https://repo.prefix.dev/conda-forge/noarch/trimesh-4.1.8-pyhd8ed1ab_0.conda + hash: + md5: 78302527eb6c9d18b07a91e6a72ef957 + sha256: 021110c37eca2f0fca85ba6ac4576c509d23079758f63942e2f9a6954282f2ce + category: main + optional: false - name: types-python-dateutil version: 2.9.0.20250516 manager: conda @@ -8558,12 +8640,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 hash: - sha256: 91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 category: main optional: false - name: geoapps-utils @@ -8575,12 +8657,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 hash: - sha256: 91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@91ec5c45ff7357cd8f2bdb75dc61c55fdd6459b5 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 category: main optional: false - name: geoh5py diff --git a/pyproject.toml b/pyproject.toml index e1a46b02..9b58e820 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,9 +63,11 @@ discretize = "0.11.*" # also in simpeg, octree-creation-app distributed = ">=2025.3, <2025.4.dev" # for dask[distributed] numpy = "~1.26.0" # also in geoh5py, simpeg pydantic = "^2.5.2" # also in geoh5py, curve-apps, geoapps-utils +Rtree = "~1.2.0" scikit-learn = "~1.4.0" scipy = "~1.14.0" tqdm = "^4.66.1" +trimesh = "~4.1.3" # solvers for simpeg: not imported, but at least one required at runtime pydiso = ">=0.1.0, <0.2.dev" diff --git a/simpeg_drivers/plate_simulation/__init__.py b/simpeg_drivers/plate_simulation/__init__.py new file mode 100644 index 00000000..20390382 --- /dev/null +++ b/simpeg_drivers/plate_simulation/__init__.py @@ -0,0 +1,23 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from __future__ import annotations + +from pathlib import Path + + +__version__ = "0.3.0-alpha.1" + +from geoapps_utils.utils.importing import assets_path as assets_path_impl + + +def assets_path() -> Path: + """Return the path to the assets folder.""" + return assets_path_impl(__file__) diff --git a/simpeg_drivers/plate_simulation/driver.py b/simpeg_drivers/plate_simulation/driver.py new file mode 100644 index 00000000..a1e13da0 --- /dev/null +++ b/simpeg_drivers/plate_simulation/driver.py @@ -0,0 +1,307 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from __future__ import annotations + +import sys +from pathlib import Path + +from geoh5py.data import FloatData, ReferencedData +from geoh5py.groups import UIJsonGroup +from geoh5py.objects import Octree, Points, Surface +from geoh5py.shared.utils import fetch_active_workspace +from geoh5py.ui_json import InputFile, monitored_directory_copy +from octree_creation_app.driver import OctreeDriver +from param_sweeps.generate import generate +from plate_simulation.logger import get_logger +from plate_simulation.models.events import Anomaly, Erosion, Overburden +from plate_simulation.models.parametric import Plate +from plate_simulation.models.series import DikeSwarm, Geology +from plate_simulation.options import PlateSimulationOptions +from plate_simulation.utils import replicate + +from simpeg_drivers.driver import InversionDriver +from simpeg_drivers.options import BaseForwardOptions + + +class PlateSimulationDriver: + """ + Driver for simulating background + plate + overburden model. + + :param params: Parameters for plate simulation (mesh, model and + series). + :param plate: Plate object used to add anomaly to the model. + :param mesh: Octree mesh in which model is built for the simulation. + :param model: Model to simulate. + :param survey: Survey object for the simulation + """ + + def __init__(self, params: PlateSimulationOptions): + self.params = params + + self._plates: list[Plate] | None = None + self._survey: Points | None = None + self._mesh: Octree | None = None + self._model: FloatData | None = None + self._simulation_parameters: BaseForwardOptions | None = None + self._simulation_driver: InversionDriver | None = None + self._out_group = self.validate_out_group(self.params.out_group) + + self._logger = get_logger("Plate Simulation") + + def run(self) -> InversionDriver: + """Create octree mesh, fill model, and simulate.""" + + self._logger.info("running the simulation...") + with fetch_active_workspace(self.params.geoh5, mode="r+"): + self.simulation_driver.run() + self.out_group.add_ui_json() + if ( + self.params.monitoring_directory is not None + and Path(self.params.monitoring_directory).is_dir() + ): + monitored_directory_copy( + str(Path(self.params.monitoring_directory).resolve()), + self.out_group, + ) + + self._logger.info("done.") + self._logger.handlers.clear() + + return self.simulation_driver + + @property + def out_group(self) -> UIJsonGroup: + """ + Returns the output group for the simulation. + """ + return self._out_group + + def validate_out_group(self, out_group: UIJsonGroup | None) -> UIJsonGroup: + """ + Validate or create a UIJsonGroup to store results. + + :param value: Output group from selection. + """ + if isinstance(out_group, UIJsonGroup): + return out_group + + with fetch_active_workspace(self.params.geoh5, mode="r+"): + out_group = UIJsonGroup.create( + self.params.geoh5, + name="Plate Simulation", + ) + out_group.entity_type.name = "Plate Simulation" + self.params = self.params.model_copy(update={"out_group": out_group}) + out_group.options = InputFile.stringify( + InputFile.demote(self.params.input_file.ui_json) + ) + out_group.metadata = None + + return out_group + + @property + def simulation_driver(self) -> InversionDriver: + if self._simulation_driver is None: + with fetch_active_workspace(self.params.geoh5, mode="r+"): + self.simulation_parameters.mesh = self.mesh + self.simulation_parameters.models.starting_model = self.model + + if not isinstance( + self.simulation_parameters.active_cells.topography_object, + Surface | Points, + ): + raise ValueError( + "The topography object of the forward simulation must be a 'Surface'." + ) + + self.simulation_parameters.out_group = None + driver_class = InversionDriver.driver_class_from_name( + self.simulation_parameters.inversion_type, forward_only=True + ) + self._simulation_driver = driver_class(self.simulation_parameters) + self._simulation_driver.out_group.parent = self.out_group + + return self._simulation_driver + + @property + def simulation_parameters(self) -> BaseForwardOptions: + if self._simulation_parameters is None: + self._simulation_parameters = self.params.simulation_parameters() + if self._simulation_parameters.physical_property == "conductivity": + self._simulation_parameters.models.model_type = "Resistivity (Ohm-m)" + return self._simulation_parameters + + @property + def survey(self): + if self._survey is None: + self._survey = self.simulation_parameters.data_object + + return self._survey + + @property + def plates(self) -> list[Plate]: + """Generate sequence of plates.""" + if self._plates is None: + offset = ( + self.params.model.overburden_model.thickness + if self.params.model.plate_model.reference_surface == "overburden" + else 0.0 + ) + center = self.params.model.plate_model.center( + self.survey, + self.topography, + depth_offset=-1 * offset, + ) + plate = Plate( + self.params.model.plate_model, + center, + ) + self._plates = replicate( + plate, + self.params.model.plate_model.number, + self.params.model.plate_model.spacing, + self.params.model.plate_model.dip_direction, + ) + return self._plates + + @property + def topography(self) -> Surface | Points: + return self.simulation_parameters.active_cells.topography_object + + @property + def mesh(self) -> Octree: + """Returns an octree mesh built from mesh parameters.""" + if self._mesh is None: + self._mesh = self.make_mesh() + + return self._mesh + + @property + def model(self) -> FloatData: + """Returns the model built from model parameters.""" + if self._model is None: + self._model = self.make_model() + + return self._model + + def make_mesh(self) -> Octree: + """ + Build specialized mesh for plate simulation from parameters. + + Mesh contains refinements for topography and any plates. + """ + + self._logger.info("making the mesh...") + octree_params = self.params.mesh.octree_params( + self.survey, + self.simulation_parameters.active_cells.topography_object, + [p.surface.copy(parent=self.out_group) for p in self.plates], + ) + octree_driver = OctreeDriver(octree_params) + mesh = octree_driver.run() + mesh.parent = self.out_group + + return mesh + + def make_model(self) -> FloatData: + """Create background + plate and overburden model from parameters.""" + + self._logger.info("Building the model...") + + overburden = Overburden( + topography=self.simulation_parameters.active_cells.topography_object, + thickness=self.params.model.overburden_model.thickness, + value=self.params.model.overburden_model.overburden, + ) + + dikes = DikeSwarm( + [Anomaly(plate, plate.params.plate) for plate in self.plates], + name="plates", + ) + + erosion = Erosion( + surface=self.simulation_parameters.active_cells.topography_object, + ) + + scenario = Geology( + workspace=self.params.geoh5, + mesh=self.mesh, + background=self.params.model.background, + history=[dikes, overburden, erosion], + ) + + geology, event_map = scenario.build() + value_map = {k: v[0] for k, v in event_map.items()} + physical_property_map = {k: v[1] for k, v in event_map.items()} + + physical_property = self.simulation_parameters.physical_property + if physical_property == "conductivity": + physical_property = "resistivity" + + model = self.mesh.add_data( + { + "geology": { + "type": "referenced", + "values": geology, + "value_map": value_map, + } + } + ) + if isinstance(model, ReferencedData): + model.add_data_map(physical_property, physical_property_map) + + starting_model_values = geology.copy() + for k, v in physical_property_map.items(): + starting_model_values[geology == k] = v + + starting_model = self.mesh.add_data( + {"starting_model": {"values": starting_model_values}} + ) + + if not isinstance(starting_model, FloatData): + raise ValueError("Starting model could not be created.") + + return starting_model + + @staticmethod + def start(ifile: str | Path | InputFile): + """Run the plate simulation driver from an input file.""" + + if isinstance(ifile, str): + ifile = Path(ifile) + + if isinstance(ifile, Path): + ifile = InputFile.read_ui_json(ifile) + + if ifile.data is None: # type: ignore + raise ValueError("Input file has no data loaded.") + + generate_sweep = ifile.data["generate_sweep"] # type: ignore + if generate_sweep: + filepath = Path(ifile.path_name) # type: ignore + ifile.data["generate_sweep"] = False # type: ignore + name = filepath.name + path = filepath.parent + ifile.write_ui_json(name=name, path=path) # type: ignore + generate( # pylint: disable=unexpected-keyword-arg + str(filepath), update_values={"conda_environment": "plate_simulation"} + ) + return None + + with ifile.geoh5.open(mode="r+"): # type: ignore + params = PlateSimulationOptions.build(ifile) + + return PlateSimulationDriver(params).run() + + +if __name__ == "__main__": + file = Path(sys.argv[1]) + PlateSimulationDriver.start(file) diff --git a/simpeg_drivers/plate_simulation/logger.py b/simpeg_drivers/plate_simulation/logger.py new file mode 100644 index 00000000..ff469ee1 --- /dev/null +++ b/simpeg_drivers/plate_simulation/logger.py @@ -0,0 +1,32 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import logging + + +def get_logger(name: str, level: int = logging.INFO) -> logging.Logger: + """ + Get a logger with a timestamped stream and speciified log level. + + :param name: Name of the logger. + :param level: Log level + """ + logger = logging.getLogger(name) + logger.setLevel(level) + stream_handler = logging.StreamHandler() + stream_handler.setLevel(level) + formatter = logging.Formatter( + "%(asctime)s : %(name)s : %(levelname)s : %(message)s" + ) + stream_handler.setFormatter(formatter) + logger.addHandler(stream_handler) + logger.propagate = False + + return logger diff --git a/simpeg_drivers/plate_simulation/mesh/__init__.py b/simpeg_drivers/plate_simulation/mesh/__init__.py new file mode 100644 index 00000000..4d06f672 --- /dev/null +++ b/simpeg_drivers/plate_simulation/mesh/__init__.py @@ -0,0 +1,9 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/simpeg_drivers/plate_simulation/mesh/options.py b/simpeg_drivers/plate_simulation/mesh/options.py new file mode 100644 index 00000000..3b99b7bd --- /dev/null +++ b/simpeg_drivers/plate_simulation/mesh/options.py @@ -0,0 +1,73 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from pathlib import Path + +from geoh5py.objects import ObjectBase, Points, Surface +from octree_creation_app.params import OctreeParams +from pydantic import BaseModel + + +class MeshOptions(BaseModel): + """Core parameters for octree mesh creation.""" + + u_cell_size: float + v_cell_size: float + w_cell_size: float + padding_distance: float + depth_core: float + max_distance: float + minimum_level: int = 8 + diagonal_balance: bool = False + + def octree_params( + self, survey: ObjectBase, topography: Surface | Points, plates: list[Surface] + ): + refinements = [ + { + "refinement_object": survey, + "levels": [4, 4, 4], + "horizon": False, + }, + { + "refinement_object": topography, + "levels": [0, 2], + "horizon": True, + "distance": 1000.0, + }, + ] + for plate in plates: + refinements.append( + { + "refinement_object": plate, + "levels": [2, 1], + "horizon": False, + } + ) + + octree_params = OctreeParams( + geoh5=survey.workspace, + objects=survey, + u_cell_size=self.u_cell_size, + v_cell_size=self.v_cell_size, + w_cell_size=self.w_cell_size, + horizontal_padding=self.padding_distance, + vertical_padding=self.padding_distance, + depth_core=self.depth_core, + max_distance=self.max_distance, + minimum_level=self.minimum_level, + diagonal_balance=self.diagonal_balance, + refinements=refinements, + ) + + assert isinstance(survey.workspace.h5file, Path) + path = survey.workspace.h5file.parent + octree_params.write_ui_json(path / "octree.ui.json") + return octree_params diff --git a/simpeg_drivers/plate_simulation/models/__init__.py b/simpeg_drivers/plate_simulation/models/__init__.py new file mode 100644 index 00000000..ca2bdfa3 --- /dev/null +++ b/simpeg_drivers/plate_simulation/models/__init__.py @@ -0,0 +1,11 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +EventMap = dict[int, tuple[str, float]] diff --git a/simpeg_drivers/plate_simulation/models/events.py b/simpeg_drivers/plate_simulation/models/events.py new file mode 100644 index 00000000..9d23c1f6 --- /dev/null +++ b/simpeg_drivers/plate_simulation/models/events.py @@ -0,0 +1,184 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from abc import ABC, abstractmethod + +import numpy as np +from geoh5py.objects import Octree, Surface +from geoh5py.shared.utils import find_unique_name +from plate_simulation.models import EventMap +from plate_simulation.models.parametric import Boundary, Parametric + + +class Event(ABC): + """ + Parameterized geological events that modify the model. + + :param value: Physical property value assigned to the event. + :param name: Name of the event. + """ + + def __init__(self, value: float, name: str): + self.value = value + self.name = name + + def _update_event_map(self, event_map: EventMap) -> tuple[int, EventMap]: + """ + Increase the event id and add name and physical property to the event map. + + :param event_map: mapping event ids to names and physical properties. + + :return: Updated event id. + :return: Updated event map. + """ + + event_id = max(event_map) + 1 + names = [elem[0] for elem in event_map.values()] + name = find_unique_name(self.name, names) + event_map[event_id] = (name, self.value) + + return event_id, event_map + + @abstractmethod + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap + ) -> tuple[np.ndarray, EventMap]: + """ + Update the model with the event realization + + :param mesh: Octree mesh on which the model is defined. + :param model: Model to be updated by the event. + :param event_map: mapping event ids to names and physical properties. + + :return: Updated model and list of events including itself. + """ + + +class Deposition(Event): + """ + Fills model below a surface with a provided property value. + + :param surface: Surface representing the top of a sedimentary layer. + :param value: The value given to the model below the surface. + :param name: Name of the event. + """ + + def __init__(self, surface: Surface, value: float, name: str = "Deposition"): + self.surface = Boundary(surface) + super().__init__(value, name) + + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap + ) -> tuple[np.ndarray, EventMap]: + """ + Implementation of parent Event abstract method. + Fill the model below the surface with the layer's value. + """ + + event_id, event_map = self._update_event_map(event_map) + model[self.surface.mask(mesh)] = event_id + + return model, event_map + + +class Overburden(Event): + """ + Add an overburden layer below the topography surface. + + :param topography: Surface representing the topography. + :param thickness: Thickness of the overburden layer. + :param value: Model value given to the overburden layer. + :param name: Name of the event. + """ + + def __init__( + self, + topography: Surface, + thickness: float, + value: float, + name: str = "Overburden", + ): + self.topography = Boundary(topography) + self.thickness = thickness + super().__init__(value, name) + + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap + ) -> tuple[np.ndarray, EventMap]: + """ + Implementation of parent Event abstract method. + Fill the model below the topography with the overburden value. + """ + event_id, event_map = self._update_event_map(event_map) + model[ + ~self.topography.mask(mesh, offset=-1 * self.thickness, reference="center") + ] = event_id + + return model, event_map + + +class Erosion(Event): + """ + Erode the model at a provided surface. + + :param surface: The surface above which the model will be + eroded (filled with nan values). + :param value: The value given to the eroded model, default to nan. + :param name: Name of the Erosion event. + """ + + def __init__(self, surface: Surface, value: float = np.nan, name: str = "Erosion"): + self.surface = Boundary(surface) + super().__init__(value, name) + + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap + ) -> tuple[np.ndarray, EventMap]: + """ + Implementation of parent Event abstract method. + Fill the model above the surface with nan values. + """ + + event_id, event_map = self._update_event_map(event_map) + model[~self.surface.mask(mesh)] = event_id + + return model, event_map + + +class Anomaly(Event): + """ + Enrich or deplete the model within a close body. + + :param body: Closed body within which the model will be filled + with the anomaly value. + :param value: Model value assigned to the anomaly. + :param name: Name of the event. + """ + + def __init__(self, body: Parametric, value: float, name: str = "Anomaly"): + self.body = body + super().__init__(value, name) + + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap, coeval: bool = False + ) -> tuple[np.ndarray, EventMap]: + """ + Implementation of parent Event abstract method. + Fill the model within the surface with the anomaly value. + """ + + if coeval: + event_id = max(event_map) + else: + event_id, event_map = self._update_event_map(event_map) + + model[self.body.mask(mesh)] = event_id + + return model, event_map diff --git a/simpeg_drivers/plate_simulation/models/options.py b/simpeg_drivers/plate_simulation/models/options.py new file mode 100644 index 00000000..c2f77828 --- /dev/null +++ b/simpeg_drivers/plate_simulation/models/options.py @@ -0,0 +1,157 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from typing import TypeVar + +import numpy as np +from geoh5py.objects import Points +from pydantic import ( + BaseModel, + ConfigDict, + ValidationInfo, + field_validator, + model_validator, +) + + +T = TypeVar("T") + + +class PlateOptions(BaseModel): + """ + Parameters describing an anomalous plate. + + :param plate: Value given to the plate(s). + :param width: V-size of the plate. + :param strike_length: U-size of the plate. + :param dip_length: W-size of the plate. + :param dip: Orientation of the v-axis in degree from horizontal. + :param dip_direction: Orientation of the u axis in degree from north. + :param reference: Point of rotation to be 'center' or 'top'. + :param number: Number of offset plates to be created. + :param spacing: Spacing between plates. + :param relative_locations: If True locations are relative to survey in xy and + mean topography in z. + :param easting: Easting offset relative to survey. + :param northing: Northing offset relative to survey. + :param elevation: plate(s) elevation. May be true elevation or relative to + overburden or topography. + :param reference_surface: Switches between using topography and overburden as + elevation reference of the plate. + :param reference_type: Type of reference for plate elevation. Can be 'mean' + 'min', or 'max'. Resulting elevation will be relative to the mean, + minimum, or maximum of the reference surface. + """ + + model_config = ConfigDict(arbitrary_types_allowed=True) + + name: str = "Plate" + plate: float + width: float + strike_length: float + dip_length: float + dip: float = 90.0 + dip_direction: float = 90.0 + number: int = 1 + spacing: float = 0.0 + relative_locations: bool = False + easting: float = 0.0 + northing: float = 0.0 + elevation: float + reference_surface: str = "topography" + reference_type: str = "mean" + + @field_validator("reference_surface", "reference_type", mode="before") + @classmethod + def none_to_default(cls, value: T | None, info: ValidationInfo) -> T: + return value or cls.model_fields[info.field_name].default # pylint: disable=unsubscriptable-object + + @model_validator(mode="after") + def single_plate(self): + if self.number == 1: + self.spacing = 0.0 + return self + + @property + def halfplate(self): + """Compute half the z-projection length of the plate.""" + return 0.5 * self.dip_length * np.sin(np.deg2rad(self.dip)) + + def center( + self, + survey: Points, + surface: Points, + depth_offset: float = 0.0, + ) -> tuple[float, float, float]: + """ + Find the plate center relative to a survey and topography. + + :param survey: geoh5py survey object for plate simulation. + :param surface: Points-like object to reference plate depth from. + :param depth_offset: Additional offset to be added to the depth of the plate. + """ + return *self._get_xy(survey), self._get_z(surface, depth_offset) + + def _get_xy(self, survey: Points) -> tuple[float, float]: + """Return true or relative locations in x and y.""" + + if self.relative_locations: + return ( + survey.vertices[:, 0].mean() + self.easting, + survey.vertices[:, 1].mean() + self.northing, + ) + + return self.easting, self.northing + + def _get_z(self, surface: Points, offset: float = 0.0) -> float: + """ + Return true or relative locations in z. + + :param surface: Points-like object to reference plate depth from. + :offset: Additional offset to be added to the depth. + + """ + if surface.vertices is None: + raise ValueError("Topography object has no vertices.") + if self.relative_locations: + z = getattr(surface.vertices[:, 2], self.reference_type)() + z += offset + self.elevation - self.halfplate + else: + z = self.elevation + + return z + + +class OverburdenOptions(BaseModel): + """ + Parameters for the overburden layer. + + :param thickness: Thickness of the overburden layer. + :param overburden: Value given to the overburden layer. + """ + + thickness: float + overburden: float + + +class ModelOptions(BaseModel): + """ + Parameters for the blackground + overburden and plate model. + + :param background: Value given to the background. + :param overburden: Overburden layer parameters. + :param plate: Plate parameters. + """ + + model_config = ConfigDict(arbitrary_types_allowed=True) + + background: float + overburden_model: OverburdenOptions + plate_model: PlateOptions diff --git a/simpeg_drivers/plate_simulation/models/parametric.py b/simpeg_drivers/plate_simulation/models/parametric.py new file mode 100644 index 00000000..c982b24b --- /dev/null +++ b/simpeg_drivers/plate_simulation/models/parametric.py @@ -0,0 +1,247 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from __future__ import annotations + +from abc import ABC, abstractmethod + +import numpy as np +from geoapps_utils.modelling.plates import PlateModel, inside_plate +from geoapps_utils.utils.transformations import ( + rotate_points, + rotate_xyz, + x_rotation_matrix, + z_rotation_matrix, +) +from geoh5py.objects import Octree, Surface +from geoh5py.shared.utils import fetch_active_workspace +from geoh5py.workspace import Workspace +from plate_simulation.models.options import PlateOptions +from trimesh import Trimesh +from trimesh.proximity import ProximityQuery + +from simpeg_drivers.utils.utils import active_from_xyz + + +class Parametric(ABC): + """ + Base class representing parametric geometries. + """ + + def __init__(self, surface: Surface): + if not isinstance(surface, Surface): + raise TypeError( + "Input attribute 'surface' should be in instance of geoh5py.Surface." + ) + + self._surface = surface + + @property + def surface(self): + """ + Surface object representing the shape of the object. + """ + return self._surface + + @abstractmethod + def mask(self, mesh: Octree) -> np.ndarray: + """ + Return logical for cells inside the parametric object. + """ + + +class Plate(Parametric): + """ + Define a rotated rectangular block in 3D space + + :param params: Parameters describing the plate. + :param surface: Surface object representing the plate. + """ + + def __init__( + self, + params: PlateOptions, + center: tuple[float, float, float] = ( + 0.0, + 0.0, + 0.0, + ), + workspace: Workspace | None = None, + ): + self.params = params + self.center = center + self._workspace = workspace + super().__init__(self._create_surface()) + + def _create_surface(self) -> Surface: + """ + Create a surface object from a plate object. + + :param workspace: Workspace object to create the surface in. + :param out_group: Output group to store the surface. + """ + with fetch_active_workspace(self.workspace) as ws: + surface = Surface.create( + ws, + vertices=self.vertices, + cells=self.triangles, + name=self.params.name, + ) + + return surface + + @property + def surface(self): + """ + A surface object representing the plate. + """ + return self._surface + + @property + def triangles(self) -> np.ndarray: + """Triangulation of the block.""" + return np.vstack( + [ + [0, 2, 1], + [1, 2, 3], + [0, 1, 4], + [4, 1, 5], + [1, 3, 5], + [5, 3, 7], + [2, 6, 3], + [3, 6, 7], + [0, 4, 2], + [2, 4, 6], + [4, 5, 6], + [6, 5, 7], + ] + ) + + @property + def vertices(self) -> np.ndarray: + """Vertices for triangulation of a rectangular prism in 3D space.""" + + u_1 = self.center[0] - (self.params.strike_length / 2.0) + u_2 = self.center[0] + (self.params.strike_length / 2.0) + v_1 = self.center[1] - (self.params.dip_length / 2.0) + v_2 = self.center[1] + (self.params.dip_length / 2.0) + w_1 = self.center[2] - (self.params.width / 2.0) + w_2 = self.center[2] + (self.params.width / 2.0) + + vertices = np.array( + [ + [u_1, v_1, w_1], + [u_2, v_1, w_1], + [u_1, v_2, w_1], + [u_2, v_2, w_1], + [u_1, v_1, w_2], + [u_2, v_1, w_2], + [u_1, v_2, w_2], + [u_2, v_2, w_2], + ] + ) + + return self._rotate(vertices) + + @property + def workspace(self) -> Workspace: + if self._workspace is None: + self._workspace = Workspace() + + return self._workspace + + def _rotate(self, vertices: np.ndarray) -> np.ndarray: + """Rotate vertices and adjust for reference point.""" + theta = -1 * self.params.dip_direction + phi = -1 * self.params.dip + rotated_vertices = rotate_xyz(vertices, self.center, theta, phi) + + return rotated_vertices + + def mask(self, mesh: Octree) -> np.ndarray: + plate = PlateModel( + strike_length=self.params.strike_length, + dip_length=self.params.dip_length, + width=self.params.width, + direction=self.params.dip_direction, + dip=self.params.dip, + origin=self.center, + ) + rotations = [ + z_rotation_matrix(np.deg2rad(self.params.dip_direction)), + x_rotation_matrix(np.deg2rad(self.params.dip)), + ] + rotated_centers = rotate_points( + mesh.centroids, origin=plate.origin, rotations=rotations + ) + return inside_plate(rotated_centers, plate) + + +class Body(Parametric): + """ + Represents a closed surface in the model. + + :param surface: geoh5py Surface object representing a closed surface + """ + + def mask(self, mesh: Octree) -> np.ndarray: + """ + True for cells that lie within the closed surface. + + :param mesh: Octree mesh on which the mask is computed. + """ + triangulation = Trimesh( + vertices=self.surface.vertices, faces=self.surface.cells + ) + proximity_query = ProximityQuery(triangulation) + dist = proximity_query.signed_distance(mesh.centroids) + return dist > 0 + + +class Boundary(Parametric): + """ + Represents a boundary in a model. + + :param surface: geoh5py Surface object representing a boundary + in the model. + """ + + def vertical_shift(self, offset: float) -> np.ndarray: + """ + Returns the surface vertices shifted vertically by offset. + + :param offset: Shifts vertices in up (positive) or down (negative). + """ + + if self.surface.vertices is None: + raise ValueError("Surface vertices are not defined.") + + shift = np.c_[ + np.zeros(self.surface.vertices.shape[0]), + np.zeros(self.surface.vertices.shape[0]), + np.ones(self.surface.vertices.shape[0]) * offset, + ] + return self.surface.vertices + shift + + def mask( + self, mesh: Octree, offset: float = 0.0, reference: str = "center" + ) -> np.ndarray: + """ + True for cells whose reference lie below the surface. + + :param mesh: Octree mesh on which the mask is computed. + :param offset: Statically shift the surface on which the mask + is computed. + :param reference: Use "bottom", "center" or "top" of the cells + in determining the mask. + + """ + + return active_from_xyz(mesh, self.vertical_shift(offset), reference) diff --git a/simpeg_drivers/plate_simulation/models/series.py b/simpeg_drivers/plate_simulation/models/series.py new file mode 100644 index 00000000..3384b9e4 --- /dev/null +++ b/simpeg_drivers/plate_simulation/models/series.py @@ -0,0 +1,229 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from __future__ import annotations + +from abc import ABC, abstractmethod +from collections.abc import Sequence +from typing import TYPE_CHECKING + +import numpy as np +from geoh5py import Workspace +from geoh5py.objects import Octree +from geoh5py.shared.utils import fetch_active_workspace +from plate_simulation.models import EventMap +from plate_simulation.models.events import Anomaly, Erosion, Event, Overburden + + +if TYPE_CHECKING: + from .events import Deposition + + +class Series(ABC): + """ + Sequence of geological events. + + :param history: Sequence of geological events. + """ + + def __init__(self, history: Sequence[Event | Series]): + self.history = history + + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap + ) -> tuple[np.ndarray, EventMap]: + """ + Realize each event in the history. + + :param mesh: Octree mesh on which the model is defined. + :param model: Model to be updated by the events in the history. + :param event_map: mapping event ids to names and physical properties. + """ + + for event in self.history: + model, event_map = event.realize(mesh, model, event_map) + + return model, event_map + + @property + @abstractmethod + def history(self): + """Sequence of geological events.""" + + @history.setter + @abstractmethod + def history(self, events): + pass + + +class Lithology(Series): + """ + Model a sequence of sedimentary layers. + + :param history: Sequence of layers to be deposited. These should be + ordered so that the first layer in the list is the bottom unit + and the last layer is the top unit + """ + + # TODO: Provide an optional bottom surface to begin the deposition. + + def __init__(self, history: Sequence[Deposition]): + super().__init__(history[::-1]) + + @property + def history(self) -> Sequence[Deposition | Erosion]: + """Sequence of geological events.""" + return self._history + + @history.setter + def history(self, events): + if not all(isinstance(k, Event) for k in events): + raise ValueError("History must be a sequence of geological events.") + + self._history = events + + +class DikeSwarm(Series): + """ + Model a set of dike intrusions. + + :param history: Sequence of intrusions represented by Anomaly objects. + :param name: Name of the dike swarm. + """ + + def __init__(self, history: Sequence[Anomaly], name: str = "Dike Swarm"): + super().__init__(history) + self.name = name + + def realize( + self, mesh: Octree, model: np.ndarray, event_map: EventMap + ) -> tuple[np.ndarray, EventMap]: + """ + Realize each event in the history. + + :param mesh: Octree mesh on which the model is defined. + :param model: Model to be updated by the events in the history. + :param event_map: mapping event ids to names and physical properties. + """ + + event_id = max(event_map) + 1 + event_map[event_id] = (self.name, self.history[0].value) + for event in self.history: + model, event_map = event.realize(mesh, model, event_map, coeval=True) + + return model, event_map + + @property + def history(self) -> Sequence[Anomaly]: + """Sequence of geological events.""" + return self._history + + @history.setter + def history(self, events): + if not all(isinstance(k, Anomaly) for k in events): + raise ValueError("History must be a sequence of geological Anomaly.") + + self._history = events + + +class GeologyViolationError(Exception): + """Raise when a geological history is invalid.""" + + def __init__(self, message): + super().__init__(message) + + +class Geology(Series): + """ + Ensures that a history is valid. + + :param history: Sequence of geological events to be validated. + """ + + def __init__( + self, + workspace: Workspace, + *, + mesh: Octree, + background: float, + history: Sequence[Event | Series], + ): + super().__init__(history) + self.workspace = workspace + self.mesh = mesh + self.background = background + + def __iter__(self): + return iter(self.history) + + @property + def history(self) -> Sequence[Event | Series]: + """Sequence of geological events.""" + return self._history + + @history.setter + def history(self, events): + if not all(isinstance(k, Event | Series) for k in events): + raise ValueError( + "History must be a sequence of geological Event or Series." + ) + + self._validate_history(events) + self._history = events + + @property + def mesh(self) -> Octree: + """Octree mesh on which the model is defined.""" + return self._mesh + + @mesh.setter + def mesh(self, val: Octree): + if val.n_cells is None: + raise ValueError("Mesh must have n_cells.") + self._mesh = val + + def build(self) -> tuple[np.ndarray, EventMap]: + """ + Realize the geological events in the scenario. + + :return: Model and event map. + """ + with fetch_active_workspace(self.workspace, mode="r+"): + if self.mesh.n_cells is None: + raise ValueError("Mesh must have n_cells.") + event_map = {1: ("Background", self.background)} + geology, event_map = super().realize( + self.mesh, np.ones(self.mesh.n_cells), event_map + ) + + return geology, event_map + + def _validate_history(self, events: Sequence[Event | Series]): + """Throw exception if the history isn't valid.""" + self._validate_overburden(events) + self._validate_topography(events) + + def _validate_overburden(self, events: Sequence[Event | Series]): + """Throw exception if Overburden is not the second last event in the history.""" + + if any(isinstance(k, Overburden) for k in events) and not isinstance( + events[-2], Overburden + ): + raise GeologyViolationError( + "Overburden events must occur before the final erosion in the history." + ) + + def _validate_topography(self, events: Sequence[Event | Series]): + """Throw exception if the last event isn't an erosion.""" + + if not isinstance(events[-1], Erosion): + raise GeologyViolationError( + "The last event in a geological history must be an erosion." + ) diff --git a/simpeg_drivers/plate_simulation/options.py b/simpeg_drivers/plate_simulation/options.py new file mode 100644 index 00000000..786f0fee --- /dev/null +++ b/simpeg_drivers/plate_simulation/options.py @@ -0,0 +1,100 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +from copy import deepcopy +from pathlib import Path +from typing import ClassVar + +from geoapps_utils.driver.data import BaseData +from geoh5py.groups import SimPEGGroup, UIJsonGroup +from geoh5py.ui_json import InputFile + +from simpeg_drivers.electricals.direct_current.three_dimensions.options import ( + DC3DForwardOptions, +) +from simpeg_drivers.electromagnetics.frequency_domain.options import ( + FDEMForwardOptions, +) +from simpeg_drivers.electromagnetics.time_domain.options import ( + TDEMForwardOptions, +) +from simpeg_drivers.natural_sources.magnetotellurics.options import ( + MTForwardOptions, +) +from simpeg_drivers.natural_sources.tipper.options import TipperForwardOptions +from simpeg_drivers.options import BaseForwardOptions +from simpeg_drivers.potential_fields.gravity.options import GravityForwardOptions +from simpeg_drivers.potential_fields.magnetic_vector.options import ( + MVIForwardOptions, +) + +from . import assets_path +from .mesh.options import MeshOptions +from .models.options import ModelOptions + + +PARAM_MAP = { + "gravity": GravityForwardOptions, + "tdem": TDEMForwardOptions, + "fem": FDEMForwardOptions, + "magnetotellurics": MTForwardOptions, + "direct current 3d": DC3DForwardOptions, + "magnetic vector": MVIForwardOptions, + "tipper": TipperForwardOptions, +} + + +class PlateSimulationOptions(BaseData): + """ + Parameters for the plate simulation driver. + + geoh5: Workspace in which the model will be built and results stored. + mesh: Parameters for the octree mesh. + model: Parameters for the background + overburden and plate model. + simulation: Simpeg group containing simulation options and a survey. Any + mesh or starting model selections will be replaced by the objects + created by the driver. + """ + + name: ClassVar[str] = "plate_simulation" + default_ui_json: ClassVar[Path] = assets_path() / "uijson/plate_simulation.ui.json" + title: ClassVar[str] = "Plate Simulation" + run_command: ClassVar[str] = "plate_simulation.driver" + out_group: UIJsonGroup | None = None + + mesh: MeshOptions + model: ModelOptions + simulation: SimPEGGroup + + def simulation_parameters(self) -> BaseForwardOptions: + """ + Create SimPEG parameters from the simulation options. + + A new SimPEGGroup is created inside the out_group to store the + result of the forward simulation. + """ + simulation_options = deepcopy(self.simulation.options) + simulation_options["geoh5"] = self.geoh5 + + input_file = InputFile(ui_json=simulation_options, validate=False) + if input_file.ui_json is None: + raise ValueError("Input file must have ui_json set.") + + input_file.ui_json["mesh"]["value"] = None + + if input_file.data is None: + raise ValueError("Input file data must be set.") + + if input_file.data["inversion_type"] in PARAM_MAP: + return PARAM_MAP[input_file.data["inversion_type"]].build(input_file.data) + + raise NotImplementedError( + f"Unknown inversion type: {input_file.data['inversion_type']}" + ) diff --git a/simpeg_drivers/plate_simulation/utils.py b/simpeg_drivers/plate_simulation/utils.py new file mode 100644 index 00000000..cce32afb --- /dev/null +++ b/simpeg_drivers/plate_simulation/utils.py @@ -0,0 +1,56 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from plate_simulation.models.parametric import Plate + + +def azimuth_to_unit_vector(azimuth: float) -> np.ndarray: + """ + Convert an azimuth to a unit vector. + + :param azimuth: Azimuth in degrees from north (0 to 360). + :return: Unit vector in the direction of the azimuth. + """ + theta = np.deg2rad(azimuth) + mat_z = np.r_[ + np.c_[np.cos(theta), -np.sin(theta), 0.0], + np.c_[np.sin(theta), np.cos(theta), 0.0], + np.c_[0.0, 0.0, 1.0], + ] + return np.array([0.0, 1.0, 0.0]).dot(mat_z) + + +def replicate( + plate: Plate, + number: int, + spacing: float, + azimuth: float, +) -> list[Plate]: + """ + Replicate a plate n times along an azimuth centered at origin. + + Plate names will be indexed. + + :param plate: models.parametric.Plate to be replicated. + :param number: Number of plates returned. + :param spacing: Spacing between plates. + :param azimuth: Azimuth of the axis along with plates are replicated. + """ + + offsets = (np.arange(number) * spacing) - ((number - 1) * spacing / 2) + + plates = [] + for i in range(number): + center = np.r_[plate.center] + azimuth_to_unit_vector(azimuth) * offsets[i] + new = Plate(plate.params.copy(), center) + new.params.name = f"{plate.params.name} offset {i + 1}" + plates.append(new) + return plates From dea66a8a519e8afeccfe271fee91dbc443762579 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 25 Jun 2025 15:47:11 -0700 Subject: [PATCH 2/9] Fix imports --- simpeg_drivers/plate_simulation/driver.py | 12 ++++++------ simpeg_drivers/plate_simulation/models/events.py | 5 +++-- simpeg_drivers/plate_simulation/models/parametric.py | 2 +- simpeg_drivers/plate_simulation/models/series.py | 10 ++++++++-- simpeg_drivers/plate_simulation/utils.py | 3 ++- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/simpeg_drivers/plate_simulation/driver.py b/simpeg_drivers/plate_simulation/driver.py index a1e13da0..09360e15 100644 --- a/simpeg_drivers/plate_simulation/driver.py +++ b/simpeg_drivers/plate_simulation/driver.py @@ -20,15 +20,15 @@ from geoh5py.ui_json import InputFile, monitored_directory_copy from octree_creation_app.driver import OctreeDriver from param_sweeps.generate import generate -from plate_simulation.logger import get_logger -from plate_simulation.models.events import Anomaly, Erosion, Overburden -from plate_simulation.models.parametric import Plate -from plate_simulation.models.series import DikeSwarm, Geology -from plate_simulation.options import PlateSimulationOptions -from plate_simulation.utils import replicate from simpeg_drivers.driver import InversionDriver from simpeg_drivers.options import BaseForwardOptions +from simpeg_drivers.plate_simulation.logger import get_logger +from simpeg_drivers.plate_simulation.models.events import Anomaly, Erosion, Overburden +from simpeg_drivers.plate_simulation.models.parametric import Plate +from simpeg_drivers.plate_simulation.models.series import DikeSwarm, Geology +from simpeg_drivers.plate_simulation.options import PlateSimulationOptions +from simpeg_drivers.plate_simulation.utils import replicate class PlateSimulationDriver: diff --git a/simpeg_drivers/plate_simulation/models/events.py b/simpeg_drivers/plate_simulation/models/events.py index 9d23c1f6..3affe1a1 100644 --- a/simpeg_drivers/plate_simulation/models/events.py +++ b/simpeg_drivers/plate_simulation/models/events.py @@ -13,8 +13,9 @@ import numpy as np from geoh5py.objects import Octree, Surface from geoh5py.shared.utils import find_unique_name -from plate_simulation.models import EventMap -from plate_simulation.models.parametric import Boundary, Parametric + +from simpeg_drivers.plate_simulation.models import EventMap +from simpeg_drivers.plate_simulation.models.parametric import Boundary, Parametric class Event(ABC): diff --git a/simpeg_drivers/plate_simulation/models/parametric.py b/simpeg_drivers/plate_simulation/models/parametric.py index c982b24b..185882db 100644 --- a/simpeg_drivers/plate_simulation/models/parametric.py +++ b/simpeg_drivers/plate_simulation/models/parametric.py @@ -23,10 +23,10 @@ from geoh5py.objects import Octree, Surface from geoh5py.shared.utils import fetch_active_workspace from geoh5py.workspace import Workspace -from plate_simulation.models.options import PlateOptions from trimesh import Trimesh from trimesh.proximity import ProximityQuery +from simpeg_drivers.plate_simulation.models.options import PlateOptions from simpeg_drivers.utils.utils import active_from_xyz diff --git a/simpeg_drivers/plate_simulation/models/series.py b/simpeg_drivers/plate_simulation/models/series.py index 3384b9e4..2f67a9a0 100644 --- a/simpeg_drivers/plate_simulation/models/series.py +++ b/simpeg_drivers/plate_simulation/models/series.py @@ -18,8 +18,14 @@ from geoh5py import Workspace from geoh5py.objects import Octree from geoh5py.shared.utils import fetch_active_workspace -from plate_simulation.models import EventMap -from plate_simulation.models.events import Anomaly, Erosion, Event, Overburden + +from simpeg_drivers.plate_simulation.models import EventMap +from simpeg_drivers.plate_simulation.models.events import ( + Anomaly, + Erosion, + Event, + Overburden, +) if TYPE_CHECKING: diff --git a/simpeg_drivers/plate_simulation/utils.py b/simpeg_drivers/plate_simulation/utils.py index cce32afb..9dcd2e21 100644 --- a/simpeg_drivers/plate_simulation/utils.py +++ b/simpeg_drivers/plate_simulation/utils.py @@ -9,7 +9,8 @@ # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' import numpy as np -from plate_simulation.models.parametric import Plate + +from simpeg_drivers.plate_simulation.models.parametric import Plate def azimuth_to_unit_vector(azimuth: float) -> np.ndarray: From c2b1834b164d1892af41f732b5b1e7b1d77ac378 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 25 Jun 2025 15:52:59 -0700 Subject: [PATCH 3/9] Move replicate method to class --- simpeg_drivers/plate_simulation/driver.py | 39 +++++++++++++++++++---- simpeg_drivers/plate_simulation/utils.py | 30 ----------------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/simpeg_drivers/plate_simulation/driver.py b/simpeg_drivers/plate_simulation/driver.py index 09360e15..9a343142 100644 --- a/simpeg_drivers/plate_simulation/driver.py +++ b/simpeg_drivers/plate_simulation/driver.py @@ -13,6 +13,7 @@ import sys from pathlib import Path +import numpy as np from geoh5py.data import FloatData, ReferencedData from geoh5py.groups import UIJsonGroup from geoh5py.objects import Octree, Points, Surface @@ -20,6 +21,7 @@ from geoh5py.ui_json import InputFile, monitored_directory_copy from octree_creation_app.driver import OctreeDriver from param_sweeps.generate import generate +from plate_simulation.utils import azimuth_to_unit_vector from simpeg_drivers.driver import InversionDriver from simpeg_drivers.options import BaseForwardOptions @@ -28,7 +30,6 @@ from simpeg_drivers.plate_simulation.models.parametric import Plate from simpeg_drivers.plate_simulation.models.series import DikeSwarm, Geology from simpeg_drivers.plate_simulation.options import PlateSimulationOptions -from simpeg_drivers.plate_simulation.utils import replicate class PlateSimulationDriver: @@ -164,12 +165,7 @@ def plates(self) -> list[Plate]: self.params.model.plate_model, center, ) - self._plates = replicate( - plate, - self.params.model.plate_model.number, - self.params.model.plate_model.spacing, - self.params.model.plate_model.dip_direction, - ) + self._plates = self.replicate(plate) return self._plates @property @@ -271,6 +267,35 @@ def make_model(self) -> FloatData: return starting_model + def replicate(self, plate: Plate) -> list[Plate]: + """ + Replicate a plate n times along an azimuth centered at origin. + + Plate names will be indexed. + + :param plate: models.parametric.Plate to be replicated. + """ + offsets = ( + np.arange(self.params.model.plate_model.number) + * self.params.model.plate_model.spacing + ) - ( + (self.params.model.plate_model.number - 1) + * self.params.model.plate_model.spacing + / 2 + ) + + plates = [] + for i in range(self.params.model.plate_model.number): + center = ( + np.r_[plate.center] + + azimuth_to_unit_vector(self.params.model.plate_model.azimuth) + * offsets[i] + ) + new = Plate(plate.params.model_copy(), center) + new.params.name = f"{plate.params.name} offset {i + 1}" + plates.append(new) + return plates + @staticmethod def start(ifile: str | Path | InputFile): """Run the plate simulation driver from an input file.""" diff --git a/simpeg_drivers/plate_simulation/utils.py b/simpeg_drivers/plate_simulation/utils.py index 9dcd2e21..168f569b 100644 --- a/simpeg_drivers/plate_simulation/utils.py +++ b/simpeg_drivers/plate_simulation/utils.py @@ -10,8 +10,6 @@ import numpy as np -from simpeg_drivers.plate_simulation.models.parametric import Plate - def azimuth_to_unit_vector(azimuth: float) -> np.ndarray: """ @@ -27,31 +25,3 @@ def azimuth_to_unit_vector(azimuth: float) -> np.ndarray: np.c_[0.0, 0.0, 1.0], ] return np.array([0.0, 1.0, 0.0]).dot(mat_z) - - -def replicate( - plate: Plate, - number: int, - spacing: float, - azimuth: float, -) -> list[Plate]: - """ - Replicate a plate n times along an azimuth centered at origin. - - Plate names will be indexed. - - :param plate: models.parametric.Plate to be replicated. - :param number: Number of plates returned. - :param spacing: Spacing between plates. - :param azimuth: Azimuth of the axis along with plates are replicated. - """ - - offsets = (np.arange(number) * spacing) - ((number - 1) * spacing / 2) - - plates = [] - for i in range(number): - center = np.r_[plate.center] + azimuth_to_unit_vector(azimuth) * offsets[i] - new = Plate(plate.params.copy(), center) - new.params.name = f"{plate.params.name} offset {i + 1}" - plates.append(new) - return plates From 95fd53423d5906f10adb79491b8e97f35ae22609 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 25 Jun 2025 17:39:08 -0700 Subject: [PATCH 4/9] Migrate tests and utilities --- simpeg_drivers/driver.py | 1 - simpeg_drivers/plate_simulation/driver.py | 62 ++--- simpeg_drivers/plate_simulation/logger.py | 32 --- .../plate_simulation/mesh/options.py | 73 ------ simpeg_drivers/plate_simulation/options.py | 62 ++++- simpeg_drivers/plate_simulation/utils.py | 27 -- .../plate_simulation}/__init__.py | 0 tests/plate_simulation/models/__init__.py | 53 ++++ tests/plate_simulation/models/events_test.py | 114 +++++++++ tests/plate_simulation/models/params_test.py | 80 ++++++ tests/plate_simulation/models/plates_test.py | 142 +++++++++++ tests/plate_simulation/models/series_test.py | 150 +++++++++++ tests/plate_simulation/runtest/__init__.py | 41 +++ tests/plate_simulation/runtest/driver_test.py | 238 ++++++++++++++++++ .../plate_simulation/runtest/gravity_test.py | 83 ++++++ 15 files changed, 996 insertions(+), 162 deletions(-) delete mode 100644 simpeg_drivers/plate_simulation/logger.py delete mode 100644 simpeg_drivers/plate_simulation/mesh/options.py delete mode 100644 simpeg_drivers/plate_simulation/utils.py rename {simpeg_drivers/plate_simulation/mesh => tests/plate_simulation}/__init__.py (100%) create mode 100644 tests/plate_simulation/models/__init__.py create mode 100644 tests/plate_simulation/models/events_test.py create mode 100644 tests/plate_simulation/models/params_test.py create mode 100644 tests/plate_simulation/models/plates_test.py create mode 100644 tests/plate_simulation/models/series_test.py create mode 100644 tests/plate_simulation/runtest/__init__.py create mode 100644 tests/plate_simulation/runtest/driver_test.py create mode 100644 tests/plate_simulation/runtest/gravity_test.py diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index 12a99b8b..5524ef97 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -687,7 +687,6 @@ def from_input_file(cls, ifile: InputFile) -> InversionDriver: class InversionLogger: def __init__(self, logfile, driver): self.driver = driver - self.forward = driver.params.forward_only self.terminal = sys.stdout self.log = open(self.get_path(logfile), "w", encoding="utf8") self.initial_time = time() diff --git a/simpeg_drivers/plate_simulation/driver.py b/simpeg_drivers/plate_simulation/driver.py index 9a343142..a6b6fda6 100644 --- a/simpeg_drivers/plate_simulation/driver.py +++ b/simpeg_drivers/plate_simulation/driver.py @@ -14,6 +14,8 @@ from pathlib import Path import numpy as np +from geoapps_utils.base import Driver, get_logger +from geoapps_utils.utils.transformations import azimuth_to_unit_vector from geoh5py.data import FloatData, ReferencedData from geoh5py.groups import UIJsonGroup from geoh5py.objects import Octree, Points, Surface @@ -21,18 +23,19 @@ from geoh5py.ui_json import InputFile, monitored_directory_copy from octree_creation_app.driver import OctreeDriver from param_sweeps.generate import generate -from plate_simulation.utils import azimuth_to_unit_vector -from simpeg_drivers.driver import InversionDriver +from simpeg_drivers.driver import InversionDriver, InversionLogger from simpeg_drivers.options import BaseForwardOptions -from simpeg_drivers.plate_simulation.logger import get_logger from simpeg_drivers.plate_simulation.models.events import Anomaly, Erosion, Overburden from simpeg_drivers.plate_simulation.models.parametric import Plate from simpeg_drivers.plate_simulation.models.series import DikeSwarm, Geology from simpeg_drivers.plate_simulation.options import PlateSimulationOptions -class PlateSimulationDriver: +logger = get_logger(__name__) + + +class PlateSimulationDriver(Driver): """ Driver for simulating background + plate + overburden model. @@ -44,8 +47,10 @@ class PlateSimulationDriver: :param survey: Survey object for the simulation """ + _params_class = PlateSimulationOptions + def __init__(self, params: PlateSimulationOptions): - self.params = params + super().__init__(params) self._plates: list[Plate] | None = None self._survey: Points | None = None @@ -55,12 +60,10 @@ def __init__(self, params: PlateSimulationOptions): self._simulation_driver: InversionDriver | None = None self._out_group = self.validate_out_group(self.params.out_group) - self._logger = get_logger("Plate Simulation") - def run(self) -> InversionDriver: """Create octree mesh, fill model, and simulate.""" - self._logger.info("running the simulation...") + logger.info("running the simulation...") with fetch_active_workspace(self.params.geoh5, mode="r+"): self.simulation_driver.run() self.out_group.add_ui_json() @@ -73,8 +76,8 @@ def run(self) -> InversionDriver: self.out_group, ) - self._logger.info("done.") - self._logger.handlers.clear() + logger.info("done.") + logger.handlers.clear() return self.simulation_driver @@ -165,7 +168,12 @@ def plates(self) -> list[Plate]: self.params.model.plate_model, center, ) - self._plates = self.replicate(plate) + self._plates = self.replicate( + plate, + self.params.model.plate_model.number, + self.params.model.plate_model.spacing, + self.params.model.plate_model.azimuth, + ) return self._plates @property @@ -195,7 +203,7 @@ def make_mesh(self) -> Octree: Mesh contains refinements for topography and any plates. """ - self._logger.info("making the mesh...") + logger.info("making the mesh...") octree_params = self.params.mesh.octree_params( self.survey, self.simulation_parameters.active_cells.topography_object, @@ -210,7 +218,7 @@ def make_mesh(self) -> Octree: def make_model(self) -> FloatData: """Create background + plate and overburden model from parameters.""" - self._logger.info("Building the model...") + logger.info("Building the model...") overburden = Overburden( topography=self.simulation_parameters.active_cells.topography_object, @@ -267,30 +275,28 @@ def make_model(self) -> FloatData: return starting_model - def replicate(self, plate: Plate) -> list[Plate]: + @staticmethod + def replicate( + plate: Plate, + number: int, + spacing: float, + azimuth: float, + ) -> list[Plate]: """ Replicate a plate n times along an azimuth centered at origin. Plate names will be indexed. :param plate: models.parametric.Plate to be replicated. + :param number: Number of plates returned. + :param spacing: Spacing between plates. + :param azimuth: Azimuth of the axis along with plates are replicated. """ - offsets = ( - np.arange(self.params.model.plate_model.number) - * self.params.model.plate_model.spacing - ) - ( - (self.params.model.plate_model.number - 1) - * self.params.model.plate_model.spacing - / 2 - ) + offsets = (np.arange(number) * spacing) - ((number - 1) * spacing / 2) plates = [] - for i in range(self.params.model.plate_model.number): - center = ( - np.r_[plate.center] - + azimuth_to_unit_vector(self.params.model.plate_model.azimuth) - * offsets[i] - ) + for i in range(number): + center = np.r_[plate.center] + azimuth_to_unit_vector(azimuth) * offsets[i] new = Plate(plate.params.model_copy(), center) new.params.name = f"{plate.params.name} offset {i + 1}" plates.append(new) diff --git a/simpeg_drivers/plate_simulation/logger.py b/simpeg_drivers/plate_simulation/logger.py deleted file mode 100644 index ff469ee1..00000000 --- a/simpeg_drivers/plate_simulation/logger.py +++ /dev/null @@ -1,32 +0,0 @@ -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -# Copyright (c) 2025 Mira Geoscience Ltd. ' -# ' -# This file is part of simpeg-drivers package. ' -# ' -# simpeg-drivers is distributed under the terms and conditions of the MIT License ' -# (see LICENSE file at the root of this source code package). ' -# ' -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -import logging - - -def get_logger(name: str, level: int = logging.INFO) -> logging.Logger: - """ - Get a logger with a timestamped stream and speciified log level. - - :param name: Name of the logger. - :param level: Log level - """ - logger = logging.getLogger(name) - logger.setLevel(level) - stream_handler = logging.StreamHandler() - stream_handler.setLevel(level) - formatter = logging.Formatter( - "%(asctime)s : %(name)s : %(levelname)s : %(message)s" - ) - stream_handler.setFormatter(formatter) - logger.addHandler(stream_handler) - logger.propagate = False - - return logger diff --git a/simpeg_drivers/plate_simulation/mesh/options.py b/simpeg_drivers/plate_simulation/mesh/options.py deleted file mode 100644 index 3b99b7bd..00000000 --- a/simpeg_drivers/plate_simulation/mesh/options.py +++ /dev/null @@ -1,73 +0,0 @@ -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -# Copyright (c) 2025 Mira Geoscience Ltd. ' -# ' -# This file is part of simpeg-drivers package. ' -# ' -# simpeg-drivers is distributed under the terms and conditions of the MIT License ' -# (see LICENSE file at the root of this source code package). ' -# ' -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -from pathlib import Path - -from geoh5py.objects import ObjectBase, Points, Surface -from octree_creation_app.params import OctreeParams -from pydantic import BaseModel - - -class MeshOptions(BaseModel): - """Core parameters for octree mesh creation.""" - - u_cell_size: float - v_cell_size: float - w_cell_size: float - padding_distance: float - depth_core: float - max_distance: float - minimum_level: int = 8 - diagonal_balance: bool = False - - def octree_params( - self, survey: ObjectBase, topography: Surface | Points, plates: list[Surface] - ): - refinements = [ - { - "refinement_object": survey, - "levels": [4, 4, 4], - "horizon": False, - }, - { - "refinement_object": topography, - "levels": [0, 2], - "horizon": True, - "distance": 1000.0, - }, - ] - for plate in plates: - refinements.append( - { - "refinement_object": plate, - "levels": [2, 1], - "horizon": False, - } - ) - - octree_params = OctreeParams( - geoh5=survey.workspace, - objects=survey, - u_cell_size=self.u_cell_size, - v_cell_size=self.v_cell_size, - w_cell_size=self.w_cell_size, - horizontal_padding=self.padding_distance, - vertical_padding=self.padding_distance, - depth_core=self.depth_core, - max_distance=self.max_distance, - minimum_level=self.minimum_level, - diagonal_balance=self.diagonal_balance, - refinements=refinements, - ) - - assert isinstance(survey.workspace.h5file, Path) - path = survey.workspace.h5file.parent - octree_params.write_ui_json(path / "octree.ui.json") - return octree_params diff --git a/simpeg_drivers/plate_simulation/options.py b/simpeg_drivers/plate_simulation/options.py index 786f0fee..c7de2545 100644 --- a/simpeg_drivers/plate_simulation/options.py +++ b/simpeg_drivers/plate_simulation/options.py @@ -14,7 +14,10 @@ from geoapps_utils.driver.data import BaseData from geoh5py.groups import SimPEGGroup, UIJsonGroup +from geoh5py.objects import ObjectBase, Points, Surface from geoh5py.ui_json import InputFile +from octree_creation_app.params import OctreeParams +from pydantic import BaseModel from simpeg_drivers.electricals.direct_current.three_dimensions.options import ( DC3DForwardOptions, @@ -36,7 +39,6 @@ ) from . import assets_path -from .mesh.options import MeshOptions from .models.options import ModelOptions @@ -51,6 +53,64 @@ } +class MeshOptions(BaseModel): + """Core parameters for octree mesh creation.""" + + u_cell_size: float + v_cell_size: float + w_cell_size: float + padding_distance: float + depth_core: float + max_distance: float + minimum_level: int = 8 + diagonal_balance: bool = False + + def octree_params( + self, survey: ObjectBase, topography: Surface | Points, plates: list[Surface] + ): + refinements = [ + { + "refinement_object": survey, + "levels": [4, 4, 4], + "horizon": False, + }, + { + "refinement_object": topography, + "levels": [0, 2], + "horizon": True, + "distance": 1000.0, + }, + ] + for plate in plates: + refinements.append( + { + "refinement_object": plate, + "levels": [2, 1], + "horizon": False, + } + ) + + octree_params = OctreeParams( + geoh5=survey.workspace, + objects=survey, + u_cell_size=self.u_cell_size, + v_cell_size=self.v_cell_size, + w_cell_size=self.w_cell_size, + horizontal_padding=self.padding_distance, + vertical_padding=self.padding_distance, + depth_core=self.depth_core, + max_distance=self.max_distance, + minimum_level=self.minimum_level, + diagonal_balance=self.diagonal_balance, + refinements=refinements, + ) + + assert isinstance(survey.workspace.h5file, Path) + path = survey.workspace.h5file.parent + octree_params.write_ui_json(path / "octree.ui.json") + return octree_params + + class PlateSimulationOptions(BaseData): """ Parameters for the plate simulation driver. diff --git a/simpeg_drivers/plate_simulation/utils.py b/simpeg_drivers/plate_simulation/utils.py deleted file mode 100644 index 168f569b..00000000 --- a/simpeg_drivers/plate_simulation/utils.py +++ /dev/null @@ -1,27 +0,0 @@ -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -# Copyright (c) 2025 Mira Geoscience Ltd. ' -# ' -# This file is part of simpeg-drivers package. ' -# ' -# simpeg-drivers is distributed under the terms and conditions of the MIT License ' -# (see LICENSE file at the root of this source code package). ' -# ' -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -import numpy as np - - -def azimuth_to_unit_vector(azimuth: float) -> np.ndarray: - """ - Convert an azimuth to a unit vector. - - :param azimuth: Azimuth in degrees from north (0 to 360). - :return: Unit vector in the direction of the azimuth. - """ - theta = np.deg2rad(azimuth) - mat_z = np.r_[ - np.c_[np.cos(theta), -np.sin(theta), 0.0], - np.c_[np.sin(theta), np.cos(theta), 0.0], - np.c_[0.0, 0.0, 1.0], - ] - return np.array([0.0, 1.0, 0.0]).dot(mat_z) diff --git a/simpeg_drivers/plate_simulation/mesh/__init__.py b/tests/plate_simulation/__init__.py similarity index 100% rename from simpeg_drivers/plate_simulation/mesh/__init__.py rename to tests/plate_simulation/__init__.py diff --git a/tests/plate_simulation/models/__init__.py b/tests/plate_simulation/models/__init__.py new file mode 100644 index 00000000..87638e04 --- /dev/null +++ b/tests/plate_simulation/models/__init__.py @@ -0,0 +1,53 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from geoh5py.objects import Surface +from octree_creation_app.driver import OctreeDriver +from octree_creation_app.params import OctreeParams + + +def get_topo_mesh(workspace): + vertices = np.array( + [ + [0.0, 0.0, 0.0], + [10.0, 0.0, 0.0], + [10.0, 10.0, 0.0], + [0.0, 10.0, 0.0], + ] + ) + cells = np.array([[0, 1, 2], [0, 2, 3]]) + + topography = Surface.create(workspace, name="topo", vertices=vertices, cells=cells) + + kwargs = { + "geoh5": workspace, + "objects": topography, + "u_cell_size": 0.5, + "v_cell_size": 0.5, + "w_cell_size": 0.5, + "horizontal_padding": 10.0, + "vertical_padding": 10.0, + "depth_core": 5.0, + "minimum_level": 4, + "diagonal_balance": False, + "refinements": [ + { + "refinement_object": topography, + "levels": [4, 2, 1], + "horizon": True, + } + ], + } + params = OctreeParams(**kwargs) + params.write_ui_json(workspace.h5file.parent / "octree.ui.json") + driver = OctreeDriver(params) + octree = driver.run() + return topography, octree diff --git a/tests/plate_simulation/models/events_test.py b/tests/plate_simulation/models/events_test.py new file mode 100644 index 00000000..ed931533 --- /dev/null +++ b/tests/plate_simulation/models/events_test.py @@ -0,0 +1,114 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from geoh5py import Workspace +from geoh5py.objects import Surface + +from simpeg_drivers.plate_simulation.models.events import ( + Anomaly, + Deposition, + Erosion, + Overburden, +) +from simpeg_drivers.plate_simulation.models.options import PlateOptions +from simpeg_drivers.plate_simulation.models.parametric import Plate + +from . import get_topo_mesh + + +def test_deposition(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + topography, octree = get_topo_mesh(ws) + locs = topography.vertices.copy() + locs[:, 2] -= 5.0 + surface = Surface.create(ws, vertices=locs, cells=topography.cells) + + deposition = Deposition(surface=surface, value=2.0, name="deposition") + background = np.ones(octree.n_cells) + event_map = {1: ("Background", 1.0)} + deposition_model, event_map = deposition.realize( + mesh=octree, model=background, event_map=event_map + ) + for event_id, props in event_map.items(): + deposition_model[deposition_model == event_id] = props[1] + model = octree.add_data({"model": {"values": deposition_model}}) + + ind = octree.centroids[:, 2] < -5.0 + assert all(model.values[ind] == 2) + assert all(model.values[~ind] == 1) + + +def test_erosion(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + topography, octree = get_topo_mesh(ws) + erosion = Erosion(surface=topography) + background = np.ones(octree.n_cells) + event_map = {1: ("Background", 1.0)} + erosion_model, event_map = erosion.realize( + mesh=octree, model=background, event_map=event_map + ) + for event_id, props in event_map.items(): + erosion_model[erosion_model == event_id] = props[1] + model = octree.add_data({"model": {"values": erosion_model}}) + + ind = octree.centroids[:, 2] < 0.0 + assert all(np.isfinite(model.values[ind])) + assert all(np.isnan(model.values[~ind])) + + +def test_overburden(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + topography, octree = get_topo_mesh(ws) + overburden = Overburden(topography=topography, thickness=5.0, value=2.0) + background = np.ones(octree.n_cells) + event_map = {1: ("Background", 1.0)} + overburden_model, event_map = overburden.realize( + mesh=octree, model=background, event_map=event_map + ) + for event_id, props in event_map.items(): + overburden_model[overburden_model == event_id] = props[1] + model = octree.add_data({"model": {"values": overburden_model}}) + + ind = octree.centroids[:, 2] < -5.0 + assert all(model.values[ind] == 1) + assert all(model.values[~ind] == 2) + + +def test_anomaly(tmp_path): + with Workspace(tmp_path / "test.geoh5") as workspace: + _, octree = get_topo_mesh(workspace) + params = PlateOptions( + name="my plate", + plate=10.0, + elevation=-1.5, + width=10.0, + strike_length=10.0, + dip_length=1.0, + ) + plate = Plate(params, center=(5.0, 5.0, -1.5)) + + anomaly = Anomaly(body=plate, value=10.0) + event_map = {1: ("Background", 1.0)} + model, event_map = anomaly.realize( + mesh=octree, model=np.ones(octree.n_cells), event_map=event_map + ) + for event_id, props in event_map.items(): + model[model == event_id] = props[1] + data = octree.add_data({"model": {"values": model}}) + ind = ( + (octree.centroids[:, 0] > 0.0) + & (octree.centroids[:, 0] < 10.0) + & (octree.centroids[:, 1] > 0.0) + & (octree.centroids[:, 1] < 10.0) + & (octree.centroids[:, 2] > -2.0) + & (octree.centroids[:, 2] < -1.0) + ) + assert all(data.values[ind] == 10.0) diff --git a/tests/plate_simulation/models/params_test.py b/tests/plate_simulation/models/params_test.py new file mode 100644 index 00000000..a07dbde3 --- /dev/null +++ b/tests/plate_simulation/models/params_test.py @@ -0,0 +1,80 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from geoh5py import Workspace +from geoh5py.objects import Points, Surface + +from simpeg_drivers.plate_simulation.models.options import PlateOptions + + +def test_plate_params(tmp_path): + workspace = Workspace(tmp_path / "test.geoh5") + params = PlateOptions( + name="my plate", + plate=1.0, + width=20.0, + strike_length=1500.0, + dip_length=400.0, + dip=90.0, + dip_direction=0.0, + reference="center", + number=1, + spacing=10.0, + relative_locations=True, + easting=10.0, + northing=10.0, + elevation=-100.0, + reference_surface="topography", + reference_type="mean", + ) + assert params.spacing == 0.0 + + survey = Points.create( + workspace, + name="survey", + vertices=np.array([[-10, -10, 0]]), + ) + topography = Surface.create( + workspace, + name="test", + vertices=np.array([[-1, -1, 0], [1, -1, 0], [1, 1, 0], [-1, 1, 0]]), + cells=np.array([[0, 1, 2], [0, 2, 3]]), + ) + + center = params.center(survey, topography) + assert np.allclose(center, [0, 0, -300]) + + params.relative_locations = False + center = params.center(survey, topography) + assert np.allclose(center, [10, 10, -100]) + + +def test_plate_params_empty_reference(): + params = PlateOptions( + name="my plate", + plate=1.0, + width=20.0, + strike_length=1500.0, + dip_length=400.0, + dip=90.0, + dip_direction=0.0, + reference="center", + number=1, + spacing=10.0, + relative_locations=True, + easting=10.0, + northing=10.0, + elevation=-100.0, + reference_surface=None, + reference_type=None, + ) + assert params.reference_surface == "topography" + assert params.reference_type == "mean" diff --git a/tests/plate_simulation/models/plates_test.py b/tests/plate_simulation/models/plates_test.py new file mode 100644 index 00000000..2e5a8d44 --- /dev/null +++ b/tests/plate_simulation/models/plates_test.py @@ -0,0 +1,142 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from geoapps_utils.utils.transformations import rotate_xyz +from geoh5py import Workspace + +from simpeg_drivers.plate_simulation.driver import PlateSimulationDriver +from simpeg_drivers.plate_simulation.models.options import PlateOptions +from simpeg_drivers.plate_simulation.models.parametric import Plate + + +def are_collocated(pts1, pts2): + truth = [] + for loc in pts1: + truth.append(any(np.allclose(loc, k) for k in pts2)) + + return np.all(truth) + + +def vertical_east_striking_plate(): + params = PlateOptions( + name="my plate", + plate=1.0, + elevation=0.0, + width=10.0, + strike_length=1000.0, + dip_length=500.0, + dip=90.0, + dip_direction=0.0, + ) + plate = Plate(params) + + return plate.surface + + +def test_vertical_east_striking_plate(): + vertical_east_striking = vertical_east_striking_plate() + assert vertical_east_striking.vertices is not None + assert vertical_east_striking.extent is not None + assert np.isclose( + vertical_east_striking.extent[1, 0] - vertical_east_striking.extent[0, 0], + 1000.0, + ) + assert np.isclose( + vertical_east_striking.extent[1, 1] - vertical_east_striking.extent[0, 1], + 10.0, + ) + assert np.isclose( + vertical_east_striking.extent[1, 2] - vertical_east_striking.extent[0, 2], + 500.0, + ) + assert ( + vertical_east_striking.vertices[:, 0].mean() == 0.0 # pylint: disable=no-member + ) + assert ( + vertical_east_striking.vertices[:, 1].mean() == 0.0 # pylint: disable=no-member + ) + assert ( + vertical_east_striking.vertices[:, 2].mean() == 0.0 # pylint: disable=no-member + ) + + +def test_dipping_plates_all_quadrants(): + reference = vertical_east_striking_plate() + + for dip_direction in np.arange(0.0, 361.0, 45.0): + for dip in [20.0, 70.0]: + params = PlateOptions( + name=f"plate dipping {dip} at {dip_direction}", + plate=1.0, + elevation=0.0, + width=10.0, + strike_length=1000.0, + dip_length=500.0, + dip=dip, + dip_direction=dip_direction, + reference="center", + ) + + plate = Plate(params) + surface = plate.surface + locs = rotate_xyz(surface.vertices, [0.0, 0.0, 0.0], dip_direction, 0.0) + locs = rotate_xyz(locs, [0.0, 0.0, 0.0], 0.0, dip - 90.0) + assert np.allclose(locs, reference.vertices) + + +def test_replicate_even(tmp_path): + workspace = Workspace.create(tmp_path / f"{__name__}.geoh5") + options = PlateOptions( + name="test", + plate=1.0, + width=1.0, + strike_length=1.0, + dip_length=1.0, + elevation=1.0, + ) + plate = Plate(options, (0, 0, 0), workspace=workspace) + plates = PlateSimulationDriver.replicate(plate, 2, 10.0, 90.0) + assert plates[0].surface.vertices is not None + assert plates[1].surface.vertices is not None + assert plates[0].params.name == "test offset 1" + assert np.allclose( + plates[0].surface.vertices.mean(axis=0), np.array([-5.0, 0.0, 0.0]) + ) + assert plates[1].params.name == "test offset 2" + assert np.allclose( + plates[1].surface.vertices.mean(axis=0), np.array([5.0, 0.0, 0.0]) + ) + + +def test_replicate_odd(tmp_path): + workspace = Workspace.create(tmp_path / f"{__name__}.geoh5") + options = PlateOptions( + name="test", + plate=1.0, + width=1.0, + strike_length=1.0, + dip_length=1.0, + elevation=1.0, + ) + plate = Plate(options, (0, 0, 0), workspace=workspace) + plates = PlateSimulationDriver.replicate(plate, 3, 5.0, 0.0) + assert plates[0].surface.vertices is not None + assert plates[1].surface.vertices is not None + assert plates[2].surface.vertices is not None + assert np.allclose( + plates[0].surface.vertices.mean(axis=0), np.array([0.0, -5.0, 0.0]) + ) + assert np.allclose( + plates[1].surface.vertices.mean(axis=0), np.array([0.0, 0.0, 0.0]) + ) + assert np.allclose( + plates[2].surface.vertices.mean(axis=0), np.array([0.0, 5.0, 0.0]) + ) diff --git a/tests/plate_simulation/models/series_test.py b/tests/plate_simulation/models/series_test.py new file mode 100644 index 00000000..c8be72e9 --- /dev/null +++ b/tests/plate_simulation/models/series_test.py @@ -0,0 +1,150 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +# pylint: disable=too-many-locals + +import numpy as np +import pytest +from geoh5py import Workspace +from geoh5py.objects import Surface + +from simpeg_drivers.plate_simulation.models.events import ( + Deposition, + Erosion, + Overburden, +) +from simpeg_drivers.plate_simulation.models.series import ( + Geology, + GeologyViolationError, + Lithology, +) + +from . import get_topo_mesh + + +def test_lithology(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + _, octree = get_topo_mesh(ws) + surfaces = {} + for n_layer, elevation in enumerate([-2.0, -5.0, -10.0]): + vertices = np.array( + [ + [0.0, 0.0, elevation], + [10.0, 0.0, elevation], + [10.0, 10.0, elevation], + [0.0, 10.0, elevation], + ] + ) + cells = np.array([[0, 1, 2], [0, 2, 3]]) + + surfaces[f"layer{n_layer + 1}"] = Surface.create( + ws, name="topo", vertices=vertices, cells=cells + ) + + lithology = Lithology( + history=[ + Deposition(surface=surfaces["layer3"], value=3.0), + Deposition(surface=surfaces["layer2"], value=2.0), + Deposition(surface=surfaces["layer1"], value=1.0), + ] + ) + event_map = {0: ("Backgrounds", 0.0)} + lithology_model, event_map = lithology.realize( + mesh=octree, model=np.zeros(octree.n_cells), event_map=event_map + ) + for event_id, props in event_map.items(): + lithology_model[lithology_model == event_id] = props[1] + + model = octree.add_data({"model": {"values": lithology_model}}) + + assert len({val[0] for val in event_map.values()}) == 4 # All unique names + assert all(model.values[octree.centroids[:, 2] > -2.0] == 0.0) + ind_layer_1 = (octree.centroids[:, 2] < -2.0) & (octree.centroids[:, 2] > -5.0) + assert all(model.values[ind_layer_1] == 1.0) + ind_layer_2 = (octree.centroids[:, 2] < -5.0) & (octree.centroids[:, 2] > -10.0) + assert all(model.values[ind_layer_2] == 2.0) + assert all(model.values[octree.centroids[:, 2] < -10.0] == 3.0) + + +def test_scenario(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + topography, octree = get_topo_mesh(ws) + surfaces = {} + for n_layer, elevation in enumerate([-2.0, -5.0, -10.0]): + surfaces[f"layer{n_layer + 1}"] = Surface.create( + ws, + name="topo", + vertices=np.array( + [ + [0.0, 0.0, elevation], + [10.0, 0.0, elevation], + [10.0, 10.0, elevation], + [0.0, 10.0, elevation], + ] + ), + cells=np.array([[0, 1, 2], [0, 2, 3]]), + ) + + lithology = Lithology( + history=[ + Deposition(surface=surfaces["layer3"], value=3.0), + Deposition(surface=surfaces["layer2"], value=2.0), + Deposition(surface=surfaces["layer1"], value=1.0), + ] + ) + overburden = Overburden(topography=topography, thickness=1.0, value=10.0) + erosion = Erosion(surface=topography) + + with pytest.raises( + GeologyViolationError, + match="Overburden events must occur before the final erosion in the history.", + ): + Geology( + workspace=ws, + mesh=octree, + background=0.0, + history=[lithology, erosion, overburden], + ) + + with pytest.raises( + GeologyViolationError, + match="The last event in a geological history must be an erosion.", + ): + Geology( + workspace=ws, + mesh=octree, + background=0.0, + history=[overburden, lithology], + ) + + scenario = Geology( + workspace=ws, + mesh=octree, + background=100.0, + history=[lithology, overburden, erosion], + ) + model, event_map = scenario.build() + assert model is not None + + for event_id, props in event_map.items(): + model[model == event_id] = props[1] + + ind = octree.centroids[:, 2] > 0.0 + assert all(np.isnan(model[ind])) + ind = (octree.centroids[:, 2] < 0.0) & (octree.centroids[:, 2] > -1.0) + assert all(model[ind] == 10.0) + ind = (octree.centroids[:, 2] < -1.0) & (octree.centroids[:, 2] > -2.0) + assert all(model[ind] == 100.0) + ind = (octree.centroids[:, 2] < -2.0) & (octree.centroids[:, 2] > -5.0) + assert all(model[ind] == 1.0) + ind = (octree.centroids[:, 2] < -5.0) & (octree.centroids[:, 2] > -10.0) + assert all(model[ind] == 2.0) + ind = octree.centroids[:, 2] < -10.0 + np.testing.assert_allclose(model[ind], 3.0) diff --git a/tests/plate_simulation/runtest/__init__.py b/tests/plate_simulation/runtest/__init__.py new file mode 100644 index 00000000..24299ff9 --- /dev/null +++ b/tests/plate_simulation/runtest/__init__.py @@ -0,0 +1,41 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from geoh5py.objects import Points, Surface + + +def get_survey(workspace, n_receivers, n_lines): + X, Y = np.meshgrid( # pylint: disable=invalid-name + np.linspace(-250, 250, n_receivers), np.linspace(-250, 250, n_lines) + ) + Z = np.zeros_like(X) # pylint: disable=invalid-name + + vertices = np.c_[X.T.flatten(), Y.T.flatten(), Z.T.flatten()] + + return Points.create( + workspace, + vertices=vertices, + name="survey", + ) + + +def get_topography(workspace): + vertices = np.array( + [ + [-500.0, -500.0, 0.0], + [500.0, -500.0, 0.0], + [500.0, 500.0, 0.0], + [-500.0, 500.0, 0.0], + ] + ) + cells = np.array([[0, 1, 2], [0, 2, 3]]) + + return Surface.create(workspace, name="topo", vertices=vertices, cells=cells) diff --git a/tests/plate_simulation/runtest/driver_test.py b/tests/plate_simulation/runtest/driver_test.py new file mode 100644 index 00000000..22413a18 --- /dev/null +++ b/tests/plate_simulation/runtest/driver_test.py @@ -0,0 +1,238 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +import os +from pathlib import Path +from uuid import UUID + +import numpy as np +from geoh5py import Workspace +from geoh5py.groups import SimPEGGroup +from geoh5py.objects import AirborneTEMReceivers, ObjectBase, Octree, Surface +from geoh5py.ui_json import InputFile + +from simpeg_drivers.electromagnetics.time_domain.options import TDEMForwardOptions +from simpeg_drivers.plate_simulation import assets_path +from simpeg_drivers.plate_simulation.driver import ( + PlateSimulationDriver, + PlateSimulationOptions, +) +from simpeg_drivers.plate_simulation.models.options import ModelOptions +from simpeg_drivers.plate_simulation.options import MeshOptions +from simpeg_drivers.potential_fields.gravity.options import GravityForwardOptions + +from . import get_survey, get_topography + + +# pylint: disable=duplicate-code + + +def get_simulation_group(workspace: Workspace, survey: ObjectBase, topography: Surface): + tem_inversion = SimPEGGroup.create(workspace) + options = TDEMForwardOptions.model_construct() + ifile = InputFile.read_ui_json(options.default_ui_json) + options_dict = ifile.ui_json + options_dict["inversion_type"] = "tdem" + options_dict["forward_only"] = True + options_dict["geoh5"] = str(workspace.h5file) + options_dict["topography_object"]["value"] = str(topography.uid) + options_dict["data_object"]["value"] = str(survey.uid) + options_dict["x_channel_bool"] = True + options_dict["y_channel_bool"] = True + options_dict["z_channel_bool"] = True + tem_inversion.options = options_dict + + return tem_inversion + + +def get_input_file(filepath: Path) -> InputFile: + with Workspace(filepath / "test.geoh5") as ws: + with Workspace(assets_path() / "demo.geoh5", mode="r") as demo_workspace: + survey = demo_workspace.get_entity("Simulation rx")[0].copy( + parent=ws, copy_children=False + ) + topography = demo_workspace.get_entity("Topography")[0].copy(parent=ws) + mask = np.zeros(survey.n_vertices, dtype=bool) + mask[::10] = True + new_survey = survey.copy(vertices=survey.vertices[mask, :], cells=None) + + simulation = get_simulation_group(ws, new_survey, topography) + ifile = InputFile.read_ui_json( + assets_path() / "uijson" / "plate_simulation.ui.json", validate=False + ) + ifile.set_data_value("name", "test_tem_plate_simulation") + ifile.set_data_value("geoh5", ws) + ifile.set_data_value("simulation", simulation) + ifile.set_data_value("u_cell_size", 50.0) + ifile.set_data_value("v_cell_size", 50.0) + ifile.set_data_value("w_cell_size", 50.0) + ifile.set_data_value("depth_core", 600.0) + ifile.set_data_value("max_distance", 200.0) + ifile.set_data_value("padding_distance", 1000.0) + ifile.set_data_value("background", 2000.0) + ifile.set_data_value("overburden", 7500.0) + ifile.set_data_value("thickness", 50.0) + ifile.set_data_value("plate", 20.0) + ifile.set_data_value("width", 100.0) + ifile.set_data_value("strike_length", 1000.0) + ifile.set_data_value("dip_length", 300.0) + ifile.set_data_value("dip", 65.0) + ifile.set_data_value("dip_direction", 65.0) + ifile.set_data_value("number", 2) + ifile.set_data_value("spacing", 600.0) + ifile.set_data_value("relative_locations", True) + ifile.set_data_value("easting", 100.0) + ifile.set_data_value("northing", 100.0) + ifile.set_data_value("elevation", -100.0) + ifile.set_data_value("reference_surface", "overburden") + ifile.set_data_value("reference_type", "min") + + return ifile + + +def test_plate_simulation(tmp_path): + mon_dir = tmp_path / "monitoring" + mon_dir.mkdir(parents=True, exist_ok=True) + + ifile = get_input_file(tmp_path) + ifile.set_data_value("monitoring_directory", str(mon_dir)) + + ifile.write_ui_json("test_plate_simulation.ui.json", path=tmp_path) + result = PlateSimulationDriver.start( + Path(tmp_path / "test_plate_simulation.ui.json") + ) + with Workspace(result.out_group.options["geoh5"]) as ws: + out_group = ws.get_entity(UUID(result.out_group.options["out_group"]["value"]))[ + 0 + ] + data = next( + obj for obj in out_group.children if isinstance(obj, AirborneTEMReceivers) + ) + mesh = next(obj for obj in out_group.children if isinstance(obj, Octree)) + model = next(k for k in mesh.children if k.name == "starting_model") + assert data.property_groups is not None + assert len(data.property_groups) == 3 + assert all( + k.name in [f"Iteration_0_{i}" for i in "xyz"] for k in data.property_groups + ) + assert all( + k.properties is not None and len(k.properties) == 20 + for k in data.property_groups + ) + assert mesh.n_cells == 16263 + assert len(np.unique(model.values)) == 4 + assert all(k in np.unique(model.values) for k in [7500, 2000, 20]) + assert any(np.isnan(np.unique(model.values))) + + # Test the monitoring directory + files = [f for f in os.listdir(mon_dir) if f.endswith("geoh5")] + assert len(files) == 1 + with Workspace(mon_dir / files[0]) as ws: + fwr_group = ws.get_entity("Tdem Forward")[0] + + # Should only contain octree, files and a survey + assert len(fwr_group.children) == 5 + + +# pylint: disable=too-many-statements +def test_plate_simulation_params_from_input_file(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + topography = get_topography(ws) + survey = get_survey(ws, 10, 10) + + ifile = InputFile.read_ui_json( + assets_path() / "uijson" / "plate_simulation.ui.json", validate=False + ) + ifile.data["name"] = "test_gravity_plate_simulation" + ifile.data["geoh5"] = ws + + # Add simulation parameter + gravity_inversion = SimPEGGroup.create(ws) + + options = GravityForwardOptions.model_construct() + fwr_ifile = InputFile.read_ui_json(options.default_ui_json) + options_dict = fwr_ifile.ui_json + options_dict["inversion_type"] = "gravity" + options_dict["forward_only"] = True + options_dict["geoh5"] = str(ws.h5file) + options_dict["topography_object"]["value"] = str(topography.uid) + options_dict["data_object"]["value"] = str(survey.uid) + gravity_inversion.options = options_dict + ifile.data["simulation"] = gravity_inversion + + # Add mesh parameters + ifile.data["u_cell_size"] = 10.0 + ifile.data["v_cell_size"] = 10.0 + ifile.data["w_cell_size"] = 10.0 + ifile.data["depth_core"] = 400.0 + ifile.data["minimum_level"] = 8 + ifile.data["max_distance"] = 200.0 + ifile.data["diagonal_balance"] = False + ifile.data["padding_distance"] = 1500.0 + + # Add model parameters + ifile.data["background"] = 1000.0 + ifile.data["overburden"] = 5.0 + ifile.data["thickness"] = 50.0 + ifile.data["plate"] = 2.0 + ifile.data["width"] = 100.0 + ifile.data["strike_length"] = 100.0 + ifile.data["dip_length"] = 100.0 + ifile.data["dip"] = 0.0 + ifile.data["dip_direction"] = 0.0 + ifile.data["number"] = 9 + ifile.data["spacing"] = 10.0 + ifile.data["relative_locations"] = True + ifile.data["easting"] = 10.0 + ifile.data["northing"] = 10.0 + ifile.data["elevation"] = -250 + ifile.data["reference_surface"] = "topography" + ifile.data["reference_type"] = "mean" + + params = PlateSimulationOptions.build(ifile) + assert isinstance(params.simulation, SimPEGGroup) + + simulation_parameters = params.simulation_parameters() + + assert simulation_parameters.inversion_type == "gravity" + assert simulation_parameters.forward_only + assert simulation_parameters.geoh5.h5file == ws.h5file + assert ( + simulation_parameters.active_cells.topography_object.uid == topography.uid + ) + assert simulation_parameters.data_object.uid == survey.uid + + assert isinstance(params.mesh, MeshOptions) + assert params.mesh.u_cell_size == 10.0 + assert params.mesh.v_cell_size == 10.0 + assert params.mesh.w_cell_size == 10.0 + assert params.mesh.depth_core == 400.0 + assert params.mesh.max_distance == 200.0 + assert params.mesh.padding_distance == 1500.0 + assert params.mesh.minimum_level == 8 + assert not params.mesh.diagonal_balance + + assert isinstance(params.model, ModelOptions) + assert params.model.plate_model.name == "test_gravity_plate_simulation" + assert params.model.background == 1000.0 + assert params.model.overburden_model.thickness == 50.0 + assert params.model.overburden_model.overburden == 5.0 + assert params.model.plate_model.plate == 2.0 + assert params.model.plate_model.width == 100.0 + assert params.model.plate_model.strike_length == 100.0 + assert params.model.plate_model.dip_length == 100.0 + assert params.model.plate_model.dip == 0.0 + assert params.model.plate_model.dip_direction == 0.0 + + assert params.model.plate_model.number == 9 + assert params.model.plate_model.spacing == 10.0 + assert params.model.plate_model.relative_locations + assert params.model.plate_model.easting == 10.0 + assert params.model.plate_model.northing == 10.0 + assert params.model.plate_model.elevation == -250.0 diff --git a/tests/plate_simulation/runtest/gravity_test.py b/tests/plate_simulation/runtest/gravity_test.py new file mode 100644 index 00000000..fc228ddc --- /dev/null +++ b/tests/plate_simulation/runtest/gravity_test.py @@ -0,0 +1,83 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2025 Mira Geoscience Ltd. ' +# ' +# This file is part of simpeg-drivers package. ' +# ' +# simpeg-drivers is distributed under the terms and conditions of the MIT License ' +# (see LICENSE file at the root of this source code package). ' +# ' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +import numpy as np +from geoh5py import Workspace +from geoh5py.groups import SimPEGGroup + +from simpeg_drivers.plate_simulation.driver import PlateSimulationDriver +from simpeg_drivers.plate_simulation.models.options import ( + ModelOptions, + OverburdenOptions, + PlateOptions, +) +from simpeg_drivers.plate_simulation.options import MeshOptions, PlateSimulationOptions +from simpeg_drivers.potential_fields.gravity.options import GravityForwardOptions + +from . import get_survey, get_topography + + +def test_gravity_plate_simulation(tmp_path): + with Workspace(tmp_path / "test.geoh5") as ws: + topography = get_topography(ws) + survey = get_survey(ws, 10, 10) + + mesh_params = MeshOptions( + u_cell_size=10.0, + v_cell_size=10.0, + w_cell_size=10.0, + padding_distance=1500.0, + depth_core=600.0, + max_distance=200.0, + ) + + overburden_params = OverburdenOptions(thickness=50.0, overburden=0.2) + + plate_params = PlateOptions( + name="plate", + plate=0.5, + elevation=-250.0, + width=100.0, + strike_length=100.0, + dip_length=100.0, + dip=0.0, + dip_direction=0.0, + reference="center", + ) + + model_params = ModelOptions( + name="density", + background=0.0, + overburden_model=overburden_params, + plate_model=plate_params, + ) + + options = GravityForwardOptions.build( + topography_object=topography, + data_object=survey, + geoh5=ws, + starting_model=0.1, + ) + + gravity_inversion = SimPEGGroup.create(ws) + gravity_inversion.options = options.serialize() + + params = PlateSimulationOptions( + title="test", + run_command="run", + geoh5=ws, + mesh=mesh_params, + model=model_params, + simulation=gravity_inversion, + ) + driver = PlateSimulationDriver(params) + driver.run() + + assert np.nanmax(driver.model.values) == 0.5 From 62e27b6990c9169ac8570696882328e88cb24dda Mon Sep 17 00:00:00 2001 From: dominiquef Date: Thu, 26 Jun 2025 08:10:25 -0700 Subject: [PATCH 5/9] Migrate assets. Fix tests --- simpeg_drivers-assets/demo.geoh5 | 3 + .../plate_simulation_demo.geoh5 | 3 + .../uijson/plate_simulation.ui.json | 253 ++++++++++++++++++ simpeg_drivers/plate_simulation/__init__.py | 14 - simpeg_drivers/plate_simulation/driver.py | 2 +- simpeg_drivers/plate_simulation/options.py | 4 +- tests/plate_simulation/runtest/driver_test.py | 6 +- 7 files changed, 266 insertions(+), 19 deletions(-) create mode 100644 simpeg_drivers-assets/demo.geoh5 create mode 100644 simpeg_drivers-assets/plate_simulation_demo.geoh5 create mode 100644 simpeg_drivers-assets/uijson/plate_simulation.ui.json diff --git a/simpeg_drivers-assets/demo.geoh5 b/simpeg_drivers-assets/demo.geoh5 new file mode 100644 index 00000000..cfc5bb86 --- /dev/null +++ b/simpeg_drivers-assets/demo.geoh5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b670cf4ccbb7970292a5ec6cfe12168e335dd761674bd3eb4a3ba298573a30d2 +size 11880 diff --git a/simpeg_drivers-assets/plate_simulation_demo.geoh5 b/simpeg_drivers-assets/plate_simulation_demo.geoh5 new file mode 100644 index 00000000..86466d31 --- /dev/null +++ b/simpeg_drivers-assets/plate_simulation_demo.geoh5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69849de2ea46ffcd817cf1209197230d3b1a3db19905bc119205e28c6f6442de +size 1343146 diff --git a/simpeg_drivers-assets/uijson/plate_simulation.ui.json b/simpeg_drivers-assets/uijson/plate_simulation.ui.json new file mode 100644 index 00000000..d0107c75 --- /dev/null +++ b/simpeg_drivers-assets/uijson/plate_simulation.ui.json @@ -0,0 +1,253 @@ +{ + "version": "0.2.0-alpha.1", + "title": "Plate simulation", + "icon": "maxwellplate", + "documentation": "https://mirageoscience-plate-simulation.readthedocs-hosted.com/en/latest/", + "conda_environment": "plate_simulation", + "run_command": "plate_simulation.driver", + "geoh5": "", + "monitoring_directory": "", + "simulation": { + "main": true, + "label": "TEM SimPEG Group", + "groupType": "{55ed3daf-c192-4d4b-a439-60fa987fe2b8}", + "value": "", + "enabled": true, + "tooltip": "Forward modelling SimPEG group with at least the topogarphy and survey set" + }, + "name": { + "main": true, + "label": "Label", + "value": "plate", + "enabled": true, + "tooltip": "Provide the name for the result group" + }, + "background": { + "main": true, + "group": "Basement", + "label": "Physical property (SI)", + "value": 2000.0, + "tooltip": "Value of the basement resisitivity (ohm-m), density (g/cc) or susceptibility (SI)", + "enabled": true + }, + "overburden": { + "main": true, + "group": "Overburden", + "label": "Physical property (SI)", + "value": 8000.0, + "tooltip": "Value of the overburden resisitivity (ohm-m), density (g/cc) or susceptibility (SI)", + "enabled": true + }, + "thickness": { + "main": true, + "group": "Overburden", + "label": "Thickness", + "value": 200.0, + "enabled": true, + "tooltip": "Thickness of the overburden" + }, + "number": { + "main": true, + "group": "Plate", + "label": "Number of plates", + "value": 1, + "enabled": true, + "tooltip": "If more than one the plates will be parallel, equally spaced over the center of the model" + }, + "spacing": { + "main": true, + "group": "Plate", + "label": "Spacing (m)", + "value": 0.0, + "enabled": true, + "tooltip": "Spacing between plates" + }, + "plate": { + "main": true, + "group": "Plate", + "label": "Physical property (SI)", + "value": 20.0, + "tooltip": "Value of the plate resisitivity (ohm-m), density (g/cc) or susceptibility (SI)", + "enabled": true + }, + "width": { + "label": "Thickness", + "group": "Plate", + "main": true, + "value": 90.0, + "enabled": true, + "tooltip": "Thickness of the plate" + }, + "strike_length": { + "label": "Strike length", + "group": "Plate", + "main": true, + "value": 800.0, + "enabled": true, + "tooltip": "Length of the plate along the strike direction" + }, + "dip_length": { + "label": "Dip length", + "group": "Plate", + "main": true, + "value": 800.0, + "enabled": true, + "tooltip": "Length of the plate along the dip direction" + }, + "dip": { + "label": "Dip", + "group": "Plate", + "main": true, + "value": 60.0, + "enabled": true, + "min": 0.0, + "max": 90.0, + "tooltip": "Dip of the plate in degrees from horizontal" + }, + "dip_direction": { + "label": "Dip direction", + "group": "Plate", + "main": true, + "value": 90.0, + "enabled": true, + "min": 0.0, + "max": 360.0, + "tooltip": "Direction of the dip vector in degrees from North" + }, + "relative_locations": { + "label": "Relative locations", + "main": true, + "group": "Plate", + "value": true, + "enabled": true, + "tooltip": "If checked locations are relative to the survey center and either topography or overburden in z according to 'Depth reference' selection" + }, + "easting": { + "label": "Easting (m)", + "group": "Plate", + "main": true, + "value": 0.0, + "enabled": true, + "tooltip": "If relative locations, Easting is relative to the center of the survey" + }, + "northing": { + "label": "Northing (m)", + "main": true, + "group": "Plate", + "value": 0.0, + "enabled": true, + "tooltip": "If relative locations, Northing is relative to the center of the survey" + }, + "elevation": { + "label": "Elevation (m)", + "main": true, + "group": "Plate", + "value": 0.0, + "enabled": true, + "tooltip": "If relative location, Elevation is relative to the topography or overburden according to 'Depth reference' selection" + }, + "reference_surface": { + "label": "Depth reference", + "main": true, + "group": "Plate", + "dependency": "relative_locations", + "dependencyType": "enabled", + "choiceList": [ + "topography", + "overburden" + ], + "tooltop": "If relative locations, the depth will be below the min/mean/max (according to 'Reference type') of the reference surface chosen.", + "value": "overburden" + }, + "reference_type": { + "label": "Reference type", + "main": true, + "group": "Plate", + "dependency": "relative_locations", + "dependencyType": "enabled", + "choiceList": [ + "min", + "mean", + "max" + ], + "tooltip": "If relative locations, the depth will be below the min/mean/max of the 'Depth reference' chosen", + "value": "min" + }, + "generate_sweep": { + "label": "Generate sweep file", + "main": true, + "value": false + }, + "u_cell_size": { + "min": 0.0, + "group": "Mesh", + "label": "Easting core cell size (m)", + "value": 25.0, + "enabled": true + }, + "v_cell_size": { + "min": 0.0, + "group": "Mesh", + "label": "Northing core cell size (m)", + "value": 25.0, + "enabled": true + }, + "w_cell_size": { + "min": 0.0, + "group": "Mesh", + "label": "Vertical core cell size (m)", + "value": 25.0, + "enabled": true + }, + "depth_core": { + "min": 0.0, + "group": "Mesh", + "label": "Depth of core refinement volume", + "value": 500.0, + "enabled": true + }, + "max_distance": { + "min": 0.0, + "group": "Mesh", + "label": "Maximum padding distance", + "value": 200.0, + "enabled": true + }, + "padding_distance": { + "min": 0.0, + "group": "Mesh", + "label": "Padding distance", + "value": 1000.0, + "enabled": true + }, + "diagonal_balance": { + "group": "Mesh", + "label": "Diagonal balance", + "main": false, + "value": true, + "tooltip": "Assure single octree level change on corner neighbours. UBC compatible mesh" + }, + "minimum_level": { + "enabled": true, + "group": "Mesh", + "label": "Minimum refinement level", + "main": false, + "min": 1, + "tooltip": "Minimum refinement in padding region: 2**(n-1) x base_cell", + "value": 6 + }, + "export_model": { + "main": false, + "label": "Export mesh/model", + "value": true, + "enabled": true + }, + "out_group": { + "label": "Simulation group", + "value": "", + "groupType": "{BB50AC61-A657-4926-9C82-067658E246A0}", + "visible": true, + "optional": true, + "enabled": false + } +} diff --git a/simpeg_drivers/plate_simulation/__init__.py b/simpeg_drivers/plate_simulation/__init__.py index 20390382..4d06f672 100644 --- a/simpeg_drivers/plate_simulation/__init__.py +++ b/simpeg_drivers/plate_simulation/__init__.py @@ -7,17 +7,3 @@ # (see LICENSE file at the root of this source code package). ' # ' # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -from __future__ import annotations - -from pathlib import Path - - -__version__ = "0.3.0-alpha.1" - -from geoapps_utils.utils.importing import assets_path as assets_path_impl - - -def assets_path() -> Path: - """Return the path to the assets folder.""" - return assets_path_impl(__file__) diff --git a/simpeg_drivers/plate_simulation/driver.py b/simpeg_drivers/plate_simulation/driver.py index a6b6fda6..0956e31c 100644 --- a/simpeg_drivers/plate_simulation/driver.py +++ b/simpeg_drivers/plate_simulation/driver.py @@ -172,7 +172,7 @@ def plates(self) -> list[Plate]: plate, self.params.model.plate_model.number, self.params.model.plate_model.spacing, - self.params.model.plate_model.azimuth, + self.params.model.plate_model.dip_direction, ) return self._plates diff --git a/simpeg_drivers/plate_simulation/options.py b/simpeg_drivers/plate_simulation/options.py index c7de2545..f9f1aff5 100644 --- a/simpeg_drivers/plate_simulation/options.py +++ b/simpeg_drivers/plate_simulation/options.py @@ -19,6 +19,7 @@ from octree_creation_app.params import OctreeParams from pydantic import BaseModel +from simpeg_drivers import assets_path from simpeg_drivers.electricals.direct_current.three_dimensions.options import ( DC3DForwardOptions, ) @@ -38,7 +39,6 @@ MVIForwardOptions, ) -from . import assets_path from .models.options import ModelOptions @@ -126,7 +126,7 @@ class PlateSimulationOptions(BaseData): name: ClassVar[str] = "plate_simulation" default_ui_json: ClassVar[Path] = assets_path() / "uijson/plate_simulation.ui.json" title: ClassVar[str] = "Plate Simulation" - run_command: ClassVar[str] = "plate_simulation.driver" + run_command: ClassVar[str] = "simpeg_drivers.plate_simulation.driver" out_group: UIJsonGroup | None = None mesh: MeshOptions diff --git a/tests/plate_simulation/runtest/driver_test.py b/tests/plate_simulation/runtest/driver_test.py index 22413a18..2d0d20c2 100644 --- a/tests/plate_simulation/runtest/driver_test.py +++ b/tests/plate_simulation/runtest/driver_test.py @@ -17,8 +17,8 @@ from geoh5py.objects import AirborneTEMReceivers, ObjectBase, Octree, Surface from geoh5py.ui_json import InputFile +from simpeg_drivers import assets_path from simpeg_drivers.electromagnetics.time_domain.options import TDEMForwardOptions -from simpeg_drivers.plate_simulation import assets_path from simpeg_drivers.plate_simulation.driver import ( PlateSimulationDriver, PlateSimulationOptions, @@ -53,7 +53,9 @@ def get_simulation_group(workspace: Workspace, survey: ObjectBase, topography: S def get_input_file(filepath: Path) -> InputFile: with Workspace(filepath / "test.geoh5") as ws: - with Workspace(assets_path() / "demo.geoh5", mode="r") as demo_workspace: + with Workspace( + assets_path() / "plate_simulation_demo.geoh5", mode="r" + ) as demo_workspace: survey = demo_workspace.get_entity("Simulation rx")[0].copy( parent=ws, copy_children=False ) From d4c88c6ffeca282cbb738e8d5402c2fc1724b6d0 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Thu, 26 Jun 2025 08:23:42 -0700 Subject: [PATCH 6/9] Remove test geoh5 --- simpeg_drivers-assets/demo.geoh5 | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 simpeg_drivers-assets/demo.geoh5 diff --git a/simpeg_drivers-assets/demo.geoh5 b/simpeg_drivers-assets/demo.geoh5 deleted file mode 100644 index cfc5bb86..00000000 --- a/simpeg_drivers-assets/demo.geoh5 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b670cf4ccbb7970292a5ec6cfe12168e335dd761674bd3eb4a3ba298573a30d2 -size 11880 From 46bca40d6b9f8bec31757da9776a6bb0cf375ec5 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Fri, 27 Jun 2025 10:37:03 -0700 Subject: [PATCH 7/9] Force forward only on params of driver --- simpeg_drivers/plate_simulation/options.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/simpeg_drivers/plate_simulation/options.py b/simpeg_drivers/plate_simulation/options.py index f9f1aff5..bf5e35c5 100644 --- a/simpeg_drivers/plate_simulation/options.py +++ b/simpeg_drivers/plate_simulation/options.py @@ -142,6 +142,9 @@ def simulation_parameters(self) -> BaseForwardOptions: """ simulation_options = deepcopy(self.simulation.options) simulation_options["geoh5"] = self.geoh5 + simulation_options["forward_only"] = ( + True # TODO remove this when mechanics use ForwardOptions + ) input_file = InputFile(ui_json=simulation_options, validate=False) if input_file.ui_json is None: From 56f914071b6d44841add6a7cfe46c77063cb8a8b Mon Sep 17 00:00:00 2001 From: dominiquef Date: Fri, 27 Jun 2025 10:51:19 -0700 Subject: [PATCH 8/9] Re-lock --- .../py-3.10-linux-64-dev.conda.lock.yml | 6 +-- environments/py-3.10-linux-64.conda.lock.yml | 4 +- .../py-3.10-win-64-dev.conda.lock.yml | 6 +-- environments/py-3.10-win-64.conda.lock.yml | 4 +- .../py-3.11-linux-64-dev.conda.lock.yml | 6 +-- environments/py-3.11-linux-64.conda.lock.yml | 4 +- .../py-3.11-win-64-dev.conda.lock.yml | 6 +-- environments/py-3.11-win-64.conda.lock.yml | 4 +- .../py-3.12-linux-64-dev.conda.lock.yml | 6 +-- environments/py-3.12-linux-64.conda.lock.yml | 4 +- .../py-3.12-win-64-dev.conda.lock.yml | 6 +-- environments/py-3.12-win-64.conda.lock.yml | 4 +- py-3.10.conda-lock.yml | 40 +++++++++---------- py-3.11.conda-lock.yml | 40 +++++++++---------- py-3.12.conda-lock.yml | 40 +++++++++---------- 15 files changed, 90 insertions(+), 90 deletions(-) diff --git a/environments/py-3.10-linux-64-dev.conda.lock.yml b/environments/py-3.10-linux-64-dev.conda.lock.yml index d5faa705..d180b782 100644 --- a/environments/py-3.10-linux-64-dev.conda.lock.yml +++ b/environments/py-3.10-linux-64-dev.conda.lock.yml @@ -140,7 +140,7 @@ dependencies: - libscotch=7.0.6=hea33c07_1 - libsodium=1.0.20=h4ab18f5_0 - libspatialindex=2.0.0=he02047a_0 - - libsqlite=3.50.1=h6cd9bfd_6 + - libsqlite=3.50.1=h6cd9bfd_7 - libssh2=1.11.1=hcf80075_0 - libstdcxx=15.1.0=h8f9b012_3 - libstdcxx-ng=15.1.0=h4852527_3 @@ -203,7 +203,7 @@ dependencies: - pthread-stubs=0.4=hb9d3cd8_1002 - ptyprocess=0.7.0=pyhd8ed1ab_1 - pure_eval=0.2.3=pyhd8ed1ab_1 - - pybtex=0.25.0=pyhd8ed1ab_1 + - pybtex=0.25.1=pyhd8ed1ab_0 - pybtex-docutils=1.0.3=py310hff52083_2 - pycparser=2.22=pyh29332c3_1 - pydantic=2.11.7=pyh3cfb1c2_0 @@ -305,7 +305,7 @@ dependencies: - zstandard=0.23.0=py310ha75aee5_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.10-linux-64.conda.lock.yml b/environments/py-3.10-linux-64.conda.lock.yml index 611d51ab..f9bd78c1 100644 --- a/environments/py-3.10-linux-64.conda.lock.yml +++ b/environments/py-3.10-linux-64.conda.lock.yml @@ -78,7 +78,7 @@ dependencies: - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 - libspatialindex=2.0.0=he02047a_0 - - libsqlite=3.50.1=h6cd9bfd_6 + - libsqlite=3.50.1=h6cd9bfd_7 - libssh2=1.11.1=hcf80075_0 - libstdcxx=15.1.0=h8f9b012_3 - libstdcxx-ng=15.1.0=h4852527_3 @@ -157,7 +157,7 @@ dependencies: - zstandard=0.23.0=py310ha75aee5_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.10-win-64-dev.conda.lock.yml b/environments/py-3.10-win-64-dev.conda.lock.yml index 375bbae8..1f85b346 100644 --- a/environments/py-3.10-win-64-dev.conda.lock.yml +++ b/environments/py-3.10-win-64-dev.conda.lock.yml @@ -131,7 +131,7 @@ dependencies: - libpng=1.6.49=h7a4582a_0 - libsodium=1.0.20=hc70643c_0 - libspatialindex=2.0.0=h5a68840_0 - - libsqlite=3.50.1=hf5d6505_6 + - libsqlite=3.50.1=hf5d6505_7 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 - libwebp-base=1.5.0=h3b0e114_0 @@ -186,7 +186,7 @@ dependencies: - psutil=7.0.0=py310ha8f682b_0 - pthread-stubs=0.4=h0e40799_1002 - pure_eval=0.2.3=pyhd8ed1ab_1 - - pybtex=0.25.0=pyhd8ed1ab_1 + - pybtex=0.25.1=pyhd8ed1ab_0 - pybtex-docutils=1.0.3=py310h5588dad_2 - pycparser=2.22=pyh29332c3_1 - pydantic=2.11.7=pyh3cfb1c2_0 @@ -295,7 +295,7 @@ dependencies: - zstandard=0.23.0=py310ha8f682b_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.10-win-64.conda.lock.yml b/environments/py-3.10-win-64.conda.lock.yml index 9b20d542..d9005f22 100644 --- a/environments/py-3.10-win-64.conda.lock.yml +++ b/environments/py-3.10-win-64.conda.lock.yml @@ -68,7 +68,7 @@ dependencies: - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 - libspatialindex=2.0.0=h5a68840_0 - - libsqlite=3.50.1=hf5d6505_6 + - libsqlite=3.50.1=hf5d6505_7 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 - libwebp-base=1.5.0=h3b0e114_0 @@ -145,7 +145,7 @@ dependencies: - zstandard=0.23.0=py310ha8f682b_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-linux-64-dev.conda.lock.yml b/environments/py-3.11-linux-64-dev.conda.lock.yml index 164bc451..cf762658 100644 --- a/environments/py-3.11-linux-64-dev.conda.lock.yml +++ b/environments/py-3.11-linux-64-dev.conda.lock.yml @@ -142,7 +142,7 @@ dependencies: - libscotch=7.0.6=hea33c07_1 - libsodium=1.0.20=h4ab18f5_0 - libspatialindex=2.0.0=he02047a_0 - - libsqlite=3.50.1=h6cd9bfd_6 + - libsqlite=3.50.1=h6cd9bfd_7 - libssh2=1.11.1=hcf80075_0 - libstdcxx=15.1.0=h8f9b012_3 - libstdcxx-ng=15.1.0=h4852527_3 @@ -205,7 +205,7 @@ dependencies: - pthread-stubs=0.4=hb9d3cd8_1002 - ptyprocess=0.7.0=pyhd8ed1ab_1 - pure_eval=0.2.3=pyhd8ed1ab_1 - - pybtex=0.25.0=pyhd8ed1ab_1 + - pybtex=0.25.1=pyhd8ed1ab_0 - pybtex-docutils=1.0.3=py311h38be061_2 - pycparser=2.22=pyh29332c3_1 - pydantic=2.11.7=pyh3cfb1c2_0 @@ -308,7 +308,7 @@ dependencies: - zstandard=0.23.0=py311h9ecbd09_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-linux-64.conda.lock.yml b/environments/py-3.11-linux-64.conda.lock.yml index 50dc8edc..d7db20af 100644 --- a/environments/py-3.11-linux-64.conda.lock.yml +++ b/environments/py-3.11-linux-64.conda.lock.yml @@ -79,7 +79,7 @@ dependencies: - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 - libspatialindex=2.0.0=he02047a_0 - - libsqlite=3.50.1=h6cd9bfd_6 + - libsqlite=3.50.1=h6cd9bfd_7 - libssh2=1.11.1=hcf80075_0 - libstdcxx=15.1.0=h8f9b012_3 - libstdcxx-ng=15.1.0=h4852527_3 @@ -159,7 +159,7 @@ dependencies: - zstandard=0.23.0=py311h9ecbd09_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-win-64-dev.conda.lock.yml b/environments/py-3.11-win-64-dev.conda.lock.yml index c7dd9846..c1f9b20a 100644 --- a/environments/py-3.11-win-64-dev.conda.lock.yml +++ b/environments/py-3.11-win-64-dev.conda.lock.yml @@ -133,7 +133,7 @@ dependencies: - libpng=1.6.49=h7a4582a_0 - libsodium=1.0.20=hc70643c_0 - libspatialindex=2.0.0=h5a68840_0 - - libsqlite=3.50.1=hf5d6505_6 + - libsqlite=3.50.1=hf5d6505_7 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 - libwebp-base=1.5.0=h3b0e114_0 @@ -188,7 +188,7 @@ dependencies: - psutil=7.0.0=py311he736701_0 - pthread-stubs=0.4=h0e40799_1002 - pure_eval=0.2.3=pyhd8ed1ab_1 - - pybtex=0.25.0=pyhd8ed1ab_1 + - pybtex=0.25.1=pyhd8ed1ab_0 - pybtex-docutils=1.0.3=py311h1ea47a8_2 - pycparser=2.22=pyh29332c3_1 - pydantic=2.11.7=pyh3cfb1c2_0 @@ -298,7 +298,7 @@ dependencies: - zstandard=0.23.0=py311he736701_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.11-win-64.conda.lock.yml b/environments/py-3.11-win-64.conda.lock.yml index 1a7b224a..9023c56a 100644 --- a/environments/py-3.11-win-64.conda.lock.yml +++ b/environments/py-3.11-win-64.conda.lock.yml @@ -69,7 +69,7 @@ dependencies: - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 - libspatialindex=2.0.0=h5a68840_0 - - libsqlite=3.50.1=hf5d6505_6 + - libsqlite=3.50.1=hf5d6505_7 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 - libwebp-base=1.5.0=h3b0e114_0 @@ -147,7 +147,7 @@ dependencies: - zstandard=0.23.0=py311he736701_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-linux-64-dev.conda.lock.yml b/environments/py-3.12-linux-64-dev.conda.lock.yml index 6b90380b..f3004131 100644 --- a/environments/py-3.12-linux-64-dev.conda.lock.yml +++ b/environments/py-3.12-linux-64-dev.conda.lock.yml @@ -142,7 +142,7 @@ dependencies: - libscotch=7.0.6=hea33c07_1 - libsodium=1.0.20=h4ab18f5_0 - libspatialindex=2.0.0=he02047a_0 - - libsqlite=3.50.1=h6cd9bfd_6 + - libsqlite=3.50.1=h6cd9bfd_7 - libssh2=1.11.1=hcf80075_0 - libstdcxx=15.1.0=h8f9b012_3 - libstdcxx-ng=15.1.0=h4852527_3 @@ -205,7 +205,7 @@ dependencies: - pthread-stubs=0.4=hb9d3cd8_1002 - ptyprocess=0.7.0=pyhd8ed1ab_1 - pure_eval=0.2.3=pyhd8ed1ab_1 - - pybtex=0.25.0=pyhd8ed1ab_1 + - pybtex=0.25.1=pyhd8ed1ab_0 - pybtex-docutils=1.0.3=py312h7900ff3_2 - pycparser=2.22=pyh29332c3_1 - pydantic=2.11.7=pyh3cfb1c2_0 @@ -308,7 +308,7 @@ dependencies: - zstandard=0.23.0=py312h66e93f0_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-linux-64.conda.lock.yml b/environments/py-3.12-linux-64.conda.lock.yml index 43604127..67fe8f49 100644 --- a/environments/py-3.12-linux-64.conda.lock.yml +++ b/environments/py-3.12-linux-64.conda.lock.yml @@ -79,7 +79,7 @@ dependencies: - libpng=1.6.49=h943b412_0 - libscotch=7.0.6=hea33c07_1 - libspatialindex=2.0.0=he02047a_0 - - libsqlite=3.50.1=h6cd9bfd_6 + - libsqlite=3.50.1=h6cd9bfd_7 - libssh2=1.11.1=hcf80075_0 - libstdcxx=15.1.0=h8f9b012_3 - libstdcxx-ng=15.1.0=h4852527_3 @@ -159,7 +159,7 @@ dependencies: - zstandard=0.23.0=py312h66e93f0_2 - zstd=1.5.7=hb8e6e7a_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-win-64-dev.conda.lock.yml b/environments/py-3.12-win-64-dev.conda.lock.yml index 8c60a2ed..9887e657 100644 --- a/environments/py-3.12-win-64-dev.conda.lock.yml +++ b/environments/py-3.12-win-64-dev.conda.lock.yml @@ -133,7 +133,7 @@ dependencies: - libpng=1.6.49=h7a4582a_0 - libsodium=1.0.20=hc70643c_0 - libspatialindex=2.0.0=h5a68840_0 - - libsqlite=3.50.1=hf5d6505_6 + - libsqlite=3.50.1=hf5d6505_7 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 - libwebp-base=1.5.0=h3b0e114_0 @@ -188,7 +188,7 @@ dependencies: - psutil=7.0.0=py312h4389bb4_0 - pthread-stubs=0.4=h0e40799_1002 - pure_eval=0.2.3=pyhd8ed1ab_1 - - pybtex=0.25.0=pyhd8ed1ab_1 + - pybtex=0.25.1=pyhd8ed1ab_0 - pybtex-docutils=1.0.3=py312h2e8e312_2 - pycparser=2.22=pyh29332c3_1 - pydantic=2.11.7=pyh3cfb1c2_0 @@ -298,7 +298,7 @@ dependencies: - zstandard=0.23.0=py312h4389bb4_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/environments/py-3.12-win-64.conda.lock.yml b/environments/py-3.12-win-64.conda.lock.yml index d952148e..fdf241ec 100644 --- a/environments/py-3.12-win-64.conda.lock.yml +++ b/environments/py-3.12-win-64.conda.lock.yml @@ -69,7 +69,7 @@ dependencies: - liblzma=5.8.1=h2466b09_2 - libpng=1.6.49=h7a4582a_0 - libspatialindex=2.0.0=h5a68840_0 - - libsqlite=3.50.1=hf5d6505_6 + - libsqlite=3.50.1=hf5d6505_7 - libssh2=1.11.1=h9aa295b_0 - libtiff=4.7.0=h05922d8_5 - libwebp-base=1.5.0=h3b0e114_0 @@ -147,7 +147,7 @@ dependencies: - zstandard=0.23.0=py312h4389bb4_2 - zstd=1.5.7=hbeecb71_2 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@99695a5e34812bfbb53cef84803033a91af137de - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@f72a1367edcb2da969002ca06f18f532340b3c27 - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@02fbd85bf7d54b8f4336f1f0094c1c3e27714e81 diff --git a/py-3.10.conda-lock.yml b/py-3.10.conda-lock.yml index acd6aa64..3600c425 100644 --- a/py-3.10.conda-lock.yml +++ b/py-3.10.conda-lock.yml @@ -3862,10 +3862,10 @@ package: __glibc: '>=2.17,<3.0.a0' libgcc: '>=13' libzlib: '>=1.3.1,<2.0a0' - url: https://repo.prefix.dev/conda-forge/linux-64/libsqlite-3.50.1-h6cd9bfd_6.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libsqlite-3.50.1-h6cd9bfd_7.conda hash: - md5: a5ea64ea2bd58803ea85e3769a659829 - sha256: 0ef71429958415129e6ae1d675006e2a6c13346d1c757665db780e4e7413d7ae + md5: c7c4888059a8324e52de475d1e7bdc53 + sha256: 9a9e5bf30178f821d4f8de25eac0ae848915bfde6a78a66ae8b77d9c33d9d0e5 category: main optional: false - name: libsqlite @@ -3876,10 +3876,10 @@ package: ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/libsqlite-3.50.1-hf5d6505_6.conda + url: https://repo.prefix.dev/conda-forge/win-64/libsqlite-3.50.1-hf5d6505_7.conda hash: - md5: c01fd2d0873bdc8d35bfa3c6eb2f54e5 - sha256: 56b8ba674b8dec6d169ee39434e68c8654e4327fd5705594fcc19625660630ad + md5: 0bc3f5143b8cb9ccf9101c2f9391c594 + sha256: 08fbdeed89ae10fb383c40f0bab3e39e3675f49700b7185a109b31e273f8762a category: main optional: false - name: libssh2 @@ -5599,7 +5599,7 @@ package: category: dev optional: true - name: pybtex - version: 0.25.0 + version: 0.25.1 manager: conda platform: linux-64 dependencies: @@ -5608,14 +5608,14 @@ package: python: '>=3.9' pyyaml: '>=3.01' setuptools: '' - url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.0-pyhd8ed1ab_1.conda + url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.1-pyhd8ed1ab_0.conda hash: - md5: 78b5c915435130d04d1f1bf3d9d42543 - sha256: 8a59892ecdc3e76e05f4a448c378bd1d6ba671f5fcab0ad9c628ab6a96f48d84 + md5: 9c25a850410220d31085173fbfdfa191 + sha256: 3053895e08ce56923e48eea7d1c07a6d8bf09948d1e69a21ae7ab9e459b0a227 category: dev optional: true - name: pybtex - version: 0.25.0 + version: 0.25.1 manager: conda platform: win-64 dependencies: @@ -5624,10 +5624,10 @@ package: python: '>=3.9' pyyaml: '>=3.01' setuptools: '' - url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.0-pyhd8ed1ab_1.conda + url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.1-pyhd8ed1ab_0.conda hash: - md5: 78b5c915435130d04d1f1bf3d9d42543 - sha256: 8a59892ecdc3e76e05f4a448c378bd1d6ba671f5fcab0ad9c628ab6a96f48d84 + md5: 9c25a850410220d31085173fbfdfa191 + sha256: 3053895e08ce56923e48eea7d1c07a6d8bf09948d1e69a21ae7ab9e459b0a227 category: dev optional: true - name: pybtex-docutils @@ -8555,12 +8555,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 hash: - sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 + sha256: ea323dc1e48634a19cca2b2693f989fae08880f1 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 category: main optional: false - name: geoapps-utils @@ -8572,12 +8572,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 hash: - sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 + sha256: ea323dc1e48634a19cca2b2693f989fae08880f1 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 category: main optional: false - name: geoh5py diff --git a/py-3.11.conda-lock.yml b/py-3.11.conda-lock.yml index 0a480c17..c434bda3 100644 --- a/py-3.11.conda-lock.yml +++ b/py-3.11.conda-lock.yml @@ -3914,10 +3914,10 @@ package: __glibc: '>=2.17,<3.0.a0' libgcc: '>=13' libzlib: '>=1.3.1,<2.0a0' - url: https://repo.prefix.dev/conda-forge/linux-64/libsqlite-3.50.1-h6cd9bfd_6.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libsqlite-3.50.1-h6cd9bfd_7.conda hash: - md5: a5ea64ea2bd58803ea85e3769a659829 - sha256: 0ef71429958415129e6ae1d675006e2a6c13346d1c757665db780e4e7413d7ae + md5: c7c4888059a8324e52de475d1e7bdc53 + sha256: 9a9e5bf30178f821d4f8de25eac0ae848915bfde6a78a66ae8b77d9c33d9d0e5 category: main optional: false - name: libsqlite @@ -3928,10 +3928,10 @@ package: ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/libsqlite-3.50.1-hf5d6505_6.conda + url: https://repo.prefix.dev/conda-forge/win-64/libsqlite-3.50.1-hf5d6505_7.conda hash: - md5: c01fd2d0873bdc8d35bfa3c6eb2f54e5 - sha256: 56b8ba674b8dec6d169ee39434e68c8654e4327fd5705594fcc19625660630ad + md5: 0bc3f5143b8cb9ccf9101c2f9391c594 + sha256: 08fbdeed89ae10fb383c40f0bab3e39e3675f49700b7185a109b31e273f8762a category: main optional: false - name: libssh2 @@ -5653,7 +5653,7 @@ package: category: dev optional: true - name: pybtex - version: 0.25.0 + version: 0.25.1 manager: conda platform: linux-64 dependencies: @@ -5662,14 +5662,14 @@ package: python: '>=3.9' pyyaml: '>=3.01' setuptools: '' - url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.0-pyhd8ed1ab_1.conda + url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.1-pyhd8ed1ab_0.conda hash: - md5: 78b5c915435130d04d1f1bf3d9d42543 - sha256: 8a59892ecdc3e76e05f4a448c378bd1d6ba671f5fcab0ad9c628ab6a96f48d84 + md5: 9c25a850410220d31085173fbfdfa191 + sha256: 3053895e08ce56923e48eea7d1c07a6d8bf09948d1e69a21ae7ab9e459b0a227 category: dev optional: true - name: pybtex - version: 0.25.0 + version: 0.25.1 manager: conda platform: win-64 dependencies: @@ -5678,10 +5678,10 @@ package: python: '>=3.9' pyyaml: '>=3.01' setuptools: '' - url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.0-pyhd8ed1ab_1.conda + url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.1-pyhd8ed1ab_0.conda hash: - md5: 78b5c915435130d04d1f1bf3d9d42543 - sha256: 8a59892ecdc3e76e05f4a448c378bd1d6ba671f5fcab0ad9c628ab6a96f48d84 + md5: 9c25a850410220d31085173fbfdfa191 + sha256: 3053895e08ce56923e48eea7d1c07a6d8bf09948d1e69a21ae7ab9e459b0a227 category: dev optional: true - name: pybtex-docutils @@ -8640,12 +8640,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 hash: - sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 + sha256: ea323dc1e48634a19cca2b2693f989fae08880f1 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 category: main optional: false - name: geoapps-utils @@ -8657,12 +8657,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 hash: - sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 + sha256: ea323dc1e48634a19cca2b2693f989fae08880f1 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 category: main optional: false - name: geoh5py diff --git a/py-3.12.conda-lock.yml b/py-3.12.conda-lock.yml index d01d78c4..08f0e359 100644 --- a/py-3.12.conda-lock.yml +++ b/py-3.12.conda-lock.yml @@ -3914,10 +3914,10 @@ package: __glibc: '>=2.17,<3.0.a0' libgcc: '>=13' libzlib: '>=1.3.1,<2.0a0' - url: https://repo.prefix.dev/conda-forge/linux-64/libsqlite-3.50.1-h6cd9bfd_6.conda + url: https://repo.prefix.dev/conda-forge/linux-64/libsqlite-3.50.1-h6cd9bfd_7.conda hash: - md5: a5ea64ea2bd58803ea85e3769a659829 - sha256: 0ef71429958415129e6ae1d675006e2a6c13346d1c757665db780e4e7413d7ae + md5: c7c4888059a8324e52de475d1e7bdc53 + sha256: 9a9e5bf30178f821d4f8de25eac0ae848915bfde6a78a66ae8b77d9c33d9d0e5 category: main optional: false - name: libsqlite @@ -3928,10 +3928,10 @@ package: ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/libsqlite-3.50.1-hf5d6505_6.conda + url: https://repo.prefix.dev/conda-forge/win-64/libsqlite-3.50.1-hf5d6505_7.conda hash: - md5: c01fd2d0873bdc8d35bfa3c6eb2f54e5 - sha256: 56b8ba674b8dec6d169ee39434e68c8654e4327fd5705594fcc19625660630ad + md5: 0bc3f5143b8cb9ccf9101c2f9391c594 + sha256: 08fbdeed89ae10fb383c40f0bab3e39e3675f49700b7185a109b31e273f8762a category: main optional: false - name: libssh2 @@ -5653,7 +5653,7 @@ package: category: dev optional: true - name: pybtex - version: 0.25.0 + version: 0.25.1 manager: conda platform: linux-64 dependencies: @@ -5662,14 +5662,14 @@ package: python: '>=3.9' pyyaml: '>=3.01' setuptools: '' - url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.0-pyhd8ed1ab_1.conda + url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.1-pyhd8ed1ab_0.conda hash: - md5: 78b5c915435130d04d1f1bf3d9d42543 - sha256: 8a59892ecdc3e76e05f4a448c378bd1d6ba671f5fcab0ad9c628ab6a96f48d84 + md5: 9c25a850410220d31085173fbfdfa191 + sha256: 3053895e08ce56923e48eea7d1c07a6d8bf09948d1e69a21ae7ab9e459b0a227 category: dev optional: true - name: pybtex - version: 0.25.0 + version: 0.25.1 manager: conda platform: win-64 dependencies: @@ -5678,10 +5678,10 @@ package: python: '>=3.9' pyyaml: '>=3.01' setuptools: '' - url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.0-pyhd8ed1ab_1.conda + url: https://repo.prefix.dev/conda-forge/noarch/pybtex-0.25.1-pyhd8ed1ab_0.conda hash: - md5: 78b5c915435130d04d1f1bf3d9d42543 - sha256: 8a59892ecdc3e76e05f4a448c378bd1d6ba671f5fcab0ad9c628ab6a96f48d84 + md5: 9c25a850410220d31085173fbfdfa191 + sha256: 3053895e08ce56923e48eea7d1c07a6d8bf09948d1e69a21ae7ab9e459b0a227 category: dev optional: true - name: pybtex-docutils @@ -8640,12 +8640,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 hash: - sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 + sha256: ea323dc1e48634a19cca2b2693f989fae08880f1 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 category: main optional: false - name: geoapps-utils @@ -8657,12 +8657,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 hash: - sha256: 8db50336926b5acf84f3c6a9c7549cb2b5af8298 + sha256: ea323dc1e48634a19cca2b2693f989fae08880f1 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@8db50336926b5acf84f3c6a9c7549cb2b5af8298 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@ea323dc1e48634a19cca2b2693f989fae08880f1 category: main optional: false - name: geoh5py From 58f9ea9863e2b1a2bd360363361b8b3cae9eba73 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Fri, 27 Jun 2025 11:46:58 -0700 Subject: [PATCH 9/9] Fix tests --- .../uijson/plate_simulation.ui.json | 4 +- tests/plate_simulation/runtest/__init__.py | 32 --- tests/plate_simulation/runtest/driver_test.py | 211 +++++------------- .../plate_simulation/runtest/gravity_test.py | 16 +- 4 files changed, 63 insertions(+), 200 deletions(-) diff --git a/simpeg_drivers-assets/uijson/plate_simulation.ui.json b/simpeg_drivers-assets/uijson/plate_simulation.ui.json index d0107c75..743d2aed 100644 --- a/simpeg_drivers-assets/uijson/plate_simulation.ui.json +++ b/simpeg_drivers-assets/uijson/plate_simulation.ui.json @@ -3,8 +3,8 @@ "title": "Plate simulation", "icon": "maxwellplate", "documentation": "https://mirageoscience-plate-simulation.readthedocs-hosted.com/en/latest/", - "conda_environment": "plate_simulation", - "run_command": "plate_simulation.driver", + "conda_environment": "simpeg_drivers", + "run_command": "simpeg_drivers.plate_simulation.driver", "geoh5": "", "monitoring_directory": "", "simulation": { diff --git a/tests/plate_simulation/runtest/__init__.py b/tests/plate_simulation/runtest/__init__.py index 24299ff9..4d06f672 100644 --- a/tests/plate_simulation/runtest/__init__.py +++ b/tests/plate_simulation/runtest/__init__.py @@ -7,35 +7,3 @@ # (see LICENSE file at the root of this source code package). ' # ' # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -import numpy as np -from geoh5py.objects import Points, Surface - - -def get_survey(workspace, n_receivers, n_lines): - X, Y = np.meshgrid( # pylint: disable=invalid-name - np.linspace(-250, 250, n_receivers), np.linspace(-250, 250, n_lines) - ) - Z = np.zeros_like(X) # pylint: disable=invalid-name - - vertices = np.c_[X.T.flatten(), Y.T.flatten(), Z.T.flatten()] - - return Points.create( - workspace, - vertices=vertices, - name="survey", - ) - - -def get_topography(workspace): - vertices = np.array( - [ - [-500.0, -500.0, 0.0], - [500.0, -500.0, 0.0], - [500.0, 500.0, 0.0], - [-500.0, 500.0, 0.0], - ] - ) - cells = np.array([[0, 1, 2], [0, 2, 3]]) - - return Surface.create(workspace, name="topo", vertices=vertices, cells=cells) diff --git a/tests/plate_simulation/runtest/driver_test.py b/tests/plate_simulation/runtest/driver_test.py index 2d0d20c2..b85d7736 100644 --- a/tests/plate_simulation/runtest/driver_test.py +++ b/tests/plate_simulation/runtest/driver_test.py @@ -7,9 +7,6 @@ # (see LICENSE file at the root of this source code package). ' # ' # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -import os -from pathlib import Path -from uuid import UUID import numpy as np from geoh5py import Workspace @@ -26,128 +23,22 @@ from simpeg_drivers.plate_simulation.models.options import ModelOptions from simpeg_drivers.plate_simulation.options import MeshOptions from simpeg_drivers.potential_fields.gravity.options import GravityForwardOptions - -from . import get_survey, get_topography - - -# pylint: disable=duplicate-code - - -def get_simulation_group(workspace: Workspace, survey: ObjectBase, topography: Surface): - tem_inversion = SimPEGGroup.create(workspace) - options = TDEMForwardOptions.model_construct() - ifile = InputFile.read_ui_json(options.default_ui_json) - options_dict = ifile.ui_json - options_dict["inversion_type"] = "tdem" - options_dict["forward_only"] = True - options_dict["geoh5"] = str(workspace.h5file) - options_dict["topography_object"]["value"] = str(topography.uid) - options_dict["data_object"]["value"] = str(survey.uid) - options_dict["x_channel_bool"] = True - options_dict["y_channel_bool"] = True - options_dict["z_channel_bool"] = True - tem_inversion.options = options_dict - - return tem_inversion - - -def get_input_file(filepath: Path) -> InputFile: - with Workspace(filepath / "test.geoh5") as ws: - with Workspace( - assets_path() / "plate_simulation_demo.geoh5", mode="r" - ) as demo_workspace: - survey = demo_workspace.get_entity("Simulation rx")[0].copy( - parent=ws, copy_children=False - ) - topography = demo_workspace.get_entity("Topography")[0].copy(parent=ws) - mask = np.zeros(survey.n_vertices, dtype=bool) - mask[::10] = True - new_survey = survey.copy(vertices=survey.vertices[mask, :], cells=None) - - simulation = get_simulation_group(ws, new_survey, topography) - ifile = InputFile.read_ui_json( - assets_path() / "uijson" / "plate_simulation.ui.json", validate=False - ) - ifile.set_data_value("name", "test_tem_plate_simulation") - ifile.set_data_value("geoh5", ws) - ifile.set_data_value("simulation", simulation) - ifile.set_data_value("u_cell_size", 50.0) - ifile.set_data_value("v_cell_size", 50.0) - ifile.set_data_value("w_cell_size", 50.0) - ifile.set_data_value("depth_core", 600.0) - ifile.set_data_value("max_distance", 200.0) - ifile.set_data_value("padding_distance", 1000.0) - ifile.set_data_value("background", 2000.0) - ifile.set_data_value("overburden", 7500.0) - ifile.set_data_value("thickness", 50.0) - ifile.set_data_value("plate", 20.0) - ifile.set_data_value("width", 100.0) - ifile.set_data_value("strike_length", 1000.0) - ifile.set_data_value("dip_length", 300.0) - ifile.set_data_value("dip", 65.0) - ifile.set_data_value("dip_direction", 65.0) - ifile.set_data_value("number", 2) - ifile.set_data_value("spacing", 600.0) - ifile.set_data_value("relative_locations", True) - ifile.set_data_value("easting", 100.0) - ifile.set_data_value("northing", 100.0) - ifile.set_data_value("elevation", -100.0) - ifile.set_data_value("reference_surface", "overburden") - ifile.set_data_value("reference_type", "min") - - return ifile - - -def test_plate_simulation(tmp_path): - mon_dir = tmp_path / "monitoring" - mon_dir.mkdir(parents=True, exist_ok=True) - - ifile = get_input_file(tmp_path) - ifile.set_data_value("monitoring_directory", str(mon_dir)) - - ifile.write_ui_json("test_plate_simulation.ui.json", path=tmp_path) - result = PlateSimulationDriver.start( - Path(tmp_path / "test_plate_simulation.ui.json") - ) - with Workspace(result.out_group.options["geoh5"]) as ws: - out_group = ws.get_entity(UUID(result.out_group.options["out_group"]["value"]))[ - 0 - ] - data = next( - obj for obj in out_group.children if isinstance(obj, AirborneTEMReceivers) - ) - mesh = next(obj for obj in out_group.children if isinstance(obj, Octree)) - model = next(k for k in mesh.children if k.name == "starting_model") - assert data.property_groups is not None - assert len(data.property_groups) == 3 - assert all( - k.name in [f"Iteration_0_{i}" for i in "xyz"] for k in data.property_groups - ) - assert all( - k.properties is not None and len(k.properties) == 20 - for k in data.property_groups - ) - assert mesh.n_cells == 16263 - assert len(np.unique(model.values)) == 4 - assert all(k in np.unique(model.values) for k in [7500, 2000, 20]) - assert any(np.isnan(np.unique(model.values))) - - # Test the monitoring directory - files = [f for f in os.listdir(mon_dir) if f.endswith("geoh5")] - assert len(files) == 1 - with Workspace(mon_dir / files[0]) as ws: - fwr_group = ws.get_entity("Tdem Forward")[0] - - # Should only contain octree, files and a survey - assert len(fwr_group.children) == 5 +from tests.testing_utils import setup_inversion_workspace # pylint: disable=too-many-statements def test_plate_simulation_params_from_input_file(tmp_path): - with Workspace(tmp_path / "test.geoh5") as ws: - topography = get_topography(ws) - survey = get_survey(ws, 10, 10) + geoh5, mesh, model, survey, topography = setup_inversion_workspace( + tmp_path, + background=0.0, + anomaly=0.0, + n_electrodes=8, + n_lines=8, + inversion_type="gravity", + flatten=False, + ) + with geoh5.open() as ws: ifile = InputFile.read_ui_json( assets_path() / "uijson" / "plate_simulation.ui.json", validate=False ) @@ -197,44 +88,42 @@ def test_plate_simulation_params_from_input_file(tmp_path): ifile.data["reference_surface"] = "topography" ifile.data["reference_type"] = "mean" - params = PlateSimulationOptions.build(ifile) - assert isinstance(params.simulation, SimPEGGroup) - - simulation_parameters = params.simulation_parameters() - - assert simulation_parameters.inversion_type == "gravity" - assert simulation_parameters.forward_only - assert simulation_parameters.geoh5.h5file == ws.h5file - assert ( - simulation_parameters.active_cells.topography_object.uid == topography.uid - ) - assert simulation_parameters.data_object.uid == survey.uid - - assert isinstance(params.mesh, MeshOptions) - assert params.mesh.u_cell_size == 10.0 - assert params.mesh.v_cell_size == 10.0 - assert params.mesh.w_cell_size == 10.0 - assert params.mesh.depth_core == 400.0 - assert params.mesh.max_distance == 200.0 - assert params.mesh.padding_distance == 1500.0 - assert params.mesh.minimum_level == 8 - assert not params.mesh.diagonal_balance - - assert isinstance(params.model, ModelOptions) - assert params.model.plate_model.name == "test_gravity_plate_simulation" - assert params.model.background == 1000.0 - assert params.model.overburden_model.thickness == 50.0 - assert params.model.overburden_model.overburden == 5.0 - assert params.model.plate_model.plate == 2.0 - assert params.model.plate_model.width == 100.0 - assert params.model.plate_model.strike_length == 100.0 - assert params.model.plate_model.dip_length == 100.0 - assert params.model.plate_model.dip == 0.0 - assert params.model.plate_model.dip_direction == 0.0 - - assert params.model.plate_model.number == 9 - assert params.model.plate_model.spacing == 10.0 - assert params.model.plate_model.relative_locations - assert params.model.plate_model.easting == 10.0 - assert params.model.plate_model.northing == 10.0 - assert params.model.plate_model.elevation == -250.0 + params = PlateSimulationOptions.build(ifile) + assert isinstance(params.simulation, SimPEGGroup) + + simulation_parameters = params.simulation_parameters() + + assert simulation_parameters.inversion_type == "gravity" + assert simulation_parameters.forward_only + assert simulation_parameters.geoh5.h5file == ws.h5file + assert simulation_parameters.active_cells.topography_object.uid == topography.uid + assert simulation_parameters.data_object.uid == survey.uid + + assert isinstance(params.mesh, MeshOptions) + assert params.mesh.u_cell_size == 10.0 + assert params.mesh.v_cell_size == 10.0 + assert params.mesh.w_cell_size == 10.0 + assert params.mesh.depth_core == 400.0 + assert params.mesh.max_distance == 200.0 + assert params.mesh.padding_distance == 1500.0 + assert params.mesh.minimum_level == 8 + assert not params.mesh.diagonal_balance + + assert isinstance(params.model, ModelOptions) + assert params.model.plate_model.name == "test_gravity_plate_simulation" + assert params.model.background == 1000.0 + assert params.model.overburden_model.thickness == 50.0 + assert params.model.overburden_model.overburden == 5.0 + assert params.model.plate_model.plate == 2.0 + assert params.model.plate_model.width == 100.0 + assert params.model.plate_model.strike_length == 100.0 + assert params.model.plate_model.dip_length == 100.0 + assert params.model.plate_model.dip == 0.0 + assert params.model.plate_model.dip_direction == 0.0 + + assert params.model.plate_model.number == 9 + assert params.model.plate_model.spacing == 10.0 + assert params.model.plate_model.relative_locations + assert params.model.plate_model.easting == 10.0 + assert params.model.plate_model.northing == 10.0 + assert params.model.plate_model.elevation == -250.0 diff --git a/tests/plate_simulation/runtest/gravity_test.py b/tests/plate_simulation/runtest/gravity_test.py index fc228ddc..40d796ab 100644 --- a/tests/plate_simulation/runtest/gravity_test.py +++ b/tests/plate_simulation/runtest/gravity_test.py @@ -20,15 +20,21 @@ ) from simpeg_drivers.plate_simulation.options import MeshOptions, PlateSimulationOptions from simpeg_drivers.potential_fields.gravity.options import GravityForwardOptions - -from . import get_survey, get_topography +from tests.testing_utils import setup_inversion_workspace def test_gravity_plate_simulation(tmp_path): - with Workspace(tmp_path / "test.geoh5") as ws: - topography = get_topography(ws) - survey = get_survey(ws, 10, 10) + geoh5, mesh, model, survey, topography = setup_inversion_workspace( + tmp_path, + background=0.0, + anomaly=0.0, + n_electrodes=8, + n_lines=8, + inversion_type="gravity", + flatten=False, + ) + with geoh5.open() as ws: mesh_params = MeshOptions( u_cell_size=10.0, v_cell_size=10.0,