diff --git a/simpeg_drivers-assets/uijson/apparent_conductivity_forward.ui.json b/simpeg_drivers-assets/uijson/apparent_conductivity_forward.ui.json
index 0007c916..b22c6220 100644
--- a/simpeg_drivers-assets/uijson/apparent_conductivity_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/apparent_conductivity_forward.ui.json
@@ -129,9 +129,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/apparent_conductivity_inversion.ui.json b/simpeg_drivers-assets/uijson/apparent_conductivity_inversion.ui.json
index 9bb5f5fe..442635e7 100644
--- a/simpeg_drivers-assets/uijson/apparent_conductivity_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/apparent_conductivity_inversion.ui.json
@@ -514,9 +514,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/direct_current_3d_forward.ui.json b/simpeg_drivers-assets/uijson/direct_current_3d_forward.ui.json
index ce8f6673..d665b31d 100644
--- a/simpeg_drivers-assets/uijson/direct_current_3d_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/direct_current_3d_forward.ui.json
@@ -123,9 +123,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/direct_current_3d_inversion.ui.json b/simpeg_drivers-assets/uijson/direct_current_3d_inversion.ui.json
index b6c83cfd..e70dcb90 100644
--- a/simpeg_drivers-assets/uijson/direct_current_3d_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/direct_current_3d_inversion.ui.json
@@ -499,9 +499,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/fdem1d_forward.ui.json b/simpeg_drivers-assets/uijson/fdem1d_forward.ui.json
index 11512518..e769de08 100644
--- a/simpeg_drivers-assets/uijson/fdem1d_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/fdem1d_forward.ui.json
@@ -178,9 +178,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/fdem1d_inversion.ui.json b/simpeg_drivers-assets/uijson/fdem1d_inversion.ui.json
index 88f68149..4189adfc 100644
--- a/simpeg_drivers-assets/uijson/fdem1d_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/fdem1d_inversion.ui.json
@@ -538,9 +538,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/fdem_forward.ui.json b/simpeg_drivers-assets/uijson/fdem_forward.ui.json
index a60b92c8..7bfc2251 100644
--- a/simpeg_drivers-assets/uijson/fdem_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/fdem_forward.ui.json
@@ -188,9 +188,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/fdem_inversion.ui.json b/simpeg_drivers-assets/uijson/fdem_inversion.ui.json
index ca2cdc3f..b6c9ba17 100644
--- a/simpeg_drivers-assets/uijson/fdem_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/fdem_inversion.ui.json
@@ -697,9 +697,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/gravity_forward.ui.json b/simpeg_drivers-assets/uijson/gravity_forward.ui.json
index b844d141..6b27f175 100644
--- a/simpeg_drivers-assets/uijson/gravity_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/gravity_forward.ui.json
@@ -170,9 +170,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/gravity_inversion.ui.json b/simpeg_drivers-assets/uijson/gravity_inversion.ui.json
index 8993ad5a..a5b1c119 100644
--- a/simpeg_drivers-assets/uijson/gravity_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/gravity_inversion.ui.json
@@ -16,7 +16,9 @@
"{6a057fdc-b355-11e3-95be-fd84a7ffcb88}",
"{f26feba3-aded-494b-b9e9-b2bbcbe298e1}",
"{48f5054a-1c5c-4ca4-9048-80f36dc60a06}",
- "{b020a277-90e2-4cd7-84d6-612ee3f25051}"
+ "{b020a277-90e2-4cd7-84d6-612ee3f25051}",
+ "{b54f6be6-0eb5-4a4e-887a-ba9d276f9a83}",
+ "{5ffa3816-358d-4cdd-9b7d-e1f7f5543e05}"
],
"value": ""
},
@@ -758,14 +760,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
- "dataType": "Float",
- "association": [
- "Vertex",
- "Cell"
- ],
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json
index e8624d25..2e3ab944 100644
--- a/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json
@@ -537,7 +537,16 @@
"tooltip": "Direct solver to use for the forward calculations",
"value": "Pardiso"
},
- "tile_spatial": 1,
+ "tile_spatial": {
+ "group": "Compute",
+ "label": "Number of tiles",
+ "value": 1,
+ "min": 1,
+ "max": 1000,
+ "verbose": 2,
+ "visible": false,
+ "tooltip": "Splits the objective function into spatial tiles for distributed computation using the Dask library"
+ },
"store_sensitivities": {
"choiceList": [
"disk",
diff --git a/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json
index d4da081f..0a5c387c 100644
--- a/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json
@@ -139,9 +139,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json
index 1b337393..98f24f36 100644
--- a/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json
@@ -515,9 +515,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/magnetic_scalar_forward.ui.json b/simpeg_drivers-assets/uijson/magnetic_scalar_forward.ui.json
index c4b5d03b..f480bae4 100644
--- a/simpeg_drivers-assets/uijson/magnetic_scalar_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetic_scalar_forward.ui.json
@@ -200,9 +200,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/magnetic_scalar_inversion.ui.json b/simpeg_drivers-assets/uijson/magnetic_scalar_inversion.ui.json
index d3013771..2bd033de 100644
--- a/simpeg_drivers-assets/uijson/magnetic_scalar_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetic_scalar_inversion.ui.json
@@ -791,9 +791,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/magnetic_vector_forward.ui.json b/simpeg_drivers-assets/uijson/magnetic_vector_forward.ui.json
index 0020bbdc..f5950069 100644
--- a/simpeg_drivers-assets/uijson/magnetic_vector_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetic_vector_forward.ui.json
@@ -46,7 +46,9 @@
"{6a057fdc-b355-11e3-95be-fd84a7ffcb88}",
"{f26feba3-aded-494b-b9e9-b2bbcbe298e1}",
"{48f5054a-1c5c-4ca4-9048-80f36dc60a06}",
- "{b020a277-90e2-4cd7-84d6-612ee3f25051}"
+ "{b020a277-90e2-4cd7-84d6-612ee3f25051}",
+ "{4b99204c-d133-4579-a916-a9c8b98cfccb}",
+ "{028e4905-cc97-4dab-b1bf-d76f58b501b5}"
],
"value": "",
"optional": true,
@@ -98,8 +100,7 @@
"{f26feba3-aded-494b-b9e9-b2bbcbe298e1}",
"{48f5054a-1c5c-4ca4-9048-80f36dc60a06}",
"{b020a277-90e2-4cd7-84d6-612ee3f25051}",
- "{4b99204c-d133-4579-a916-a9c8b98cfccb}",
- "{028e4905-cc97-4dab-b1bf-d76f58b501b5}"
+ "{4b99204c-d133-4579-a916-a9c8b98cfccb}"
],
"value": ""
},
@@ -232,9 +233,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/magnetic_vector_inversion.ui.json b/simpeg_drivers-assets/uijson/magnetic_vector_inversion.ui.json
index 891be062..ea9cad09 100644
--- a/simpeg_drivers-assets/uijson/magnetic_vector_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetic_vector_inversion.ui.json
@@ -839,9 +839,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/magnetic_vector_pde_forward.ui.json b/simpeg_drivers-assets/uijson/magnetic_vector_pde_forward.ui.json
index 1405802b..d7d10023 100644
--- a/simpeg_drivers-assets/uijson/magnetic_vector_pde_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetic_vector_pde_forward.ui.json
@@ -46,7 +46,8 @@
"{6a057fdc-b355-11e3-95be-fd84a7ffcb88}",
"{f26feba3-aded-494b-b9e9-b2bbcbe298e1}",
"{48f5054a-1c5c-4ca4-9048-80f36dc60a06}",
- "{b020a277-90e2-4cd7-84d6-612ee3f25051}"
+ "{b020a277-90e2-4cd7-84d6-612ee3f25051}",
+ "{028e4905-cc97-4dab-b1bf-d76f58b501b5}"
],
"value": "",
"optional": true,
@@ -98,8 +99,7 @@
"{f26feba3-aded-494b-b9e9-b2bbcbe298e1}",
"{48f5054a-1c5c-4ca4-9048-80f36dc60a06}",
"{b020a277-90e2-4cd7-84d6-612ee3f25051}",
- "{4b99204c-d133-4579-a916-a9c8b98cfccb}",
- "{028e4905-cc97-4dab-b1bf-d76f58b501b5}"
+ "{4b99204c-d133-4579-a916-a9c8b98cfccb}"
],
"value": ""
},
@@ -196,13 +196,11 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
"verbose": 2,
+ "visible": false,
"tooltip": "Splits the objective function into spatial tiles for distributed computation using the Dask library"
},
"max_chunk_size": {
diff --git a/simpeg_drivers-assets/uijson/magnetic_vector_pde_inversion.ui.json b/simpeg_drivers-assets/uijson/magnetic_vector_pde_inversion.ui.json
index 8ef6fbb8..a8cabc48 100644
--- a/simpeg_drivers-assets/uijson/magnetic_vector_pde_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetic_vector_pde_inversion.ui.json
@@ -627,13 +627,11 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
"verbose": 2,
+ "visible": false,
"tooltip": "Splits the objective function into spatial tiles for distributed computation using the Dask library"
},
"out_group": {
diff --git a/simpeg_drivers-assets/uijson/magnetotellurics_forward.ui.json b/simpeg_drivers-assets/uijson/magnetotellurics_forward.ui.json
index 2790747c..4fe8895e 100644
--- a/simpeg_drivers-assets/uijson/magnetotellurics_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetotellurics_forward.ui.json
@@ -177,9 +177,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/magnetotellurics_inversion.ui.json b/simpeg_drivers-assets/uijson/magnetotellurics_inversion.ui.json
index 72a4df81..4c16a597 100644
--- a/simpeg_drivers-assets/uijson/magnetotellurics_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/magnetotellurics_inversion.ui.json
@@ -728,9 +728,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/plate_sweep.ui.json b/simpeg_drivers-assets/uijson/plate_sweep.ui.json
index ffe4c361..6673d41e 100644
--- a/simpeg_drivers-assets/uijson/plate_sweep.ui.json
+++ b/simpeg_drivers-assets/uijson/plate_sweep.ui.json
@@ -23,10 +23,9 @@
"main": true,
"group": "Base",
"label": "Output directory",
- "directoryOnly": true,
"enabled": false,
"optional": true,
- "tootip": "Directory to store simulation results, relative to the working geoh5.",
+ "tooltip": "Directory to store simulation results, relative to the working geoh5.",
"value": "./simulations"
},
"generate_summary": {
@@ -34,7 +33,7 @@
"group": "Base",
"label": "Generate summary file (.xlsx)",
"enabled": true,
- "tootip": "Create an xlsx file summarizing the parameters of all simulations found in the 'Output directory'.",
+ "tooltip": "Create an xlsx file summarizing the parameters of all simulations found in the 'Output directory'.",
"value": true
},
"background_start": {
diff --git a/simpeg_drivers-assets/uijson/tdem1d_forward.ui.json b/simpeg_drivers-assets/uijson/tdem1d_forward.ui.json
index a030eec2..c90c5e6d 100644
--- a/simpeg_drivers-assets/uijson/tdem1d_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/tdem1d_forward.ui.json
@@ -34,7 +34,7 @@
"
WireCurrent * number of turns (NI).",
""
],
- "value": "dB/dt (T/s)"
+ "value": "Airborne dB/dt (V/Am^4)"
},
"z_channel_bool": {
"group": "Survey",
@@ -192,9 +192,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/tdem1d_inversion.ui.json b/simpeg_drivers-assets/uijson/tdem1d_inversion.ui.json
index 53ade0fd..694e9c6b 100644
--- a/simpeg_drivers-assets/uijson/tdem1d_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/tdem1d_inversion.ui.json
@@ -34,7 +34,7 @@
"WireCurrent * number of turns (NI).",
""
],
- "value": "dB/dt (T/s)"
+ "value": "Airborne dB/dt (V/Am^4)"
},
"z_channel": {
"association": [
@@ -520,9 +520,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/tdem_forward.ui.json b/simpeg_drivers-assets/uijson/tdem_forward.ui.json
index 5b85136e..dbc2d85f 100644
--- a/simpeg_drivers-assets/uijson/tdem_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/tdem_forward.ui.json
@@ -56,7 +56,7 @@
"WireCurrent * number of turns (NI).",
""
],
- "value": "dB/dt (T/s)"
+ "value": "Airborne dB/dt (V/Am^4)"
},
"vertical_channel_bool": {
"group": "Survey",
@@ -187,9 +187,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/tdem_inversion.ui.json
index 10d4fc85..340a04d3 100644
--- a/simpeg_drivers-assets/uijson/tdem_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/tdem_inversion.ui.json
@@ -56,7 +56,7 @@
"WireCurrent * number of turns (NI).",
""
],
- "value": "dB/dt (T/s)"
+ "value": "Airborne dB/dt (V/Am^4)"
},
"vertical_channel": {
"association": [
@@ -604,9 +604,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/tipper_forward.ui.json b/simpeg_drivers-assets/uijson/tipper_forward.ui.json
index 7794a830..76d5d7c0 100644
--- a/simpeg_drivers-assets/uijson/tipper_forward.ui.json
+++ b/simpeg_drivers-assets/uijson/tipper_forward.ui.json
@@ -153,9 +153,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers-assets/uijson/tipper_inversion.ui.json b/simpeg_drivers-assets/uijson/tipper_inversion.ui.json
index 7e9c8be4..d0d22783 100644
--- a/simpeg_drivers-assets/uijson/tipper_inversion.ui.json
+++ b/simpeg_drivers-assets/uijson/tipper_inversion.ui.json
@@ -608,9 +608,6 @@
"tile_spatial": {
"group": "Compute",
"label": "Number of tiles",
- "parent": "data_object",
- "isValue": true,
- "property": "",
"value": 1,
"min": 1,
"max": 1000,
diff --git a/simpeg_drivers/depth_of_investigation/sensitivity_cutoff/options.py b/simpeg_drivers/depth_of_investigation/sensitivity_cutoff/options.py
index a284eb41..f70cec3e 100644
--- a/simpeg_drivers/depth_of_investigation/sensitivity_cutoff/options.py
+++ b/simpeg_drivers/depth_of_investigation/sensitivity_cutoff/options.py
@@ -37,6 +37,7 @@ class SensitivityCutoffOptions(Options):
)
title: str = "Depth of Investigation: Sensitivity Cutoff"
+ icon: str = "grd"
run_command: str = "simpeg_drivers.depth_of_investigation.sensitivity_cutoff.driver"
conda_environment: str = "simpeg_drivers"
diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py
index 91e3df00..4fb1b058 100644
--- a/simpeg_drivers/driver.py
+++ b/simpeg_drivers/driver.py
@@ -14,7 +14,7 @@
from __future__ import annotations
from abc import abstractmethod, ABC
-
+from typing import Self
from copy import deepcopy
import sys
from datetime import datetime, timedelta
@@ -29,9 +29,11 @@
from geoapps_utils.run import load_ui_json_as_dict
from geoapps_utils.utils.importing import GeoAppsError
+from geoh5py import Workspace
from geoh5py.groups import SimPEGGroup
from geoh5py.objects import FEMSurvey
from geoh5py.shared.utils import fetch_active_workspace
+from geoh5py.ui_json import BaseUIJson
from simpeg import (
directives,
@@ -68,6 +70,7 @@
BaseInversionOptions,
)
from simpeg_drivers.joint.options import BaseJointOptions
+from simpeg_drivers.uijson import SimPEGDriversUIJson
from simpeg_drivers.utils.nested import tile_locations
from simpeg_drivers.utils.regularization import cell_neighbors, set_rotated_operators
from simpeg_drivers.utils.utils import (
@@ -489,6 +492,46 @@ def run(self):
with fetch_active_workspace(self.workspace, mode="r+"):
self.directives.save_iteration_log_files.write(1)
+ @classmethod
+ def start(cls, filepath: str | Path | BaseUIJson, mode="r+", **kwargs) -> Self:
+ """
+ Run application specified by 'filepath' ui.json file.
+
+ TODO: To be replaced by the base Driver class implementation on geoapps_utils
+ :param filepath: Path to valid ui.json file for the application driver.
+ :param mode: Mode to open the geoh5 file with.
+ :param kwargs: Additional keyword arguments for Options class.
+
+ :return: Self object.
+ """
+
+ uijson = (
+ SimPEGDriversUIJson.read(filepath)
+ if isinstance(filepath, str | Path)
+ else filepath
+ )
+
+ if not isinstance(uijson, BaseUIJson):
+ raise TypeError("Input file must be a string path or a BaseUIJson object.")
+
+ if uijson.geoh5 is None:
+ raise GeoAppsError("The application needs a valid 'geoh5' file.")
+
+ with Workspace(uijson.geoh5, mode=mode) as workspace:
+ try:
+ data = uijson.to_params(workspace)
+ kwargs.update(data)
+ params = cls._params_class.build(workspace=workspace, **kwargs)
+ driver = cls(params)
+ driver.run()
+ except GeoAppsError as error:
+ logging.getLogger(__name__).warning(
+ "\n\nApplicationError: %s\n\n", error
+ )
+ sys.exit(1)
+
+ return driver
+
@classmethod
def start_dask_run(
cls, json_path: Path, n_workers: int | None = None, n_threads: int | None = None
diff --git a/simpeg_drivers/electricals/base_2d.py b/simpeg_drivers/electricals/base_2d.py
index 3f0cf079..b5a4553b 100644
--- a/simpeg_drivers/electricals/base_2d.py
+++ b/simpeg_drivers/electricals/base_2d.py
@@ -14,9 +14,10 @@
from logging import getLogger
import numpy as np
+from geoh5py.data import FloatData
from geoh5py.objects import DrapeModel, Octree, PotentialElectrode
from geoh5py.ui_json.ui_json import fetch_active_workspace
-from pydantic import field_validator, model_validator
+from pydantic import AliasChoices, Field, field_validator, model_validator
from simpeg_drivers.components.meshes import InversionMesh
from simpeg_drivers.driver import BaseDriver
@@ -24,6 +25,8 @@
CoreOptions,
DrapeModelOptions,
LineSelectionOptions,
+ ModelOptions,
+ ModelTypeEnum,
)
from simpeg_drivers.utils.surveys import (
create_mesh_by_line_id,
@@ -34,6 +37,26 @@
logger = getLogger(__name__)
+class Conductivity2DModelOptions(ModelOptions):
+ """
+ Options for the conductivity model of 2D inverse problems.
+
+ :param conductivity_model: Conductivity model or background conductivity value.
+ :param model_type: Either a 'conductivity' or 'resistivity' model. The default is 'conductivity'.
+ :param length_scale_y: Overloads length scales in y direction since not used in 2D inversions.
+ :param y_norm: Overloads norm in the y direction since not used in 2D inversions.
+ """
+
+ model_type: ModelTypeEnum = ModelTypeEnum.conductivity
+ conductivity_model: float | FloatData | None = Field(
+ None,
+ validation_alias=AliasChoices("background_conductivity", "conductivity_model"),
+ )
+
+ length_scale_y: None = None
+ y_norm: None = None
+
+
class Base2DOptions(CoreOptions):
"""
Base options for the Direct Current 2D forward and inverse driver.
diff --git a/simpeg_drivers/electricals/direct_current/three_dimensions/options.py b/simpeg_drivers/electricals/direct_current/three_dimensions/options.py
index 728fa663..259a4260 100644
--- a/simpeg_drivers/electricals/direct_current/three_dimensions/options.py
+++ b/simpeg_drivers/electricals/direct_current/three_dimensions/options.py
@@ -40,6 +40,7 @@ class DC3DForwardOptions(BaseForwardOptions):
"simpeg_drivers.electricals.direct_current.three_dimensions.forward"
)
title: str = "Direct Current 3D Forward"
+ icon: str = "PotentialElectrode"
physical_property: str = "conductivity"
inversion_type: str = "direct current 3d"
@@ -64,6 +65,7 @@ class DC3DInversionOptions(BaseInversionOptions):
"simpeg_drivers.electricals.direct_current.three_dimensions.inversion"
)
title: str = "Direct Current 3D Inversion"
+ icon: str = "PotentialElectrode"
physical_property: str = "conductivity"
inversion_type: str = "direct current 3d"
diff --git a/simpeg_drivers/electricals/direct_current/two_dimensions/options.py b/simpeg_drivers/electricals/direct_current/two_dimensions/options.py
index d60b882a..5c2cf09c 100644
--- a/simpeg_drivers/electricals/direct_current/two_dimensions/options.py
+++ b/simpeg_drivers/electricals/direct_current/two_dimensions/options.py
@@ -17,12 +17,8 @@
from geoh5py.data import FloatData
from simpeg_drivers import assets_path
-from simpeg_drivers.electricals.base_2d import Base2DOptions
-from simpeg_drivers.options import (
- BaseForwardOptions,
- BaseInversionOptions,
- ConductivityModelOptions,
-)
+from simpeg_drivers.electricals.base_2d import Base2DOptions, Conductivity2DModelOptions
+from simpeg_drivers.options import BaseForwardOptions, BaseInversionOptions
class DC2DForwardOptions(BaseForwardOptions, Base2DOptions):
@@ -38,11 +34,12 @@ class DC2DForwardOptions(BaseForwardOptions, Base2DOptions):
)
title: str = "Direct Current 2D Forward"
+ icon: str = "PotentialElectrode"
physical_property: str = "conductivity"
inversion_type: str = "direct current 2d"
potential_channel_bool: bool = True
- models: ConductivityModelOptions
+ models: Conductivity2DModelOptions
class DC2DInversionOptions(BaseInversionOptions, Base2DOptions):
@@ -59,11 +56,11 @@ class DC2DInversionOptions(BaseInversionOptions, Base2DOptions):
default_ui_json: ClassVar[Path] = (
assets_path() / "uijson/direct_current_2d_inversion.ui.json"
)
-
+ icon: str = "PotentialElectrode"
title: str = "Direct Current 2D Inversion"
physical_property: str = "conductivity"
inversion_type: str = "direct current 2d"
potential_channel: FloatData
potential_uncertainty: float | FloatData | None = None
- models: ConductivityModelOptions
+ models: Conductivity2DModelOptions
diff --git a/simpeg_drivers/electricals/induced_polarization/three_dimensions/options.py b/simpeg_drivers/electricals/induced_polarization/three_dimensions/options.py
index 780e256a..b9449a5d 100644
--- a/simpeg_drivers/electricals/induced_polarization/three_dimensions/options.py
+++ b/simpeg_drivers/electricals/induced_polarization/three_dimensions/options.py
@@ -36,8 +36,8 @@ class IP3DForwardOptions(BaseForwardOptions):
default_ui_json: ClassVar[Path] = (
assets_path() / "uijson/induced_polarization_3d_forward.ui.json"
)
-
title: str = "Induced Polarization 3D Forward"
+ icon: str = "PotentialElectrode"
physical_property: str = "chargeability"
inversion_type: str = "induced polarization 3d"
@@ -58,8 +58,8 @@ class IP3DInversionOptions(BaseInversionOptions):
default_ui_json: ClassVar[Path] = (
assets_path() / "uijson/induced_polarization_3d_inversion.ui.json"
)
-
title: str = "Induced Polarization 3D Inversion"
+ icon: str = "PotentialElectrode"
physical_property: str = "chargeability"
inversion_type: str = "induced polarization 3d"
diff --git a/simpeg_drivers/electricals/induced_polarization/two_dimensions/options.py b/simpeg_drivers/electricals/induced_polarization/two_dimensions/options.py
index b92fcfcd..444caafe 100644
--- a/simpeg_drivers/electricals/induced_polarization/two_dimensions/options.py
+++ b/simpeg_drivers/electricals/induced_polarization/two_dimensions/options.py
@@ -39,6 +39,7 @@ class IP2DForwardOptions(BaseForwardOptions, Base2DOptions):
)
title: str = "Induced Polarization 2D Forward"
+ icon: str = "PotentialElectrode"
physical_property: str = "chargeability"
inversion_type: str = "induced polarization 2d"
@@ -61,6 +62,7 @@ class IP2DInversionOptions(BaseInversionOptions, Base2DOptions):
)
title: str = "Induced Polarization 2D Inversion"
+ icon: str = "PotentialElectrode"
physical_property: str = "chargeability"
inversion_type: str = "induced polarization 2d"
diff --git a/simpeg_drivers/electromagnetics/frequency_domain/options.py b/simpeg_drivers/electromagnetics/frequency_domain/options.py
index b8cdaa15..19bd5a0a 100644
--- a/simpeg_drivers/electromagnetics/frequency_domain/options.py
+++ b/simpeg_drivers/electromagnetics/frequency_domain/options.py
@@ -99,6 +99,7 @@ class FDEMForwardOptions(BaseForwardOptions, BaseFDEMOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/fdem_forward.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.frequency_domain.forward"
title: str = "Frequency-domain EM (FEM) Forward"
+ icon: str = "surveyairborneem"
physical_property: str = "conductivity"
inversion_type: str = "fdem"
@@ -170,6 +171,7 @@ class FDEMInversionOptions(BaseFDEMOptions, BaseInversionOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/fdem_inversion.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.frequency_domain.inversion"
title: str = "Frequency-domain EM (FEM) Inversion"
+ icon: str = "surveyairborneem"
physical_property: str = "conductivity"
inversion_type: str = "fdem"
diff --git a/simpeg_drivers/electromagnetics/frequency_domain_1d/options.py b/simpeg_drivers/electromagnetics/frequency_domain_1d/options.py
index c8ecc957..ddc2f34d 100644
--- a/simpeg_drivers/electromagnetics/frequency_domain_1d/options.py
+++ b/simpeg_drivers/electromagnetics/frequency_domain_1d/options.py
@@ -42,6 +42,7 @@ class FDEM1DForwardOptions(BaseForwardOptions, BaseFDEMOptions, Base1DOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/fdem1d_forward.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.frequency_domain_1d.forward"
title: str = "Frequency-domain EM-1D (FEM-1D) Forward"
+ icon: str = "surveyairborneem"
physical_property: str = "conductivity"
inversion_type: str = "fdem 1d"
data_object: AirborneFEMReceivers
@@ -75,6 +76,7 @@ class FDEM1DInversionOptions(BaseFDEMOptions, BaseInversionOptions, Base1DOption
default_ui_json: ClassVar[Path] = assets_path() / "uijson/fdem1d_inversion.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.frequency_domain_1d.inversion"
title: str = "Frequency-domain EM-1D (FEM-1D) Inversion"
+ icon: str = "surveyairborneem"
physical_property: str = "conductivity"
inversion_type: str = "fdem 1d"
diff --git a/simpeg_drivers/electromagnetics/time_domain/options.py b/simpeg_drivers/electromagnetics/time_domain/options.py
index 17776658..f3da99f1 100644
--- a/simpeg_drivers/electromagnetics/time_domain/options.py
+++ b/simpeg_drivers/electromagnetics/time_domain/options.py
@@ -87,6 +87,7 @@ class TDEMForwardOptions(BaseTDEMOptions, BaseForwardOptions):
run_command: str = "simpeg_drivers.electromagnetics.time_domain.forward"
title: str = "Time-domain EM (TEM) Forward"
+ icon: str = "surveyairborneem"
physical_property: str = "conductivity"
inversion_type: str = "tdem"
@@ -124,6 +125,7 @@ class TDEMInversionOptions(BaseTDEMOptions, BaseInversionOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/tdem_inversion.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.time_domain.inversion"
title: str = "Time-domain EM (TEM) Inversion"
+ icon: str = "surveyairborneem"
physical_property: str = "conductivity"
inversion_type: str = "tdem"
diff --git a/simpeg_drivers/electromagnetics/time_domain_1d/options.py b/simpeg_drivers/electromagnetics/time_domain_1d/options.py
index f934ab83..37ce088a 100644
--- a/simpeg_drivers/electromagnetics/time_domain_1d/options.py
+++ b/simpeg_drivers/electromagnetics/time_domain_1d/options.py
@@ -40,6 +40,7 @@ class TDEM1DForwardOptions(TDEMForwardOptions, Base1DOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/tdem1d_forward.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.time_domain_1d.forward"
title: str = "Time-domain EM-1D (TEM-1D) Forward"
+ icon: str = "surveyairborneem"
inversion_type: str = "tdem 1d"
vertical_channel_bool: bool = Field(
@@ -60,6 +61,7 @@ class TDEM1DInversionOptions(TDEMInversionOptions, Base1DOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/tdem1d_inversion.ui.json"
run_command: str = "simpeg_drivers.electromagnetics.time_domain_1d.inversion"
title: str = "Time-domain EM-1D (TEM-1D) Inversion"
+ icon: str = "surveyairborneem"
inversion_type: str = "tdem 1d"
vertical_channel: PropertyGroup | None = Field(
diff --git a/simpeg_drivers/joint/joint_cross_gradient/options.py b/simpeg_drivers/joint/joint_cross_gradient/options.py
index f4f39698..3480ed58 100644
--- a/simpeg_drivers/joint/joint_cross_gradient/options.py
+++ b/simpeg_drivers/joint/joint_cross_gradient/options.py
@@ -38,6 +38,7 @@ class JointCrossGradientOptions(BaseJointOptions):
)
run_command: str = "simpeg_drivers.joint.joint_cross_gradient.driver"
title: str = "Joint Cross Gradient Inversion"
+ icon: str = "function"
inversion_type: str = "joint cross gradient"
mesh: Octree | None = None
diff --git a/simpeg_drivers/joint/joint_petrophysics/options.py b/simpeg_drivers/joint/joint_petrophysics/options.py
index 399abc86..2e1a2488 100644
--- a/simpeg_drivers/joint/joint_petrophysics/options.py
+++ b/simpeg_drivers/joint/joint_petrophysics/options.py
@@ -48,6 +48,7 @@ class JointPetrophysicsOptions(BaseJointOptions):
)
run_command: str = "simpeg_drivers.joint.joint_petrophysics.driver"
title: str = "Joint Petrophysically Guided Inversion (PGI)"
+ icon: str = "referencedata"
inversion_type: str = "joint petrophysics"
group_a_multiplier: float | None = None
diff --git a/simpeg_drivers/joint/joint_surveys/options.py b/simpeg_drivers/joint/joint_surveys/options.py
index 5acc7b21..4fc92c9d 100644
--- a/simpeg_drivers/joint/joint_surveys/options.py
+++ b/simpeg_drivers/joint/joint_surveys/options.py
@@ -45,6 +45,7 @@ class JointSurveysOptions(BaseJointOptions):
)
run_command: str = "simpeg_drivers.joint.joint_surveys.driver"
title: str = "Joint Surveys Inversion"
+ icon: str = "model"
inversion_type: str = "joint surveys"
models: JointSurveysModelOptions
diff --git a/simpeg_drivers/natural_sources/apparent_conductivity/options.py b/simpeg_drivers/natural_sources/apparent_conductivity/options.py
index 832f3b67..ad425291 100644
--- a/simpeg_drivers/natural_sources/apparent_conductivity/options.py
+++ b/simpeg_drivers/natural_sources/apparent_conductivity/options.py
@@ -38,6 +38,7 @@ class AppConForwardOptions(EMDataMixin, BaseForwardOptions):
)
run_command: str = "simpeg_drivers.natural_sources.apparent_conductivity.forward"
title: str = "Apparent Conductivity Forward"
+ icon: str = "surveyztem"
physical_property: str = "conductivity"
inversion_type: str = "apparent conductivity"
app_con_channel_bool: bool = True
@@ -59,6 +60,7 @@ class AppConInversionOptions(EMDataMixin, BaseInversionOptions):
)
run_command: str = "simpeg_drivers.natural_sources.apparent_conductivity.inversion"
title: str = "Apparent Conductivity Inversion"
+ icon: str = "surveyztem"
physical_property: str = "conductivity"
inversion_type: str = "apparent conductivity"
diff --git a/simpeg_drivers/natural_sources/magnetotellurics/options.py b/simpeg_drivers/natural_sources/magnetotellurics/options.py
index 60911bb1..3e1d64f0 100644
--- a/simpeg_drivers/natural_sources/magnetotellurics/options.py
+++ b/simpeg_drivers/natural_sources/magnetotellurics/options.py
@@ -49,6 +49,7 @@ class MTForwardOptions(EMDataMixin, BaseForwardOptions):
)
run_command: str = "simpeg_drivers.natural_sources.magnetotellurics.forward"
title: str = "Magnetotellurics Forward"
+ icon: str = "surveymagnetotellurics"
physical_property: str = "conductivity"
inversion_type: str = "magnetotellurics"
@@ -96,6 +97,7 @@ class MTInversionOptions(EMDataMixin, BaseInversionOptions):
)
run_command: str = "simpeg_drivers.natural_sources.magnetotellurics.inversion"
title: str = "Magnetotellurics Inversion"
+ icon: str = "surveymagnetotellurics"
physical_property: str = "conductivity"
inversion_type: str = "magnetotellurics"
diff --git a/simpeg_drivers/natural_sources/tipper/options.py b/simpeg_drivers/natural_sources/tipper/options.py
index 5196b53c..7600614a 100644
--- a/simpeg_drivers/natural_sources/tipper/options.py
+++ b/simpeg_drivers/natural_sources/tipper/options.py
@@ -42,6 +42,7 @@ class TipperForwardOptions(EMDataMixin, BaseForwardOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/tipper_forward.ui.json"
run_command: str = "simpeg_drivers.natural_sources.tipper.forward"
title: str = "Tipper Forward"
+ icon: str = "surveyztem"
physical_property: str = "conductivity"
inversion_type: str = "tipper"
@@ -72,6 +73,7 @@ class TipperInversionOptions(EMDataMixin, BaseInversionOptions):
default_ui_json: ClassVar[Path] = assets_path() / "uijson/tipper_inversion.ui.json"
run_command: str = "simpeg_drivers.natural_sources.tipper.inversion"
title: str = "Tipper Inversion"
+ icon: str = "surveyztem"
physical_property: str = "conductivity"
inversion_type: str = "tipper"
diff --git a/simpeg_drivers/options.py b/simpeg_drivers/options.py
index d1b35a10..446cf5e4 100644
--- a/simpeg_drivers/options.py
+++ b/simpeg_drivers/options.py
@@ -18,6 +18,7 @@
import numpy as np
from geoapps_utils.base import Options
+from geoapps_utils.utils.formatters import recursive_flatten
from geoh5py.data import (
BooleanData,
DataAssociationEnum,
@@ -29,7 +30,7 @@
from geoh5py.groups import PropertyGroup, SimPEGGroup, UIJsonGroup
from geoh5py.objects import DrapeModel, Grid2D, Octree, Points
from geoh5py.objects.surveys.electromagnetics.base import BaseEMSurvey
-from geoh5py.ui_json import InputFile
+from geoh5py.ui_json import BaseUIJson
from pydantic import (
AliasChoices,
BaseModel,
@@ -41,8 +42,10 @@
model_validator,
)
+from simpeg_drivers.uijson import SimPEGDriversUIJson
+from simpeg_drivers.utils.regularization import direction_and_dip
+
from . import public_version
-from .utils.regularization import direction_and_dip
logger = getLogger(__name__)
@@ -235,10 +238,18 @@ def padding_cells(self) -> int:
return 4 if self.inversion_type in ["fdem", "tdem"] else 6
- def _create_input_file_from_attributes(self) -> InputFile:
- ifile = super()._create_input_file_from_attributes()
- ifile.set_data_value("version", public_version())
- return ifile
+ def write_ui_json(self, path: Path) -> Path:
+ """
+ Write UI JSON file.
+
+ TODO: Replace in favor of base Options implementation
+ after geoapps_utils@feature/uijson is merged
+ """
+ ui_json = SimPEGDriversUIJson.read(self.default_ui_json)
+ flatten = recursive_flatten(self.model_dump(exclude_unset=True))
+ ui_json.set_values(**flatten)
+
+ return ui_json.write(path)
class ModelOptions(BaseModel):
diff --git a/simpeg_drivers/plate_simulation/match/driver.py b/simpeg_drivers/plate_simulation/match/driver.py
index 467fd50d..65f4cd3d 100644
--- a/simpeg_drivers/plate_simulation/match/driver.py
+++ b/simpeg_drivers/plate_simulation/match/driver.py
@@ -33,7 +33,6 @@
from geoh5py.groups import PropertyGroup, SimPEGGroup
from geoh5py.objects import AirborneTEMReceivers, MaxwellPlate, Surface
from geoh5py.objects.maxwell_plate import PlateGeometry
-from geoh5py.ui_json import InputFile
from scipy import ndimage, signal
from scipy.sparse import csr_matrix
from scipy.spatial import cKDTree
@@ -42,6 +41,7 @@
from simpeg_drivers.electromagnetics.time_domain.options import CONVERSION
from simpeg_drivers.plate_simulation.match.options import PlateMatchOptions
from simpeg_drivers.plate_simulation.options import ModelOptions, PlateSimulationOptions
+from simpeg_drivers.uijson import SimPEGDriversUIJson
from simpeg_drivers.utils.utils import (
get_default_parallelization_params,
start_dask_run,
@@ -166,17 +166,17 @@ def start(cls, filepath: str | Path, mode="r+", **_) -> Self:
filepath = Path(filepath).resolve()
# TODO: Replace with UIJson when fully implemented
- # uijson = PlateMatchUIJson.read(filepath)
- uijson = InputFile.read_ui_json(filepath)
+ uijson = SimPEGDriversUIJson.read(filepath)
- with uijson.geoh5.open(mode=mode):
+ with Workspace(uijson.geoh5, mode=mode) as workspace:
try:
- options = PlateMatchOptions.build(uijson)
+ data = uijson.to_params(workspace)
+ options = PlateMatchOptions.build(**data)
logger.info("Initializing application . . .")
driver = cls(options)
logger.info("Running application . . .")
driver.run()
- logger.info("Results saved to %s", options.geoh5.h5file)
+ logger.info("Results saved to %s", uijson.geoh5)
except GeoAppsError as error:
logger.warning("\n\nApplicationError: %s\n\n", error)
@@ -385,14 +385,13 @@ def run(self):
with Workspace(self.params.simulation_files[best], mode="r") as ws:
survey = fetch_survey(ws)
- ui_json = survey.parent.parent.options
-
- ui_json["geoh5"] = ws
- ifile = InputFile(ui_json=ui_json)
+ ui_json_dict = survey.parent.parent.options
+ ui_json_dict["geoh5"] = ws
+ uijson = SimPEGDriversUIJson.from_dict(ui_json_dict)
# Avoid getting pydantic deprecation warnings from old PlateSimulations stored
with suppress_logging():
- options = PlateSimulationOptions.build(ifile)
+ options = PlateSimulationOptions.build(**uijson.to_params(ws))
dir_correction = strike_angle[ii] + 180 if flip else strike_angle[ii]
ind_center = int(centers[best])
diff --git a/simpeg_drivers/plate_simulation/match/options.py b/simpeg_drivers/plate_simulation/match/options.py
index e589a7fe..f3690c24 100644
--- a/simpeg_drivers/plate_simulation/match/options.py
+++ b/simpeg_drivers/plate_simulation/match/options.py
@@ -39,6 +39,7 @@ class PlateMatchOptions(Options):
name: ClassVar[str] = "plate_match"
default_ui_json: ClassVar[Path] = assets_path() / "uijson/plate_match.ui.json"
title: str = "Plate Match"
+ icon: str = "maxwellplate"
run_command: str = "simpeg_drivers.plate_simulation.match.driver"
out_group: SimPEGGroup | None = None
diff --git a/simpeg_drivers/plate_simulation/options.py b/simpeg_drivers/plate_simulation/options.py
index 0db21ce7..28d47ec0 100644
--- a/simpeg_drivers/plate_simulation/options.py
+++ b/simpeg_drivers/plate_simulation/options.py
@@ -14,10 +14,11 @@
from geoapps_utils.base import Options
from geoh5py.groups import SimPEGGroup, UIJsonGroup
-from geoh5py.ui_json import InputFile
+from geoh5py.shared.utils import fetch_active_workspace
from simpeg_drivers import assets_path
from simpeg_drivers.options import BaseForwardOptions
+from simpeg_drivers.uijson import SimPEGDriversUIJson
from simpeg_drivers.utils.synthetics.meshes import MeshOptions
from simpeg_drivers.utils.utils import driver_class_from_dict
@@ -39,6 +40,7 @@ class PlateSimulationOptions(Options):
name: ClassVar[str] = "plate_simulation"
default_ui_json: ClassVar[Path] = assets_path() / "uijson/plate_simulation.ui.json"
title: str = "Plate Simulation"
+ icon: str = "maxwellplate"
run_command: str = "simpeg_drivers.plate_simulation.driver"
out_group: SimPEGGroup | UIJsonGroup | None = None
forward_only: bool = True
@@ -58,15 +60,10 @@ def simulation_parameters(self) -> BaseForwardOptions:
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.")
+ ui_json = SimPEGDriversUIJson.from_dict(simulation_options)
- input_file.ui_json["mesh"]["value"] = None
+ with fetch_active_workspace(self.geoh5) as workspace:
+ data = ui_json.to_params(workspace=workspace, validate=False)
+ driver = driver_class_from_dict(data)
- if input_file.data is None:
- raise ValueError("Input file data must be set.")
-
- driver = driver_class_from_dict(input_file.data)
-
- return driver._params_class.build(input_file.data) # pylint: disable=protected-access
+ return driver._params_class.build(data) # pylint: disable=protected-access
diff --git a/simpeg_drivers/plate_simulation/sweep/options.py b/simpeg_drivers/plate_simulation/sweep/options.py
index ba6a9913..8165051e 100644
--- a/simpeg_drivers/plate_simulation/sweep/options.py
+++ b/simpeg_drivers/plate_simulation/sweep/options.py
@@ -14,12 +14,13 @@
import numpy as np
from geoapps_utils.base import Options
+from geoh5py import Workspace
from geoh5py.groups import SimPEGGroup, UIJsonGroup
-from geoh5py.shared.utils import stringify
-from geoh5py.ui_json import InputFile
+from geoh5py.shared.utils import fetch_active_workspace, stringify
from pydantic import BaseModel, ConfigDict, field_serializer, field_validator
from simpeg_drivers import assets_path
+from simpeg_drivers.uijson import SimPEGDriversUIJson
class ParamSweep(BaseModel):
@@ -58,6 +59,7 @@ class SweepOptions(Options):
name: ClassVar[str] = "plate_sweep"
default_ui_json: ClassVar[Path] = assets_path() / "uijson/plate_sweep.ui.json"
title: str = "Plate Sweep"
+ icon: str = "maxwellplate"
run_command: str = "simpeg_drivers.plate_simulation.sweep.driver"
out_group: SimPEGGroup | None = None
forward_only: bool = True
@@ -142,26 +144,36 @@ def trials(self) -> list[dict]:
return trials
@staticmethod
- def all_hashable_options(options: dict) -> dict:
- """Recurses through UIJson options to return flat dictionary of all key/values."""
+ def all_hashable_options(options: dict, workspace: Workspace) -> dict:
+ """
+ Recurses through UIJson options to return flat dictionary of all key/values.
- # TODO: Use the base UIJson to read options and flatten instead of
- # InputFile. Requires GEOPY-1875.
+ :param options: Options dictionary
+ :param workspace: Workspace to fetch objects from.
- ifile = InputFile(ui_json=options, validate=False)
- exceptions = list(Options.model_fields) + ["version", "icon", "documentation"]
- # TODO: add these to the Options fields with empty string defaults.
- out = {}
- for k, v in ifile.data.items():
- if k in exceptions:
- continue
+ :return: Flat dictionary of all key/values.
+ """
+ ifile = SimPEGDriversUIJson.from_dict(options)
+
+ with fetch_active_workspace(workspace, mode="r") as ws:
+ data = ifile.to_params(workspace=ws, validate=False)
+ exceptions = list(Options.model_fields) + [
+ "version",
+ "icon",
+ "documentation",
+ ]
+ # TODO: add these to the Options fields with empty string defaults.
+ out = {}
+ for k, v in data.items():
+ if k in exceptions:
+ continue
- if isinstance(v, SimPEGGroup | UIJsonGroup):
- opts = v.options
- opts["geoh5"] = options["geoh5"]
- out.update(SweepOptions.all_hashable_options(opts))
- else:
- out[k] = v
+ if isinstance(v, SimPEGGroup | UIJsonGroup):
+ opts = v.options
+ opts["geoh5"] = ws
+ out.update(SweepOptions.all_hashable_options(opts, ws))
+ else:
+ out[k] = v
return out
@@ -170,4 +182,7 @@ def template_options(self):
"""Return a flat version of the template.options dictionary."""
options = self.template.options
options["geoh5"] = self.geoh5
- return stringify(SweepOptions.all_hashable_options(options))
+
+ with fetch_active_workspace(self.geoh5, mode="r") as workspace:
+ template = SweepOptions.all_hashable_options(options, workspace)
+ return stringify(template)
diff --git a/simpeg_drivers/potential_fields/gravity/options.py b/simpeg_drivers/potential_fields/gravity/options.py
index 763607ce..5333d90c 100644
--- a/simpeg_drivers/potential_fields/gravity/options.py
+++ b/simpeg_drivers/potential_fields/gravity/options.py
@@ -44,6 +44,7 @@ class GravityForwardOptions(BaseForwardOptions):
run_command: str = "simpeg_drivers.potential_fields.gravity.forward"
title: str = "Gravity Forward"
+ icon: str = "surveyairbornegravity"
physical_property: str = "density"
inversion_type: str = "gravity"
@@ -88,6 +89,7 @@ class GravityInversionOptions(BaseInversionOptions):
run_command: str = "simpeg_drivers.potential_fields.gravity.inversion"
title: str = "Gravity Inversion"
+ icon: str = "surveyairbornegravity"
physical_property: str = "density"
inversion_type: str = "gravity"
diff --git a/simpeg_drivers/potential_fields/magnetic_scalar/options.py b/simpeg_drivers/potential_fields/magnetic_scalar/options.py
index 1e1839e7..7f422791 100644
--- a/simpeg_drivers/potential_fields/magnetic_scalar/options.py
+++ b/simpeg_drivers/potential_fields/magnetic_scalar/options.py
@@ -56,6 +56,7 @@ class MagneticForwardOptions(BaseForwardOptions):
run_command: str = "simpeg_drivers.potential_fields.magnetic_scalar.forward"
title: str = "Magnetic Scalar Forward"
+ icon: str = "surveyairbornemagnetics"
physical_property: str = "susceptibility"
inversion_type: str = "magnetic scalar"
@@ -112,6 +113,7 @@ class MagneticInversionOptions(BaseInversionOptions):
run_command: str = "simpeg_drivers.potential_fields.magnetic_scalar.inversion"
title: str = "Magnetic Scalar Inversion"
+ icon: str = "surveyairbornemagnetics"
physical_property: str = "susceptibility"
inversion_type: str = "magnetic scalar"
diff --git a/simpeg_drivers/potential_fields/magnetic_vector/options.py b/simpeg_drivers/potential_fields/magnetic_vector/options.py
index 58e72ae9..70ab0bfe 100644
--- a/simpeg_drivers/potential_fields/magnetic_vector/options.py
+++ b/simpeg_drivers/potential_fields/magnetic_vector/options.py
@@ -60,6 +60,7 @@ class MagneticVectorForwardOptions(BaseForwardOptions):
)
run_command: str = "simpeg_drivers.potential_fields.magnetic_vector.forward"
title: str = "Magnetic Vector Forward"
+ icon: str = "surveyairbornemagnetics"
physical_property: str = "susceptibility"
inversion_type: str = "magnetic vector"
@@ -114,6 +115,7 @@ class MagneticVectorInversionOptions(BaseInversionOptions):
)
run_command: str = "simpeg_drivers.potential_fields.magnetic_vector.inversion"
title: str = "Magnetic Vector Inversion"
+ icon: str = "surveyairbornemagnetics"
physical_property: str = "susceptibility"
inversion_type: str = "magnetic vector"
diff --git a/simpeg_drivers/uijson.py b/simpeg_drivers/uijson.py
index c9495195..809c0e1a 100644
--- a/simpeg_drivers/uijson.py
+++ b/simpeg_drivers/uijson.py
@@ -84,3 +84,27 @@ def write_default(cls):
data = uijson.model_dump_json(indent=4, exclude_unset=False)
with open(cls.default_ui_json, "w", encoding="utf-8") as file:
file.write(data)
+
+ @classmethod
+ def from_dict(cls, data: dict) -> BaseUIJson:
+ """
+ Create a UIJson instance from a dictionary.
+
+ Deal with known issues in legacy files
+
+ :param data: Dictionary representing the ui json object.
+
+ :returns: UIJson object.
+ """
+ kwargs = {}
+ for key, item in data.items():
+ if isinstance(item, dict) and key == "tile_spatial":
+ item.pop("isValue", None)
+ item.pop("property", None)
+ item.pop("parent", None)
+
+ kwargs[key] = item if item != "" else None
+
+ ui_json_class = cls.infer(**kwargs)
+
+ return ui_json_class(**kwargs)
diff --git a/simpeg_drivers/utils/tile_estimate.py b/simpeg_drivers/utils/tile_estimate.py
index 18ef5296..f68ec2a4 100644
--- a/simpeg_drivers/utils/tile_estimate.py
+++ b/simpeg_drivers/utils/tile_estimate.py
@@ -41,6 +41,7 @@ class TileParameters(Options):
"""
default_ui_json: ClassVar[Path] = assets_path() / "uijson/tile_estimator.ui.json"
+ icon: str = "tilelist"
simulation: SimPEGGroup
render_plot: bool = True
diff --git a/simpeg_drivers/utils/utils.py b/simpeg_drivers/utils/utils.py
index 7b8810d5..bb488316 100644
--- a/simpeg_drivers/utils/utils.py
+++ b/simpeg_drivers/utils/utils.py
@@ -40,12 +40,12 @@
from geoh5py.objects.surveys.electromagnetics.base import LargeLoopGroundEMSurvey
from geoh5py.shared import INTEGER_NDV
from geoh5py.shared.utils import fetch_active_workspace, mask_by_extent, stringify
-from geoh5py.ui_json import InputFile
from grid_apps.utils import octree_2_treemesh
from scipy.interpolate import interp1d
from scipy.spatial import ConvexHull, cKDTree
from simpeg_drivers import DRIVER_MAP
+from simpeg_drivers.uijson import SimPEGDriversUIJson
if TYPE_CHECKING:
@@ -608,14 +608,14 @@ def simpeg_group_to_driver(group: SimPEGGroup, workspace: Workspace) -> Driver:
:returns: InversionDriver object.
"""
+ ui_json_dict = deepcopy(group.options)
+ ui_json_dict["geoh5"] = workspace
+ uijson = SimPEGDriversUIJson.from_dict(ui_json_dict)
+ data = uijson.to_params(workspace)
+ data["out_group"] = group
- ui_json = deepcopy(group.options)
- ui_json["geoh5"] = workspace
-
- ifile = InputFile(ui_json=ui_json)
- inversion_driver = driver_class_from_dict(ifile.ui_json)
- ifile.set_data_value("out_group", group)
- params = inversion_driver._params_class.build(ifile) # pylint: disable=protected-access
+ inversion_driver = driver_class_from_dict(ui_json_dict)
+ params = inversion_driver._params_class.build(**data) # pylint: disable=protected-access
return inversion_driver(params)
diff --git a/tests/plate_simulation/runtest/driver_test.py b/tests/plate_simulation/runtest/driver_test.py
index 297237c4..6b2f9432 100644
--- a/tests/plate_simulation/runtest/driver_test.py
+++ b/tests/plate_simulation/runtest/driver_test.py
@@ -11,7 +11,7 @@
import logging
from geoh5py.groups import SimPEGGroup
-from geoh5py.ui_json import InputFile
+from geoh5py.ui_json import BaseUIJson
from simpeg_drivers import assets_path
from simpeg_drivers.plate_simulation.driver import (
@@ -31,6 +31,7 @@
SurveyOptions,
SyntheticsComponentsOptions,
)
+from simpeg_drivers.utils.utils import validate_out_group
from tests.utils.targets import get_workspace
@@ -45,52 +46,52 @@ def test_plate_simulation_params_from_input_file(tmp_path, caplog):
with get_workspace(tmp_path / "inversion_test.ui.geoh5") as geoh5:
components = SyntheticsComponents(geoh5, options=opts)
- ifile = InputFile.read_ui_json(
- assets_path() / "uijson" / "plate_simulation.ui.json", validate=False
- )
- ifile.data["name"] = "test_gravity_plate_simulation"
- ifile.data["geoh5"] = geoh5
-
# Add simulation parameter
- gravity_inversion = SimPEGGroup.create(geoh5)
-
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(geoh5.h5file)
- options_dict["topography_object"]["value"] = str(components.topography.uid)
- options_dict["data_object"]["value"] = str(components.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_property"] = 5.0
- ifile.data["thickness"] = 50.0
- ifile.data["plate_property"] = 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["elevation"] = 20
+ fwr_ifile = BaseUIJson.read(options.default_ui_json)
+ options_dict = {
+ "inversion_type": "gravity",
+ "forward_only": True,
+ "topography_object": str(components.topography.uid),
+ "data_object": str(components.survey.uid),
+ "title": "gravity fwd",
+ }
+ fwr_ifile.set_values(**options_dict)
+ options_dict = fwr_ifile.to_params(workspace=geoh5)
+ options = GravityForwardOptions.build(options_dict)
+ gravity_inversion = validate_out_group(options)
+
+ ifile = BaseUIJson.read(assets_path() / "uijson" / "plate_simulation.ui.json")
+ options_dict = {
+ "simulation": gravity_inversion,
+ # Add mesh parameters
+ "u_cell_size": 10.0,
+ "v_cell_size": 10.0,
+ "w_cell_size": 10.0,
+ "depth_core": 400.0,
+ "minimum_level": 8,
+ "max_distance": 200.0,
+ "diagonal_balance": False,
+ "padding_distance": 1500.0,
+ "name": "test_gravity_plate_simulation",
+ # Add model parameters
+ "background": 1000.0,
+ "overburden_property": 5.0,
+ "thickness": 50.0,
+ "plate_property": 2.0,
+ "width": 100.0,
+ "strike_length": 100.0,
+ "dip_length": 100.0,
+ "dip": 0.0,
+ "dip_direction": 0.0,
+ "number": 9,
+ "spacing": 10.0,
+ "elevation": 20,
+ }
+ ifile.set_values(**options_dict)
with caplog.at_level(logging.WARNING):
- params = PlateSimulationOptions.build(ifile)
+ params = PlateSimulationOptions.build(ifile.to_params(workspace=geoh5))
assert "Overburden thickness exceeds the plate depth" in caplog.text
assert isinstance(params.simulation, SimPEGGroup)
diff --git a/tests/plate_simulation/runtest/match_test.py b/tests/plate_simulation/runtest/match_test.py
index 3841b267..2a6770ae 100644
--- a/tests/plate_simulation/runtest/match_test.py
+++ b/tests/plate_simulation/runtest/match_test.py
@@ -19,7 +19,7 @@
from geoh5py.data import FilenameData
from geoh5py.groups import PropertyGroup, SimPEGGroup
from geoh5py.objects import Points
-from geoh5py.ui_json import InputFile
+from geoh5py.ui_json import BaseUIJson
from scipy import signal
from simpeg_drivers import assets_path
@@ -146,13 +146,10 @@ def test_matching_driver(tmp_path: Path):
fwr_driver = TDEMForwardDriver(params)
- ifile = InputFile.read_ui_json(
- assets_path() / "uijson" / "plate_simulation.ui.json", validate=False
- )
- ifile.data["geoh5"] = geoh5
- ifile.data["simulation"] = fwr_driver.out_group
+ ifile = BaseUIJson.read(assets_path() / "uijson" / "plate_simulation.ui.json")
+ ifile.set_values(simulation=fwr_driver.out_group)
- plate_options = PlateSimulationOptions.build(ifile.data)
+ plate_options = PlateSimulationOptions.build(ifile.to_params(workspace=geoh5))
plate_options.model.overburden_options.thickness = 25.0
plate_options.model.overburden_options.overburden_property = 10000
plate_options.model.plate_options.geometry.dip_length = 300.0
@@ -222,13 +219,17 @@ def test_matching_driver(tmp_path: Path):
topography_object=components.topography,
simulations=new_dir,
)
- match_driver = PlateMatchDriver(options)
- results = match_driver.run()
+ json_file = options.write_ui_json(tmp_path / "match_options.ui.json")
+
+ PlateMatchDriver.start(json_file)
+ with geoh5.open():
+ out_group = geoh5.get_entity("Plate Match")[0]
+ results = out_group.get_entity("Points")[0]
assert isinstance(results, Points)
names = results.get_data("file")[0]
- assert names.values[0] == file.stem + f"_[{1}].geoh5"
+ assert names.values == file.stem + f"_[{1}].geoh5"
plate = geoh5.get_entity("Query [0]")[0]
assert plate.geometry.dip_direction == 45.0
diff --git a/tests/plate_simulation/runtest/sweep_test.py b/tests/plate_simulation/runtest/sweep_test.py
index 4484b6ae..58e52c6a 100644
--- a/tests/plate_simulation/runtest/sweep_test.py
+++ b/tests/plate_simulation/runtest/sweep_test.py
@@ -10,7 +10,7 @@
from geoh5py import Workspace
from geoh5py.groups import SimPEGGroup
-from geoh5py.ui_json import InputFile
+from geoh5py.ui_json import BaseUIJson
from pandas import read_excel
from simpeg_drivers import assets_path
@@ -27,38 +27,38 @@ def setup_plate_sweep(workspace) -> SimPEGGroup:
data = get_survey(workspace, method="gravity", options=options.survey)
topo = get_topography_surface(workspace, options)
- gravity = SimPEGGroup.create(workspace, name="gravity fwd")
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(workspace.h5file)
- options_dict["topography_object"]["value"] = str(topo.uid)
- options_dict["data_object"]["value"] = str(data.uid)
- options_dict["out_group"]["value"] = str(gravity.uid)
- gravity.options = options_dict
-
- simulation = SimPEGGroup.create(workspace, name="plate simulation")
+ fwr_file = BaseUIJson.read(options.default_ui_json)
+
+ fwr_file.inversion_type = "gravity"
+ fwr_file.forward_only = True
+ fwr_file.geoh5 = str(workspace.h5file)
+ fwr_file.topography_object.value = str(topo.uid)
+ fwr_file.data_object.value = str(data.uid)
+
+ gravity = fwr_file.to_ui_json_group(workspace=workspace, name="gravity fwd")
+
options = PlateSimulationOptions.model_construct()
- plate_ifile = InputFile.read_ui_json(options.default_ui_json)
- options_dict = plate_ifile.ui_json
- options_dict["simulation"]["value"] = str(gravity.uid)
- options_dict["overburden_property"]["value"] = 100.0
- options_dict["thickness"]["value"] = 20.0
- options_dict["u_cell_size"]["value"] = 10.0
- options_dict["v_cell_size"]["value"] = 10.0
- options_dict["w_cell_size"]["value"] = 10.0
- options_dict["depth_core"]["value"] = 400.0
- options_dict["minimum_level"]["value"] = 8
- options_dict["max_distance"]["value"] = 200.0
- options_dict["diagonal_balance"]["value"] = False
- options_dict["padding_distance"]["value"] = 1500.0
- options_dict["dip_direction"]["value"] = 0.0
- options_dict["number"]["value"] = 1
- options_dict["elevation"]["value"] = 100.0
- options_dict["out_group"]["value"] = str(simulation.uid)
- simulation.options = options_dict
+ plate_ifile = BaseUIJson.read(options.default_ui_json)
+
+ plate_ifile.simulation.value = str(gravity.uid)
+ plate_ifile.overburden_property.value = 100.0
+ plate_ifile.thickness.value = 20.0
+ plate_ifile.u_cell_size.value = 10.0
+ plate_ifile.v_cell_size.value = 10.0
+ plate_ifile.w_cell_size.value = 10.0
+ plate_ifile.depth_core.value = 400.0
+ plate_ifile.minimum_level.value = 8
+ plate_ifile.max_distance.value = 200.0
+ plate_ifile.diagonal_balance.value = False
+ plate_ifile.padding_distance.value = 1500.0
+ plate_ifile.dip_direction.value = 0.0
+ plate_ifile.number.value = 1
+ plate_ifile.elevation.value = 100.0
+
+ simulation = plate_ifile.to_ui_json_group(
+ workspace=workspace, name="plate simulation"
+ )
return simulation
@@ -69,30 +69,30 @@ def test_sweep(tmp_path):
with Workspace.create(tmp_path / "test.geoh5") as ws:
plate_simulation = setup_plate_sweep(ws)
- ifile = InputFile.read_ui_json(
- assets_path() / "uijson" / "plate_sweep.ui.json", validate=False
- )
- ifile.data["name"] = "test_gravity_plate_simulation"
- ifile.data["geoh5"] = ws
- ifile.data["template"] = str(plate_simulation.uid)
- ifile.data["workdir"] = str(workdir)
- ifile.data["background_start"] = 0.0
- ifile.data["background_stop"] = 100.0
- ifile.data["background_count"] = 2
- ifile.data["plate_start"] = 500.0
- ifile.data["plate_stop"] = 1000.0
- ifile.data["plate_count"] = 2
- ifile.data["out_group"] = None
-
- ifile.write_ui_json(name="plate_sweep.ui.json", path=tmp_path)
+ ifile = BaseUIJson.read(assets_path() / "uijson" / "plate_sweep.ui.json")
+ data = {
+ "name": "test_gravity_plate_simulation",
+ "geoh5": ws,
+ "template": str(plate_simulation.uid),
+ "workdir": str(workdir),
+ "background_start": 0.0,
+ "background_stop": 100.0,
+ "background_count": 2,
+ "plate_start": 500.0,
+ "plate_stop": 1000.0,
+ "plate_count": 2,
+ "out_group": None,
+ }
+ ifile.set_values(**data)
+ ifile.write(tmp_path / "plate_sweep.ui.json")
PlateSweepDriver.start(tmp_path / "plate_sweep.ui.json")
assert workdir.exists()
with Workspace(tmp_path / "test.geoh5"):
- ifile = InputFile.read_ui_json(tmp_path / "plate_sweep.ui.json")
- ifile.set_data_value("background_count", 3)
- ifile.write_ui_json(path=tmp_path, name="plate_sweep_modified.ui.json")
+ ifile = BaseUIJson.read(tmp_path / "plate_sweep.ui.json")
+ ifile.set_values(background_count=3)
+ ifile.write(tmp_path / "plate_sweep_modified.ui.json")
PlateSweepDriver.start(tmp_path / "plate_sweep_modified.ui.json")
diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py
index 41e5400b..cb06f566 100644
--- a/tests/run_tests/driver_grav_test.py
+++ b/tests/run_tests/driver_grav_test.py
@@ -133,6 +133,7 @@ def test_gravity_run(
starting_model=1e-4,
topography_object=components.topography,
reference_model=0.0,
+ sens_wts_threshold=1.0,
save_sensitivities=True,
)
params.write_ui_json(path=tmp_path / "Inv_run.ui.json")
diff --git a/tests/run_tests/driver_joint_cross_gradient_test.py b/tests/run_tests/driver_joint_cross_gradient_test.py
index 4b33ab32..3fbc085e 100644
--- a/tests/run_tests/driver_joint_cross_gradient_test.py
+++ b/tests/run_tests/driver_joint_cross_gradient_test.py
@@ -15,6 +15,7 @@
from geoh5py.groups import GroupTypeEnum, PropertyGroup
from geoh5py.objects import CurrentElectrode, Octree, Points
from geoh5py.workspace import Workspace
+from simpeg.directives import UpdateIRLS
from simpeg_drivers.electricals.direct_current.three_dimensions import (
DC3DForwardDriver,
@@ -234,6 +235,7 @@ def test_joint_cross_gradient_inv_run(
reference_model=0.0,
upper_bound=1.0,
tile_spatial=2,
+ x_norm=1.1,
auto_scale_tiles=True,
chi_factor=0.8,
)
@@ -296,17 +298,19 @@ def test_joint_cross_gradient_inv_run(
cross_gradient_weight_a_b=1e0,
cross_gradient_weight_c_a=1e0,
cross_gradient_weight_c_b=1e0,
+ sens_wts_threshold=1.0,
percentile=100,
)
-
- driver = JointCrossGradientDriver(joint_params)
-
- # Check that chi factors set on the sub drivers are preserved forward
- np.testing.assert_allclose(
- driver.data_misfit.multipliers, [0.8, 0.8, 1.0, 1.0, 1.0], atol=1e-3
+ file = joint_params.write_ui_json(tmp_path / "Joint_Inv_run.ui.json")
+ driver = JointCrossGradientDriver.start(file)
+
+ # Check that the norm applied to the sub-driver is maintained
+ irls_directive = next(
+ directive
+ for directive in driver.directives.directive_list
+ if isinstance(directive, UpdateIRLS)
)
-
- driver.run()
+ np.testing.assert_almost_equal(irls_directive.metrics.input_norms[0][1], 1.1)
if not pytest:
return
diff --git a/tests/run_tests/driver_rotated_gradients_test.py b/tests/run_tests/driver_rotated_gradients_test.py
index 0b47de3e..dca72fa6 100644
--- a/tests/run_tests/driver_rotated_gradients_test.py
+++ b/tests/run_tests/driver_rotated_gradients_test.py
@@ -151,6 +151,7 @@ def test_rotated_grad_run(
max_global_iterations=max_iterations,
initial_beta_ratio=1e-1,
percentile=95,
+ sens_wts_threshold=1.0,
save_sensitivities=True,
)
params.write_ui_json(path=tmp_path / "Inv_run.ui.json")
diff --git a/tests/uijson_test.py b/tests/uijson_test.py
index 8b686da6..f1eb88b9 100644
--- a/tests/uijson_test.py
+++ b/tests/uijson_test.py
@@ -18,7 +18,6 @@
from geoapps_utils.driver.data import BaseData
from geoapps_utils.run import load_ui_json_as_dict
from geoh5py import Workspace
-from geoh5py.ui_json import InputFile
from geoh5py.ui_json.annotations import Deprecated
from packaging.version import Version
from pydantic import AliasChoices, Field
@@ -277,13 +276,13 @@ def test_legacy_uijson(tmp_path: Path, caplog):
version_path = tmp_path / directory.name
for file in directory.glob("*.ui.json"):
- ifile = InputFile.read_ui_json(file, validate=False)
- inversion_type = ifile.data.get("inversion_type", None)
+ ifile = SimPEGDriversUIJson.read(file)
+ inversion_type = ifile.inversion_type
if inversion_type not in CHANNEL_NAME:
continue
- forward = ifile.data.get("forward_only", None)
+ forward = ifile.forward_only
work_path = version_path / (
inversion_type + (" fwr" if forward else " inv")
@@ -304,18 +303,19 @@ def test_legacy_uijson(tmp_path: Path, caplog):
)
with Workspace.create(work_path / "inversion_test.ui.geoh5") as geoh5:
components = SyntheticsComponents(geoh5, options=opts)
- ifile.data["geoh5"] = geoh5
- ifile.data["mesh"] = components.mesh
- ifile.data["starting_model"] = components.model
- ifile.data["data_object"] = components.survey
- ifile.data["topography_object"] = components.topography
+ options = ifile.to_params(workspace=geoh5, validate=False)
+ options["geoh5"] = geoh5
+ options["mesh"] = components.mesh
+ options["starting_model"] = components.model
+ options["data_object"] = components.survey
+ options["topography_object"] = components.topography
# Test deprecated name
- ifile.data["coolingFactor"] = 4.0
+ options["coolingFactor"] = 4.0
if "2d" in inversion_type or "pseudo 3d" in inversion_type:
line_id = geoh5.get_entity("line_ids")[0]
- ifile.data["line_object"] = line_id
+ options["line_object"] = line_id
if not forward:
n_vals = components.survey.n_vertices
@@ -344,13 +344,13 @@ def test_legacy_uijson(tmp_path: Path, caplog):
else:
channel = data[0]
- ifile.data[CHANNEL_NAME[inversion_type] + "_channel"] = channel
- ifile.data[CHANNEL_NAME[inversion_type] + "_uncertainty"] = channel
+ options[CHANNEL_NAME[inversion_type] + "_channel"] = channel
+ options[CHANNEL_NAME[inversion_type] + "_uncertainty"] = channel
- driver = driver_class_from_dict(ifile.data)
+ driver = driver_class_from_dict(options)
with caplog.at_level(logging.WARNING):
- params = driver._params_class.build(ifile) # pylint: disable=protected-access
+ params = driver._params_class.build(options) # pylint: disable=protected-access
driver = driver(params)
if "pseudo" in inversion_type: