From f8e2014fd866dcd0032da7663b03170df8780a12 Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 19 Aug 2026 15:29:22 -0700 Subject: [PATCH 01/20] Initial implementation of borehole tem --- .../uijson/borehole_tdem_forward.ui.json | 231 ++++++ .../uijson/borehole_tdem_inversion.ui.json | 660 ++++++++++++++++++ simpeg_drivers/__init__.py | 7 + simpeg_drivers/components/data.py | 1 + .../factories/directives_factory.py | 2 + .../components/factories/receiver_factory.py | 3 + .../components/factories/simpeg_factory.py | 1 + .../factories/simulation_factory.py | 2 + .../borehole_time_domain/__init__.py | 9 + .../borehole_time_domain/forward.py | 27 + .../borehole_time_domain/inversion.py | 29 + .../borehole_time_domain/options.py | 64 ++ 12 files changed, 1036 insertions(+) create mode 100644 simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json create mode 100644 simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json create mode 100644 simpeg_drivers/electromagnetics/borehole_time_domain/__init__.py create mode 100644 simpeg_drivers/electromagnetics/borehole_time_domain/forward.py create mode 100644 simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py create mode 100644 simpeg_drivers/electromagnetics/borehole_time_domain/options.py diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json new file mode 100644 index 000000000..cfc7fd72b --- /dev/null +++ b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json @@ -0,0 +1,231 @@ +{ + "version": "0.0.0", + "title": "Borehole TDEM Forward", + "icon": "surveyairborneem", + "documentation": "https://mirageoscience-simpeg-drivers.readthedocs-hosted.com/en/latest/", + "conda_environment": "simpeg-drivers", + "run_command": "simpeg_drivers.electromagnetics.borehole_time_domain.forward", + "geoh5": "", + "monitoring_directory": "", + "data_object": { + "main": true, + "group": "Survey", + "label": "Object", + "meshType": [ + "{19730589-fd28-4649-9de0-ad47249d9aba}", + "{deebe11a-b57b-4a03-99d6-8f27b25eb2a8}" + ], + "value": "" + }, + "receivers_orientation": { + "group": "Survey", + "main": true, + "association": "Vertex", + "dataType": "Float", + "dataGroupType": [ + "Dip direction & dip", + "3D vector" + ], + "label": "Receivers orientation", + "tooltip": [ + "Receivers orientation provided as 'Dip direction & dip' or '3D vector' data group. If not provided, it assumes:
", + "
In-line component
Positive towards North (Y)
", + "
Cross-line component
Positive towards East (X)
", + "
Vertical component
Positive up (Z)
", + "
" + ], + "optional": true, + "enabled": false, + "parent": "data_object", + "value": "", + "visible": false + }, + "data_units": { + "choiceList": [ + "Airborne dB/dt (V/Am^4)", + "Airborne B (T/Am^2)", + "Ground dB/dt (V/Am^2)", + "Ground B (T/A)" + ], + "group": "Survey", + "main": true, + "label": "Data type", + "tooltip": [ + "Set the units of the data.

", + "Data are expected to be normalized by the source strength, dependent on the type:

", + "
Dipole
Current * area * number of turns (NIA)
", + "
Wire
Current * number of turns (NI)
", + "
" + ], + "value": "Airborne dB/dt (V/Am^4)" + }, + "inline_channel_bool": { + "group": "Survey", + "main": true, + "label": "A-component", + "tooltip": "Axial (A) component parallel to the hole trace.\nPositive upward along the hole trace", + "value": true + }, + "vertical_channel_bool": { + "group": "Survey", + "main": true, + "label": "U-component", + "tooltip": "Perpendicular (U) component of the magnetic data.\nPositive upward in the hole dip direction", + "value": true + }, + "crossline_channel_bool": { + "group": "Survey", + "main": true, + "label": "V-component", + "tooltip": "Perpendicular (V) component of the magnetic data.\nHorizontal, to left of hole dip direction", + "value": true + }, + "mesh": { + "group": "Mesh and models", + "main": true, + "label": "Mesh", + "meshType": "{4ea87376-3ece-438b-bf12-3479733ded46}", + "value": "", + "optional": true, + "enabled": false, + "tooltip": "Select a mesh for the forward modelling" + }, + "model_type": { + "choiceList": [ + "Conductivity (S/m)", + "Resistivity (Ohm-m)" + ], + "main": true, + "group": "Mesh and models", + "label": "Model units", + "tooltip": "Select the units of the model", + "value": "Conductivity (S/m)" + }, + "starting_model": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Mesh and models", + "main": true, + "isValue": true, + "parent": "mesh", + "label": "Value(s)", + "property": "", + "value": 0.001 + }, + "topography_object": { + "main": true, + "group": "Topography", + "label": "Topography", + "meshType": [ + "{202c5db1-a56d-4004-9cad-baafd8899406}", + "{6a057fdc-b355-11e3-95be-fd84a7ffcb88}", + "{f26feba3-aded-494b-b9e9-b2bbcbe298e1}", + "{48f5054a-1c5c-4ca4-9048-80f36dc60a06}", + "{b020a277-90e2-4cd7-84d6-612ee3f25051}" + ], + "value": "", + "optional": true, + "enabled": true, + "tooltip": "Select a topography object to define the active cells for forward modelling" + }, + "topography": { + "association": [ + "Vertex", + "Cell" + ], + "dataType": "Float", + "group": "Topography", + "main": true, + "optional": true, + "enabled": false, + "label": "Elevation channel", + "tooltip": "Set elevation from channel. If not set the topography will be set from the geometry of the selected 'topography' object", + "parent": "topography_object", + "dependency": "topography_object", + "dependencyType": "enabled", + "value": "", + "verbose": 2 + }, + "active_model": { + "association": "Cell", + "dataType": [ + "Referenced", + "Boolean", + "Integer" + ], + "group": "Topography", + "main": true, + "enabled": false, + "dependency": "topography_object", + "dependencyType": "disabled", + "label": "Active model", + "tooltip": "Provide the active cell Boolean model directly if topography not set", + "parent": "mesh", + "value": "" + }, + "n_cpu": { + "min": 1, + "group": "Compute", + "optional": true, + "enabled": false, + "label": "Number of CPUs", + "value": 1, + "visible": false + }, + "solver_type": { + "choiceList": [ + "Pardiso", + "Mumps" + ], + "group": "Compute", + "label": "Direct solver", + "tooltip": "Direct solver to use for the forward calculations", + "value": "Pardiso" + }, + "tile_spatial": { + "group": "Compute", + "label": "Number of tiles", + "value": 1, + "min": 1, + "max": 1000, + "verbose": 2, + "tooltip": "Splits the objective function into spatial tiles for distributed computation using the Dask library" + }, + "max_chunk_size": { + "min": 0, + "group": "Compute", + "optional": true, + "enabled": true, + "label": "Maximum chunk size (MB)", + "value": 128, + "verbose": 3, + "visible": false, + "tooltip": "Limit the chunk size used by Dask for distributed computation" + }, + "out_group": { + "label": "SimPEG group", + "value": "", + "groupType": "{55ed3daf-c192-4d4b-a439-60fa987fe2b8}", + "group": "Drag-and-drop options", + "visible": true, + "optional": true, + "enabled": false, + "tooltip": "Optionally set the SimPEG group to which results will be saved" + }, + "generate_sweep": { + "label": "Generate sweep file", + "group": "Python run preferences", + "main": true, + "value": false, + "visible": false, + "tooltip": "Generates a file for sweeping parameters instead of running the application" + }, + "n_workers": null, + "n_threads": null, + "max_ram": "", + "performance_report": false, + "distributed_workers": "" +} diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json new file mode 100644 index 000000000..ccaf8bfe5 --- /dev/null +++ b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json @@ -0,0 +1,660 @@ +{ + "version": "0.0.0", + "title": "Borehole TDEM Forward", + "icon": "surveyairborneem", + "documentation": "https://mirageoscience-simpeg-drivers.readthedocs-hosted.com/en/latest/", + "conda_environment": "simpeg-drivers", + "run_command": "simpeg_drivers.electromagnetics.borehole_time_domain.inversion", + "geoh5": "", + "monitoring_directory": "", + "data_object": { + "main": true, + "group": "Data", + "label": "Object", + "meshType": [ + "{19730589-fd28-4649-9de0-ad47249d9aba}", + "{deebe11a-b57b-4a03-99d6-8f27b25eb2a8}" + ], + "value": "" + }, + "receivers_orientation": { + "group": "Survey", + "main": true, + "association": "Vertex", + "dataType": "Float", + "dataGroupType": [ + "Dip direction & dip", + "3D vector" + ], + "label": "Receivers orientation", + "tooltip": [ + "Receivers orientation provided as 'Dip direction & dip' or '3D vector' data group. If not provided, it assumes:
", + "
In-line component
Positive towards North (Y)
", + "
Cross-line component
Positive towards East (X)
", + "
Vertical component
Positive up (Z)
", + "
" + ], + "optional": true, + "enabled": false, + "parent": "data_object", + "value": "", + "visible": false + }, + "data_units": { + "choiceList": [ + "Airborne dB/dt (V/Am^4)", + "Airborne B (T/Am^2)", + "Ground dB/dt (V/Am^2)", + "Ground B (T/A)" + ], + "group": "Survey", + "main": true, + "label": "Data type", + "tooltip": [ + "Set the units of the data.

", + "Data are expected to be normalized by the source strength, dependent on the type:

", + "
Dipole
Current * area * number of turns (NIA)
", + "
Wire
Current * number of turns (NI)
", + "
" + ], + "value": "Airborne dB/dt (V/Am^4)" + }, + "inline_channel": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Data", + "dataGroupType": "Multi-element", + "main": true, + "label": "A-component", + "parent": "data_object", + "tooltip": "Axial (A) component parallel to the hole trace.\nPositive upward along the hole trace", + "optional": true, + "enabled": false, + "value": "" + }, + "inline_uncertainty": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Data", + "dataGroupType": "Multi-element", + "main": true, + "label": "Uncertainty", + "parent": "data_object", + "dependency": "inline_channel", + "dependencyType": "enabled", + "value": "" + }, + "vertical_channel": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Data", + "dataGroupType": "Multi-element", + "main": true, + "label": "U-component", + "parent": "data_object", + "tooltip": "Perpendicular (U) component of the magnetic data.\nPositive upward in the hole dip direction", + "optional": true, + "enabled": true, + "value": "" + }, + "vertical_uncertainty": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Data", + "dataGroupType": "Multi-element", + "main": true, + "label": "Uncertainty", + "parent": "data_object", + "dependency": "vertical_channel", + "dependencyType": "enabled", + "value": "" + }, + "crossline_channel": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Data", + "dataGroupType": "Multi-element", + "main": true, + "label": "V-component", + "tooltip": "Perpendicular (V) component of the magnetic data.\nHorizontal, to left of hole dip direction", + "parent": "data_object", + "optional": true, + "enabled": false, + "value": "" + }, + "crossline_uncertainty": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Data", + "dataGroupType": "Multi-element", + "main": true, + "label": "Uncertainty", + "parent": "data_object", + "dependency": "crossline_channel", + "dependencyType": "enabled", + "value": "" + }, + "mesh": { + "group": "Mesh and models", + "main": true, + "label": "Mesh", + "meshType": "{4ea87376-3ece-438b-bf12-3479733ded46}", + "value": "", + "optional": true, + "enabled": false, + "tooltip": "Select a mesh for the inversion" + }, + "model_type": { + "choiceList": [ + "Conductivity (S/m)", + "Resistivity (Ohm-m)" + ], + "main": true, + "group": "Mesh and models", + "label": "Model units", + "tooltip": "Select the units of the model", + "value": "Conductivity (S/m)" + }, + "starting_model": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "group": "Mesh and models", + "main": true, + "isValue": true, + "parent": "mesh", + "label": "Initial", + "property": "", + "value": 0.001 + }, + "reference_model": { + "association": [ + "Cell", + "Vertex" + ], + "dataType": "Float", + "main": true, + "group": "Mesh and models", + "isValue": true, + "parent": "mesh", + "label": "Reference", + "property": "", + "optional": true, + "enabled": false, + "value": 0.001 + }, + "lower_bound": { + "association": "Cell", + "main": true, + "dataType": "Float", + "group": "Mesh and models", + "isValue": true, + "parent": "mesh", + "label": "Lower bound", + "property": "", + "optional": true, + "value": 1e-08, + "enabled": false + }, + "upper_bound": { + "association": "Cell", + "main": true, + "dataType": "Float", + "group": "Mesh and models", + "isValue": true, + "parent": "mesh", + "label": "Upper bound", + "property": "", + "optional": true, + "value": 100.0, + "enabled": false + }, + "topography_object": { + "main": true, + "group": "Topography", + "label": "Topography", + "meshType": [ + "{202c5db1-a56d-4004-9cad-baafd8899406}", + "{6a057fdc-b355-11e3-95be-fd84a7ffcb88}", + "{f26feba3-aded-494b-b9e9-b2bbcbe298e1}", + "{48f5054a-1c5c-4ca4-9048-80f36dc60a06}", + "{b020a277-90e2-4cd7-84d6-612ee3f25051}" + ], + "value": "", + "optional": true, + "enabled": true, + "tooltip": "Select a topography object to define the active cells for inversion" + }, + "topography": { + "association": [ + "Vertex", + "Cell" + ], + "dataType": "Float", + "group": "Topography", + "main": true, + "optional": true, + "enabled": false, + "label": "Elevation channel", + "tooltip": "Set elevation from channel. If not set the topography will be set from the geometry of the selected 'topography' object", + "parent": "topography_object", + "dependency": "topography_object", + "dependencyType": "enabled", + "value": "", + "verbose": 2 + }, + "active_model": { + "association": "Cell", + "dataType": [ + "Referenced", + "Boolean", + "Integer" + ], + "group": "Topography", + "main": true, + "enabled": false, + "dependency": "topography_object", + "dependencyType": "disabled", + "label": "Active model", + "tooltip": "Provide the active cell Boolean model directly if topography not set", + "parent": "mesh", + "value": "" + }, + "alpha_s": { + "min": 0.0, + "group": "Regularization", + "label": "Reference weight", + "value": 1.0, + "tooltip": "Constant ratio compared to other weights. Larger values result in models that remain close to the reference model", + "dependency": "reference_model", + "dependencyType": "enabled", + "isValue": true, + "parent": "mesh", + "association": "Cell", + "dataType": "Float", + "property": "", + "enabled": true + }, + "length_scale_x": { + "min": 0.0, + "group": "Regularization", + "label": "X-smoothness weight", + "tooltip": "Larger values relative to other smoothness weights will result in x biased smoothness", + "value": 1.0, + "isValue": true, + "parent": "mesh", + "association": "Cell", + "dataType": "Float", + "property": "", + "enabled": true + }, + "length_scale_y": { + "min": 0.0, + "group": "Regularization", + "label": "Y-smoothness weight", + "tooltip": "Larger values relative to other smoothness weights will result in y biased smoothness", + "value": 1.0, + "isValue": true, + "parent": "mesh", + "association": "Cell", + "dataType": "Float", + "property": "", + "enabled": true + }, + "length_scale_z": { + "min": 0.0, + "group": "Regularization", + "label": "Z-smoothness weight", + "tooltip": "Larger values relative to other smoothness weights will result in z biased smoothness", + "value": 1.0, + "isValue": true, + "parent": "mesh", + "association": "Cell", + "dataType": "Float", + "property": "", + "enabled": true + }, + "gradient_rotation": { + "group": "Regularization", + "association": "Cell", + "dataType": "Float", + "dataGroupType": [ + "Strike & dip", + "Dip direction & dip", + "3D vector" + ], + "label": "Gradient rotation", + "parent": "mesh", + "value": "", + "optional": true, + "tooltip": "Rotate the gradient of the regularization to align with a provided structural orientation.\nThe data should be provided as a data group in the form of either strike & dip, dip direction & dip, or x/y/z components.", + "enabled": false + }, + "s_norm": { + "association": "Cell", + "dataType": "Float", + "group": "Sparse/blocky model", + "label": "Smallness norm", + "isValue": true, + "parent": "mesh", + "property": "", + "value": 0.0, + "min": 0.0, + "max": 2.0, + "precision": 2, + "lineEdit": true, + "enabled": true, + "dependency": "reference_model", + "dependencyType": "enabled", + "tooltip": "Lp-norm used in the smallness term of the objective function" + }, + "x_norm": { + "association": "Cell", + "dataType": "Float", + "group": "Sparse/blocky model", + "label": "X-smoothness norm", + "isValue": true, + "parent": "mesh", + "property": "", + "value": 2.0, + "min": 0.0, + "max": 2.0, + "precision": 2, + "lineEdit": false, + "enabled": true, + "tooltip": "Lp-norm used in the x-smoothness term of the objective function" + }, + "y_norm": { + "association": "Cell", + "dataType": "Float", + "group": "Sparse/blocky model", + "label": "Y-smoothness norm", + "isValue": true, + "parent": "mesh", + "property": "", + "value": 2.0, + "min": 0.0, + "max": 2.0, + "precision": 2, + "lineEdit": false, + "enabled": true, + "tooltip": "Lp-norm used in the y-smoothness term of the objective function" + }, + "z_norm": { + "association": "Cell", + "dataType": "Float", + "group": "Sparse/blocky model", + "label": "Z-smoothness norm", + "isValue": true, + "parent": "mesh", + "property": "", + "value": 2.0, + "min": 0.0, + "max": 2.0, + "precision": 2, + "lineEdit": false, + "enabled": true, + "tooltip": "Lp-norm used in the z-smoothness term of the objective function" + }, + "max_irls_iterations": { + "min": 0, + "group": "Sparse/blocky model", + "label": "Maximum IRLS iterations", + "tooltip": "Iterative Re-Weighted Least-squares (IRLS) iterations for non-L2 problems", + "value": 25, + "enabled": true, + "verbose": 2 + }, + "starting_chi_factor": { + "group": "Sparse/blocky model", + "label": "IRLS start chi factor", + "enabled": true, + "value": 1.0, + "tooltip": "This chi factor will be used to determine the misfit threshold after which IRLS iterations begin", + "verbose": 3 + }, + "beta_tol": { + "group": "Update IRLS directive", + "label": "Beta tolerance", + "value": 0.5, + "min": 0.0001, + "verbose": 3, + "visible": false + }, + "percentile": { + "group": "Update IRLS directive", + "label": "Percentile", + "value": 95, + "max": 100, + "min": 5, + "verbose": 3, + "visible": false + }, + "chi_factor": { + "min": 0.1, + "max": 20.0, + "precision": 1, + "lineEdit": false, + "group": "Cooling schedule/target", + "label": "Chi factor", + "value": 1.0, + "enabled": true, + "tooltip": "The global target data misfit value" + }, + "auto_scale_tiles": { + "group": "Cooling schedule/target", + "label": "Auto-scale tiles", + "value": false, + "verbose": 3, + "visible": true, + "tooltip": "Whether to auto-scale the misfit function of tiles based on chi-factor" + }, + "initial_beta_ratio": { + "min": 0.0, + "precision": 2, + "group": "Cooling schedule/target", + "optional": true, + "enabled": true, + "label": "Initial beta ratio", + "value": 100.0, + "verbose": 2, + "tooltip": "Estimate the trade-off parameter by scaling the ratio between the largest derivatives in the objective function gradients" + }, + "initial_beta": { + "min": 0.0, + "group": "Cooling schedule/target", + "optional": true, + "enabled": false, + "dependency": "initial_beta_ratio", + "dependencyType": "disabled", + "label": "Initial beta", + "value": 1.0, + "verbose": 2, + "tooltip": "Trade-off parameter between data misfit and regularization" + }, + "cooling_factor": { + "group": "Cooling schedule/target", + "label": "Beta cooling factor", + "tooltip": "Each beta cooling step will be calculated by dividing the current beta by this factor", + "value": 2.0, + "min": 1.1, + "max": 100, + "precision": 1, + "lineEdit": false, + "verbose": 2 + }, + "cooling_rate": { + "group": "Optimization", + "label": "Iterations per beta", + "value": 2, + "min": 1, + "LineEdit": false, + "max": 10, + "precision": 1, + "verbose": 2, + "enabled": true, + "tooltip": "Set the number of iterations per beta value. Use higher values for more non-linear optimization problems" + }, + "epsilon_cooling_factor": 1.2, + "max_global_iterations": { + "min": 1, + "lineEdit": false, + "group": "Optimization", + "label": "Maximum iterations", + "tooltip": "Number of L2 and IRLS iterations combined", + "value": 50, + "enabled": true + }, + "max_line_search_iterations": { + "group": "Optimization", + "label": "Maximum number of line searches", + "value": 20, + "min": 1, + "enabled": true, + "verbose": 3, + "tooltip": "Perform an Armijo backtracking line search for the provided number of iterations" + }, + "max_cg_iterations": { + "min": 0, + "group": "Optimization", + "label": "Maximum CG iterations", + "value": 30, + "enabled": true, + "tooltip": "Maximum number of iterations for the conjugate gradient solver used in the optimization", + "verbose": 2 + }, + "tol_cg": { + "min": 0, + "group": "Optimization", + "label": "Conjugate gradient tolerance", + "value": 0.0001, + "enabled": true, + "tooltip": "Tolerance for the conjugate gradient solver used in the optimization", + "verbose": 3 + }, + "f_min_change": { + "group": "Optimization", + "label": "Minimum change in objective function", + "value": 0.01, + "min": 1e-06, + "verbose": 3, + "enabled": true, + "tooltip": "Minimum decrease in regularization beyond which the IRLS procedure is deemed to have completed" + }, + "sens_wts_threshold": { + "group": "Update sensitivity weights directive", + "tooltip": "Threshold below which sensitivity weights become constant. Measured as a percentage of the maximum sensitivity weight.", + "label": "Threshold (%)", + "value": 1.0, + "max": 100.0, + "min": 0.0, + "precision": 3, + "enabled": true, + "verbose": 2 + }, + "every_iteration_bool": { + "group": "Update sensitivity weights directive", + "tooltip": "Update weights at every iteration", + "label": "Every iteration", + "value": true, + "verbose": 2, + "enabled": true + }, + "save_sensitivities": { + "group": "Update sensitivity weights directive", + "label": "Save sensitivities", + "tooltip": "Save the summed square row sensitivities to geoh5", + "value": false + }, + "n_cpu": { + "min": 1, + "group": "Compute", + "optional": true, + "enabled": false, + "label": "Number of CPUs", + "value": 1, + "visible": false + }, + "solver_type": { + "choiceList": [ + "Pardiso", + "Mumps" + ], + "group": "Compute", + "label": "Direct solver", + "tooltip": "Direct solver to use for the forward calculations", + "value": "Pardiso" + }, + "tile_spatial": { + "group": "Compute", + "label": "Number of tiles", + "value": 1, + "min": 1, + "max": 1000, + "verbose": 2, + "tooltip": "Splits the objective function into spatial tiles for distributed computation using the Dask library" + }, + "store_sensitivities": { + "choiceList": [ + "ram" + ], + "group": "Compute", + "label": "Storage device", + "tooltip": "Only RAM storage available for now", + "value": "ram" + }, + "max_chunk_size": { + "min": 0, + "group": "Compute", + "optional": true, + "enabled": true, + "label": "Maximum chunk size (MB)", + "value": 128, + "verbose": 3, + "visible": false, + "tooltip": "Limit the chunk size used by Dask for distributed computation" + }, + "out_group": { + "label": "SimPEG group", + "value": "", + "groupType": "{55ed3daf-c192-4d4b-a439-60fa987fe2b8}", + "group": "Drag-and-drop options", + "visible": true, + "optional": true, + "enabled": false, + "tooltip": "Optionally set the SimPEG group to which results will be saved" + }, + "generate_sweep": { + "label": "Generate sweep file", + "group": "Python run preferences", + "main": true, + "value": false, + "visible": false, + "tooltip": "Generates a file for sweeping parameters instead of running the application" + }, + "n_workers": null, + "n_threads": null, + "max_ram": "", + "performance_report": false, + "distributed_workers": "" +} diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index 10d2b354d..c8ef0ff1d 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -54,6 +54,13 @@ def assets_path() -> Path: "simpeg_drivers.natural_sources.apparent_conductivity", {"forward": "AppConForwardDriver", "inversion": "AppConInversionDriver"}, ), + "borehole tdem": ( + "simpeg_drivers.electromagnetics.borehole_time_domain", + { + "forward": "BoreholeTDEMForwardDriver", + "inversion": "BoreholeTDEMInversionDriver", + }, + ), "direct current 3d": ( "simpeg_drivers.electricals.direct_current.three_dimensions", { diff --git a/simpeg_drivers/components/data.py b/simpeg_drivers/components/data.py index ebcd1a957..eed8089bb 100644 --- a/simpeg_drivers/components/data.py +++ b/simpeg_drivers/components/data.py @@ -188,6 +188,7 @@ def save_data(self): """Write out the data to geoh5""" has_channels = self.params.inversion_type in [ "apparent conductivity", + "borehole tdem", "magnetotellurics", "tipper", "tdem", diff --git a/simpeg_drivers/components/factories/directives_factory.py b/simpeg_drivers/components/factories/directives_factory.py index c7b9c5631..8502f14da 100644 --- a/simpeg_drivers/components/factories/directives_factory.py +++ b/simpeg_drivers/components/factories/directives_factory.py @@ -262,6 +262,7 @@ def save_iteration_residual_directive(self): not in [ "apparent conductivity", "tdem", + "borehole tdem", "tdem 1d", "fdem", "fdem 1d", @@ -440,6 +441,7 @@ def assemble_keyword_arguments( "magnetotellurics", "tipper", "tdem", + "borehole tdem", "tdem 1d", "fdem", "fdem 1d", diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index aac55f10e..da3df0964 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -271,4 +271,7 @@ def validate_orientations(self): return orientations + # elif "borehole" in self.params.inversion_type: + # pass + return normals diff --git a/simpeg_drivers/components/factories/simpeg_factory.py b/simpeg_drivers/components/factories/simpeg_factory.py index 853aa76cc..c145ce916 100644 --- a/simpeg_drivers/components/factories/simpeg_factory.py +++ b/simpeg_drivers/components/factories/simpeg_factory.py @@ -46,6 +46,7 @@ class SimPEGFactory(ABC): valid_factory_types = [ "apparent conductivity", + "borehole tdem", "direct current pseudo 3d", "direct current 3d", "direct current 2d", diff --git a/simpeg_drivers/components/factories/simulation_factory.py b/simpeg_drivers/components/factories/simulation_factory.py index fcc59606e..c9f37d67b 100644 --- a/simpeg_drivers/components/factories/simulation_factory.py +++ b/simpeg_drivers/components/factories/simulation_factory.py @@ -41,6 +41,7 @@ def __init__(self, params: BaseParams | BaseOptions): self.solver = None if self.factory_type in [ "apparent conductivity", + "borehole tdem", "direct current pseudo 3d", "direct current 3d", "direct current 2d", @@ -185,6 +186,7 @@ def assemble_keyword_arguments(self, survey=None, mesh=None, models=None, **kwar if self.factory_type in [ "apparent conductivity", + "borehole tdem", "direct current 3d", "direct current 2d", "magnetotellurics", diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/__init__.py b/simpeg_drivers/electromagnetics/borehole_time_domain/__init__.py new file mode 100644 index 000000000..df32b2043 --- /dev/null +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/__init__.py @@ -0,0 +1,9 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2023-2026 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/electromagnetics/borehole_time_domain/forward.py b/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py new file mode 100644 index 000000000..2a4a8ff56 --- /dev/null +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py @@ -0,0 +1,27 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2023-2026 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 simpeg_drivers.driver import ForwardDriver +from simpeg_drivers.electromagnetics.time_domain.options import TDEMForwardOptions +from simpeg_drivers.utils.utils import argument_parser + + +class BoreholeTDEMForwardDriver(ForwardDriver): + """Time Domain Electromagnetic forward driver.""" + + _params_class = TDEMForwardOptions + + +if __name__ == "__main__": + file, args = argument_parser() + BoreholeTDEMForwardDriver.start_dask_run(file, **args) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py b/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py new file mode 100644 index 000000000..031c471c2 --- /dev/null +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py @@ -0,0 +1,29 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2023-2026 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 simpeg_drivers.driver import InversionDriver +from simpeg_drivers.electromagnetics.borehole_time_domain.options import ( + BoreholeTDEMInversionOptions, +) +from simpeg_drivers.utils.utils import argument_parser + + +class BoreholeTDEMInversionDriver(InversionDriver): + """Time Domain Electromagnetic inversion driver.""" + + _params_class = BoreholeTDEMInversionOptions + + +if __name__ == "__main__": + file, args = argument_parser() + BoreholeTDEMInversionDriver.start_dask_run(file, **args) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py new file mode 100644 index 000000000..cde98f7f6 --- /dev/null +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py @@ -0,0 +1,64 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2023-2026 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 +from typing import ClassVar + +from simpeg_drivers import assets_path +from simpeg_drivers.electromagnetics.time_domain.options import ( + TDEMForwardOptions, + TDEMInversionOptions, +) + + +class BoreholeTDEMForwardOptions(TDEMForwardOptions): + """ + Time Domain Electromagnetic forward options for borehole surveys. + + :param vertical_channel_bool: Vertical (U) data channel boolean. + :param inline_channel_bool: In-line (A) data channel boolean. + :param crossline_channel_bool: Cross-line (V) data channel boolean. + """ + + name: ClassVar[str] = "Borehole TDEM Forward" + default_ui_json: ClassVar[Path] = ( + assets_path() / "uijson/borehole_tdem_forward.ui.json" + ) + run_command: str = "simpeg_drivers.electromagnetics.borehole_time_domain.forward" + + title: str = "Borehole TDEM Forward" + icon: str = "surveyairborneem" + inversion_type: str = "borehole tdem" + + +class BoreholeTDEMInversionOptions(TDEMInversionOptions): + """ + Time Domain Electromagnetic Inversion options for borehole surveys. + + :param vertical_channel: Vertical (U) component data channel. + :param vertical_uncertainty: Vertical (U) component data channel uncertainty. + :param inline_channel: In-line (A) data channel. + :param inline_uncertainty: In-line (A) data channel uncertainty. + :param crossline_channel: Cross-line (V) data channel. + :param crossline_uncertainty: Cross-line(V) data channel uncertainty. + """ + + name: ClassVar[str] = "Borehole TDEM Inversion" + default_ui_json: ClassVar[Path] = ( + assets_path() / "uijson/borehole_tdem_inversion.ui.json" + ) + run_command: str = "simpeg_drivers.electromagnetics.borehole_time_domain.inversion" + title: str = "Borehole TDEM Inversion" + icon: str = "surveyairborneem" + physical_property: str = "conductivity" + inversion_type: str = "borehole tdem" From af0d7b8b520b7e0b1aa468c78a6d658ddab2e835 Mon Sep 17 00:00:00 2001 From: domfournier Date: Thu, 20 Aug 2026 10:24:39 -0700 Subject: [PATCH 02/20] Improve logic for orientation on boerhole --- .../uijson/borehole_tdem_forward.ui.json | 3 +-- .../uijson/borehole_tdem_inversion.ui.json | 3 +-- .../components/factories/receiver_factory.py | 21 ++++++++----------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json index cfc7fd72b..508b6d6ba 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json @@ -37,8 +37,7 @@ "optional": true, "enabled": false, "parent": "data_object", - "value": "", - "visible": false + "value": "" }, "data_units": { "choiceList": [ diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json index ccaf8bfe5..189277bb8 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json @@ -37,8 +37,7 @@ "optional": true, "enabled": false, "parent": "data_object", - "value": "", - "visible": false + "value": "" }, "data_units": { "choiceList": [ diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index da3df0964..e0b18900e 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -14,15 +14,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING - - -if TYPE_CHECKING: - from geoapps_utils.driver.params import BaseParams - - from simpeg_drivers.options import BaseOptions - import numpy as np +from geoapps_utils.utils.locations import azimuth_dip_from_segments from geoapps_utils.utils.transformations import x_rotation_matrix, z_rotation_matrix from geoh5py.objects.surveys.electromagnetics.base import ( AirborneEMSurvey, @@ -30,6 +23,7 @@ ) from simpeg_drivers.components.factories.simpeg_factory import SimPEGFactory +from simpeg_drivers.options import CoreOptions from simpeg_drivers.utils.regularization import direction_and_dip, get_cell_normals @@ -45,7 +39,7 @@ class ReceiversFactory(SimPEGFactory): """Build SimPEG receivers objects based on factory type.""" - def __init__(self, params: BaseParams | BaseOptions): + def __init__(self, params: CoreOptions): """ :param params: Options object containing SimPEG object parameters. @@ -259,9 +253,15 @@ def validate_orientations(self): for comp in "xyz" } + azi_dip = None if getattr(self.params, "receivers_orientation", None): azm, dip = direction_and_dip(self.params.receivers_orientation) azi_dip = np.deg2rad(np.c_[azm.values, dip.values]) + + elif "borehole" in self.params.inversion_type: + azi_dip = azimuth_dip_from_segments(self.params.data_object) + + if azi_dip is not None: orientations = {} for axis in "xyz": orientations[axis] = ( @@ -271,7 +271,4 @@ def validate_orientations(self): return orientations - # elif "borehole" in self.params.inversion_type: - # pass - return normals From 5e2868df40a6532078e51cb67acfcb7bc9c506b9 Mon Sep 17 00:00:00 2001 From: domfournier Date: Thu, 20 Aug 2026 16:41:37 -0700 Subject: [PATCH 03/20] Switch to AUV channels --- .../uijson/borehole_tdem_forward.ui.json | 6 +- .../uijson/borehole_tdem_inversion.ui.json | 22 +++---- .../components/factories/receiver_factory.py | 27 ++++++-- .../factories/simulation_factory.py | 2 +- .../borehole_time_domain/forward.py | 11 ++-- .../borehole_time_domain/inversion.py | 5 +- .../borehole_time_domain/options.py | 65 +++++++++++++++---- 7 files changed, 99 insertions(+), 39 deletions(-) diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json index 508b6d6ba..5e6ac4c73 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json @@ -58,21 +58,21 @@ ], "value": "Airborne dB/dt (V/Am^4)" }, - "inline_channel_bool": { + "A_channel_bool": { "group": "Survey", "main": true, "label": "A-component", "tooltip": "Axial (A) component parallel to the hole trace.\nPositive upward along the hole trace", "value": true }, - "vertical_channel_bool": { + "U_channel_bool": { "group": "Survey", "main": true, "label": "U-component", "tooltip": "Perpendicular (U) component of the magnetic data.\nPositive upward in the hole dip direction", "value": true }, - "crossline_channel_bool": { + "V_channel_bool": { "group": "Survey", "main": true, "label": "V-component", diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json index 189277bb8..8ee1c8034 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json @@ -58,7 +58,7 @@ ], "value": "Airborne dB/dt (V/Am^4)" }, - "inline_channel": { + "A_channel": { "association": [ "Cell", "Vertex" @@ -71,10 +71,10 @@ "parent": "data_object", "tooltip": "Axial (A) component parallel to the hole trace.\nPositive upward along the hole trace", "optional": true, - "enabled": false, + "enabled": true, "value": "" }, - "inline_uncertainty": { + "A_uncertainty": { "association": [ "Cell", "Vertex" @@ -85,11 +85,11 @@ "main": true, "label": "Uncertainty", "parent": "data_object", - "dependency": "inline_channel", + "dependency": "A_channel", "dependencyType": "enabled", "value": "" }, - "vertical_channel": { + "U_channel": { "association": [ "Cell", "Vertex" @@ -102,10 +102,10 @@ "parent": "data_object", "tooltip": "Perpendicular (U) component of the magnetic data.\nPositive upward in the hole dip direction", "optional": true, - "enabled": true, + "enabled": false, "value": "" }, - "vertical_uncertainty": { + "U_uncertainty": { "association": [ "Cell", "Vertex" @@ -116,11 +116,11 @@ "main": true, "label": "Uncertainty", "parent": "data_object", - "dependency": "vertical_channel", + "dependency": "U_channel", "dependencyType": "enabled", "value": "" }, - "crossline_channel": { + "V_channel": { "association": [ "Cell", "Vertex" @@ -136,7 +136,7 @@ "enabled": false, "value": "" }, - "crossline_uncertainty": { + "V_uncertainty": { "association": [ "Cell", "Vertex" @@ -147,7 +147,7 @@ "main": true, "label": "Uncertainty", "parent": "data_object", - "dependency": "crossline_channel", + "dependency": "V_channel", "dependencyType": "enabled", "value": "" }, diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index e0b18900e..efb8028f1 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -16,7 +16,12 @@ import numpy as np from geoapps_utils.utils.locations import azimuth_dip_from_segments -from geoapps_utils.utils.transformations import x_rotation_matrix, z_rotation_matrix +from geoapps_utils.utils.transformations import ( + cartesian_to_azimuth_dip, + x_rotation_matrix, + z_rotation_matrix, +) +from geoh5py.groups.property_group_type import GroupTypeEnum from geoh5py.objects.surveys.electromagnetics.base import ( AirborneEMSurvey, LargeLoopGroundEMSurvey, @@ -33,6 +38,9 @@ "vertical": "z", "inline": "y", "crossline": "x", + "A": "y", + "U": "z", + "V": "x", } @@ -254,9 +262,20 @@ def validate_orientations(self): } azi_dip = None - if getattr(self.params, "receivers_orientation", None): - azm, dip = direction_and_dip(self.params.receivers_orientation) - azi_dip = np.deg2rad(np.c_[azm.values, dip.values]) + + if property_group := getattr(self.params, "receivers_orientation", None): + group_type = property_group.property_group_type + azi_dip = np.vstack( + [ + property_group.parent.get_data(k)[0].values + for k in property_group.properties + ] + ).T + + if group_type == GroupTypeEnum.VECTOR: + azi_dip = cartesian_to_azimuth_dip(azi_dip) + else: + azi_dip = np.deg2rad(azi_dip) elif "borehole" in self.params.inversion_type: azi_dip = azimuth_dip_from_segments(self.params.data_object) diff --git a/simpeg_drivers/components/factories/simulation_factory.py b/simpeg_drivers/components/factories/simulation_factory.py index c9f37d67b..ad9b20a30 100644 --- a/simpeg_drivers/components/factories/simulation_factory.py +++ b/simpeg_drivers/components/factories/simulation_factory.py @@ -111,7 +111,7 @@ def concrete_object(self): return simulation_1d.Simulation1DLayered - if self.factory_type in ["tdem"]: + if self.factory_type in ["tdem", "borehole tdem"]: from simpeg.electromagnetics.time_domain import simulation return simulation.Simulation3DMagneticFluxDensity diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py b/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py index 2a4a8ff56..5893d84a3 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py @@ -12,16 +12,19 @@ from __future__ import annotations from simpeg_drivers.driver import ForwardDriver -from simpeg_drivers.electromagnetics.time_domain.options import TDEMForwardOptions +from simpeg_drivers.electromagnetics.borehole_time_domain.options import ( + BoreholeTDEMForwardOptions, +) from simpeg_drivers.utils.utils import argument_parser class BoreholeTDEMForwardDriver(ForwardDriver): """Time Domain Electromagnetic forward driver.""" - _params_class = TDEMForwardOptions + _params_class = BoreholeTDEMForwardOptions if __name__ == "__main__": - file, args = argument_parser() - BoreholeTDEMForwardDriver.start_dask_run(file, **args) + # file, args = argument_parser() + file = r"C:\Users\dominiquef\Documents\tests\Borehole_EM\fwr_model_A.ui.json" + BoreholeTDEMForwardDriver.start_dask_run(file) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py b/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py index 031c471c2..c3743165e 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py @@ -25,5 +25,6 @@ class BoreholeTDEMInversionDriver(InversionDriver): if __name__ == "__main__": - file, args = argument_parser() - BoreholeTDEMInversionDriver.start_dask_run(file, **args) + # file, args = argument_parser() + file = r"C:\Users\dominiquef\Documents\tests\Borehole_EM\inv_run1.ui.json" + BoreholeTDEMInversionDriver.start_dask_run(file) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py index cde98f7f6..4bcb4feba 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py @@ -14,20 +14,29 @@ from pathlib import Path from typing import ClassVar +from geoh5py.groups import PropertyGroup +from geoh5py.objects import ( + AirborneTEMReceivers, + LargeLoopGroundTEMReceivers, + MovingLoopGroundTEMReceivers, +) + from simpeg_drivers import assets_path -from simpeg_drivers.electromagnetics.time_domain.options import ( - TDEMForwardOptions, - TDEMInversionOptions, +from simpeg_drivers.electromagnetics.time_domain.options import BaseTDEMOptions +from simpeg_drivers.options import ( + BaseForwardOptions, + BaseInversionOptions, + ConductivityModelOptions, ) -class BoreholeTDEMForwardOptions(TDEMForwardOptions): +class BoreholeTDEMForwardOptions(BaseTDEMOptions, BaseForwardOptions): """ Time Domain Electromagnetic forward options for borehole surveys. - :param vertical_channel_bool: Vertical (U) data channel boolean. - :param inline_channel_bool: In-line (A) data channel boolean. - :param crossline_channel_bool: Cross-line (V) data channel boolean. + :param A_channel_bool: In-line (A) data channel boolean. + :param U_channel_bool: Vertical (U) data channel boolean. + :param V_channel_bool: Cross-line (V) data channel boolean. """ name: ClassVar[str] = "Borehole TDEM Forward" @@ -39,18 +48,31 @@ class BoreholeTDEMForwardOptions(TDEMForwardOptions): title: str = "Borehole TDEM Forward" icon: str = "surveyairborneem" inversion_type: str = "borehole tdem" + physical_property: str = "conductivity" + + data_object: ( + MovingLoopGroundTEMReceivers + | LargeLoopGroundTEMReceivers + | AirborneTEMReceivers + ) + receivers_orientation: PropertyGroup | None = None + A_channel_bool: bool = False + U_channel_bool: bool = False + V_channel_bool: bool = False + models: ConductivityModelOptions -class BoreholeTDEMInversionOptions(TDEMInversionOptions): + +class BoreholeTDEMInversionOptions(BaseTDEMOptions, BaseInversionOptions): """ Time Domain Electromagnetic Inversion options for borehole surveys. - :param vertical_channel: Vertical (U) component data channel. - :param vertical_uncertainty: Vertical (U) component data channel uncertainty. - :param inline_channel: In-line (A) data channel. - :param inline_uncertainty: In-line (A) data channel uncertainty. - :param crossline_channel: Cross-line (V) data channel. - :param crossline_uncertainty: Cross-line(V) data channel uncertainty. + :param U_channel: Vertical (U) component data channel. + :param U_uncertainty: Vertical (U) component data channel uncertainty. + :param A_channel: In-line (A) data channel. + :param A_uncertainty: In-line (A) data channel uncertainty. + :param V_channel: Cross-line (V) data channel. + :param V_uncertainty: Cross-line(V) data channel uncertainty. """ name: ClassVar[str] = "Borehole TDEM Inversion" @@ -62,3 +84,18 @@ class BoreholeTDEMInversionOptions(TDEMInversionOptions): icon: str = "surveyairborneem" physical_property: str = "conductivity" inversion_type: str = "borehole tdem" + + data_object: ( + MovingLoopGroundTEMReceivers + | LargeLoopGroundTEMReceivers + | AirborneTEMReceivers + ) + receivers_orientation: PropertyGroup | None = None + U_channel: PropertyGroup | None = None + U_uncertainty: PropertyGroup | None = None + A_channel: PropertyGroup | None = None + A_uncertainty: PropertyGroup | None = None + V_channel: PropertyGroup | None = None + V_uncertainty: PropertyGroup | None = None + + models: ConductivityModelOptions From 67dfd67fe328a45b478594adb023c17c6e01f2cf Mon Sep 17 00:00:00 2001 From: domfournier Date: Thu, 20 Aug 2026 16:49:31 -0700 Subject: [PATCH 04/20] Update deps-lock --- .../py-3.12-linux-64-dev.conda.lock.yml | 2 +- .../py-3.12-win-64-dev.conda.lock.yml | 6 ++-- environments/py-3.12-win-64.conda.lock.yml | 4 +-- .../py-3.13-linux-64-dev.conda.lock.yml | 2 +- .../py-3.13-win-64-dev.conda.lock.yml | 6 ++-- environments/py-3.13-win-64.conda.lock.yml | 4 +-- py-3.12.conda-lock.yml | 30 +++++++++---------- py-3.13.conda-lock.yml | 30 +++++++++---------- 8 files changed, 42 insertions(+), 42 deletions(-) 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 f59830762..1a1a76488 100644 --- a/environments/py-3.12-linux-64-dev.conda.lock.yml +++ b/environments/py-3.12-linux-64-dev.conda.lock.yml @@ -12,7 +12,7 @@ dependencies: - annotated-types=0.8.0=pyhd8ed1ab_0 - anyio=4.14.2=pyhcf101f3_0 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - - argon2-cffi-bindings=25.1.0=py312h4c3975b_2 + - argon2-cffi-bindings=26.1.0=py312h5cc1888_0 - arrow=1.4.0=pyhcf101f3_0 - asciitree=0.3.3=py_2 - astroid=4.0.4=py312h7900ff3_0 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 86c03fcfd..146f67e80 100644 --- a/environments/py-3.12-win-64-dev.conda.lock.yml +++ b/environments/py-3.12-win-64-dev.conda.lock.yml @@ -12,7 +12,7 @@ dependencies: - annotated-types=0.8.0=pyhd8ed1ab_0 - anyio=4.14.2=pyhcf101f3_0 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - - argon2-cffi-bindings=25.1.0=py312he06e257_2 + - argon2-cffi-bindings=26.1.0=py312he06e257_0 - arrow=1.4.0=pyhcf101f3_0 - asciitree=0.3.3=py_2 - astroid=4.0.4=py312h2e8e312_0 @@ -146,8 +146,8 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h57928b3_10 - libxcb=1.17.0=h874e120_1 - - libxml2=2.15.3=h8ef44ab_0 - - libxml2-16=2.15.3=h3cfd58e_0 + - libxml2=2.15.3=h8ef44ab_1 + - libxml2-16=2.15.3=h3cfd58e_1 - libzlib=1.3.2=hfd05255_3 - llvm-openmp=22.1.8=h4fa8253_0 - locket=1.0.0=pyhd8ed1ab_0 diff --git a/environments/py-3.12-win-64.conda.lock.yml b/environments/py-3.12-win-64.conda.lock.yml index 8ce1ffa08..28b9cbcda 100644 --- a/environments/py-3.12-win-64.conda.lock.yml +++ b/environments/py-3.12-win-64.conda.lock.yml @@ -85,8 +85,8 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h57928b3_10 - libxcb=1.17.0=h874e120_1 - - libxml2=2.15.3=h8ef44ab_0 - - libxml2-16=2.15.3=h3cfd58e_0 + - libxml2=2.15.3=h8ef44ab_1 + - libxml2-16=2.15.3=h3cfd58e_1 - libzlib=1.3.2=hfd05255_3 - llvm-openmp=22.1.8=h4fa8253_0 - locket=1.0.0=pyhd8ed1ab_0 diff --git a/environments/py-3.13-linux-64-dev.conda.lock.yml b/environments/py-3.13-linux-64-dev.conda.lock.yml index be6c30a34..37fe0f41f 100644 --- a/environments/py-3.13-linux-64-dev.conda.lock.yml +++ b/environments/py-3.13-linux-64-dev.conda.lock.yml @@ -12,7 +12,7 @@ dependencies: - annotated-types=0.8.0=pyhd8ed1ab_0 - anyio=4.14.2=pyhcf101f3_0 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - - argon2-cffi-bindings=25.1.0=py313h07c4f96_2 + - argon2-cffi-bindings=26.1.0=py313h995f894_0 - arrow=1.4.0=pyhcf101f3_0 - asciitree=0.3.3=py_2 - astroid=4.0.4=py313h78bf25f_0 diff --git a/environments/py-3.13-win-64-dev.conda.lock.yml b/environments/py-3.13-win-64-dev.conda.lock.yml index cee746e26..cb570c442 100644 --- a/environments/py-3.13-win-64-dev.conda.lock.yml +++ b/environments/py-3.13-win-64-dev.conda.lock.yml @@ -12,7 +12,7 @@ dependencies: - annotated-types=0.8.0=pyhd8ed1ab_0 - anyio=4.14.2=pyhcf101f3_0 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - - argon2-cffi-bindings=25.1.0=py313h5ea7bf4_2 + - argon2-cffi-bindings=26.1.0=py313h5ea7bf4_0 - arrow=1.4.0=pyhcf101f3_0 - asciitree=0.3.3=py_2 - astroid=4.0.4=py313hfa70ccb_0 @@ -147,8 +147,8 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h57928b3_10 - libxcb=1.17.0=h874e120_1 - - libxml2=2.15.3=h8ef44ab_0 - - libxml2-16=2.15.3=h3cfd58e_0 + - libxml2=2.15.3=h8ef44ab_1 + - libxml2-16=2.15.3=h3cfd58e_1 - libzlib=1.3.2=hfd05255_3 - llvm-openmp=22.1.8=h4fa8253_0 - locket=1.0.0=pyhd8ed1ab_0 diff --git a/environments/py-3.13-win-64.conda.lock.yml b/environments/py-3.13-win-64.conda.lock.yml index 23a45ba42..95471aa82 100644 --- a/environments/py-3.13-win-64.conda.lock.yml +++ b/environments/py-3.13-win-64.conda.lock.yml @@ -86,8 +86,8 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h57928b3_10 - libxcb=1.17.0=h874e120_1 - - libxml2=2.15.3=h8ef44ab_0 - - libxml2-16=2.15.3=h3cfd58e_0 + - libxml2=2.15.3=h8ef44ab_1 + - libxml2-16=2.15.3=h3cfd58e_1 - libzlib=1.3.2=hfd05255_3 - llvm-openmp=22.1.8=h4fa8253_0 - locket=1.0.0=pyhd8ed1ab_0 diff --git a/py-3.12.conda-lock.yml b/py-3.12.conda-lock.yml index bf4002e6e..383888552 100644 --- a/py-3.12.conda-lock.yml +++ b/py-3.12.conda-lock.yml @@ -189,23 +189,23 @@ package: category: dev optional: true - name: argon2-cffi-bindings - version: 25.1.0 + version: 26.1.0 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' cffi: '>=1.0.1' - libgcc: '>=14' + libgcc: '>=15' python: '>=3.12,<3.13.0a0' python_abi: 3.12.* - url: https://repo.prefix.dev/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py312h4c3975b_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/argon2-cffi-bindings-26.1.0-py312h5cc1888_0.conda hash: - md5: 1567f06d717246abab170736af8bad1b - sha256: 7988c207b2b766dad5ebabf25a92b8d75cb8faed92f256fd7a4e0875c9ec6d58 + md5: 206a3c2e73a15a4956df784f165f4ed8 + sha256: 9b97ce25a43e1aa998286971da972a13f5803cccb12df45013edff46ed3dc2b3 category: dev optional: true - name: argon2-cffi-bindings - version: 25.1.0 + version: 26.1.0 manager: conda platform: win-64 dependencies: @@ -215,10 +215,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/argon2-cffi-bindings-25.1.0-py312he06e257_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/argon2-cffi-bindings-26.1.0-py312he06e257_0.conda hash: - md5: 5dc3781bbc4ddce0bf250a04c1a192c2 - sha256: 38c5e43d991b0c43713fa2ceba3063afa4ccad2dd4c8eb720143de54d461a338 + md5: 38764c8f1723841acac6c0bc2d766afc + sha256: ae4d0f74b48266849555b69b195ee96e5db7067359ffde700d5f35dc41d5f8f1 category: dev optional: true - name: arrow @@ -4385,10 +4385,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/libxml2-2.15.3-h8ef44ab_0.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-2.15.3-h8ef44ab_1.conda hash: - md5: 95591ca5671d2213f5b2d5aa7818420d - sha256: a4599c6bbbbdd7db570896e520c557eec8e66d94e839a59d17dc1f24a3d5f82b + md5: 45a5a1c709a69f14cf176220788d18a9 + sha256: a83e9adcf7c50f20289dc6890707c8e4e84151b4204b0f7344998138807458d1 category: main optional: false - name: libxml2-16 @@ -4420,10 +4420,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/libxml2-16-2.15.3-h3cfd58e_0.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-16-2.15.3-h3cfd58e_1.conda hash: - md5: 9e8dd0d90ed830107b2c36801035b7db - sha256: 3b61ee3caba702d2ff432fa3920835db963026e5c99c4e6fdca0c6114f59e7ce + md5: 6e7dadff3f3bde2d29d29a3ec34f2d58 + sha256: 8163de24a7ddb4ebf9587c3a45ba950caf3690b9646b76f007ca15e6e52b5881 category: main optional: false - name: libzlib diff --git a/py-3.13.conda-lock.yml b/py-3.13.conda-lock.yml index a3219438b..753ada955 100644 --- a/py-3.13.conda-lock.yml +++ b/py-3.13.conda-lock.yml @@ -189,23 +189,23 @@ package: category: dev optional: true - name: argon2-cffi-bindings - version: 25.1.0 + version: 26.1.0 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' cffi: '>=1.0.1' - libgcc: '>=14' + libgcc: '>=15' python: '>=3.13,<3.14.0a0' python_abi: 3.13.* - url: https://repo.prefix.dev/conda-forge/linux-64/argon2-cffi-bindings-25.1.0-py313h07c4f96_2.conda + url: https://repo.prefix.dev/conda-forge/linux-64/argon2-cffi-bindings-26.1.0-py313h995f894_0.conda hash: - md5: 27bbec9f2f3a15d32b60ec5734f5b41c - sha256: ad188ccc06a06c633dc124b09e9e06fb9df4c32ffc38acc96ecc86e506062090 + md5: db73f7be4911943040efc5ca79c9775e + sha256: e07a2c721f480ee8109b519ca2201603abcc3aed5a9673fb830adbc9b6768ab8 category: dev optional: true - name: argon2-cffi-bindings - version: 25.1.0 + version: 26.1.0 manager: conda platform: win-64 dependencies: @@ -215,10 +215,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/argon2-cffi-bindings-25.1.0-py313h5ea7bf4_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/argon2-cffi-bindings-26.1.0-py313h5ea7bf4_0.conda hash: - md5: eabb4b677b54874d7d6ab775fdaa3d27 - sha256: 3f8a1affdfeb2be5289d709e365fc6e386d734773895215cf8cbc5100fa6af9a + md5: 0e05f2b2dba8c28bc6be0ee952ce4fbc + sha256: 0532093a043aa452c90798cbff19dfc3ab4e331726239dad42ffce83538d94cc category: dev optional: true - name: arrow @@ -4384,10 +4384,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/libxml2-2.15.3-h8ef44ab_0.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-2.15.3-h8ef44ab_1.conda hash: - md5: 95591ca5671d2213f5b2d5aa7818420d - sha256: a4599c6bbbbdd7db570896e520c557eec8e66d94e839a59d17dc1f24a3d5f82b + md5: 45a5a1c709a69f14cf176220788d18a9 + sha256: a83e9adcf7c50f20289dc6890707c8e4e84151b4204b0f7344998138807458d1 category: main optional: false - name: libxml2-16 @@ -4419,10 +4419,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/libxml2-16-2.15.3-h3cfd58e_0.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-16-2.15.3-h3cfd58e_1.conda hash: - md5: 9e8dd0d90ed830107b2c36801035b7db - sha256: 3b61ee3caba702d2ff432fa3920835db963026e5c99c4e6fdca0c6114f59e7ce + md5: 6e7dadff3f3bde2d29d29a3ec34f2d58 + sha256: 8163de24a7ddb4ebf9587c3a45ba950caf3690b9646b76f007ca15e6e52b5881 category: main optional: false - name: libzlib From 408b7bd68048a959e6948c232a5b69d410ee75eb Mon Sep 17 00:00:00 2001 From: domfournier Date: Thu, 20 Aug 2026 16:57:05 -0700 Subject: [PATCH 05/20] Fix title of borehole inversion --- simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json index 8ee1c8034..83c4db3f6 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json @@ -1,6 +1,6 @@ { "version": "0.0.0", - "title": "Borehole TDEM Forward", + "title": "Borehole TDEM Inversion", "icon": "surveyairborneem", "documentation": "https://mirageoscience-simpeg-drivers.readthedocs-hosted.com/en/latest/", "conda_environment": "simpeg-drivers", From 0be23371a97f6a2d148fdc2c56b93db3d4c331d7 Mon Sep 17 00:00:00 2001 From: domfournier Date: Thu, 20 Aug 2026 17:06:01 -0700 Subject: [PATCH 06/20] Reset mains --- .../electromagnetics/borehole_time_domain/forward.py | 5 ++--- .../electromagnetics/borehole_time_domain/inversion.py | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py b/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py index 5893d84a3..d9c7e0eb7 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/forward.py @@ -25,6 +25,5 @@ class BoreholeTDEMForwardDriver(ForwardDriver): if __name__ == "__main__": - # file, args = argument_parser() - file = r"C:\Users\dominiquef\Documents\tests\Borehole_EM\fwr_model_A.ui.json" - BoreholeTDEMForwardDriver.start_dask_run(file) + file, args = argument_parser() + BoreholeTDEMForwardDriver.start_dask_run(file, **args) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py b/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py index c3743165e..031c471c2 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/inversion.py @@ -25,6 +25,5 @@ class BoreholeTDEMInversionDriver(InversionDriver): if __name__ == "__main__": - # file, args = argument_parser() - file = r"C:\Users\dominiquef\Documents\tests\Borehole_EM\inv_run1.ui.json" - BoreholeTDEMInversionDriver.start_dask_run(file) + file, args = argument_parser() + BoreholeTDEMInversionDriver.start_dask_run(file, **args) From ddf85a90d75ac4dcbedc6528dea2a78c46c806f7 Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 26 Aug 2026 12:49:20 -0700 Subject: [PATCH 07/20] Switch to lower case components a,u,v --- pyproject.toml | 8 +- .../uijson/borehole_tdem_forward.ui.json | 6 +- .../uijson/borehole_tdem_inversion.ui.json | 18 +- .../components/factories/receiver_factory.py | 6 +- .../borehole_time_domain/options.py | 36 +- tests/run_tests/driver_borehole_tem_test.py | 307 ++++++++++++++++++ 6 files changed, 344 insertions(+), 37 deletions(-) create mode 100644 tests/run_tests/driver_borehole_tem_test.py diff --git a/pyproject.toml b/pyproject.toml index 9cf2e7dd9..2ac06cadc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -94,16 +94,16 @@ trimesh = "^4.1.3" ## Pip dependencies from Git repositories #---------------------------------------- # geoh5py = {version = ">=0.14.0a, 0.14.*", source = "pypi", allow-prereleases = true} -geoh5py = {git = "https://github.com/MiraGeoscience/geoh5py.git", rev = "feature/uijson"} +geoh5py = {git = "https://github.com/MiraGeoscience/geoh5py.git", rev = "develop"} # grid-apps = {version = ">=0.3.0a, 0.3.*", source = "pypi", allow-prereleases = true} -grid-apps = {git = "https://github.com/MiraGeoscience/grid-apps.git", rev = "GEOPY-2965"} +grid-apps = {git = "https://github.com/MiraGeoscience/grid-apps.git", rev = "develop"} # geoapps-utils = {version = ">=0.8.0a, 0.8.*", source = "pypi", allow-prereleases = true} -geoapps-utils = {git = "https://github.com/MiraGeoscience/geoapps-utils.git", rev = "feature/uijson"} +geoapps-utils = {git = "https://github.com/MiraGeoscience/geoapps-utils.git", rev = "develop"} # mira-simpeg = {version = ">=0.25.0.2a, 0.25.0.*", source="pypi", allow-prereleases = true, extras = ["dask"]} -mira-simpeg = {git = "https://github.com/MiraGeoscience/simpeg.git", rev = "GEOPY-2880", extras = ["dask"]} +mira-simpeg = {git = "https://github.com/MiraGeoscience/simpeg.git", rev = "develop", extras = ["dask"]} ## about pip dependencies # to be specified to work with conda-lock diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json index 5e6ac4c73..dacb53101 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json @@ -58,21 +58,21 @@ ], "value": "Airborne dB/dt (V/Am^4)" }, - "A_channel_bool": { + "a_channel_bool": { "group": "Survey", "main": true, "label": "A-component", "tooltip": "Axial (A) component parallel to the hole trace.\nPositive upward along the hole trace", "value": true }, - "U_channel_bool": { + "u_channel_bool": { "group": "Survey", "main": true, "label": "U-component", "tooltip": "Perpendicular (U) component of the magnetic data.\nPositive upward in the hole dip direction", "value": true }, - "V_channel_bool": { + "v_channel_bool": { "group": "Survey", "main": true, "label": "V-component", diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json index 83c4db3f6..d211c2c48 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json @@ -58,7 +58,7 @@ ], "value": "Airborne dB/dt (V/Am^4)" }, - "A_channel": { + "a_channel": { "association": [ "Cell", "Vertex" @@ -74,7 +74,7 @@ "enabled": true, "value": "" }, - "A_uncertainty": { + "a_uncertainty": { "association": [ "Cell", "Vertex" @@ -85,11 +85,11 @@ "main": true, "label": "Uncertainty", "parent": "data_object", - "dependency": "A_channel", + "dependency": "a_channel", "dependencyType": "enabled", "value": "" }, - "U_channel": { + "u_channel": { "association": [ "Cell", "Vertex" @@ -105,7 +105,7 @@ "enabled": false, "value": "" }, - "U_uncertainty": { + "u_uncertainty": { "association": [ "Cell", "Vertex" @@ -116,11 +116,11 @@ "main": true, "label": "Uncertainty", "parent": "data_object", - "dependency": "U_channel", + "dependency": "u_channel", "dependencyType": "enabled", "value": "" }, - "V_channel": { + "v_channel": { "association": [ "Cell", "Vertex" @@ -136,7 +136,7 @@ "enabled": false, "value": "" }, - "V_uncertainty": { + "v_uncertainty": { "association": [ "Cell", "Vertex" @@ -147,7 +147,7 @@ "main": true, "label": "Uncertainty", "parent": "data_object", - "dependency": "V_channel", + "dependency": "v_channel", "dependencyType": "enabled", "value": "" }, diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index efb8028f1..1a0423081 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -38,9 +38,9 @@ "vertical": "z", "inline": "y", "crossline": "x", - "A": "y", - "U": "z", - "V": "x", + "a": "y", + "u": "z", + "v": "x", } diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py index 4bcb4feba..7902009bf 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py @@ -34,9 +34,9 @@ class BoreholeTDEMForwardOptions(BaseTDEMOptions, BaseForwardOptions): """ Time Domain Electromagnetic forward options for borehole surveys. - :param A_channel_bool: In-line (A) data channel boolean. - :param U_channel_bool: Vertical (U) data channel boolean. - :param V_channel_bool: Cross-line (V) data channel boolean. + :param a_channel_bool: In-line (A) data channel boolean. + :param u_channel_bool: Vertical (U) data channel boolean. + :param v_channel_bool: Cross-line (V) data channel boolean. """ name: ClassVar[str] = "Borehole TDEM Forward" @@ -56,9 +56,9 @@ class BoreholeTDEMForwardOptions(BaseTDEMOptions, BaseForwardOptions): | AirborneTEMReceivers ) receivers_orientation: PropertyGroup | None = None - A_channel_bool: bool = False - U_channel_bool: bool = False - V_channel_bool: bool = False + a_channel_bool: bool = False + u_channel_bool: bool = False + v_channel_bool: bool = False models: ConductivityModelOptions @@ -67,12 +67,12 @@ class BoreholeTDEMInversionOptions(BaseTDEMOptions, BaseInversionOptions): """ Time Domain Electromagnetic Inversion options for borehole surveys. - :param U_channel: Vertical (U) component data channel. - :param U_uncertainty: Vertical (U) component data channel uncertainty. - :param A_channel: In-line (A) data channel. - :param A_uncertainty: In-line (A) data channel uncertainty. - :param V_channel: Cross-line (V) data channel. - :param V_uncertainty: Cross-line(V) data channel uncertainty. + :param u_channel: Vertical (U) component data channel. + :param u_uncertainty: Vertical (U) component data channel uncertainty. + :param a_channel: In-line (A) data channel. + :param a_uncertainty: In-line (A) data channel uncertainty. + :param v_channel: Cross-line (V) data channel. + :param v_uncertainty: Cross-line(V) data channel uncertainty. """ name: ClassVar[str] = "Borehole TDEM Inversion" @@ -91,11 +91,11 @@ class BoreholeTDEMInversionOptions(BaseTDEMOptions, BaseInversionOptions): | AirborneTEMReceivers ) receivers_orientation: PropertyGroup | None = None - U_channel: PropertyGroup | None = None - U_uncertainty: PropertyGroup | None = None - A_channel: PropertyGroup | None = None - A_uncertainty: PropertyGroup | None = None - V_channel: PropertyGroup | None = None - V_uncertainty: PropertyGroup | None = None + u_channel: PropertyGroup | None = None + u_uncertainty: PropertyGroup | None = None + a_channel: PropertyGroup | None = None + a_uncertainty: PropertyGroup | None = None + v_channel: PropertyGroup | None = None + v_uncertainty: PropertyGroup | None = None models: ConductivityModelOptions diff --git a/tests/run_tests/driver_borehole_tem_test.py b/tests/run_tests/driver_borehole_tem_test.py new file mode 100644 index 000000000..389cff256 --- /dev/null +++ b/tests/run_tests/driver_borehole_tem_test.py @@ -0,0 +1,307 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2023-2026 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 re +from logging import INFO, getLogger +from pathlib import Path + +import numpy as np +from geoapps_utils.modelling.plates import PlateModel +from geoh5py.workspace import Workspace +from pymatsolver.direct import Mumps + +from simpeg_drivers.electromagnetics.time_domain.forward import ( + TDEMForwardDriver, + TDEMForwardOptions, +) +from simpeg_drivers.electromagnetics.time_domain.inversion import ( + TDEMInversionDriver, + TDEMInversionOptions, +) +from simpeg_drivers.utils.synthetics.driver import ( + SyntheticsComponents, +) +from simpeg_drivers.utils.synthetics.options import ( + MeshOptions, + ModelOptions, + SurveyOptions, + SyntheticsComponentsOptions, +) +from tests.utils.targets import check_target, get_inversion_output, get_workspace + + +logger = getLogger(__name__) + + +# To test the full run and validate the inversion. +# Move this file out of the test directory and run. + +target_run = {"data_norm": 1.8460e-11, "phi_d": 3.0390e01, "phi_m": 2.0320e04} + + +def test_tiling_ground_tem( + tmp_path: Path, + *, + n_grid_points=4, + cell_size=(20.0, 20.0, 20.0), + refinement=(2,), + **_, +): + # Run the forward + opts = SyntheticsComponentsOptions( + method="ground tdem", + refine_plate=True, + survey=SurveyOptions( + n_stations=n_grid_points, + n_lines=n_grid_points, + drape=5.0, + topography=lambda x, y: np.zeros(x.shape), + name="ground_tdem_survey", + ), + mesh=MeshOptions( + u_cell_size=cell_size[0], + v_cell_size=cell_size[1], + w_cell_size=cell_size[2], + survey_refinement=list(refinement), + topography_refinement=[0, 0, 1], + plate_refinement=[1], + padding_distance=1000.0, + ), + model=ModelOptions( + background=0.001, + plate=PlateModel( + strike_length=40.0, + dip_length=40.0, + width=40.0, + easting=0.0, + northing=0.0, + elevation=-50.0, + ), + ), + ) + with get_workspace(tmp_path / "inversion_test.ui.geoh5") as geoh5: + components = SyntheticsComponents(geoh5, options=opts) + params = TDEMForwardOptions.build( + geoh5=geoh5, + mesh=components.mesh, + topography_object=components.topography, + data_object=components.survey, + starting_model=components.model, + x_channel_bool=True, + y_channel_bool=True, + z_channel_bool=True, + tile_spatial=4, + solver_type="Mumps", + ) + fwr_driver = TDEMForwardDriver(params) + + with geoh5.open(): + tiles = fwr_driver.get_tiles() + + assert len(tiles[None]) == 4 + + for tile in tiles[None]: + assert len(np.unique(components.survey.tx_id_property.values[tile])) == 1 + + fwr_driver.run() + + +def test_ground_tem_fwr_run( + tmp_path: Path, + caplog, + n_grid_points=4, + refinement=(2,), + cell_size=(20.0, 20.0, 20.0), + pytest=True, +): + if pytest and caplog: + caplog.set_level(INFO) + # Run the forward + opts = SyntheticsComponentsOptions( + method="ground tdem", + refine_plate=True, + survey=SurveyOptions( + n_stations=n_grid_points, + n_lines=n_grid_points, + drape=5.0, + topography=lambda x, y: np.zeros(x.shape), + ), + mesh=MeshOptions( + u_cell_size=cell_size[0], + v_cell_size=cell_size[1], + w_cell_size=cell_size[2], + survey_refinement=list(refinement), + topography_refinement=[0, 0, 1], + plate_refinement=[1], + padding_distance=1000.0, + ), + model=ModelOptions( + background=0.001, + plate=PlateModel( + strike_length=40.0, + dip_length=40.0, + width=40.0, + easting=0.0, + northing=0.0, + elevation=-50.0, + ), + ), + ) + with get_workspace(tmp_path / "inversion_test.ui.geoh5") as geoh5: + components = SyntheticsComponents(geoh5, options=opts) + components.survey.transmitters.remove_cells([15]) + params = TDEMForwardOptions.build( + geoh5=geoh5, + mesh=components.mesh, + topography_object=components.topography, + data_object=components.survey, + starting_model=components.model, + x_channel_bool=True, + y_channel_bool=True, + z_channel_bool=True, + data_units="Ground B (T/A)", + solver_type="Mumps", + ) + + fwr_driver = TDEMForwardDriver(params) + + assert fwr_driver.out_group is not None + with components.survey.workspace.open(): + components.survey.tx_id_property.name = "tx_id" + assert fwr_driver.inversion_data.survey.source_list[0].n_segments == 16 + + if pytest and caplog: + loop_warnings = [ + k + for k in caplog.records + if re.match(r"Loop \d+ modified", k.message) is not None + ] + assert len(loop_warnings) == 2 + for record in loop_warnings: + assert record.levelname == "INFO" + assert "counter-clockwise" in record.message + + assert "closed" in loop_warnings[0].message + + assert ( + fwr_driver.data_misfit.objfcts[0].simulation.simulations[0].solver == Mumps + ) + fwr_driver.run() + + +def test_ground_tem_run(tmp_path: Path, max_iterations=1, pytest=True): + workpath = tmp_path / "inversion_test.ui.geoh5" + if pytest: + workpath = ( + tmp_path.parent / "test_ground_tem_fwr_run0" / "inversion_test.ui.geoh5" + ) + + with Workspace(workpath) as geoh5: + components = SyntheticsComponents(geoh5) + data = {} + uncertainties = {} + channels = { + "vertical": "vertical", + } + + for chan, cname in channels.items(): + data[cname] = [] + uncertainties[f"{cname} uncertainties"] = [] + for ii, _ in enumerate(components.survey.channels): + data_entity = geoh5.get_entity(f"Iteration_0_{chan}_[{ii}]")[0].copy( + parent=components.survey + ) + data[cname].append(data_entity) + + uncert = components.survey.add_data( + { + f"uncertainty_{chan}_[{ii}]": { + "values": np.ones_like(data_entity.values) + * np.median(np.abs(data_entity.values)) + / 2.0 + } + } + ) + uncertainties[f"{cname} uncertainties"].append(uncert) + + components.survey.add_components_data(data) + components.survey.add_components_data(uncertainties) + + data_kwargs = {} + for chan in channels: + data_kwargs[f"{chan}_channel"] = components.survey.fetch_property_group( + name="vertical" + ) + data_kwargs[f"{chan}_uncertainty"] = components.survey.fetch_property_group( + name="vertical uncertainties" + ) + + orig_dBzdt = geoh5.get_entity("Iteration_0_vertical_[0]")[0].values + + # Run the inverse + params = TDEMInversionOptions.build( + geoh5=geoh5, + mesh=components.mesh, + topography_object=components.topography, + data_object=components.survey, + starting_model=1e-3, + reference_model=1e-3, + chi_factor=0.1, + s_norm=2.0, + x_norm=2.0, + y_norm=2.0, + z_norm=2.0, + alpha_s=0e-1, + lower_bound=2e-6, + upper_bound=1e2, + max_global_iterations=max_iterations, + initial_beta_ratio=1e1, + cooling_rate=2, + max_cg_iterations=200, + percentile=100, + solver_type="Mumps", + data_units="Ground B (T/A)", + **data_kwargs, + ) + params.write_ui_json(path=tmp_path / "Inv_run.ui.json") + + driver = TDEMInversionDriver(params) + driver.run() + + with geoh5.open() as run_ws: + output = get_inversion_output( + driver.params.geoh5.h5file, driver.params.out_group.uid + ) + assert driver.inversion_data.entity.tx_id_property.name == "tx_id" + output["data"] = orig_dBzdt + if pytest: + check_target(output, target_run) + nan_ind = np.isnan(run_ws.get_entity("Iteration_0_model")[0].values) + inactive_ind = run_ws.get_entity("active_cells")[0].values == 0 + assert np.all(nan_ind == inactive_ind) + + +if __name__ == "__main__": + # Full run + test_ground_tem_fwr_run( + Path("./"), + None, + n_grid_points=5, + refinement=(2, 2, 2), + cell_size=(5.0, 5.0, 5.0), + pytest=False, + ) + test_ground_tem_run( + Path("./"), + max_iterations=15, + pytest=False, + ) From d7200ace65c5de3696e2c93c1563a31578adb340 Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 26 Aug 2026 12:49:48 -0700 Subject: [PATCH 08/20] Clean up some imports --- simpeg_drivers/components/data.py | 1 - simpeg_drivers/components/factories/source_factory.py | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/simpeg_drivers/components/data.py b/simpeg_drivers/components/data.py index 630994a9e..73b9c6f05 100644 --- a/simpeg_drivers/components/data.py +++ b/simpeg_drivers/components/data.py @@ -33,7 +33,6 @@ if TYPE_CHECKING: from geoh5py.workspace import Workspace - from simpeg_drivers.components.meshes import InversionMesh from simpeg_drivers.options import InversionBaseOptions diff --git a/simpeg_drivers/components/factories/source_factory.py b/simpeg_drivers/components/factories/source_factory.py index c9498c146..a67124cfc 100644 --- a/simpeg_drivers/components/factories/source_factory.py +++ b/simpeg_drivers/components/factories/source_factory.py @@ -28,15 +28,13 @@ if TYPE_CHECKING: - from geoapps_utils.driver.params import BaseParams - - from simpeg_drivers.options import BaseOptions + from simpeg_drivers.options import CoreOptions class SourcesFactory(SimPEGFactory): """Build SimPEG sources objects based on factory type.""" - def __init__(self, params: BaseParams | BaseOptions): + def __init__(self, params: CoreOptions): """ :param params: Options object containing SimPEG object parameters. From 7171a25a8719c60a1356ba4d627b120af004d12e Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 26 Aug 2026 14:14:01 -0700 Subject: [PATCH 09/20] Fix changes to numpy cross --- simpeg_drivers/utils/surveys.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/simpeg_drivers/utils/surveys.py b/simpeg_drivers/utils/surveys.py index b3de3035b..8e7e6b4bd 100644 --- a/simpeg_drivers/utils/surveys.py +++ b/simpeg_drivers/utils/surveys.py @@ -57,10 +57,15 @@ def counter_clockwise_sort(segments: np.ndarray, vertices: np.ndarray) -> np.nda :return: Sorted segments. """ - center = np.mean(vertices[segments[:, 0], :2], axis=0) - center_to_vertices = vertices[segments[:, 0], :2] - center[:2] - deltas = vertices[segments[:, 1], :2] - vertices[segments[:, 0], :2] + center = np.mean(vertices[segments[:, 0], :], axis=0) + center_to_vertices = vertices[segments[:, 0], :] - center[:] + deltas = vertices[segments[:, 1], :] - vertices[segments[:, 0], :] + + # Turn into a flat 2D problem + center_to_vertices[:, -1] = 0 + deltas[:, -1] = 0 cross = np.cross(center_to_vertices, deltas) + cross = cross[:, -1] # Only keep the Z component if np.mean(np.sign(cross[cross != 0])) < 0: segments = segments[::-1, ::-1] From bedfe30ddc6833095f3daa3145700f1cdcae040c Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 26 Aug 2026 14:16:22 -0700 Subject: [PATCH 10/20] Add dedicated synthetic borehole survey constructor --- .../components/factories/receiver_factory.py | 2 +- .../utils/synthetics/surveys/factory.py | 11 +++-- .../{airborne_tdem.py => airborne.py} | 0 .../surveys/time_domain/borehole.py | 44 +++++++++++++++++++ .../time_domain/{ground_tdem.py => ground.py} | 13 +++++- tests/plate_simulation/leroi_air/__init__.py | 2 +- 6 files changed, 65 insertions(+), 7 deletions(-) rename simpeg_drivers/utils/synthetics/surveys/time_domain/{airborne_tdem.py => airborne.py} (100%) create mode 100644 simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py rename simpeg_drivers/utils/synthetics/surveys/time_domain/{ground_tdem.py => ground.py} (90%) diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index 1a0423081..bee4c6de5 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -278,7 +278,7 @@ def validate_orientations(self): azi_dip = np.deg2rad(azi_dip) elif "borehole" in self.params.inversion_type: - azi_dip = azimuth_dip_from_segments(self.params.data_object) + azi_dip = azimuth_dip_from_segments(self.params.data_object, reverse=True) if azi_dip is not None: orientations = {} diff --git a/simpeg_drivers/utils/synthetics/surveys/factory.py b/simpeg_drivers/utils/synthetics/surveys/factory.py index ef86c809a..a3af9f860 100644 --- a/simpeg_drivers/utils/synthetics/surveys/factory.py +++ b/simpeg_drivers/utils/synthetics/surveys/factory.py @@ -22,8 +22,9 @@ from .natural_sources.apparent_conductivity import generate_apparent_conductivity_survey from .natural_sources.magnetotellurics import generate_magnetotellurics_survey from .natural_sources.tipper import generate_tipper_survey -from .time_domain.airborne_tdem import generate_airborne_tdem_survey -from .time_domain.ground_tdem import generate_tdem_survey +from .time_domain.airborne import generate_airborne_tdem_survey +from .time_domain.borehole import generate_borehole_tdem_survey +from .time_domain.ground import generate_tdem_survey def grid_layout( @@ -102,11 +103,13 @@ def get_survey( return generate_airborne_tdem_survey( geoh5, grid_x, grid_y, grid_z, name=options.name ) - else: - return generate_tdem_survey( + elif "borehole" in method: + return generate_borehole_tdem_survey( geoh5, grid_x, grid_y, grid_z, name=options.name ) + return generate_tdem_survey(geoh5, grid_x, grid_y, grid_z, name=options.name) + return Points.create( geoh5, vertices=np.column_stack( diff --git a/simpeg_drivers/utils/synthetics/surveys/time_domain/airborne_tdem.py b/simpeg_drivers/utils/synthetics/surveys/time_domain/airborne.py similarity index 100% rename from simpeg_drivers/utils/synthetics/surveys/time_domain/airborne_tdem.py rename to simpeg_drivers/utils/synthetics/surveys/time_domain/airborne.py diff --git a/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py b/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py new file mode 100644 index 000000000..bc5fd7722 --- /dev/null +++ b/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py @@ -0,0 +1,44 @@ +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# Copyright (c) 2023-2026 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 y_rotation_matrix +from geoh5py import Workspace +from geoh5py.objects import ( + LargeLoopGroundTEMReceivers, +) + +from simpeg_drivers.utils.synthetics.surveys.time_domain import CHANNELS, WAVEFORM +from simpeg_drivers.utils.synthetics.surveys.time_domain.ground import ( + generate_tdem_survey, +) + + +def generate_borehole_tdem_survey( + geoh5: Workspace, + X: np.ndarray, + Y: np.ndarray, + Z: np.ndarray, + channels: np.ndarray = CHANNELS, + waveform: np.ndarray = WAVEFORM, + name: str = "survey", +) -> LargeLoopGroundTEMReceivers: + """Create a large loop TDEM survey object from survey grid locations.""" + + survey = generate_tdem_survey( + geoh5, X, Y, Z, channels=channels, waveform=waveform, name=name + ) + + center = survey.vertices[0, :] + survey.vertices = ( + y_rotation_matrix(np.pi / 2) @ (survey.vertices - center).T + ).T + center + + return survey diff --git a/simpeg_drivers/utils/synthetics/surveys/time_domain/ground_tdem.py b/simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py similarity index 90% rename from simpeg_drivers/utils/synthetics/surveys/time_domain/ground_tdem.py rename to simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py index 5421e9d2c..582749a0a 100644 --- a/simpeg_drivers/utils/synthetics/surveys/time_domain/ground_tdem.py +++ b/simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py @@ -10,6 +10,7 @@ import numpy as np from geoapps_utils.utils.locations import gaussian +from geoapps_utils.utils.transformations import y_rotation_matrix from geoh5py import Workspace from geoh5py.objects import ( LargeLoopGroundTEMReceivers, @@ -95,7 +96,17 @@ def generate_tdem_survey( name=f"{name}_tx", ) transmitters.tx_id_property = transmitters.parts + 1 - survey = LargeLoopGroundTEMReceivers.create(geoh5, name=name, vertices=vertices) + + cells = [] + count = 0 + for _ in range(X.shape[0]): + inds = np.arange(count, count + X.shape[1] - 1) + cells.append(np.c_[inds, inds + 1]) + count += X.shape[1] + + survey = LargeLoopGroundTEMReceivers.create( + geoh5, name=name, vertices=vertices, cells=np.vstack(cells) + ) survey.transmitters = transmitters survey.tx_id_property = np.hstack(loop_id) diff --git a/tests/plate_simulation/leroi_air/__init__.py b/tests/plate_simulation/leroi_air/__init__.py index 94728ad80..b8f4cca56 100644 --- a/tests/plate_simulation/leroi_air/__init__.py +++ b/tests/plate_simulation/leroi_air/__init__.py @@ -17,7 +17,7 @@ LeroiAirOptions, SurveyOptions, ) -from simpeg_drivers.utils.synthetics.surveys.time_domain.airborne_tdem import ( +from simpeg_drivers.utils.synthetics.surveys.time_domain.airborne import ( generate_airborne_tdem_survey, ) From 11835d74525cb040a9c31aa5d6cde7e1bc5598c3 Mon Sep 17 00:00:00 2001 From: domfournier Date: Fri, 28 Aug 2026 10:44:08 -0500 Subject: [PATCH 11/20] Add orientation of receivers if not supplied --- .../components/factories/entity_factory.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/simpeg_drivers/components/factories/entity_factory.py b/simpeg_drivers/components/factories/entity_factory.py index fa3e0620f..314040770 100644 --- a/simpeg_drivers/components/factories/entity_factory.py +++ b/simpeg_drivers/components/factories/entity_factory.py @@ -18,6 +18,9 @@ import numpy as np from geoapps_utils.utils.importing import GeoAppsError +from geoapps_utils.utils.locations import azimuth_dip_from_segments +from geoapps_utils.utils.transformations import x_rotation_matrix, z_rotation_matrix +from geoh5py.groups import PropertyGroup from geoh5py.objects import ( CurrentElectrode, Curve, @@ -96,8 +99,45 @@ def _build(self, inversion_data: InversionData): if tx_freq: tx_freq[0].copy(parent=entity.transmitters) + if "borehole" in self.params.inversion_type: + if property_group := self.params.receivers_orientation is not None: + property_group.copy(parent=entity) + else: + self._add_auv_data_groups(entity) + return entity + @staticmethod + def _add_auv_data_groups(entity: Curve): + """ + Compute the segments orientation and add A, U and V vector data + to the entity. + + :param entity: Curve entity + """ + azi_dip = azimuth_dip_from_segments(entity, reverse=True) + + for ind, comp in enumerate("vau"): + vector = np.zeros((azi_dip.shape[0], 3)) + vector[:, ind] = 1 + vector = ( + z_rotation_matrix(-azi_dip[:, 0]) + * (x_rotation_matrix(-azi_dip[:, 1]) * vector.flatten()) + ).reshape((-1, 3)) + vec_data = entity.add_data( + { + f"{comp}_x": {"values": vector[:, 0]}, + f"{comp}_y": {"values": vector[:, 1]}, + f"{comp}_z": {"values": vector[:, 2]}, + } + ) + PropertyGroup( + entity, + property_group_type="3D vector", + name=f"{comp}_ori".capitalize(), + properties=vec_data, + ) + @staticmethod def _prune_from_indices(curve: Curve, cell_indices: np.ndarray): cells = curve.cells[cell_indices] From e23ecd9e4db3ad222822966b2e40aa2b40b9d048 Mon Sep 17 00:00:00 2001 From: domfournier Date: Fri, 28 Aug 2026 10:48:55 -0500 Subject: [PATCH 12/20] Allow to specify number of transmitter loop in synthetic ground EM --- .../components/factories/receiver_factory.py | 2 +- .../borehole_time_domain/options.py | 4 ++-- .../surveys/time_domain/borehole.py | 2 +- .../synthetics/surveys/time_domain/ground.py | 22 ++++++++----------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index bee4c6de5..90ee1098b 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -29,7 +29,7 @@ from simpeg_drivers.components.factories.simpeg_factory import SimPEGFactory from simpeg_drivers.options import CoreOptions -from simpeg_drivers.utils.regularization import direction_and_dip, get_cell_normals +from simpeg_drivers.utils.regularization import get_cell_normals ORIENTATION_MAP = { diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py index 7902009bf..5268c887f 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py @@ -91,10 +91,10 @@ class BoreholeTDEMInversionOptions(BaseTDEMOptions, BaseInversionOptions): | AirborneTEMReceivers ) receivers_orientation: PropertyGroup | None = None - u_channel: PropertyGroup | None = None - u_uncertainty: PropertyGroup | None = None a_channel: PropertyGroup | None = None a_uncertainty: PropertyGroup | None = None + u_channel: PropertyGroup | None = None + u_uncertainty: PropertyGroup | None = None v_channel: PropertyGroup | None = None v_uncertainty: PropertyGroup | None = None diff --git a/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py b/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py index bc5fd7722..43ccd9afa 100644 --- a/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py +++ b/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py @@ -33,7 +33,7 @@ def generate_borehole_tdem_survey( """Create a large loop TDEM survey object from survey grid locations.""" survey = generate_tdem_survey( - geoh5, X, Y, Z, channels=channels, waveform=waveform, name=name + geoh5, X, Y, Z, channels=channels, waveform=waveform, name=name, n_loops=1 ) center = survey.vertices[0, :] diff --git a/simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py b/simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py index 582749a0a..5472b7697 100644 --- a/simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py +++ b/simpeg_drivers/utils/synthetics/surveys/time_domain/ground.py @@ -28,6 +28,7 @@ def generate_tdem_survey( channels: np.ndarray = CHANNELS, waveform: np.ndarray = WAVEFORM, name: str = "survey", + n_loops: int = 2, ) -> LargeLoopGroundTEMReceivers: """Create a large loop TDEM survey object from survey grid locations.""" @@ -36,19 +37,15 @@ def generate_tdem_survey( center = np.mean(vertices, axis=0) if flatten: center[2] -= np.mean(Z) - n_lines = X.shape[0] + + x_blocks = np.array_split(X, n_loops, axis=0) + y_blocks = np.array_split(Y, n_loops, axis=0) + z_blocks = np.array_split(Z, n_loops, axis=0) arrays = [ - np.c_[ - X[: int(n_lines / 2), :].flatten(), - Y[: int(n_lines / 2), :].flatten(), - Z[: int(n_lines / 2), :].flatten(), - ], - np.c_[ - X[int(n_lines / 2) :, :].flatten(), - Y[int(n_lines / 2) :, :].flatten(), - Z[int(n_lines / 2) :, :].flatten(), - ], + np.c_[x.flatten(), y.flatten(), z.flatten()] + for x, y, z in zip(x_blocks, y_blocks, z_blocks, strict=True) ] + loops = [] loop_cells = [] loop_id = [] @@ -83,8 +80,7 @@ def generate_tdem_survey( if flatten else gaussian(loop[:, 0], loop[:, 1], amplitude=50.0, width=100.0) ) - loop = np.c_[loop, elevation] - loops += [loop + np.asarray(center)] + loops += [np.c_[loop, elevation]] loop_cells += [np.c_[np.arange(15) + count, np.arange(15) + count + 1]] loop_cells += [np.c_[count + 15, count]] count += 16 From 5b5cb56d0c5d161614e9c399c6a13d8f15fceae4 Mon Sep 17 00:00:00 2001 From: domfournier Date: Fri, 28 Aug 2026 11:04:04 -0500 Subject: [PATCH 13/20] Add unit test for borehole TEM --- tests/run_tests/driver_borehole_tem_test.py | 179 +++++--------------- 1 file changed, 45 insertions(+), 134 deletions(-) diff --git a/tests/run_tests/driver_borehole_tem_test.py b/tests/run_tests/driver_borehole_tem_test.py index 389cff256..66ef501de 100644 --- a/tests/run_tests/driver_borehole_tem_test.py +++ b/tests/run_tests/driver_borehole_tem_test.py @@ -10,7 +10,6 @@ from __future__ import annotations -import re from logging import INFO, getLogger from pathlib import Path @@ -19,13 +18,13 @@ from geoh5py.workspace import Workspace from pymatsolver.direct import Mumps -from simpeg_drivers.electromagnetics.time_domain.forward import ( - TDEMForwardDriver, - TDEMForwardOptions, +from simpeg_drivers.electromagnetics.borehole_time_domain.forward import ( + BoreholeTDEMForwardDriver, + BoreholeTDEMForwardOptions, ) -from simpeg_drivers.electromagnetics.time_domain.inversion import ( - TDEMInversionDriver, - TDEMInversionOptions, +from simpeg_drivers.electromagnetics.borehole_time_domain.inversion import ( + BoreholeTDEMInversionDriver, + BoreholeTDEMInversionOptions, ) from simpeg_drivers.utils.synthetics.driver import ( SyntheticsComponents, @@ -45,77 +44,10 @@ # To test the full run and validate the inversion. # Move this file out of the test directory and run. -target_run = {"data_norm": 1.8460e-11, "phi_d": 3.0390e01, "phi_m": 2.0320e04} +target_run = {"data_norm": 6.3414e-11, "phi_d": 1.1820e04, "phi_m": 9.7920e02} -def test_tiling_ground_tem( - tmp_path: Path, - *, - n_grid_points=4, - cell_size=(20.0, 20.0, 20.0), - refinement=(2,), - **_, -): - # Run the forward - opts = SyntheticsComponentsOptions( - method="ground tdem", - refine_plate=True, - survey=SurveyOptions( - n_stations=n_grid_points, - n_lines=n_grid_points, - drape=5.0, - topography=lambda x, y: np.zeros(x.shape), - name="ground_tdem_survey", - ), - mesh=MeshOptions( - u_cell_size=cell_size[0], - v_cell_size=cell_size[1], - w_cell_size=cell_size[2], - survey_refinement=list(refinement), - topography_refinement=[0, 0, 1], - plate_refinement=[1], - padding_distance=1000.0, - ), - model=ModelOptions( - background=0.001, - plate=PlateModel( - strike_length=40.0, - dip_length=40.0, - width=40.0, - easting=0.0, - northing=0.0, - elevation=-50.0, - ), - ), - ) - with get_workspace(tmp_path / "inversion_test.ui.geoh5") as geoh5: - components = SyntheticsComponents(geoh5, options=opts) - params = TDEMForwardOptions.build( - geoh5=geoh5, - mesh=components.mesh, - topography_object=components.topography, - data_object=components.survey, - starting_model=components.model, - x_channel_bool=True, - y_channel_bool=True, - z_channel_bool=True, - tile_spatial=4, - solver_type="Mumps", - ) - fwr_driver = TDEMForwardDriver(params) - - with geoh5.open(): - tiles = fwr_driver.get_tiles() - - assert len(tiles[None]) == 4 - - for tile in tiles[None]: - assert len(np.unique(components.survey.tx_id_property.values[tile])) == 1 - - fwr_driver.run() - - -def test_ground_tem_fwr_run( +def test_borehole_tem_fwr_run( tmp_path: Path, caplog, n_grid_points=4, @@ -127,10 +59,10 @@ def test_ground_tem_fwr_run( caplog.set_level(INFO) # Run the forward opts = SyntheticsComponentsOptions( - method="ground tdem", + method="borehole tdem", refine_plate=True, survey=SurveyOptions( - n_stations=n_grid_points, + n_stations=n_grid_points * 2, n_lines=n_grid_points, drape=5.0, topography=lambda x, y: np.zeros(x.shape), @@ -150,59 +82,36 @@ def test_ground_tem_fwr_run( strike_length=40.0, dip_length=40.0, width=40.0, - easting=0.0, + easting=-40.0, northing=0.0, - elevation=-50.0, + elevation=-75.0, ), ), ) with get_workspace(tmp_path / "inversion_test.ui.geoh5") as geoh5: components = SyntheticsComponents(geoh5, options=opts) - components.survey.transmitters.remove_cells([15]) - params = TDEMForwardOptions.build( + params = BoreholeTDEMForwardOptions.build( geoh5=geoh5, mesh=components.mesh, topography_object=components.topography, data_object=components.survey, starting_model=components.model, - x_channel_bool=True, - y_channel_bool=True, - z_channel_bool=True, - data_units="Ground B (T/A)", + a_channel_bool=True, + u_channel_bool=True, + v_channel_bool=True, solver_type="Mumps", + data_units="Ground B (T/A)", ) - fwr_driver = TDEMForwardDriver(params) - - assert fwr_driver.out_group is not None - with components.survey.workspace.open(): - components.survey.tx_id_property.name = "tx_id" - assert fwr_driver.inversion_data.survey.source_list[0].n_segments == 16 - - if pytest and caplog: - loop_warnings = [ - k - for k in caplog.records - if re.match(r"Loop \d+ modified", k.message) is not None - ] - assert len(loop_warnings) == 2 - for record in loop_warnings: - assert record.levelname == "INFO" - assert "counter-clockwise" in record.message - - assert "closed" in loop_warnings[0].message - - assert ( - fwr_driver.data_misfit.objfcts[0].simulation.simulations[0].solver == Mumps - ) + fwr_driver = BoreholeTDEMForwardDriver(params) fwr_driver.run() -def test_ground_tem_run(tmp_path: Path, max_iterations=1, pytest=True): +def test_borehole_tem_run(tmp_path: Path, max_iterations=1, pytest=True): workpath = tmp_path / "inversion_test.ui.geoh5" if pytest: workpath = ( - tmp_path.parent / "test_ground_tem_fwr_run0" / "inversion_test.ui.geoh5" + tmp_path.parent / "test_borehole_tem_fwr_run0" / "inversion_test.ui.geoh5" ) with Workspace(workpath) as geoh5: @@ -210,28 +119,28 @@ def test_ground_tem_run(tmp_path: Path, max_iterations=1, pytest=True): data = {} uncertainties = {} channels = { - "vertical": "vertical", + "a": "a", + "u": "u", + "v": "v", } - for chan, cname in channels.items(): - data[cname] = [] - uncertainties[f"{cname} uncertainties"] = [] + for chan in channels: + data[chan] = [] + uncertainties[f"{chan} uncertainties"] = [] for ii, _ in enumerate(components.survey.channels): data_entity = geoh5.get_entity(f"Iteration_0_{chan}_[{ii}]")[0].copy( parent=components.survey ) - data[cname].append(data_entity) + data[chan].append(data_entity) uncert = components.survey.add_data( { f"uncertainty_{chan}_[{ii}]": { - "values": np.ones_like(data_entity.values) - * np.median(np.abs(data_entity.values)) - / 2.0 + "values": np.abs(data_entity.values) * 0.05 + 3e-13 } } ) - uncertainties[f"{cname} uncertainties"].append(uncert) + uncertainties[f"{chan} uncertainties"].append(uncert) components.survey.add_components_data(data) components.survey.add_components_data(uncertainties) @@ -239,49 +148,51 @@ def test_ground_tem_run(tmp_path: Path, max_iterations=1, pytest=True): data_kwargs = {} for chan in channels: data_kwargs[f"{chan}_channel"] = components.survey.fetch_property_group( - name="vertical" + name=f"{chan}" ) data_kwargs[f"{chan}_uncertainty"] = components.survey.fetch_property_group( - name="vertical uncertainties" + name=f"{chan} uncertainties" ) - orig_dBzdt = geoh5.get_entity("Iteration_0_vertical_[0]")[0].values + orig_dBzdt = geoh5.get_entity("Iteration_0_a_[0]")[0].values # Run the inverse - params = TDEMInversionOptions.build( + params = BoreholeTDEMInversionOptions.build( geoh5=geoh5, mesh=components.mesh, topography_object=components.topography, data_object=components.survey, - starting_model=1e-3, + starting_model=3e-3, reference_model=1e-3, chi_factor=0.1, - s_norm=2.0, + s_norm=0.0, x_norm=2.0, y_norm=2.0, z_norm=2.0, - alpha_s=0e-1, + alpha_s=0e-0, lower_bound=2e-6, upper_bound=1e2, max_global_iterations=max_iterations, initial_beta_ratio=1e1, - cooling_rate=2, + starting_chi_factor=1000, + cooling_rate=1, max_cg_iterations=200, - percentile=100, + percentile=5, + sens_wts_threshold=1.0, solver_type="Mumps", data_units="Ground B (T/A)", **data_kwargs, ) params.write_ui_json(path=tmp_path / "Inv_run.ui.json") - driver = TDEMInversionDriver(params) + driver = BoreholeTDEMInversionDriver(params) driver.run() with geoh5.open() as run_ws: output = get_inversion_output( driver.params.geoh5.h5file, driver.params.out_group.uid ) - assert driver.inversion_data.entity.tx_id_property.name == "tx_id" + assert driver.inversion_data.entity.tx_id_property.name == "Transmitter ID" output["data"] = orig_dBzdt if pytest: check_target(output, target_run) @@ -292,7 +203,7 @@ def test_ground_tem_run(tmp_path: Path, max_iterations=1, pytest=True): if __name__ == "__main__": # Full run - test_ground_tem_fwr_run( + test_borehole_tem_fwr_run( Path("./"), None, n_grid_points=5, @@ -300,8 +211,8 @@ def test_ground_tem_run(tmp_path: Path, max_iterations=1, pytest=True): cell_size=(5.0, 5.0, 5.0), pytest=False, ) - test_ground_tem_run( + test_borehole_tem_run( Path("./"), - max_iterations=15, + max_iterations=10, pytest=False, ) From 523572da3393f7d5327d57507e392a6594321845 Mon Sep 17 00:00:00 2001 From: domfournier Date: Mon, 31 Aug 2026 12:34:50 -0700 Subject: [PATCH 14/20] Coplilot comments --- simpeg_drivers/components/factories/entity_factory.py | 2 +- simpeg_drivers/utils/surveys.py | 2 +- tests/run_tests/driver_borehole_tem_test.py | 8 +------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/simpeg_drivers/components/factories/entity_factory.py b/simpeg_drivers/components/factories/entity_factory.py index 314040770..e4b0c6006 100644 --- a/simpeg_drivers/components/factories/entity_factory.py +++ b/simpeg_drivers/components/factories/entity_factory.py @@ -100,7 +100,7 @@ def _build(self, inversion_data: InversionData): tx_freq[0].copy(parent=entity.transmitters) if "borehole" in self.params.inversion_type: - if property_group := self.params.receivers_orientation is not None: + if (property_group := self.params.receivers_orientation) is not None: property_group.copy(parent=entity) else: self._add_auv_data_groups(entity) diff --git a/simpeg_drivers/utils/surveys.py b/simpeg_drivers/utils/surveys.py index 8e7e6b4bd..a9056f668 100644 --- a/simpeg_drivers/utils/surveys.py +++ b/simpeg_drivers/utils/surveys.py @@ -156,7 +156,7 @@ def compute_em_projections(locations, simulation): projection = 0.0 orientations = receiver.orientation.reshape((-1, 3)) for orientation, comp in zip(orientations.T, "xyz", strict=True): - if len(orientation) == 1 and orientation == 0: + if len(orientation) == 1 and orientation.item() == 0: continue orientation = diags(orientation) diff --git a/tests/run_tests/driver_borehole_tem_test.py b/tests/run_tests/driver_borehole_tem_test.py index 66ef501de..62f1fec29 100644 --- a/tests/run_tests/driver_borehole_tem_test.py +++ b/tests/run_tests/driver_borehole_tem_test.py @@ -10,7 +10,7 @@ from __future__ import annotations -from logging import INFO, getLogger +from logging import getLogger from pathlib import Path import numpy as np @@ -49,14 +49,10 @@ def test_borehole_tem_fwr_run( tmp_path: Path, - caplog, n_grid_points=4, refinement=(2,), cell_size=(20.0, 20.0, 20.0), - pytest=True, ): - if pytest and caplog: - caplog.set_level(INFO) # Run the forward opts = SyntheticsComponentsOptions( method="borehole tdem", @@ -205,11 +201,9 @@ def test_borehole_tem_run(tmp_path: Path, max_iterations=1, pytest=True): # Full run test_borehole_tem_fwr_run( Path("./"), - None, n_grid_points=5, refinement=(2, 2, 2), cell_size=(5.0, 5.0, 5.0), - pytest=False, ) test_borehole_tem_run( Path("./"), From 9641451600739cc79c4149318d98e1067c6a7ad5 Mon Sep 17 00:00:00 2001 From: domfournier Date: Tue, 1 Sep 2026 13:15:32 -0700 Subject: [PATCH 15/20] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../uijson/borehole_tdem_forward.ui.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json index dacb53101..6a6af4142 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_forward.ui.json @@ -28,10 +28,10 @@ ], "label": "Receivers orientation", "tooltip": [ - "Receivers orientation provided as 'Dip direction & dip' or '3D vector' data group. If not provided, it assumes:
", - "
In-line component
Positive towards North (Y)
", - "
Cross-line component
Positive towards East (X)
", - "
Vertical component
Positive up (Z)
", + "Receiver orientation provided as a 'Dip direction & dip' or '3D vector' data group. If not provided, it is derived from the borehole trace:
", + "
Axial (A)
Parallel to and positive upward along the hole trace
", + "
Perpendicular (U)
Positive upward in the hole dip direction
", + "
Perpendicular (V)
Horizontal, to the left of the hole dip direction
", "
" ], "optional": true, From a57850a866015f3ecb8a3c2957cf8dc560b56afb Mon Sep 17 00:00:00 2001 From: domfournier Date: Tue, 1 Sep 2026 13:15:48 -0700 Subject: [PATCH 16/20] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../uijson/borehole_tdem_inversion.ui.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json index d211c2c48..40d3f48a5 100644 --- a/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/borehole_tdem_inversion.ui.json @@ -28,10 +28,10 @@ ], "label": "Receivers orientation", "tooltip": [ - "Receivers orientation provided as 'Dip direction & dip' or '3D vector' data group. If not provided, it assumes:
", - "
In-line component
Positive towards North (Y)
", - "
Cross-line component
Positive towards East (X)
", - "
Vertical component
Positive up (Z)
", + "Receiver orientation provided as a 'Dip direction & dip' or '3D vector' data group. If not provided, it is derived from the borehole trace:
", + "
Axial (A)
Parallel to and positive upward along the hole trace
", + "
Perpendicular (U)
Positive upward in the hole dip direction
", + "
Perpendicular (V)
Horizontal, to the left of the hole dip direction
", "
" ], "optional": true, From f383c55639de4e71d9e8448e19c01985cad6fc09 Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 9 Sep 2026 12:01:35 -0700 Subject: [PATCH 17/20] Update test --- simpeg_drivers/utils/synthetics/options.py | 5 --- .../surveys/time_domain/borehole.py | 2 +- tests/run_tests/driver_borehole_tem_test.py | 41 +++++++++++++------ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/simpeg_drivers/utils/synthetics/options.py b/simpeg_drivers/utils/synthetics/options.py index 6b2565ef2..cb5b37af8 100644 --- a/simpeg_drivers/utils/synthetics/options.py +++ b/simpeg_drivers/utils/synthetics/options.py @@ -85,11 +85,6 @@ def octree_params( survey = Points.create(geoh5, vertices=locs) refinements = [ - { - "refinement_object": survey, - "levels": self.survey_refinement, - "horizon": False, - }, { "refinement_object": survey, "levels": self.survey_refinement, diff --git a/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py b/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py index 43ccd9afa..5f97486f1 100644 --- a/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py +++ b/simpeg_drivers/utils/synthetics/surveys/time_domain/borehole.py @@ -38,7 +38,7 @@ def generate_borehole_tdem_survey( center = survey.vertices[0, :] survey.vertices = ( - y_rotation_matrix(np.pi / 2) @ (survey.vertices - center).T + y_rotation_matrix(np.pi / 4) @ (survey.vertices - center).T ).T + center return survey diff --git a/tests/run_tests/driver_borehole_tem_test.py b/tests/run_tests/driver_borehole_tem_test.py index 62f1fec29..2977afa08 100644 --- a/tests/run_tests/driver_borehole_tem_test.py +++ b/tests/run_tests/driver_borehole_tem_test.py @@ -10,7 +10,7 @@ from __future__ import annotations -from logging import getLogger +from logging import INFO, getLogger from pathlib import Path import numpy as np @@ -44,15 +44,19 @@ # To test the full run and validate the inversion. # Move this file out of the test directory and run. -target_run = {"data_norm": 6.3414e-11, "phi_d": 1.1820e04, "phi_m": 9.7920e02} +target_run = {"data_norm": 4.6386e-11, "phi_d": 1.4840e03, "phi_m": 2.8200e04} def test_borehole_tem_fwr_run( tmp_path: Path, + caplog, n_grid_points=4, refinement=(2,), cell_size=(20.0, 20.0, 20.0), + pytest=True, ): + if pytest and caplog: + caplog.set_level(INFO) # Run the forward opts = SyntheticsComponentsOptions( method="borehole tdem", @@ -74,18 +78,28 @@ def test_borehole_tem_fwr_run( ), model=ModelOptions( background=0.001, + anomaly=1, plate=PlateModel( strike_length=40.0, dip_length=40.0, width=40.0, - easting=-40.0, - northing=0.0, - elevation=-75.0, + easting=0.0, + northing=-40.0, + elevation=-40.0, ), ), ) with get_workspace(tmp_path / "inversion_test.ui.geoh5") as geoh5: components = SyntheticsComponents(geoh5, options=opts) + components.mesh.origin = ( + np.r_[ + components.mesh.origin["x"], + components.mesh.origin["y"], + components.mesh.origin["z"], + ] + + np.r_[-2.5, -2.5, 0.0] + ) + # components.survey.complement.vertices = components.survey.complement.vertices + np.r_[-100.0, -100.0, 0.0] params = BoreholeTDEMForwardOptions.build( geoh5=geoh5, mesh=components.mesh, @@ -95,7 +109,6 @@ def test_borehole_tem_fwr_run( a_channel_bool=True, u_channel_bool=True, v_channel_bool=True, - solver_type="Mumps", data_units="Ground B (T/A)", ) @@ -132,7 +145,7 @@ def test_borehole_tem_run(tmp_path: Path, max_iterations=1, pytest=True): uncert = components.survey.add_data( { f"uncertainty_{chan}_[{ii}]": { - "values": np.abs(data_entity.values) * 0.05 + 3e-13 + "values": np.abs(data_entity.values) * 0.0 + 1e-12 } } ) @@ -158,7 +171,7 @@ def test_borehole_tem_run(tmp_path: Path, max_iterations=1, pytest=True): mesh=components.mesh, topography_object=components.topography, data_object=components.survey, - starting_model=3e-3, + starting_model=1e-3, reference_model=1e-3, chi_factor=0.1, s_norm=0.0, @@ -170,13 +183,13 @@ def test_borehole_tem_run(tmp_path: Path, max_iterations=1, pytest=True): upper_bound=1e2, max_global_iterations=max_iterations, initial_beta_ratio=1e1, - starting_chi_factor=1000, + starting_chi_factor=0.1, cooling_rate=1, max_cg_iterations=200, - percentile=5, - sens_wts_threshold=1.0, - solver_type="Mumps", + percentile=100, + sens_wts_threshold=0.1, data_units="Ground B (T/A)", + save_sensitivities=True, **data_kwargs, ) params.write_ui_json(path=tmp_path / "Inv_run.ui.json") @@ -201,12 +214,14 @@ def test_borehole_tem_run(tmp_path: Path, max_iterations=1, pytest=True): # Full run test_borehole_tem_fwr_run( Path("./"), + None, n_grid_points=5, refinement=(2, 2, 2), cell_size=(5.0, 5.0, 5.0), + pytest=False, ) test_borehole_tem_run( Path("./"), - max_iterations=10, + max_iterations=15, pytest=False, ) From a4bf0186a6d0ccc33a00da2ccc31769450e9522f Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 9 Sep 2026 12:01:56 -0700 Subject: [PATCH 18/20] Fix docstrings --- .../electromagnetics/borehole_time_domain/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py index 5268c887f..9f72cc640 100644 --- a/simpeg_drivers/electromagnetics/borehole_time_domain/options.py +++ b/simpeg_drivers/electromagnetics/borehole_time_domain/options.py @@ -67,10 +67,10 @@ class BoreholeTDEMInversionOptions(BaseTDEMOptions, BaseInversionOptions): """ Time Domain Electromagnetic Inversion options for borehole surveys. - :param u_channel: Vertical (U) component data channel. - :param u_uncertainty: Vertical (U) component data channel uncertainty. :param a_channel: In-line (A) data channel. :param a_uncertainty: In-line (A) data channel uncertainty. + :param u_channel: Vertical (U) component data channel. + :param u_uncertainty: Vertical (U) component data channel uncertainty. :param v_channel: Cross-line (V) data channel. :param v_uncertainty: Cross-line(V) data channel uncertainty. """ From e19acf63b47faef925560af4c6a190ae0994200e Mon Sep 17 00:00:00 2001 From: domfournier Date: Wed, 9 Sep 2026 13:12:08 -0700 Subject: [PATCH 19/20] Fix issue with copying property_group --- simpeg_drivers/components/factories/entity_factory.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/simpeg_drivers/components/factories/entity_factory.py b/simpeg_drivers/components/factories/entity_factory.py index e4b0c6006..8a980bd02 100644 --- a/simpeg_drivers/components/factories/entity_factory.py +++ b/simpeg_drivers/components/factories/entity_factory.py @@ -99,11 +99,11 @@ def _build(self, inversion_data: InversionData): if tx_freq: tx_freq[0].copy(parent=entity.transmitters) - if "borehole" in self.params.inversion_type: - if (property_group := self.params.receivers_orientation) is not None: - property_group.copy(parent=entity) - else: - self._add_auv_data_groups(entity) + if ( + "borehole" in self.params.inversion_type + and self.params.receivers_orientation is None + ): + self._add_auv_data_groups(entity) return entity From 4c9dd502dc18f5d64c6f8faed518f7ae564274b3 Mon Sep 17 00:00:00 2001 From: domfournier Date: Thu, 10 Sep 2026 13:21:27 -0700 Subject: [PATCH 20/20] Re-lock --- .../py-3.12-linux-64-dev.conda.lock.yml | 20 +- environments/py-3.12-linux-64.conda.lock.yml | 14 +- .../py-3.12-win-64-dev.conda.lock.yml | 26 +-- environments/py-3.12-win-64.conda.lock.yml | 18 +- .../py-3.13-linux-64-dev.conda.lock.yml | 20 +- environments/py-3.13-linux-64.conda.lock.yml | 14 +- .../py-3.13-win-64-dev.conda.lock.yml | 26 +-- environments/py-3.13-win-64.conda.lock.yml | 18 +- py-3.12.conda-lock.yml | 217 +++++++++--------- py-3.13.conda-lock.yml | 217 +++++++++--------- 10 files changed, 290 insertions(+), 300 deletions(-) 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 61690e41f..ceb8c4023 100644 --- a/environments/py-3.12-linux-64-dev.conda.lock.yml +++ b/environments/py-3.12-linux-64-dev.conda.lock.yml @@ -10,7 +10,7 @@ dependencies: - _python_abi3_support=1.0=hd8ed1ab_3 - alabaster=0.7.16=pyhd8ed1ab_0 - annotated-types=0.8.0=pyhd8ed1ab_0 - - anyio=4.15.0=pyh5ded981_0 + - anyio=4.15.1=pyh5ded981_1 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - argon2-cffi-bindings=26.1.0=py312h5cc1888_1 - arrow=1.4.0=pyhcf101f3_0 @@ -45,7 +45,7 @@ dependencies: - certifi=2026.7.22=pyhd8ed1ab_0 - cffi=2.1.1=py312h703531f_3 - charset-normalizer=3.5.1=pyhd8ed1ab_0 - - click=8.4.2=pyhc90fa1f_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - colorama=0.4.6=pyhd8ed1ab_1 - comm=0.2.3=pyhe01879c_0 @@ -100,7 +100,7 @@ dependencies: - jsonschema-specifications=2025.9.1=pyhcf101f3_0 - jsonschema-with-format-nongpl=4.26.0=hcf101f3_1 - jupyter-book=2.1.6=pyhcf101f3_0 - - jupyter-builder=1.2.2=pyhcf101f3_0 + - jupyter-builder=1.2.3=pyh5ded981_0 - jupyter-lsp=2.3.1=pyhcf101f3_0 - jupyter_client=8.10.0=pyhcf101f3_0 - jupyter_core=5.9.1=pyhc90fa1f_0 @@ -163,7 +163,7 @@ dependencies: - libxml2=2.15.1=h26afc86_0 - libxml2-16=2.15.1=ha9997c6_0 - libzlib=1.3.2=h25fd6f3_3 - - llvm-openmp=23.1.0=h7148c6a_0 + - llvm-openmp=23.1.1=h7148c6a_0 - locket=1.0.0=pyhd8ed1ab_0 - markdown-it-py=4.2.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py312h8a5da7c_1 @@ -206,7 +206,7 @@ dependencies: - pexpect=4.9.0=pyhd8ed1ab_1 - pillow=12.3.0=py312h38079b3_1 - pip=26.2.1=pyh8b19718_0 - - platformdirs=4.11.6=pyh5ded981_0 + - platformdirs=4.11.8=pyh5ded981_0 - pluggy=1.6.0=pyhf9edf01_1 - prometheus_client=0.26.0=pyhd8ed1ab_0 - prompt-toolkit=3.0.53=pyha770c72_0 @@ -264,7 +264,7 @@ dependencies: - sphinxcontrib-qthelp=2.0.0=pyhd8ed1ab_1 - sphinxcontrib-serializinghtml=2.0.0=pyhd8ed1ab_0 - stack_data=0.6.3=pyhd8ed1ab_1 - - tbb=2023.0.0=hab88423_2 + - tbb=2023.1.0=hfd44327_0 - tblib=3.2.2=pyhcf101f3_0 - terminado=0.18.1=pyhc90fa1f_1 - threadpoolctl=3.6.0=pyhecae5ae_0 @@ -292,9 +292,9 @@ dependencies: - wheel=0.48.0=pyhd8ed1ab_0 - widgetsnbextension=3.6.10=pyhd8ed1ab_0 - wrapt=2.4.0=py312h1b36aeb_0 - - xorg-libxau=1.0.12=hb03c661_2 + - xorg-libxau=1.0.12=h7cc23a3_2 - xorg-libxdmcp=1.1.5=hb03c661_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=hebe6cf0_3 - zarr=2.14.2=pyhd8ed1ab_0 - zeromq=4.3.5=h09e67af_11 @@ -304,8 +304,8 @@ dependencies: - zlib-ng=2.3.3=hce19668_1 - zstd=1.5.7=hb78ec9c_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/environments/py-3.12-linux-64.conda.lock.yml b/environments/py-3.12-linux-64.conda.lock.yml index c17b7ab64..be928d80a 100644 --- a/environments/py-3.12-linux-64.conda.lock.yml +++ b/environments/py-3.12-linux-64.conda.lock.yml @@ -28,7 +28,7 @@ dependencies: - ca-certificates=2026.7.22=hbd8a1cb_0 - cached-property=2.0.1=pyhcf101f3_0 - cached_property=2.0.1=pyhcf101f3_0 - - click=8.4.2=pyhc90fa1f_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - contourpy=1.3.3=py312h0a2e395_4 - cycler=0.12.1=pyhcf101f3_2 @@ -100,7 +100,7 @@ dependencies: - libxml2=2.15.1=h26afc86_0 - libxml2-16=2.15.1=ha9997c6_0 - libzlib=1.3.2=h25fd6f3_3 - - llvm-openmp=23.1.0=h7148c6a_0 + - llvm-openmp=23.1.1=h7148c6a_0 - locket=1.0.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py312h8a5da7c_1 - matplotlib-base=3.10.9=py312he3d6523_0 @@ -146,7 +146,7 @@ dependencies: - setuptools=84.0.0=pyh332efcf_0 - six=1.17.0=pyhe01879c_1 - sortedcontainers=2.4.0=pyhd8ed1ab_1 - - tbb=2023.0.0=hab88423_2 + - tbb=2023.1.0=hfd44327_0 - tblib=3.2.2=pyhcf101f3_0 - threadpoolctl=3.6.0=pyhecae5ae_0 - tk=8.6.13=noxft_h1df4ec4_4 @@ -162,9 +162,9 @@ dependencies: - urllib3=2.7.0=pyhd8ed1ab_0 - wheel=0.48.0=pyhd8ed1ab_0 - wrapt=2.4.0=py312h1b36aeb_0 - - xorg-libxau=1.0.12=hb03c661_2 + - xorg-libxau=1.0.12=h7cc23a3_2 - xorg-libxdmcp=1.1.5=hb03c661_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=hebe6cf0_3 - zarr=2.14.2=pyhd8ed1ab_0 - zict=3.0.0=pyhd8ed1ab_1 @@ -172,8 +172,8 @@ dependencies: - zlib-ng=2.3.3=hce19668_1 - zstd=1.5.7=hb78ec9c_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 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 312cf4fd0..083880bbb 100644 --- a/environments/py-3.12-win-64-dev.conda.lock.yml +++ b/environments/py-3.12-win-64-dev.conda.lock.yml @@ -10,7 +10,7 @@ dependencies: - _python_abi3_support=1.0=hd8ed1ab_3 - alabaster=0.7.16=pyhd8ed1ab_0 - annotated-types=0.8.0=pyhd8ed1ab_0 - - anyio=4.15.0=pyh5ded981_0 + - anyio=4.15.1=pyh5ded981_1 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - argon2-cffi-bindings=26.1.0=py312he06e257_1 - arrow=1.4.0=pyhcf101f3_0 @@ -44,7 +44,7 @@ dependencies: - certifi=2026.7.22=pyhd8ed1ab_0 - cffi=2.1.1=py312he06e257_3 - charset-normalizer=3.5.1=pyhd8ed1ab_0 - - click=8.4.2=pyh6dadd2b_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - colorama=0.4.6=pyhd8ed1ab_1 - comm=0.2.3=pyhe01879c_0 @@ -99,7 +99,7 @@ dependencies: - jsonschema-specifications=2025.9.1=pyhcf101f3_0 - jsonschema-with-format-nongpl=4.26.0=hcf101f3_1 - jupyter-book=2.1.6=pyhcf101f3_0 - - jupyter-builder=1.2.2=pyhcf101f3_0 + - jupyter-builder=1.2.3=pyh5ded981_0 - jupyter-lsp=2.3.1=pyhcf101f3_0 - jupyter_client=8.10.0=pyhcf101f3_0 - jupyter_core=5.9.1=pyh6dadd2b_0 @@ -147,10 +147,10 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h11686cb_11 - libxcb=1.17.0=h874e120_2 - - libxml2=2.15.3=h8ef44ab_1 - - libxml2-16=2.15.3=h3cfd58e_1 + - libxml2=2.15.4=he095d88_0 + - libxml2-16=2.15.4=h3cfd58e_0 - libzlib=1.3.2=hfd05255_3 - - llvm-openmp=23.1.0=h49e36cd_0 + - llvm-openmp=23.1.1=h49e36cd_0 - locket=1.0.0=pyhd8ed1ab_0 - markdown-it-py=4.2.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py312h05f76fc_1 @@ -171,7 +171,7 @@ dependencies: - nbconvert-pandoc=7.16.6=h7d6f222_1 - nbformat=5.11.1=pyhcf101f3_0 - nest-asyncio2=1.7.2=pyhcf101f3_0 - - nodejs=26.8.0=h80d1838_1 + - nodejs=26.8.1=h80d1838_1 - notebook=7.6.2=pyhcf101f3_0 - notebook-shim=0.2.4=pyhd8ed1ab_1 - numcodecs=0.15.1=py312hc128f0a_1 @@ -189,7 +189,7 @@ dependencies: - partd=1.4.2=pyhd8ed1ab_0 - pillow=12.3.0=py312h31f0997_1 - pip=26.2.1=pyh8b19718_0 - - platformdirs=4.11.6=pyh5ded981_0 + - platformdirs=4.11.8=pyh5ded981_0 - pluggy=1.6.0=pyhf9edf01_1 - prometheus_client=0.26.0=pyhd8ed1ab_0 - prompt-toolkit=3.0.53=pyha770c72_0 @@ -246,7 +246,7 @@ dependencies: - sphinxcontrib-qthelp=2.0.0=pyhd8ed1ab_1 - sphinxcontrib-serializinghtml=2.0.0=pyhd8ed1ab_0 - stack_data=0.6.3=pyhd8ed1ab_1 - - tbb=2023.0.0=hd3d4ead_2 + - tbb=2023.1.0=hdcfe883_0 - tblib=3.2.2=pyhcf101f3_0 - terminado=0.18.1=pyh6dadd2b_1 - threadpoolctl=3.6.0=pyhecae5ae_0 @@ -280,9 +280,9 @@ dependencies: - win_inet_pton=1.1.0=pyh7428d3b_8 - winpty=0.4.3=4 - wrapt=2.4.0=py312he5662c2_0 - - xorg-libxau=1.0.12=hba3369d_2 + - xorg-libxau=1.0.12=hfa92662_2 - xorg-libxdmcp=1.1.5=hba3369d_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=h6a83c73_3 - zarr=2.14.2=pyhd8ed1ab_0 - zeromq=4.3.5=h3a581c9_11 @@ -292,8 +292,8 @@ dependencies: - zlib-ng=2.3.3=h0261ad2_1 - zstd=1.5.7=h534d264_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/environments/py-3.12-win-64.conda.lock.yml b/environments/py-3.12-win-64.conda.lock.yml index a87d01121..df1014405 100644 --- a/environments/py-3.12-win-64.conda.lock.yml +++ b/environments/py-3.12-win-64.conda.lock.yml @@ -27,7 +27,7 @@ dependencies: - ca-certificates=2026.7.22=h4c7d964_0 - cached-property=2.0.1=pyhcf101f3_0 - cached_property=2.0.1=pyhcf101f3_0 - - click=8.4.2=pyh6dadd2b_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - colorama=0.4.6=pyhd8ed1ab_1 - contourpy=1.3.3=py312h78d62e6_4 @@ -86,10 +86,10 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h11686cb_11 - libxcb=1.17.0=h874e120_2 - - libxml2=2.15.3=h8ef44ab_1 - - libxml2-16=2.15.3=h3cfd58e_1 + - libxml2=2.15.4=he095d88_0 + - libxml2-16=2.15.4=h3cfd58e_0 - libzlib=1.3.2=hfd05255_3 - - llvm-openmp=23.1.0=h49e36cd_0 + - llvm-openmp=23.1.1=h49e36cd_0 - locket=1.0.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py312h05f76fc_1 - matplotlib-base=3.10.9=py312h0ebf65c_0 @@ -130,7 +130,7 @@ dependencies: - setuptools=84.0.0=pyh332efcf_0 - six=1.17.0=pyhe01879c_1 - sortedcontainers=2.4.0=pyhd8ed1ab_1 - - tbb=2023.0.0=hd3d4ead_2 + - tbb=2023.1.0=hdcfe883_0 - tblib=3.2.2=pyhcf101f3_0 - threadpoolctl=3.6.0=pyhecae5ae_0 - tk=8.6.13=h967ab96_4 @@ -151,9 +151,9 @@ dependencies: - wheel=0.48.0=pyhd8ed1ab_0 - win_inet_pton=1.1.0=pyh7428d3b_8 - wrapt=2.4.0=py312he5662c2_0 - - xorg-libxau=1.0.12=hba3369d_2 + - xorg-libxau=1.0.12=hfa92662_2 - xorg-libxdmcp=1.1.5=hba3369d_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=h6a83c73_3 - zarr=2.14.2=pyhd8ed1ab_0 - zict=3.0.0=pyhd8ed1ab_1 @@ -162,8 +162,8 @@ dependencies: - zlib-ng=2.3.3=h0261ad2_1 - zstd=1.5.7=h534d264_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/environments/py-3.13-linux-64-dev.conda.lock.yml b/environments/py-3.13-linux-64-dev.conda.lock.yml index a5f245e86..d148a10df 100644 --- a/environments/py-3.13-linux-64-dev.conda.lock.yml +++ b/environments/py-3.13-linux-64-dev.conda.lock.yml @@ -10,7 +10,7 @@ dependencies: - _python_abi3_support=1.0=hd8ed1ab_3 - alabaster=0.7.16=pyhd8ed1ab_0 - annotated-types=0.8.0=pyhd8ed1ab_0 - - anyio=4.15.0=pyh5ded981_0 + - anyio=4.15.1=pyh5ded981_1 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - argon2-cffi-bindings=26.1.0=py313h995f894_1 - arrow=1.4.0=pyhcf101f3_0 @@ -45,7 +45,7 @@ dependencies: - certifi=2026.7.22=pyhd8ed1ab_0 - cffi=2.1.1=py313ha52865f_3 - charset-normalizer=3.5.1=pyhd8ed1ab_0 - - click=8.4.2=pyhc90fa1f_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - colorama=0.4.6=pyhd8ed1ab_1 - comm=0.2.3=pyhe01879c_0 @@ -100,7 +100,7 @@ dependencies: - jsonschema-specifications=2025.9.1=pyhcf101f3_0 - jsonschema-with-format-nongpl=4.26.0=hcf101f3_1 - jupyter-book=2.1.6=pyhcf101f3_0 - - jupyter-builder=1.2.2=pyhcf101f3_0 + - jupyter-builder=1.2.3=pyh5ded981_0 - jupyter-lsp=2.3.1=pyhcf101f3_0 - jupyter_client=8.10.0=pyhcf101f3_0 - jupyter_core=5.9.1=pyhc90fa1f_0 @@ -162,7 +162,7 @@ dependencies: - libxml2=2.15.1=h26afc86_0 - libxml2-16=2.15.1=ha9997c6_0 - libzlib=1.3.2=h25fd6f3_3 - - llvm-openmp=23.1.0=h7148c6a_0 + - llvm-openmp=23.1.1=h7148c6a_0 - locket=1.0.0=pyhd8ed1ab_0 - markdown-it-py=4.2.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py313h3dea7bd_1 @@ -205,7 +205,7 @@ dependencies: - pexpect=4.9.0=pyhd8ed1ab_1 - pillow=12.3.0=py313h3b26573_1 - pip=26.2.1=pyh145f28c_0 - - platformdirs=4.11.6=pyh5ded981_0 + - platformdirs=4.11.8=pyh5ded981_0 - pluggy=1.6.0=pyhf9edf01_1 - prometheus_client=0.26.0=pyhd8ed1ab_0 - prompt-toolkit=3.0.53=pyha770c72_0 @@ -262,7 +262,7 @@ dependencies: - sphinxcontrib-qthelp=2.0.0=pyhd8ed1ab_1 - sphinxcontrib-serializinghtml=2.0.0=pyhd8ed1ab_0 - stack_data=0.6.3=pyhd8ed1ab_1 - - tbb=2023.0.0=hab88423_2 + - tbb=2023.1.0=hfd44327_0 - tblib=3.2.2=pyhcf101f3_0 - terminado=0.18.1=pyhc90fa1f_1 - threadpoolctl=3.6.0=pyhecae5ae_0 @@ -288,9 +288,9 @@ dependencies: - websocket-client=1.9.2=pyh5ded981_1 - widgetsnbextension=3.6.10=pyhd8ed1ab_0 - wrapt=2.4.0=py313hd42f317_0 - - xorg-libxau=1.0.12=hb03c661_2 + - xorg-libxau=1.0.12=h7cc23a3_2 - xorg-libxdmcp=1.1.5=hb03c661_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=hebe6cf0_3 - zarr=2.14.2=pyhd8ed1ab_0 - zeromq=4.3.5=h09e67af_11 @@ -300,8 +300,8 @@ dependencies: - zlib-ng=2.3.3=hce19668_1 - zstd=1.5.7=hb78ec9c_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/environments/py-3.13-linux-64.conda.lock.yml b/environments/py-3.13-linux-64.conda.lock.yml index ff8517a74..5856db7be 100644 --- a/environments/py-3.13-linux-64.conda.lock.yml +++ b/environments/py-3.13-linux-64.conda.lock.yml @@ -28,7 +28,7 @@ dependencies: - ca-certificates=2026.7.22=hbd8a1cb_0 - cached-property=2.0.1=pyhcf101f3_0 - cached_property=2.0.1=pyhcf101f3_0 - - click=8.4.2=pyhc90fa1f_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - contourpy=1.3.3=py313hc8edb43_4 - cycler=0.12.1=pyhcf101f3_2 @@ -99,7 +99,7 @@ dependencies: - libxml2=2.15.1=h26afc86_0 - libxml2-16=2.15.1=ha9997c6_0 - libzlib=1.3.2=h25fd6f3_3 - - llvm-openmp=23.1.0=h7148c6a_0 + - llvm-openmp=23.1.1=h7148c6a_0 - locket=1.0.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py313h3dea7bd_1 - matplotlib-base=3.10.9=py313h683a580_0 @@ -144,7 +144,7 @@ dependencies: - scipy=1.17.1=py313h4b8bb8b_1 - six=1.17.0=pyhe01879c_1 - sortedcontainers=2.4.0=pyhd8ed1ab_1 - - tbb=2023.0.0=hab88423_2 + - tbb=2023.1.0=hfd44327_0 - tblib=3.2.2=pyhcf101f3_0 - threadpoolctl=3.6.0=pyhecae5ae_0 - tk=8.6.13=noxft_h1df4ec4_4 @@ -158,9 +158,9 @@ dependencies: - tzdata=2026c=h151e31d_0 - urllib3=2.7.0=pyhd8ed1ab_0 - wrapt=2.4.0=py313hd42f317_0 - - xorg-libxau=1.0.12=hb03c661_2 + - xorg-libxau=1.0.12=h7cc23a3_2 - xorg-libxdmcp=1.1.5=hb03c661_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=hebe6cf0_3 - zarr=2.14.2=pyhd8ed1ab_0 - zict=3.0.0=pyhd8ed1ab_1 @@ -168,8 +168,8 @@ dependencies: - zlib-ng=2.3.3=hce19668_1 - zstd=1.5.7=hb78ec9c_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/environments/py-3.13-win-64-dev.conda.lock.yml b/environments/py-3.13-win-64-dev.conda.lock.yml index ee66f17e0..81286f1d5 100644 --- a/environments/py-3.13-win-64-dev.conda.lock.yml +++ b/environments/py-3.13-win-64-dev.conda.lock.yml @@ -10,7 +10,7 @@ dependencies: - _python_abi3_support=1.0=hd8ed1ab_3 - alabaster=0.7.16=pyhd8ed1ab_0 - annotated-types=0.8.0=pyhd8ed1ab_0 - - anyio=4.15.0=pyh5ded981_0 + - anyio=4.15.1=pyh5ded981_1 - argon2-cffi=25.1.0=pyhd8ed1ab_0 - argon2-cffi-bindings=26.1.0=py313h5ea7bf4_1 - arrow=1.4.0=pyhcf101f3_0 @@ -44,7 +44,7 @@ dependencies: - certifi=2026.7.22=pyhd8ed1ab_0 - cffi=2.1.1=py313h5ea7bf4_3 - charset-normalizer=3.5.1=pyhd8ed1ab_0 - - click=8.4.2=pyh6dadd2b_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - colorama=0.4.6=pyhd8ed1ab_1 - comm=0.2.3=pyhe01879c_0 @@ -99,7 +99,7 @@ dependencies: - jsonschema-specifications=2025.9.1=pyhcf101f3_0 - jsonschema-with-format-nongpl=4.26.0=hcf101f3_1 - jupyter-book=2.1.6=pyhcf101f3_0 - - jupyter-builder=1.2.2=pyhcf101f3_0 + - jupyter-builder=1.2.3=pyh5ded981_0 - jupyter-lsp=2.3.1=pyhcf101f3_0 - jupyter_client=8.10.0=pyhcf101f3_0 - jupyter_core=5.9.1=pyh6dadd2b_0 @@ -148,10 +148,10 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h11686cb_11 - libxcb=1.17.0=h874e120_2 - - libxml2=2.15.3=h8ef44ab_1 - - libxml2-16=2.15.3=h3cfd58e_1 + - libxml2=2.15.4=he095d88_0 + - libxml2-16=2.15.4=h3cfd58e_0 - libzlib=1.3.2=hfd05255_3 - - llvm-openmp=23.1.0=h49e36cd_0 + - llvm-openmp=23.1.1=h49e36cd_0 - locket=1.0.0=pyhd8ed1ab_0 - markdown-it-py=4.2.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py313hd650c13_1 @@ -172,7 +172,7 @@ dependencies: - nbconvert-pandoc=7.16.6=h7d6f222_1 - nbformat=5.11.1=pyhcf101f3_0 - nest-asyncio2=1.7.2=pyhcf101f3_0 - - nodejs=26.8.0=h80d1838_1 + - nodejs=26.8.1=h80d1838_1 - notebook=7.6.2=pyhcf101f3_0 - notebook-shim=0.2.4=pyhd8ed1ab_1 - numcodecs=0.15.1=py313hc90dcd4_1 @@ -190,7 +190,7 @@ dependencies: - partd=1.4.2=pyhd8ed1ab_0 - pillow=12.3.0=py313h38f99e1_1 - pip=26.2.1=pyh145f28c_0 - - platformdirs=4.11.6=pyh5ded981_0 + - platformdirs=4.11.8=pyh5ded981_0 - pluggy=1.6.0=pyhf9edf01_1 - prometheus_client=0.26.0=pyhd8ed1ab_0 - prompt-toolkit=3.0.53=pyha770c72_0 @@ -246,7 +246,7 @@ dependencies: - sphinxcontrib-qthelp=2.0.0=pyhd8ed1ab_1 - sphinxcontrib-serializinghtml=2.0.0=pyhd8ed1ab_0 - stack_data=0.6.3=pyhd8ed1ab_1 - - tbb=2023.0.0=hd3d4ead_2 + - tbb=2023.1.0=hdcfe883_0 - tblib=3.2.2=pyhcf101f3_0 - terminado=0.18.1=pyh6dadd2b_1 - threadpoolctl=3.6.0=pyhecae5ae_0 @@ -278,9 +278,9 @@ dependencies: - win_inet_pton=1.1.0=pyh7428d3b_8 - winpty=0.4.3=4 - wrapt=2.4.0=py313h5fd188c_0 - - xorg-libxau=1.0.12=hba3369d_2 + - xorg-libxau=1.0.12=hfa92662_2 - xorg-libxdmcp=1.1.5=hba3369d_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=h6a83c73_3 - zarr=2.14.2=pyhd8ed1ab_0 - zeromq=4.3.5=h3a581c9_11 @@ -290,8 +290,8 @@ dependencies: - zlib-ng=2.3.3=h0261ad2_1 - zstd=1.5.7=h534d264_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/environments/py-3.13-win-64.conda.lock.yml b/environments/py-3.13-win-64.conda.lock.yml index e2a497893..0af94b8e5 100644 --- a/environments/py-3.13-win-64.conda.lock.yml +++ b/environments/py-3.13-win-64.conda.lock.yml @@ -27,7 +27,7 @@ dependencies: - ca-certificates=2026.7.22=h4c7d964_0 - cached-property=2.0.1=pyhcf101f3_0 - cached_property=2.0.1=pyhcf101f3_0 - - click=8.4.2=pyh6dadd2b_0 + - click=8.5.0=pyh5ded981_0 - cloudpickle=3.1.2=pyhcf101f3_1 - colorama=0.4.6=pyhd8ed1ab_1 - contourpy=1.3.3=py313h1a38498_4 @@ -87,10 +87,10 @@ dependencies: - libwebp-base=1.6.0=h4d5522a_1 - libwinpthread=12.0.0.r4.gg4f2fc60ca=h11686cb_11 - libxcb=1.17.0=h874e120_2 - - libxml2=2.15.3=h8ef44ab_1 - - libxml2-16=2.15.3=h3cfd58e_1 + - libxml2=2.15.4=he095d88_0 + - libxml2-16=2.15.4=h3cfd58e_0 - libzlib=1.3.2=hfd05255_3 - - llvm-openmp=23.1.0=h49e36cd_0 + - llvm-openmp=23.1.1=h49e36cd_0 - locket=1.0.0=pyhd8ed1ab_0 - markupsafe=3.0.3=py313hd650c13_1 - matplotlib-base=3.10.9=py313he1ded55_0 @@ -130,7 +130,7 @@ dependencies: - scipy=1.17.1=py313he51e9a2_1 - six=1.17.0=pyhe01879c_1 - sortedcontainers=2.4.0=pyhd8ed1ab_1 - - tbb=2023.0.0=hd3d4ead_2 + - tbb=2023.1.0=hdcfe883_0 - tblib=3.2.2=pyhcf101f3_0 - threadpoolctl=3.6.0=pyhecae5ae_0 - tk=8.6.13=h967ab96_4 @@ -149,9 +149,9 @@ dependencies: - vcomp14=14.51.36247=habf1de7_41 - win_inet_pton=1.1.0=pyh7428d3b_8 - wrapt=2.4.0=py313h5fd188c_0 - - xorg-libxau=1.0.12=hba3369d_2 + - xorg-libxau=1.0.12=hfa92662_2 - xorg-libxdmcp=1.1.5=hba3369d_2 - - xyzservices=2026.3.0=pyhd8ed1ab_0 + - xyzservices=2026.9.1=pyhd8ed1ab_0 - yaml=0.2.5=h6a83c73_3 - zarr=2.14.2=pyhd8ed1ab_0 - zict=3.0.0=pyhd8ed1ab_1 @@ -160,8 +160,8 @@ dependencies: - zlib-ng=2.3.3=h0261ad2_1 - zstd=1.5.7=h534d264_7 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 - - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 + - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 - grid-apps @ git+https://github.com/MiraGeoscience/grid-apps.git@32b32031020ddf26fde40b2da817c14b9d8b86e9 - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@54e7b09e58ffa63ee0cdad1b811df8225aafcfb1 diff --git a/py-3.12.conda-lock.yml b/py-3.12.conda-lock.yml index da3df344b..c1a5875da 100644 --- a/py-3.12.conda-lock.yml +++ b/py-3.12.conda-lock.yml @@ -131,33 +131,31 @@ package: category: main optional: false - name: anyio - version: 4.15.0 + version: 4.15.1 manager: conda platform: linux-64 dependencies: - exceptiongroup: '>=1.0.2' idna: '>=2.8' python: '' - typing_extensions: '>=4.5' - url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.0-pyh5ded981_0.conda + typing_extensions: '>=4.16.0' + url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.1-pyh5ded981_1.conda hash: - md5: 28190db0e223089024a41b06c11af36e - sha256: 35fefb7c4bc39bca28d8764b4f59bd7b739c47e3af8e5e20ee22621db0c594b3 + md5: 33cdc5ba7c481b371f08f88e6c048c55 + sha256: fc25a84c9c1ad4b48c136ad2363100e8b0faa3b0ab8985e61c9c8fa0b3431945 category: dev optional: true - name: anyio - version: 4.15.0 + version: 4.15.1 manager: conda platform: win-64 dependencies: - exceptiongroup: '>=1.0.2' idna: '>=2.8' python: '' - typing_extensions: '>=4.5' - url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.0-pyh5ded981_0.conda + typing_extensions: '>=4.16.0' + url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.1-pyh5ded981_1.conda hash: - md5: 28190db0e223089024a41b06c11af36e - sha256: 35fefb7c4bc39bca28d8764b4f59bd7b739c47e3af8e5e20ee22621db0c594b3 + md5: 33cdc5ba7c481b371f08f88e6c048c55 + sha256: fc25a84c9c1ad4b48c136ad2363100e8b0faa3b0ab8985e61c9c8fa0b3431945 category: dev optional: true - name: argon2-cffi @@ -1131,30 +1129,27 @@ package: category: dev optional: true - name: click - version: 8.4.2 + version: 8.5.0 manager: conda platform: linux-64 dependencies: - __unix: '' - python: '>=3.10' - url: https://repo.prefix.dev/conda-forge/noarch/click-8.4.2-pyhc90fa1f_0.conda + python: '' + url: https://repo.prefix.dev/conda-forge/noarch/click-8.5.0-pyh5ded981_0.conda hash: - md5: 2c4bd6aeb90bb157456841c3270a0d92 - sha256: ccc4787f511964f9a1f2d2d2859c91c5d571fb60f7f09d4c4e092c9b7a94e671 + md5: dea5b13a211bbf99876deb980b408a66 + sha256: 9afb0c2c089330321a219c7ee5a25313bd574d4024be606cbb33e7a5735df662 category: main optional: false - name: click - version: 8.4.2 + version: 8.5.0 manager: conda platform: win-64 dependencies: - __win: '' - colorama: '' python: '' - url: https://repo.prefix.dev/conda-forge/noarch/click-8.4.2-pyh6dadd2b_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/click-8.5.0-pyh5ded981_0.conda hash: - md5: 8a0d65027e25e367f9f1754f0604e8de - sha256: 5b5c96afdd801dd9c3b78ebc2cd9a9f3ce34186257415d394dde1aa8468aa3c0 + md5: dea5b13a211bbf99876deb980b408a66 + sha256: 9afb0c2c089330321a219c7ee5a25313bd574d4024be606cbb33e7a5735df662 category: main optional: false - name: cloudpickle @@ -2769,7 +2764,7 @@ package: category: dev optional: true - name: jupyter-builder - version: 1.2.2 + version: 1.2.3 manager: conda platform: linux-64 dependencies: @@ -2777,14 +2772,14 @@ package: python: '' tomli: '' traitlets: '' - url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.2-pyhcf101f3_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.3-pyh5ded981_0.conda hash: - md5: 9672806e67ea8b09a61408597a418e20 - sha256: 46777dd25ae623f960ec9ed9eae44cc7f96f371f3bc96f85d3ebf95737bd4e88 + md5: bac0e43cada154f38a627bde5e7e6016 + sha256: 3eba9c6b859a217ad8de382d1af76983611c221364a059bfd379f2f09dd663ef category: dev optional: true - name: jupyter-builder - version: 1.2.2 + version: 1.2.3 manager: conda platform: win-64 dependencies: @@ -2792,10 +2787,10 @@ package: python: '' tomli: '' traitlets: '' - url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.2-pyhcf101f3_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.3-pyh5ded981_0.conda hash: - md5: 9672806e67ea8b09a61408597a418e20 - sha256: 46777dd25ae623f960ec9ed9eae44cc7f96f371f3bc96f85d3ebf95737bd4e88 + md5: bac0e43cada154f38a627bde5e7e6016 + sha256: 3eba9c6b859a217ad8de382d1af76983611c221364a059bfd379f2f09dd663ef category: dev optional: true - name: jupyter-lsp @@ -4401,22 +4396,22 @@ package: category: main optional: false - name: libxml2 - version: 2.15.3 + version: 2.15.4 manager: conda platform: win-64 dependencies: icu: '>=78.3,<79.0a0' libiconv: '>=1.18,<2.0a0' liblzma: '>=5.8.3,<6.0a0' - libxml2-16: 2.15.3 + libxml2-16: 2.15.4 libzlib: '>=1.3.2,<2.0a0' ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/libxml2-2.15.3-h8ef44ab_1.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda hash: - md5: 45a5a1c709a69f14cf176220788d18a9 - sha256: a83e9adcf7c50f20289dc6890707c8e4e84151b4204b0f7344998138807458d1 + md5: 3ce54d0f8f24dfab99d82414411640aa + sha256: a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88 category: main optional: false - name: libxml2-16 @@ -4437,7 +4432,7 @@ package: category: main optional: false - name: libxml2-16 - version: 2.15.3 + version: 2.15.4 manager: conda platform: win-64 dependencies: @@ -4448,10 +4443,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/libxml2-16-2.15.3-h3cfd58e_1.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda hash: - md5: 6e7dadff3f3bde2d29d29a3ec34f2d58 - sha256: 8163de24a7ddb4ebf9587c3a45ba950caf3690b9646b76f007ca15e6e52b5881 + md5: bab5489f4bd38494ffaa83d6ab924c1f + sha256: 9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac category: main optional: false - name: libzlib @@ -4481,29 +4476,29 @@ package: category: main optional: false - name: llvm-openmp - version: 23.1.0 + version: 23.1.1 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' - url: https://repo.prefix.dev/conda-forge/linux-64/llvm-openmp-23.1.0-h7148c6a_0.conda + url: https://repo.prefix.dev/conda-forge/linux-64/llvm-openmp-23.1.1-h7148c6a_0.conda hash: - md5: 58b4529023435973ab911c3c51892671 - sha256: b6fa85a30cceca3ad7a811ab34f842b9c2ae9d9d4c520e084b62b2abe50e9a70 + md5: d976d1fcca0f3c861f02aff9fb95508f + sha256: 4d6dab4691baec13109bc251506a74da448340b6a5de92de30563871105f8e7c category: main optional: false - name: llvm-openmp - version: 23.1.0 + version: 23.1.1 manager: conda platform: win-64 dependencies: ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/llvm-openmp-23.1.0-h49e36cd_0.conda + url: https://repo.prefix.dev/conda-forge/win-64/llvm-openmp-23.1.1-h49e36cd_0.conda hash: - md5: 79055ec79e1b43749763122cead30976 - sha256: f9658ec83a6744f38e2b8188c76e1c2dea2614f5aa0e14d9d274b19f60646b8c + md5: f895db3df946e742c3ce07cfce271bdd + sha256: 49b0967e84eae82cc2acaf4400629c7b9c08a491b9c8d3343f3f5f2feee7138d category: main optional: false - name: locket @@ -5177,14 +5172,14 @@ package: category: dev optional: true - name: nodejs - version: 26.8.0 + version: 26.8.1 manager: conda platform: win-64 dependencies: {} - url: https://repo.prefix.dev/conda-forge/win-64/nodejs-26.8.0-h80d1838_1.conda + url: https://repo.prefix.dev/conda-forge/win-64/nodejs-26.8.1-h80d1838_1.conda hash: - md5: 786fbc873be1ca0d9e5f1a66c5de1f18 - sha256: dde0723015f908149905e353f69ee2d380e7810fa2d0d46203ea3fa1bfd85901 + md5: dbac9bb103c17d1318589036f1862dfe + sha256: 6c3d7797fe9855375e160ce6acf4ef076f41cb02b4b92c8b768326da303b5348 category: dev optional: true - name: notebook @@ -5725,27 +5720,27 @@ package: category: main optional: false - name: platformdirs - version: 4.11.6 + version: 4.11.8 manager: conda platform: linux-64 dependencies: python: '' - url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.6-pyh5ded981_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.8-pyh5ded981_0.conda hash: - md5: fb0f75910f804de1d8c6e91f73673d11 - sha256: 8fe66c78f015fecfe096e4ff78a2626c4d926cde9b6951cf3b8e1ff0aaeb0a6c + md5: 48e9ecf08b0578a4313f13b2e2b0fd72 + sha256: 8cbae1fed8437e63c9bcc691927402edb3809fccb26b15eb095df7dd2eb73e5f category: dev optional: true - name: platformdirs - version: 4.11.6 + version: 4.11.8 manager: conda platform: win-64 dependencies: python: '' - url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.6-pyh5ded981_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.8-pyh5ded981_0.conda hash: - md5: fb0f75910f804de1d8c6e91f73673d11 - sha256: 8fe66c78f015fecfe096e4ff78a2626c4d926cde9b6951cf3b8e1ff0aaeb0a6c + md5: 48e9ecf08b0578a4313f13b2e2b0fd72 + sha256: 8cbae1fed8437e63c9bcc691927402edb3809fccb26b15eb095df7dd2eb73e5f category: dev optional: true - name: pluggy @@ -7403,22 +7398,22 @@ package: category: dev optional: true - name: tbb - version: 2023.0.0 + version: 2023.1.0 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' - libgcc: '>=14' + libgcc: '>=15' libhwloc: '>=2.13.0,<2.13.1.0a0' - libstdcxx: '>=14' - url: https://repo.prefix.dev/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda + libstdcxx: '>=15' + url: https://repo.prefix.dev/conda-forge/linux-64/tbb-2023.1.0-hfd44327_0.conda hash: - md5: 7073b15f9364ebc118998601ac6ca6a6 - sha256: 30cb9355c2fefc20ff1a3d6566b9714d5614086a2524c07721fc344eb20515ae + md5: b17ef6c181922df16e9b1330fd00fe85 + sha256: ea35780ec77e2431bcfc193e75ddcc3ec1ae79a34464469b0b2186d93035c9e7 category: main optional: false - name: tbb - version: 2023.0.0 + version: 2023.1.0 manager: conda platform: win-64 dependencies: @@ -7426,10 +7421,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/tbb-2023.0.0-hd3d4ead_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/tbb-2023.1.0-hdcfe883_0.conda hash: - md5: 8ee01a693aecff5432069eaaf1183c45 - sha256: 8a4053839b8e997a5965e2dff7d6cf3c77be62d82c0e48c8a04a5ed2d2e73035 + md5: 8b1275f06705cdc2ab67f3bfdf4df843 + sha256: 7a65accbe954d0304b9056005f59fbee8b3928ceced38b1e3e8272aa1af0b750 category: main optional: false - name: tblib @@ -8208,11 +8203,11 @@ package: platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' - libgcc: '>=14' - url: https://repo.prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_2.conda + libgcc: '>=15' + url: https://repo.prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-h7cc23a3_2.conda hash: - md5: f06ef439c280a5f90b8bf62355008dbc - sha256: cbf891f6cc1a859347680af1c8562bc6b033bf182a2a3bb536016932be3206de + md5: da33efee1a93603d92e06d4a2b68def6 + sha256: 3ec065b94554dc48a4ca582a960a5484bc166b26e83ce0954653e08d17e8bd53 category: main optional: false - name: xorg-libxau @@ -8220,13 +8215,13 @@ package: manager: conda platform: win-64 dependencies: - libgcc: '>=14' + libgcc: '>=15' libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' ucrt: '>=10.0.20348.0' - url: https://repo.prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hfa92662_2.conda hash: - md5: 87aee04978ab77bf4c0f42b983c216cc - sha256: 892ad69b1a9ecc3903ed5a1b18fa097013eaf462eeed3c6ff31bf5c12e71e84b + md5: 68403004c805ce03b71a5889a4c47fa1 + sha256: b9f063792e4d50ef2669c30dfc4ba14aefb4fdc37e384241a71093bee0493ad1 category: main optional: false - name: xorg-libxdmcp @@ -8257,27 +8252,27 @@ package: category: main optional: false - name: xyzservices - version: 2026.3.0 + version: 2026.9.1 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.3.0-pyhd8ed1ab_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.9.1-pyhd8ed1ab_0.conda hash: - md5: 4487b9c371d0161d54b5c7bbd890c0fc - sha256: 663ea9b00d68c2da309114923924686ab6d3f59ef1b196c5029ba16799e7bb07 + md5: 5d7c149ba9c728d4951f3fe6d3ce0f84 + sha256: b9439f1716ff580ce56e9b4a4df7ea92e5ed2bdc9567d25cdff223d62c3183a8 category: main optional: false - name: xyzservices - version: 2026.3.0 + version: 2026.9.1 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.3.0-pyhd8ed1ab_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.9.1-pyhd8ed1ab_0.conda hash: - md5: 4487b9c371d0161d54b5c7bbd890c0fc - sha256: 663ea9b00d68c2da309114923924686ab6d3f59ef1b196c5029ba16799e7bb07 + md5: 5d7c149ba9c728d4951f3fe6d3ce0f84 + sha256: b9439f1716ff580ce56e9b4a4df7ea92e5ed2bdc9567d25cdff223d62c3183a8 category: main optional: false - name: yaml @@ -8504,75 +8499,75 @@ package: category: main optional: false - name: geoapps-utils - version: 0.7.1.dev103+14c4c81 + version: 0.8.0a3.dev11+fd9e5b6 manager: pip platform: linux-64 dependencies: - geoh5py: 0.14.0a1.dev275+ca917b6f + geoh5py: 0.14.0a1 matplotlib: '>=3.10.0,<3.11.0' numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 hash: - sha256: 14c4c814e956277c10e64263b27717c720021b88 + sha256: fd9e5b69283159d7626c501918a246fd2f5202b9 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 category: main optional: false - name: geoapps-utils - version: 0.7.1.dev103+14c4c81 + version: 0.8.0a3.dev11+fd9e5b6 manager: pip platform: win-64 dependencies: - geoh5py: 0.14.0a1.dev275+ca917b6f + geoh5py: 0.14.0a1 matplotlib: '>=3.10.0,<3.11.0' numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 hash: - sha256: 14c4c814e956277c10e64263b27717c720021b88 + sha256: fd9e5b69283159d7626c501918a246fd2f5202b9 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 category: main optional: false - name: geoh5py - version: 0.14.0a1.dev275+ca917b6f + version: 0.14.0a1 manager: pip platform: linux-64 dependencies: h5py: '>=3.15.0,<3.16.0' numpy: '>=2.4.0,<2.5.0' - pillow: '>=12.2.0,<12.3.0' + pillow: '>=12.2.0,<13.0.0' psutil: '>=7.2.2,<7.3.0' pydantic: '>=2.12.0,<2.13.0' - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 hash: - sha256: ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + sha256: d45f41aa5af7958ced737f136ec27cca28068b54 source: type: url - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 category: main optional: false - name: geoh5py - version: 0.14.0a1.dev275+ca917b6f + version: 0.14.0a1 manager: pip platform: win-64 dependencies: h5py: '>=3.15.0,<3.16.0' numpy: '>=2.4.0,<2.5.0' - pillow: '>=12.2.0,<12.3.0' + pillow: '>=12.2.0,<13.0.0' psutil: '>=7.2.2,<7.3.0' pydantic: '>=2.12.0,<2.13.0' - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 hash: - sha256: ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + sha256: d45f41aa5af7958ced737f136ec27cca28068b54 source: type: url - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 category: main optional: false - name: grid-apps @@ -8581,8 +8576,8 @@ package: platform: linux-64 dependencies: discretize: '>=0.12.0,<0.13.0' - geoapps-utils: 0.7.1.dev103+14c4c81 - geoh5py: 0.14.0a1.dev275+ca917b6f + geoapps-utils: 0.8.0a3.dev11+fd9e5b6 + geoh5py: 0.14.0a1 numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' @@ -8600,8 +8595,8 @@ package: platform: win-64 dependencies: discretize: '>=0.12.0,<0.13.0' - geoapps-utils: 0.7.1.dev103+14c4c81 - geoh5py: 0.14.0a1.dev275+ca917b6f + geoapps-utils: 0.8.0a3.dev11+fd9e5b6 + geoh5py: 0.14.0a1 numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' diff --git a/py-3.13.conda-lock.yml b/py-3.13.conda-lock.yml index 4558dc17d..a802a3274 100644 --- a/py-3.13.conda-lock.yml +++ b/py-3.13.conda-lock.yml @@ -131,33 +131,31 @@ package: category: main optional: false - name: anyio - version: 4.15.0 + version: 4.15.1 manager: conda platform: linux-64 dependencies: - exceptiongroup: '>=1.0.2' idna: '>=2.8' python: '' - typing_extensions: '>=4.5' - url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.0-pyh5ded981_0.conda + typing_extensions: '>=4.16.0' + url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.1-pyh5ded981_1.conda hash: - md5: 28190db0e223089024a41b06c11af36e - sha256: 35fefb7c4bc39bca28d8764b4f59bd7b739c47e3af8e5e20ee22621db0c594b3 + md5: 33cdc5ba7c481b371f08f88e6c048c55 + sha256: fc25a84c9c1ad4b48c136ad2363100e8b0faa3b0ab8985e61c9c8fa0b3431945 category: dev optional: true - name: anyio - version: 4.15.0 + version: 4.15.1 manager: conda platform: win-64 dependencies: - exceptiongroup: '>=1.0.2' idna: '>=2.8' python: '' - typing_extensions: '>=4.5' - url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.0-pyh5ded981_0.conda + typing_extensions: '>=4.16.0' + url: https://repo.prefix.dev/conda-forge/noarch/anyio-4.15.1-pyh5ded981_1.conda hash: - md5: 28190db0e223089024a41b06c11af36e - sha256: 35fefb7c4bc39bca28d8764b4f59bd7b739c47e3af8e5e20ee22621db0c594b3 + md5: 33cdc5ba7c481b371f08f88e6c048c55 + sha256: fc25a84c9c1ad4b48c136ad2363100e8b0faa3b0ab8985e61c9c8fa0b3431945 category: dev optional: true - name: argon2-cffi @@ -1131,30 +1129,27 @@ package: category: dev optional: true - name: click - version: 8.4.2 + version: 8.5.0 manager: conda platform: linux-64 dependencies: - __unix: '' - python: '>=3.10' - url: https://repo.prefix.dev/conda-forge/noarch/click-8.4.2-pyhc90fa1f_0.conda + python: '' + url: https://repo.prefix.dev/conda-forge/noarch/click-8.5.0-pyh5ded981_0.conda hash: - md5: 2c4bd6aeb90bb157456841c3270a0d92 - sha256: ccc4787f511964f9a1f2d2d2859c91c5d571fb60f7f09d4c4e092c9b7a94e671 + md5: dea5b13a211bbf99876deb980b408a66 + sha256: 9afb0c2c089330321a219c7ee5a25313bd574d4024be606cbb33e7a5735df662 category: main optional: false - name: click - version: 8.4.2 + version: 8.5.0 manager: conda platform: win-64 dependencies: - __win: '' - colorama: '' python: '' - url: https://repo.prefix.dev/conda-forge/noarch/click-8.4.2-pyh6dadd2b_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/click-8.5.0-pyh5ded981_0.conda hash: - md5: 8a0d65027e25e367f9f1754f0604e8de - sha256: 5b5c96afdd801dd9c3b78ebc2cd9a9f3ce34186257415d394dde1aa8468aa3c0 + md5: dea5b13a211bbf99876deb980b408a66 + sha256: 9afb0c2c089330321a219c7ee5a25313bd574d4024be606cbb33e7a5735df662 category: main optional: false - name: cloudpickle @@ -2767,7 +2762,7 @@ package: category: dev optional: true - name: jupyter-builder - version: 1.2.2 + version: 1.2.3 manager: conda platform: linux-64 dependencies: @@ -2775,14 +2770,14 @@ package: python: '' tomli: '' traitlets: '' - url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.2-pyhcf101f3_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.3-pyh5ded981_0.conda hash: - md5: 9672806e67ea8b09a61408597a418e20 - sha256: 46777dd25ae623f960ec9ed9eae44cc7f96f371f3bc96f85d3ebf95737bd4e88 + md5: bac0e43cada154f38a627bde5e7e6016 + sha256: 3eba9c6b859a217ad8de382d1af76983611c221364a059bfd379f2f09dd663ef category: dev optional: true - name: jupyter-builder - version: 1.2.2 + version: 1.2.3 manager: conda platform: win-64 dependencies: @@ -2790,10 +2785,10 @@ package: python: '' tomli: '' traitlets: '' - url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.2-pyhcf101f3_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/jupyter-builder-1.2.3-pyh5ded981_0.conda hash: - md5: 9672806e67ea8b09a61408597a418e20 - sha256: 46777dd25ae623f960ec9ed9eae44cc7f96f371f3bc96f85d3ebf95737bd4e88 + md5: bac0e43cada154f38a627bde5e7e6016 + sha256: 3eba9c6b859a217ad8de382d1af76983611c221364a059bfd379f2f09dd663ef category: dev optional: true - name: jupyter-lsp @@ -4400,22 +4395,22 @@ package: category: main optional: false - name: libxml2 - version: 2.15.3 + version: 2.15.4 manager: conda platform: win-64 dependencies: icu: '>=78.3,<79.0a0' libiconv: '>=1.18,<2.0a0' liblzma: '>=5.8.3,<6.0a0' - libxml2-16: 2.15.3 + libxml2-16: 2.15.4 libzlib: '>=1.3.2,<2.0a0' ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/libxml2-2.15.3-h8ef44ab_1.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-2.15.4-he095d88_0.conda hash: - md5: 45a5a1c709a69f14cf176220788d18a9 - sha256: a83e9adcf7c50f20289dc6890707c8e4e84151b4204b0f7344998138807458d1 + md5: 3ce54d0f8f24dfab99d82414411640aa + sha256: a19bb3821830f6b1281e782844d5dd265f796dfed2e4812b16c9995a8c778c88 category: main optional: false - name: libxml2-16 @@ -4436,7 +4431,7 @@ package: category: main optional: false - name: libxml2-16 - version: 2.15.3 + version: 2.15.4 manager: conda platform: win-64 dependencies: @@ -4447,10 +4442,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/libxml2-16-2.15.3-h3cfd58e_1.conda + url: https://repo.prefix.dev/conda-forge/win-64/libxml2-16-2.15.4-h3cfd58e_0.conda hash: - md5: 6e7dadff3f3bde2d29d29a3ec34f2d58 - sha256: 8163de24a7ddb4ebf9587c3a45ba950caf3690b9646b76f007ca15e6e52b5881 + md5: bab5489f4bd38494ffaa83d6ab924c1f + sha256: 9fa71cec30425c9cc8eda6af3574af1faf4fefa5e239c9e037b1f778ef3ce8ac category: main optional: false - name: libzlib @@ -4480,29 +4475,29 @@ package: category: main optional: false - name: llvm-openmp - version: 23.1.0 + version: 23.1.1 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' - url: https://repo.prefix.dev/conda-forge/linux-64/llvm-openmp-23.1.0-h7148c6a_0.conda + url: https://repo.prefix.dev/conda-forge/linux-64/llvm-openmp-23.1.1-h7148c6a_0.conda hash: - md5: 58b4529023435973ab911c3c51892671 - sha256: b6fa85a30cceca3ad7a811ab34f842b9c2ae9d9d4c520e084b62b2abe50e9a70 + md5: d976d1fcca0f3c861f02aff9fb95508f + sha256: 4d6dab4691baec13109bc251506a74da448340b6a5de92de30563871105f8e7c category: main optional: false - name: llvm-openmp - version: 23.1.0 + version: 23.1.1 manager: conda platform: win-64 dependencies: ucrt: '>=10.0.20348.0' vc: '>=14.3,<15' vc14_runtime: '>=14.44.35208' - url: https://repo.prefix.dev/conda-forge/win-64/llvm-openmp-23.1.0-h49e36cd_0.conda + url: https://repo.prefix.dev/conda-forge/win-64/llvm-openmp-23.1.1-h49e36cd_0.conda hash: - md5: 79055ec79e1b43749763122cead30976 - sha256: f9658ec83a6744f38e2b8188c76e1c2dea2614f5aa0e14d9d274b19f60646b8c + md5: f895db3df946e742c3ce07cfce271bdd + sha256: 49b0967e84eae82cc2acaf4400629c7b9c08a491b9c8d3343f3f5f2feee7138d category: main optional: false - name: locket @@ -5176,14 +5171,14 @@ package: category: dev optional: true - name: nodejs - version: 26.8.0 + version: 26.8.1 manager: conda platform: win-64 dependencies: {} - url: https://repo.prefix.dev/conda-forge/win-64/nodejs-26.8.0-h80d1838_1.conda + url: https://repo.prefix.dev/conda-forge/win-64/nodejs-26.8.1-h80d1838_1.conda hash: - md5: 786fbc873be1ca0d9e5f1a66c5de1f18 - sha256: dde0723015f908149905e353f69ee2d380e7810fa2d0d46203ea3fa1bfd85901 + md5: dbac9bb103c17d1318589036f1862dfe + sha256: 6c3d7797fe9855375e160ce6acf4ef076f41cb02b4b92c8b768326da303b5348 category: dev optional: true - name: notebook @@ -5720,27 +5715,27 @@ package: category: main optional: false - name: platformdirs - version: 4.11.6 + version: 4.11.8 manager: conda platform: linux-64 dependencies: python: '' - url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.6-pyh5ded981_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.8-pyh5ded981_0.conda hash: - md5: fb0f75910f804de1d8c6e91f73673d11 - sha256: 8fe66c78f015fecfe096e4ff78a2626c4d926cde9b6951cf3b8e1ff0aaeb0a6c + md5: 48e9ecf08b0578a4313f13b2e2b0fd72 + sha256: 8cbae1fed8437e63c9bcc691927402edb3809fccb26b15eb095df7dd2eb73e5f category: dev optional: true - name: platformdirs - version: 4.11.6 + version: 4.11.8 manager: conda platform: win-64 dependencies: python: '' - url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.6-pyh5ded981_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/platformdirs-4.11.8-pyh5ded981_0.conda hash: - md5: fb0f75910f804de1d8c6e91f73673d11 - sha256: 8fe66c78f015fecfe096e4ff78a2626c4d926cde9b6951cf3b8e1ff0aaeb0a6c + md5: 48e9ecf08b0578a4313f13b2e2b0fd72 + sha256: 8cbae1fed8437e63c9bcc691927402edb3809fccb26b15eb095df7dd2eb73e5f category: dev optional: true - name: pluggy @@ -7376,22 +7371,22 @@ package: category: dev optional: true - name: tbb - version: 2023.0.0 + version: 2023.1.0 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' - libgcc: '>=14' + libgcc: '>=15' libhwloc: '>=2.13.0,<2.13.1.0a0' - libstdcxx: '>=14' - url: https://repo.prefix.dev/conda-forge/linux-64/tbb-2023.0.0-hab88423_2.conda + libstdcxx: '>=15' + url: https://repo.prefix.dev/conda-forge/linux-64/tbb-2023.1.0-hfd44327_0.conda hash: - md5: 7073b15f9364ebc118998601ac6ca6a6 - sha256: 30cb9355c2fefc20ff1a3d6566b9714d5614086a2524c07721fc344eb20515ae + md5: b17ef6c181922df16e9b1330fd00fe85 + sha256: ea35780ec77e2431bcfc193e75ddcc3ec1ae79a34464469b0b2186d93035c9e7 category: main optional: false - name: tbb - version: 2023.0.0 + version: 2023.1.0 manager: conda platform: win-64 dependencies: @@ -7399,10 +7394,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/tbb-2023.0.0-hd3d4ead_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/tbb-2023.1.0-hdcfe883_0.conda hash: - md5: 8ee01a693aecff5432069eaaf1183c45 - sha256: 8a4053839b8e997a5965e2dff7d6cf3c77be62d82c0e48c8a04a5ed2d2e73035 + md5: 8b1275f06705cdc2ab67f3bfdf4df843 + sha256: 7a65accbe954d0304b9056005f59fbee8b3928ceced38b1e3e8272aa1af0b750 category: main optional: false - name: tblib @@ -8124,11 +8119,11 @@ package: platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' - libgcc: '>=14' - url: https://repo.prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-hb03c661_2.conda + libgcc: '>=15' + url: https://repo.prefix.dev/conda-forge/linux-64/xorg-libxau-1.0.12-h7cc23a3_2.conda hash: - md5: f06ef439c280a5f90b8bf62355008dbc - sha256: cbf891f6cc1a859347680af1c8562bc6b033bf182a2a3bb536016932be3206de + md5: da33efee1a93603d92e06d4a2b68def6 + sha256: 3ec065b94554dc48a4ca582a960a5484bc166b26e83ce0954653e08d17e8bd53 category: main optional: false - name: xorg-libxau @@ -8136,13 +8131,13 @@ package: manager: conda platform: win-64 dependencies: - libgcc: '>=14' + libgcc: '>=15' libwinpthread: '>=12.0.0.r4.gg4f2fc60ca' ucrt: '>=10.0.20348.0' - url: https://repo.prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hba3369d_2.conda + url: https://repo.prefix.dev/conda-forge/win-64/xorg-libxau-1.0.12-hfa92662_2.conda hash: - md5: 87aee04978ab77bf4c0f42b983c216cc - sha256: 892ad69b1a9ecc3903ed5a1b18fa097013eaf462eeed3c6ff31bf5c12e71e84b + md5: 68403004c805ce03b71a5889a4c47fa1 + sha256: b9f063792e4d50ef2669c30dfc4ba14aefb4fdc37e384241a71093bee0493ad1 category: main optional: false - name: xorg-libxdmcp @@ -8173,27 +8168,27 @@ package: category: main optional: false - name: xyzservices - version: 2026.3.0 + version: 2026.9.1 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.3.0-pyhd8ed1ab_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.9.1-pyhd8ed1ab_0.conda hash: - md5: 4487b9c371d0161d54b5c7bbd890c0fc - sha256: 663ea9b00d68c2da309114923924686ab6d3f59ef1b196c5029ba16799e7bb07 + md5: 5d7c149ba9c728d4951f3fe6d3ce0f84 + sha256: b9439f1716ff580ce56e9b4a4df7ea92e5ed2bdc9567d25cdff223d62c3183a8 category: main optional: false - name: xyzservices - version: 2026.3.0 + version: 2026.9.1 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.3.0-pyhd8ed1ab_0.conda + url: https://repo.prefix.dev/conda-forge/noarch/xyzservices-2026.9.1-pyhd8ed1ab_0.conda hash: - md5: 4487b9c371d0161d54b5c7bbd890c0fc - sha256: 663ea9b00d68c2da309114923924686ab6d3f59ef1b196c5029ba16799e7bb07 + md5: 5d7c149ba9c728d4951f3fe6d3ce0f84 + sha256: b9439f1716ff580ce56e9b4a4df7ea92e5ed2bdc9567d25cdff223d62c3183a8 category: main optional: false - name: yaml @@ -8420,75 +8415,75 @@ package: category: main optional: false - name: geoapps-utils - version: 0.7.1.dev103+14c4c81 + version: 0.8.0a3.dev11+fd9e5b6 manager: pip platform: linux-64 dependencies: - geoh5py: 0.14.0a1.dev275+ca917b6f + geoh5py: 0.14.0a1 matplotlib: '>=3.10.0,<3.11.0' numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 hash: - sha256: 14c4c814e956277c10e64263b27717c720021b88 + sha256: fd9e5b69283159d7626c501918a246fd2f5202b9 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 category: main optional: false - name: geoapps-utils - version: 0.7.1.dev103+14c4c81 + version: 0.8.0a3.dev11+fd9e5b6 manager: pip platform: win-64 dependencies: - geoh5py: 0.14.0a1.dev275+ca917b6f + geoh5py: 0.14.0a1 matplotlib: '>=3.10.0,<3.11.0' numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 hash: - sha256: 14c4c814e956277c10e64263b27717c720021b88 + sha256: fd9e5b69283159d7626c501918a246fd2f5202b9 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@14c4c814e956277c10e64263b27717c720021b88 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@fd9e5b69283159d7626c501918a246fd2f5202b9 category: main optional: false - name: geoh5py - version: 0.14.0a1.dev275+ca917b6f + version: 0.14.0a1 manager: pip platform: linux-64 dependencies: h5py: '>=3.15.0,<3.16.0' numpy: '>=2.4.0,<2.5.0' - pillow: '>=12.2.0,<12.3.0' + pillow: '>=12.2.0,<13.0.0' psutil: '>=7.2.2,<7.3.0' pydantic: '>=2.12.0,<2.13.0' - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 hash: - sha256: ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + sha256: d45f41aa5af7958ced737f136ec27cca28068b54 source: type: url - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 category: main optional: false - name: geoh5py - version: 0.14.0a1.dev275+ca917b6f + version: 0.14.0a1 manager: pip platform: win-64 dependencies: h5py: '>=3.15.0,<3.16.0' numpy: '>=2.4.0,<2.5.0' - pillow: '>=12.2.0,<12.3.0' + pillow: '>=12.2.0,<13.0.0' psutil: '>=7.2.2,<7.3.0' pydantic: '>=2.12.0,<2.13.0' - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 hash: - sha256: ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + sha256: d45f41aa5af7958ced737f136ec27cca28068b54 source: type: url - url: git+https://github.com/MiraGeoscience/geoh5py.git@ca917b6f4e88bb687ed18f68630c5ac993cd7e76 + url: git+https://github.com/MiraGeoscience/geoh5py.git@d45f41aa5af7958ced737f136ec27cca28068b54 category: main optional: false - name: grid-apps @@ -8497,8 +8492,8 @@ package: platform: linux-64 dependencies: discretize: '>=0.12.0,<0.13.0' - geoapps-utils: 0.7.1.dev103+14c4c81 - geoh5py: 0.14.0a1.dev275+ca917b6f + geoapps-utils: 0.8.0a3.dev11+fd9e5b6 + geoh5py: 0.14.0a1 numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0' @@ -8516,8 +8511,8 @@ package: platform: win-64 dependencies: discretize: '>=0.12.0,<0.13.0' - geoapps-utils: 0.7.1.dev103+14c4c81 - geoh5py: 0.14.0a1.dev275+ca917b6f + geoapps-utils: 0.8.0a3.dev11+fd9e5b6 + geoh5py: 0.14.0a1 numpy: '>=2.4.2,<2.5.0' pydantic: '>=2.12.0,<2.13.0' scipy: '>=1.17.0,<1.18.0'