From 65e0c2588e33b33a5a4eda4eb5040abb442dab0f Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 30 Apr 2025 11:54:38 -0700 Subject: [PATCH 1/5] Remove obsolete methods. Use keys as index --- .../components/factories/__init__.py | 2 +- .../components/factories/survey_factory.py | 37 ++----------------- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/simpeg_drivers/components/factories/__init__.py b/simpeg_drivers/components/factories/__init__.py index b1317380..0b7451f3 100644 --- a/simpeg_drivers/components/factories/__init__.py +++ b/simpeg_drivers/components/factories/__init__.py @@ -19,7 +19,7 @@ from .entity_factory import EntityFactory from .misfit_factory import MisfitFactory from .simulation_factory import SimulationFactory -from .survey_factory import SurveyFactory, receiver_group +from .survey_factory import SurveyFactory # pylint: disable=unused-import # flake8: noqa diff --git a/simpeg_drivers/components/factories/survey_factory.py b/simpeg_drivers/components/factories/survey_factory.py index ca78655d..5ba1b035 100644 --- a/simpeg_drivers/components/factories/survey_factory.py +++ b/simpeg_drivers/components/factories/survey_factory.py @@ -33,39 +33,6 @@ from simpeg_drivers.components.factories.source_factory import SourcesFactory -def receiver_group(txi, potential_electrodes): - """ - Group receivers by common transmitter id. - - :param: txi : transmitter index number. - :param: potential_electrodes : geoh5py object that holds potential electrodes - ab_map and ab_cell_id for a dc survey. - - :return: ids : list of ids of potential electrodes used with transmitter txi. - """ - - index_map = potential_electrodes.ab_map() - index_map = {int(v): k for k, v in index_map.items() if v != "Unknown"} - ids = np.where( - potential_electrodes.ab_cell_id.values.astype(int) == index_map[txi] - )[0] - - return ids - - -def group_locations(obj, ids): - """ - Return vertex locations for possible group of cells. - - :param obj : geoh5py object containing cells, vertices structure. - :param ids : list of ids (or possibly single id) that indexes cells array. - - :return locations : tuple of n locations arrays where n is length of second - dimension of cells array. - """ - return (obj.vertices[obj.cells[ids, i]] for i in range(obj.cells.shape[1])) - - class SurveyFactory(SimPEGFactory): """Build SimPEG sources objects based on factory type.""" @@ -289,7 +256,9 @@ def _dcip_arguments(self, data=None, local_index=None): sources = [] self.local_index = [] for source_id in source_ids[np.argsort(order)]: # Cycle in original order - receiver_indices = receiver_group(source_id, receiver_entity) + receiver_indices = np.where(receiver_entity.ab_cell_id.values == source_id)[ + 0 + ] if local_index is not None: receiver_indices = list(set(receiver_indices).intersection(local_index)) From 4aa8871ac73dfec4ff0bce5f6c6167f832ef09a5 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 30 Apr 2025 11:56:50 -0700 Subject: [PATCH 2/5] Add grid 2D as type option --- simpeg_drivers/options.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simpeg_drivers/options.py b/simpeg_drivers/options.py index f19ad176..403ffaeb 100644 --- a/simpeg_drivers/options.py +++ b/simpeg_drivers/options.py @@ -27,7 +27,7 @@ ReferencedData, ) from geoh5py.groups import PropertyGroup, SimPEGGroup, UIJsonGroup -from geoh5py.objects import DrapeModel, Octree, Points +from geoh5py.objects import DrapeModel, Grid2D, Octree, Points from geoh5py.shared.utils import fetch_active_workspace from geoh5py.ui_json import InputFile from pydantic import BaseModel, ConfigDict, field_validator, model_validator @@ -54,7 +54,7 @@ class ActiveCellsOptions(BaseModel): model_config = ConfigDict( arbitrary_types_allowed=True, ) - topography_object: Points | None = None + topography_object: Points | Grid2D | None = None topography: FloatData | float | None = None active_model: BooleanData | IntegerData | None = None From be5688c479b2a8c8c8ee687b2b143035250687a6 Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 30 Apr 2025 12:47:18 -0700 Subject: [PATCH 3/5] Move the starting IP value off the bound --- .../uijson/induced_polarization_2d_forward.ui.json | 2 +- .../uijson/induced_polarization_2d_inversion.ui.json | 2 +- .../uijson/induced_polarization_3d_forward.ui.json | 2 +- .../uijson/induced_polarization_3d_inversion.ui.json | 2 +- .../uijson/induced_polarization_batch2d_forward.ui.json | 2 +- .../uijson/induced_polarization_batch2d_inversion.ui.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json index 1d3b32df..548d1c3d 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_2d_forward.ui.json @@ -135,7 +135,7 @@ "parent": "mesh", "label": "Value(s)", "property": "", - "value": 0.0 + "value": 0.0001 }, "topography_object": { "main": true, diff --git a/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json index 665942b4..b932df4c 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_2d_inversion.ui.json @@ -154,7 +154,7 @@ "parent": "mesh", "label": "Initial chargeability (V/V)", "property": "", - "value": 0.0 + "value": 0.0001 }, "reference_model": { "association": "Cell", diff --git a/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json index ad74bf9e..d4fdba3b 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_3d_forward.ui.json @@ -69,7 +69,7 @@ "property": "", "min": 0.0, "max": 10000.0, - "value": 0.0 + "value": 0.0001 }, "topography_object": { "main": true, diff --git a/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json index 18243153..41e1d78f 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_3d_inversion.ui.json @@ -94,7 +94,7 @@ "property": "", "min": 0.0, "max": 10000.0, - "value": 0.0 + "value": 0.0001 }, "reference_model": { "association": [ diff --git a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json index 827d957a..e74591b3 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_forward.ui.json @@ -118,7 +118,7 @@ "parent": "mesh", "label": "Value(s)", "property": "", - "value": 0.001 + "value": 0.0001 }, "topography_object": { "main": true, diff --git a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json index 7863b81c..38b403e8 100644 --- a/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json +++ b/simpeg_drivers-assets/uijson/induced_polarization_batch2d_inversion.ui.json @@ -137,7 +137,7 @@ "parent": "mesh", "label": "Initial chargeability (V/V)", "property": "", - "value": 0.001 + "value": 0.0001 }, "reference_model": { "association": "Cell", From 62e86be5ab38f71a1eb4c0df2ebc82daffd56d2f Mon Sep 17 00:00:00 2001 From: dominiquef Date: Wed, 30 Apr 2025 16:24:35 -0700 Subject: [PATCH 4/5] Avoid -1 in the neighbours --- simpeg_drivers/components/topography.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index 34ff9ecb..62cf0e8f 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -164,13 +164,16 @@ def expand_actives( neighbours = get_neighbouring_cells(mesh.mesh, containing_cells) neighbours_xy = np.r_[neighbours[0] + neighbours[1]] + neighbours_xy = neighbours_xy[neighbours_xy != -1] # Make sure the new actives are connected to the old actives new_actives = ~active_cells[neighbours_xy] if np.any(new_actives): neighbours = get_neighbouring_cells( mesh.mesh, neighbours_xy[new_actives] ) - active_cells[np.r_[neighbours[2][0]]] = True # z-axis neighbours + neighbours_z = np.r_[neighbours[2][0]] + neighbours_z = neighbours_z[neighbours_z != -1] + active_cells[neighbours_z] = True # z-axis neighbours active_cells[neighbours_xy] = True # xy-axis neighbours From 0109b6c34df470be3c76787d01d151bc8c4c965b Mon Sep 17 00:00:00 2001 From: dominiquef Date: Thu, 1 May 2025 10:44:00 -0700 Subject: [PATCH 5/5] Augment test to check for --- tests/topography_test.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/topography_test.py b/tests/topography_test.py index dfb96024..e0f5114c 100644 --- a/tests/topography_test.py +++ b/tests/topography_test.py @@ -14,14 +14,14 @@ import numpy as np -from simpeg_drivers.components import InversionTopography +from simpeg_drivers.components import InversionData, InversionMesh, InversionTopography from simpeg_drivers.options import ActiveCellsOptions from simpeg_drivers.potential_fields import MVIInversionOptions from simpeg_drivers.utils.testing import Geoh5Tester, setup_inversion_workspace def test_get_locations(tmp_path: Path): - geoh5, entity, model, survey, topography = setup_inversion_workspace( + geoh5, mesh, model, survey, topography = setup_inversion_workspace( tmp_path, background=0.0, anomaly=0.05, @@ -31,7 +31,6 @@ def test_get_locations(tmp_path: Path): inversion_type="magnetic_vector", ) with geoh5.open(): - mesh = model.parent tmi_channel, gyz_channel = survey.add_data( { "tmi": {"values": np.random.rand(survey.n_vertices)}, @@ -51,6 +50,7 @@ def test_get_locations(tmp_path: Path): ), starting_model=1.0, ) + geoh5 = params.geoh5 with geoh5.open(): topo = InversionTopography(geoh5, params) @@ -60,6 +60,25 @@ def test_get_locations(tmp_path: Path): params.active_cells.topography.values, ) + # Check that boundary cells are handled properly + # Shift one of the survey vertices to the corner + survey.vertices[0, :] = mesh.centroids[0, :] + geoh5.update_attribute(survey, "vertices") + inversion_mesh = InversionMesh(geoh5, params) + inversion_data = InversionData(geoh5, params) + params.inversion_type = "magnetotellurics" + active_cells = topo.active_cells(inversion_mesh, inversion_data) + + mesh.add_data( + { + "active_cells": { + "values": active_cells, + } + } + ) + assert not active_cells[-1] + + # Test flat topo params.active_cells.topography = 199.0 locs = topo.get_locations(params.active_cells.topography_object) np.testing.assert_allclose(locs[:, 2], np.ones_like(locs[:, 2]) * 199.0)