From 56d400a0edb2fb990d0e09eeed136d3dd6bd841d Mon Sep 17 00:00:00 2001 From: benjamink Date: Fri, 17 Jan 2025 09:07:15 -0800 Subject: [PATCH 01/21] ..working on gravity unit test --- simpeg_drivers/__init__.py | 2 +- .../direct_current/three_dimensions/params.py | 2 +- .../three_dimensions/params.py | 2 +- simpeg_drivers/electricals/params.py | 2 +- .../frequency_domain/params.py | 2 +- .../electromagnetics/time_domain/params.py | 2 +- .../magnetotellurics/params.py | 2 +- .../natural_sources/tipper/params.py | 2 +- simpeg_drivers/params.py | 296 +++++++- .../potential_fields/gravity/params.py | 650 ++++++++++-------- .../magnetic_scalar/params.py | 2 +- .../magnetic_vector/params.py | 2 +- tests/params_test.py | 51 +- 13 files changed, 711 insertions(+), 306 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index 2b0740e4..ea8b8e4f 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -19,7 +19,7 @@ from pathlib import Path from simpeg_drivers.constants import default_ui_json -from simpeg_drivers.params import InversionBaseParams +# from simpeg_drivers.params import InversionBaseParams logging.basicConfig(level=logging.INFO) diff --git a/simpeg_drivers/electricals/direct_current/three_dimensions/params.py b/simpeg_drivers/electricals/direct_current/three_dimensions/params.py index 56b833d7..81dd87da 100644 --- a/simpeg_drivers/electricals/direct_current/three_dimensions/params.py +++ b/simpeg_drivers/electricals/direct_current/three_dimensions/params.py @@ -13,7 +13,7 @@ from copy import deepcopy -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/electricals/induced_polarization/three_dimensions/params.py b/simpeg_drivers/electricals/induced_polarization/three_dimensions/params.py index 8ecaa5bc..e85c9af0 100644 --- a/simpeg_drivers/electricals/induced_polarization/three_dimensions/params.py +++ b/simpeg_drivers/electricals/induced_polarization/three_dimensions/params.py @@ -13,7 +13,7 @@ from copy import deepcopy -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/electricals/params.py b/simpeg_drivers/electricals/params.py index b13c6f90..e2b55a95 100644 --- a/simpeg_drivers/electricals/params.py +++ b/simpeg_drivers/electricals/params.py @@ -14,7 +14,7 @@ import numpy as np from geoh5py.data import Data, DataAssociationEnum -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from simpeg_drivers.utils.utils import get_drape_model diff --git a/simpeg_drivers/electromagnetics/frequency_domain/params.py b/simpeg_drivers/electromagnetics/frequency_domain/params.py index ed48874d..2791f19a 100644 --- a/simpeg_drivers/electromagnetics/frequency_domain/params.py +++ b/simpeg_drivers/electromagnetics/frequency_domain/params.py @@ -14,7 +14,7 @@ from copy import deepcopy from uuid import UUID -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/electromagnetics/time_domain/params.py b/simpeg_drivers/electromagnetics/time_domain/params.py index 0f2d9340..6affbc8d 100644 --- a/simpeg_drivers/electromagnetics/time_domain/params.py +++ b/simpeg_drivers/electromagnetics/time_domain/params.py @@ -14,7 +14,7 @@ from copy import deepcopy from uuid import UUID -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/natural_sources/magnetotellurics/params.py b/simpeg_drivers/natural_sources/magnetotellurics/params.py index ed2696c8..19df502f 100644 --- a/simpeg_drivers/natural_sources/magnetotellurics/params.py +++ b/simpeg_drivers/natural_sources/magnetotellurics/params.py @@ -14,7 +14,7 @@ from copy import deepcopy from uuid import UUID -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/natural_sources/tipper/params.py b/simpeg_drivers/natural_sources/tipper/params.py index ceb71d53..d1ca825a 100644 --- a/simpeg_drivers/natural_sources/tipper/params.py +++ b/simpeg_drivers/natural_sources/tipper/params.py @@ -14,7 +14,7 @@ from copy import deepcopy from uuid import UUID -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index b124f93f..f422578d 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -12,17 +12,307 @@ from __future__ import annotations import warnings +from pathlib import Path from copy import deepcopy from uuid import UUID import numpy as np +from typing import ClassVar +from pydantic import BaseModel, ConfigDict, field_validator, model_validator + +from geoapps_utils.driver.data import BaseData from geoapps_utils.driver.params import BaseParams -from geoh5py.data import NumericData -from geoh5py.groups import SimPEGGroup -from geoh5py.objects import Octree +from geoh5py.data import NumericData, BooleanData +from geoh5py.groups import SimPEGGroup, UIJsonGroup +from geoh5py.objects import Octree, DrapeModel, Points +from geoh5py.data import FloatData from geoh5py.shared.utils import fetch_active_workspace from geoh5py.ui_json import InputFile +from simpeg_drivers import assets_path + + +class ActiveCellsData(BaseModel): + """ + Active cells data as a topography surface or 3d model. + + :param topography_object: Topography object. + :param topography: Topography data. + :param active_model: Topography + """ + model_config = ConfigDict( + # frozen=True, + arbitrary_types_allowed=True, + ) + topography_object: Points# | None = None + # topography: FloatData | None = None + # active_model: BooleanData | None = None + + @model_validator(mode="before") + @classmethod + def at_least_one(cls, data): + if all(v is None for v in data.values()): + raise ValueError("Must provide either topography or active model.") + return data + + + +class CoreData(BaseModel): + """ + Core parameters shared by inverse and forward operations. + + :param run_command: Command (module name) used to run the application from + command line. + :param conda_environment: Name of the conda environment used to run the + application with all of its dependencies. + :param data_object: Data object containing survey geometry and data + channels. + :param mesh: Mesh object containing models (starting, reference, active, etc..). + :param starting_model: Starting model used to start inversion or for simulating + data in the forward operation. + :param topography_object: Topography object used to define the active cells of + the model. + """ + model_config = ConfigDict( + frozen=True, + arbitrary_types_allowed=True, + ) + run_command: ClassVar[str] = "simpeg_drivers.driver" + conda_environment: str = "simpeg_drivers" + data_object: Points + mesh: Octree | None + starting_model: float | FloatData + active: ActiveCellsData + tile_spatial: int = 1 + out_group: SimPEGGroup | UIJsonGroup | None = None + generate_sweep: bool = False + + @field_validator("mesh", mode="before") + @classmethod + def mesh_cannot_be_rotated(cls, value: Octree): + if isinstance(value, Octree) and value.rotation not in [0.0, None]: + raise ValueError( + "Rotated meshes are not supported. Please use a mesh with an angle of 0.0." + ) + + @property + def channels(self) -> list[str]: + return [k for k in self.__dict__ if "channel" in k] + + @property + def padding_cells(self) -> int: + """ + Default padding cells used for tiling. + """ + # Keep whole mesh for 1 tile + if self.tile_spatial == 1: + return 100 + + return 4 if self.inversion_type in ["fem", "tdem"] else 6 + + +class BaseForwardData(BaseData, CoreData): + """ + Base class for forward parameters. + + :param name: Name of the application. + :param title: Title of the application + :param core: Core parameters for forward (data, mesh, starting model, active). + """ + + forward_only: bool = True + + @property + def default_ui_json(self) -> Path: + name = '_'.join(self.title.lower().split()) + return assets_path() / "ui_json" / f"{name}_forward.ui.json" + + @property + def components(self) -> list[str]: + """Retrieve component names used to index channel and uncertainty data.""" + comps = [] + for c in self.channels: + if getattr(self, f"{c}_channel_bool", None) is not None: + comps.append(c) + + return comps + + +class BaseInversionData(BaseData, CoreData): + """ + Base class for inversion parameters. + + :param core: Core parameters for inversion (data, mesh, starting model, active). + + :param reference_model: Reference model. + :param lower_bound: Lower bound. + :param upper_bound: Upper bound. + + :param alpha_s: Alpha s. + :param length_scale_x: Length scale x. + :param length_scale_y: Length scale y. + :param length_scale_z: Length scale z. + + :param s_norm: S norm. + :param x_norm: X norm. + :param y_norm: Y norm. + :param z_norm: Z norm. + :param gradient_type: Gradient type. + :param max_irls_iterations: Maximum IRLS iterations. + :param starting_chi_factor: Starting chi factor. + + :param prctile: Prctile. + :param beta_tol: Beta tolerance. + + :param chi_factor: Chi factor. + :param auto_scale_misfits: Automatically scale misfits. + :param initial_beta: Initial beta. + :param initial_beta_ratio: Initial beta ratio. + :param coolingFactor: Cooling factor. + + :param coolingRate: Cooling rate. + :param max_global_iterations: Maximum global iterations. + :param max_line_search_iterations: Maximum line search iterations. + :param max_cg_iterations: Maximum CG iterations. + :param tol_cg: Tolerance CG. + :param f_min_change: F min change. + + :param sens_wts_threshold: Sensitivity weights threshold. + :param every_iteration_bool: Every iteration bool. + :param save_sensitivities: Save sensitivities. + + :param parallelized: Parallelized. + :param n_cpu: Number of CPUs. + :param tile_spatial: Tile the data spatially. + :param store_sensitivities: Store sensitivities. + :param max_chunk_size: Maximum chunk size. + :param chunk_by_rows: Chunk by rows. + + :param out_group: Output group. + + :param generate_sweep: Generate sweep. + + :param output_tile_files: Output tile files. + :param inversion_style: Inversion style. + :param max_ram: Maximum RAM. :param coolEps_q: Cool eps q. + :param coolEpsFact: Cool eps fact. + :param beta_search: Beta search. + :param ga_group: GA group. + :param distributed_workers: Distributed workers. + :param no_data_value: No data value. + """ + + model_config = ConfigDict( + frozen=True, + arbitrary_types_allowed=True, + ) + + name: ClassVar[str] = "Inversion" + title: ClassVar[str] = "Geophysical inversion" + run_command: ClassVar[str] = "simpeg_drivers.driver" + + conda_environment: str = "simpeg_drivers" + reference_model: float | FloatData | None + lower_bound: float | FloatData | None + upper_bound: float | FloatData | None + + forward_only: bool = False + + topography: FloatData | None + active_model: BooleanData | None + + alpha_s: float | FloatData = 1.0 + length_scale_x: float | FloatData = 1.0 + length_scale_y: float | FloatData = 1.0 + length_scale_z: float | FloatData = 1.0 + + s_norm: float | FloatData = 0.0 + x_norm: float | FloatData = 2.0 + y_norm: float | FloatData = 2.0 + z_norm: float | FloatData = 2.0 + gradient_type: str = "total" + max_irls_iterations: int = 25 + starting_chi_factor: float = 1.0 + + chi_factor: float = 1.0 + auto_scale_misfits: bool = True + initial_beta_ratio: float | None = 100.0 + initial_beta: float | None = None + coolingFactor: float = 2.0 + + coolingRate: float = 2.0 + max_global_iterations: int = 50 + max_line_search_iterations: int = 20 + max_cg_iterations: int = 30 + tol_cg: float = 1e-4 + f_min_change: float = 1e-2 + sens_wts_threshold: float + every_iteration_bool: bool + save_sensitivities: bool + + sens_wts_threshold: float = 1e-3 + every_iteration_bool: bool = True + save_sensitivities: bool = False + + tile_spatial: int = 1 + store_sensitivities: str = "ram" + + parallelized: bool + n_cpu: int + max_chunk_size: int + chunk_by_rows: bool + prctile: float + beta_tol: float + output_tile_files: bool + inversion_style: str + max_ram: float + ga_group: SimPEGGroup + distributed_workers: int + no_data_value: float + + @property + def default_ui_json(self) -> Path: + return assets_path() / "ui_json" / f"{'_'.join(self.title.lower().split())}_inversion.ui.json" + + def data_channel(self, component: str) -> NumericData | None: + """Return the data object associated with the component.""" + return getattr(self, "_".join([component, "channel"]), None) + + def uncertainty_channel(self, component: str) -> NumericData | None: + """Return the uncertainty object associated with the component.""" + return getattr(self, "_".join([component, "uncertainty"]), None) + + def data(self, component: str) -> np.ndarray | None: + """Returns array of data for chosen data component if it exists.""" + data_entity = self.data_channel(component) + if isinstance(data_entity, NumericData): + return data_entity.values.astype(float) + return None + + def uncertainty(self, component: str) -> np.ndarray | None: + """Returns uncertainty for chosen data component if it exists.""" + uncertainty_entity = self.uncertainty_channel(component) + if isinstance(uncertainty_entity, NumericData): + return uncertainty_entity.values.astype(float) + elif self.data(component) is not None: + d = self.data(component) + if isinstance(uncertainty_entity, int | float): + return np.array([float(uncertainty_entity)] * len(d)) + else: + return d * 0.0 + 1.0 # Default + else: + return None + + def model_norms(self) -> list[float]: + """Returns model norm components as a list.""" + return [ + self.s_norm, + self.x_norm, + self.y_norm, + self.z_norm, + ] + + class InversionBaseParams(BaseParams): """ diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index eaba1f75..c0827c7d 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -11,9 +11,12 @@ from __future__ import annotations +from typing import ClassVar from copy import deepcopy -from simpeg_drivers.params import InversionBaseParams +from geoh5py.data import FloatData + +from simpeg_drivers.params import BaseForwardData, BaseInversionData from .constants import ( default_ui_json, @@ -22,298 +25,361 @@ validations, ) - -class GravityParams(InversionBaseParams): +class GravityForwardParams(BaseForwardData): """ - Parameter class for gravity->density inversion. + Gravity forward parameters. + + :param gx_channel_bool: gx channel boolean. + :param gy_channel_bool: gy channel boolean. + :param gz_channel_bool: gz channel boolean. + :param gxx_channel_bool: gxx channel boolean. + :param gxy_channel_bool: gxy channel boolean. + :param gxz_channel_bool: gxz channel boolean. + :param gyy_channel_bool: gyy channel boolean. + :param gyz_channel_bool: gyz channel boolean. + :param gzz_channel_bool: gzz channel boolean. """ - _physical_property = "density" - - def __init__(self, input_file=None, forward_only=False, **kwargs): - self._default_ui_json = deepcopy(default_ui_json) - self._forward_defaults = deepcopy(forward_defaults) - self._inversion_defaults = deepcopy(inversion_defaults) - self._inversion_type = "gravity" - self._validations = validations - self._gz_channel_bool = None - self._gz_channel = None - self._gz_uncertainty = None - self._guv_channel_bool = None - self._guv_channel = None - self._guv_uncertainty = None - self._gxy_channel_bool = None - self._gxy_channel = None - self._gxy_uncertainty = None - self._gxx_channel_bool = None - self._gxx_channel = None - self._gxx_uncertainty = None - self._gyy_channel_bool = None - self._gyy_channel = None - self._gyy_uncertainty = None - self._gzz_channel_bool = None - self._gzz_channel = None - self._gzz_uncertainty = None - self._gxz_channel_bool = None - self._gxz_channel = None - self._gxz_uncertainty = None - self._gyz_channel_bool = None - self._gyz_channel = None - self._gyz_uncertainty = None - self._gx_channel_bool = None - self._gx_channel = None - self._gx_uncertainty = None - self._gy_channel_bool = None - self._gy_channel = None - self._gy_uncertainty = None - self._out_group = None - - super().__init__(input_file=input_file, forward_only=forward_only, **kwargs) - - def components(self) -> list[str]: - """Retrieve component names used to index channel and uncertainty data.""" - comps = super().components() - if self.forward_only: - if len(comps) == 0: - comps = ["gz"] - return comps - - @property - def gz_channel_bool(self): - return self._gz_channel_bool - - @gz_channel_bool.setter - def gz_channel_bool(self, val): - self.setter_validator("gz_channel_bool", val) - - @property - def gz_channel(self): - return self._gz_channel - - @gz_channel.setter - def gz_channel(self, val): - self.setter_validator("gz_channel", val, fun=self._uuid_promoter) - - @property - def gz_uncertainty(self): - return self._gz_uncertainty - - @gz_uncertainty.setter - def gz_uncertainty(self, val): - self.setter_validator("gz_uncertainty", val, fun=self._uuid_promoter) - - @property - def guv_channel_bool(self): - return self._guv_channel_bool - - @guv_channel_bool.setter - def guv_channel_bool(self, val): - self.setter_validator("guv_channel_bool", val) - - @property - def guv_channel(self): - return self._guv_channel - - @guv_channel.setter - def guv_channel(self, val): - self.setter_validator("guv_channel", val, fun=self._uuid_promoter) - - @property - def guv_uncertainty(self): - return self._guv_uncertainty - - @guv_uncertainty.setter - def guv_uncertainty(self, val): - self.setter_validator("guv_uncertainty", val, fun=self._uuid_promoter) - - @property - def gxy_channel_bool(self): - return self._gxy_channel_bool - - @gxy_channel_bool.setter - def gxy_channel_bool(self, val): - self.setter_validator("gxy_channel_bool", val) - - @property - def gxy_channel(self): - return self._gxy_channel - - @gxy_channel.setter - def gxy_channel(self, val): - self.setter_validator("gxy_channel", val, fun=self._uuid_promoter) - - @property - def gxy_uncertainty(self): - return self._gxy_uncertainty - - @gxy_uncertainty.setter - def gxy_uncertainty(self, val): - self.setter_validator("gxy_uncertainty", val, fun=self._uuid_promoter) - - @property - def gxx_channel_bool(self): - return self._gxx_channel_bool - - @gxx_channel_bool.setter - def gxx_channel_bool(self, val): - self.setter_validator("gxx_channel_bool", val) - - @property - def gxx_channel(self): - return self._gxx_channel - - @gxx_channel.setter - def gxx_channel(self, val): - self.setter_validator("gxx_channel", val, fun=self._uuid_promoter) - - @property - def gxx_uncertainty(self): - return self._gxx_uncertainty - - @gxx_uncertainty.setter - def gxx_uncertainty(self, val): - self.setter_validator("gxx_uncertainty", val, fun=self._uuid_promoter) - - @property - def gyy_channel_bool(self): - return self._gyy_channel_bool - - @gyy_channel_bool.setter - def gyy_channel_bool(self, val): - self.setter_validator("gyy_channel_bool", val) - - @property - def gyy_channel(self): - return self._gyy_channel - - @gyy_channel.setter - def gyy_channel(self, val): - self.setter_validator("gyy_channel", val, fun=self._uuid_promoter) - - @property - def gyy_uncertainty(self): - return self._gyy_uncertainty - - @gyy_uncertainty.setter - def gyy_uncertainty(self, val): - self.setter_validator("gyy_uncertainty", val, fun=self._uuid_promoter) - - @property - def gzz_channel_bool(self): - return self._gzz_channel_bool - - @gzz_channel_bool.setter - def gzz_channel_bool(self, val): - self.setter_validator("gzz_channel_bool", val) - - @property - def gzz_channel(self): - return self._gzz_channel - - @gzz_channel.setter - def gzz_channel(self, val): - self.setter_validator("gzz_channel", val, fun=self._uuid_promoter) - - @property - def gzz_uncertainty(self): - return self._gzz_uncertainty - - @gzz_uncertainty.setter - def gzz_uncertainty(self, val): - self.setter_validator("gzz_uncertainty", val, fun=self._uuid_promoter) - - @property - def gxz_channel_bool(self): - return self._gxz_channel_bool - - @gxz_channel_bool.setter - def gxz_channel_bool(self, val): - self.setter_validator("gxz_channel_bool", val) - - @property - def gxz_channel(self): - return self._gxz_channel - - @gxz_channel.setter - def gxz_channel(self, val): - self.setter_validator("gxz_channel", val, fun=self._uuid_promoter) - - @property - def gxz_uncertainty(self): - return self._gxz_uncertainty - - @gxz_uncertainty.setter - def gxz_uncertainty(self, val): - self.setter_validator("gxz_uncertainty", val, fun=self._uuid_promoter) - - @property - def gyz_channel_bool(self): - return self._gyz_channel_bool - - @gyz_channel_bool.setter - def gyz_channel_bool(self, val): - self.setter_validator("gyz_channel_bool", val) - - @property - def gyz_channel(self): - return self._gyz_channel - - @gyz_channel.setter - def gyz_channel(self, val): - self.setter_validator("gyz_channel", val, fun=self._uuid_promoter) - - @property - def gyz_uncertainty(self): - return self._gyz_uncertainty - - @gyz_uncertainty.setter - def gyz_uncertainty(self, val): - self.setter_validator("gyz_uncertainty", val, fun=self._uuid_promoter) - - @property - def gx_channel_bool(self): - return self._gx_channel_bool - - @gx_channel_bool.setter - def gx_channel_bool(self, val): - self.setter_validator("gx_channel_bool", val) - - @property - def gx_channel(self): - return self._gx_channel - - @gx_channel.setter - def gx_channel(self, val): - self.setter_validator("gx_channel", val, fun=self._uuid_promoter) - - @property - def gx_uncertainty(self): - return self._gx_uncertainty - - @gx_uncertainty.setter - def gx_uncertainty(self, val): - self.setter_validator("gx_uncertainty", val, fun=self._uuid_promoter) - - @property - def gy_channel_bool(self): - return self._gy_channel_bool - - @gy_channel_bool.setter - def gy_channel_bool(self, val): - self.setter_validator("gy_channel_bool", val) - - @property - def gy_channel(self): - return self._gy_channel - - @gy_channel.setter - def gy_channel(self, val): - self.setter_validator("gy_channel", val, fun=self._uuid_promoter) - - @property - def gy_uncertainty(self): - return self._gy_uncertainty +class GravityInversionParams(BaseInversionData): + """ + Gravity inversion parameters. + + :param gx_channel: gx channel. + :param gy_channel: gy channel. + :param gz_channel: gz channel. + :param gxx_channel: gxx channel. + :param gxy_channel: gxy channel. + :param gxz_channel: gxz channel. + :param gyy_channel: gyy channel. + :param gyz_channel: gyz channel. + :param gzz_channel: gzz channel. + :param gx_uncertainty: gx uncertainty. + :param gy_uncertainty: gy uncertainty. + :param gz_uncertainty: gz uncertainty. + :param gxx_uncertainty: gxx uncertainty. + :param gxy_uncertainty: gxy uncertainty. + :param gxz_uncertainty: gxz uncertainty. + :param gyy_uncertainty: gyy uncertainty. + :param gyz_uncertainty: gyz uncertainty. + :param gzz_uncertainty: gzz uncertainty. + """ - @gy_uncertainty.setter - def gy_uncertainty(self, val): - self.setter_validator("gy_uncertainty", val, fun=self._uuid_promoter) + name: ClassVar[str] = "Gravity Inversion" + title: ClassVar[str] = "Gravity Inversion" + + inversion_type: str = "gravity" + physical_property: str = "density" + gx_channel: FloatData | None = None + gy_channel: FloatData | None = None + gz_channel: FloatData | None = None + gxx_channel: FloatData | None = None + gxy_channel: FloatData | None = None + gxz_channel: FloatData | None = None + gyy_channel: FloatData | None = None + gyz_channel: FloatData | None = None + gzz_channel: FloatData | None = None + gx_uncertainty: FloatData | None = None + gy_uncertainty: FloatData | None = None + gz_uncertainty: FloatData | None = None + gxx_uncertainty: FloatData | None = None + gxy_uncertainty: FloatData | None = None + gxz_uncertainty: FloatData | None = None + gyy_uncertainty: FloatData | None = None + gyz_uncertainty: FloatData | None = None + gzz_uncertainty: FloatData | None = None + + +# class GravityParams(InversionBaseParams): +# """ +# Parameter class for gravity->density inversion. +# """ +# +# _physical_property = "density" +# +# def __init__(self, input_file=None, forward_only=False, **kwargs): +# self._default_ui_json = deepcopy(default_ui_json) +# self._forward_defaults = deepcopy(forward_defaults) +# self._inversion_defaults = deepcopy(inversion_defaults) +# self._inversion_type = "gravity" +# self._validations = validations +# self._gz_channel_bool = None +# self._gz_channel = None +# self._gz_uncertainty = None +# self._guv_channel_bool = None +# self._guv_channel = None +# self._guv_uncertainty = None +# self._gxy_channel_bool = None +# self._gxy_channel = None +# self._gxy_uncertainty = None +# self._gxx_channel_bool = None +# self._gxx_channel = None +# self._gxx_uncertainty = None +# self._gyy_channel_bool = None +# self._gyy_channel = None +# self._gyy_uncertainty = None +# self._gzz_channel_bool = None +# self._gzz_channel = None +# self._gzz_uncertainty = None +# self._gxz_channel_bool = None +# self._gxz_channel = None +# self._gxz_uncertainty = None +# self._gyz_channel_bool = None +# self._gyz_channel = None +# self._gyz_uncertainty = None +# self._gx_channel_bool = None +# self._gx_channel = None +# self._gx_uncertainty = None +# self._gy_channel_bool = None +# self._gy_channel = None +# self._gy_uncertainty = None +# self._out_group = None +# +# super().__init__(input_file=input_file, forward_only=forward_only, **kwargs) +# +# def components(self) -> list[str]: +# """Retrieve component names used to index channel and uncertainty data.""" +# comps = super().components() +# if self.forward_only: +# if len(comps) == 0: +# comps = ["gz"] +# return comps +# +# @property +# def gz_channel_bool(self): +# return self._gz_channel_bool +# +# @gz_channel_bool.setter +# def gz_channel_bool(self, val): +# self.setter_validator("gz_channel_bool", val) +# +# @property +# def gz_channel(self): +# return self._gz_channel +# +# @gz_channel.setter +# def gz_channel(self, val): +# self.setter_validator("gz_channel", val, fun=self._uuid_promoter) +# +# @property +# def gz_uncertainty(self): +# return self._gz_uncertainty +# +# @gz_uncertainty.setter +# def gz_uncertainty(self, val): +# self.setter_validator("gz_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def guv_channel_bool(self): +# return self._guv_channel_bool +# +# @guv_channel_bool.setter +# def guv_channel_bool(self, val): +# self.setter_validator("guv_channel_bool", val) +# +# @property +# def guv_channel(self): +# return self._guv_channel +# +# @guv_channel.setter +# def guv_channel(self, val): +# self.setter_validator("guv_channel", val, fun=self._uuid_promoter) +# +# @property +# def guv_uncertainty(self): +# return self._guv_uncertainty +# +# @guv_uncertainty.setter +# def guv_uncertainty(self, val): +# self.setter_validator("guv_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gxy_channel_bool(self): +# return self._gxy_channel_bool +# +# @gxy_channel_bool.setter +# def gxy_channel_bool(self, val): +# self.setter_validator("gxy_channel_bool", val) +# +# @property +# def gxy_channel(self): +# return self._gxy_channel +# +# @gxy_channel.setter +# def gxy_channel(self, val): +# self.setter_validator("gxy_channel", val, fun=self._uuid_promoter) +# +# @property +# def gxy_uncertainty(self): +# return self._gxy_uncertainty +# +# @gxy_uncertainty.setter +# def gxy_uncertainty(self, val): +# self.setter_validator("gxy_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gxx_channel_bool(self): +# return self._gxx_channel_bool +# +# @gxx_channel_bool.setter +# def gxx_channel_bool(self, val): +# self.setter_validator("gxx_channel_bool", val) +# +# @property +# def gxx_channel(self): +# return self._gxx_channel +# +# @gxx_channel.setter +# def gxx_channel(self, val): +# self.setter_validator("gxx_channel", val, fun=self._uuid_promoter) +# +# @property +# def gxx_uncertainty(self): +# return self._gxx_uncertainty +# +# @gxx_uncertainty.setter +# def gxx_uncertainty(self, val): +# self.setter_validator("gxx_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gyy_channel_bool(self): +# return self._gyy_channel_bool +# +# @gyy_channel_bool.setter +# def gyy_channel_bool(self, val): +# self.setter_validator("gyy_channel_bool", val) +# +# @property +# def gyy_channel(self): +# return self._gyy_channel +# +# @gyy_channel.setter +# def gyy_channel(self, val): +# self.setter_validator("gyy_channel", val, fun=self._uuid_promoter) +# +# @property +# def gyy_uncertainty(self): +# return self._gyy_uncertainty +# +# @gyy_uncertainty.setter +# def gyy_uncertainty(self, val): +# self.setter_validator("gyy_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gzz_channel_bool(self): +# return self._gzz_channel_bool +# +# @gzz_channel_bool.setter +# def gzz_channel_bool(self, val): +# self.setter_validator("gzz_channel_bool", val) +# +# @property +# def gzz_channel(self): +# return self._gzz_channel +# +# @gzz_channel.setter +# def gzz_channel(self, val): +# self.setter_validator("gzz_channel", val, fun=self._uuid_promoter) +# +# @property +# def gzz_uncertainty(self): +# return self._gzz_uncertainty +# +# @gzz_uncertainty.setter +# def gzz_uncertainty(self, val): +# self.setter_validator("gzz_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gxz_channel_bool(self): +# return self._gxz_channel_bool +# +# @gxz_channel_bool.setter +# def gxz_channel_bool(self, val): +# self.setter_validator("gxz_channel_bool", val) +# +# @property +# def gxz_channel(self): +# return self._gxz_channel +# +# @gxz_channel.setter +# def gxz_channel(self, val): +# self.setter_validator("gxz_channel", val, fun=self._uuid_promoter) +# +# @property +# def gxz_uncertainty(self): +# return self._gxz_uncertainty +# +# @gxz_uncertainty.setter +# def gxz_uncertainty(self, val): +# self.setter_validator("gxz_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gyz_channel_bool(self): +# return self._gyz_channel_bool +# +# @gyz_channel_bool.setter +# def gyz_channel_bool(self, val): +# self.setter_validator("gyz_channel_bool", val) +# +# @property +# def gyz_channel(self): +# return self._gyz_channel +# +# @gyz_channel.setter +# def gyz_channel(self, val): +# self.setter_validator("gyz_channel", val, fun=self._uuid_promoter) +# +# @property +# def gyz_uncertainty(self): +# return self._gyz_uncertainty +# +# @gyz_uncertainty.setter +# def gyz_uncertainty(self, val): +# self.setter_validator("gyz_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gx_channel_bool(self): +# return self._gx_channel_bool +# +# @gx_channel_bool.setter +# def gx_channel_bool(self, val): +# self.setter_validator("gx_channel_bool", val) +# +# @property +# def gx_channel(self): +# return self._gx_channel +# +# @gx_channel.setter +# def gx_channel(self, val): +# self.setter_validator("gx_channel", val, fun=self._uuid_promoter) +# +# @property +# def gx_uncertainty(self): +# return self._gx_uncertainty +# +# @gx_uncertainty.setter +# def gx_uncertainty(self, val): +# self.setter_validator("gx_uncertainty", val, fun=self._uuid_promoter) +# +# @property +# def gy_channel_bool(self): +# return self._gy_channel_bool +# +# @gy_channel_bool.setter +# def gy_channel_bool(self, val): +# self.setter_validator("gy_channel_bool", val) +# +# @property +# def gy_channel(self): +# return self._gy_channel +# +# @gy_channel.setter +# def gy_channel(self, val): +# self.setter_validator("gy_channel", val, fun=self._uuid_promoter) +# +# @property +# def gy_uncertainty(self): +# return self._gy_uncertainty +# +# @gy_uncertainty.setter +# def gy_uncertainty(self, val): +# self.setter_validator("gy_uncertainty", val, fun=self._uuid_promoter) diff --git a/simpeg_drivers/potential_fields/magnetic_scalar/params.py b/simpeg_drivers/potential_fields/magnetic_scalar/params.py index 3a637c68..3f727946 100644 --- a/simpeg_drivers/potential_fields/magnetic_scalar/params.py +++ b/simpeg_drivers/potential_fields/magnetic_scalar/params.py @@ -17,7 +17,7 @@ from copy import deepcopy -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/simpeg_drivers/potential_fields/magnetic_vector/params.py b/simpeg_drivers/potential_fields/magnetic_vector/params.py index 3a58e427..faf4f9bc 100644 --- a/simpeg_drivers/potential_fields/magnetic_vector/params.py +++ b/simpeg_drivers/potential_fields/magnetic_vector/params.py @@ -13,7 +13,7 @@ from copy import deepcopy -from simpeg_drivers import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams from .constants import ( default_ui_json, diff --git a/tests/params_test.py b/tests/params_test.py index 0767b77f..3e1edecf 100644 --- a/tests/params_test.py +++ b/tests/params_test.py @@ -16,6 +16,7 @@ from uuid import UUID, uuid4 import pytest +from geoh5py.objects import DrapeModel from geoh5py.shared.exceptions import ( AssociationValidationError, OptionalValidationError, @@ -35,7 +36,7 @@ InducedPolarization3DParams, ) from simpeg_drivers.potential_fields import ( - GravityParams, + GravityInversionParams, MagneticScalarParams, MagneticVectorParams, ) @@ -582,3 +583,51 @@ def test_conductivity_model(ip_params): match="Must be one of: 'str', 'UUID', 'int', 'float', 'Entity'.", ): ip_params.conductivity_model = ip_params.geoh5 + +def test_active_cells_data(tmp_path): + from simpeg_drivers.params import ActiveCellsData + from geoh5py import Workspace + from geoh5py.objects import Points + import numpy as np + + ws = Workspace(tmp_path / "test.geoh5") + pts = Points.create(ws, vertices=np.random.rand(10, 3)) + data = ActiveCellsData(topography_object=pts) + assert True + +def test_something(tmp_path): + + from typing import ClassVar + from geoh5py import Workspace + from geoh5py.objects import Points, Octree + from pydantic import BaseModel, ConfigDict + from geoapps_utils.driver.data import BaseData + + ws = Workspace(tmp_path / "test.geoh5") + + class CoreData(BaseModel): + model_config = ConfigDict( + frozen=True, + arbitrary_types_allowed=True, + ) + run_command: ClassVar[str] = "simpeg_drivers.driver" + conda_environment: str = "simpeg_drivers" + data_object: Points | None + mesh: Octree | None + + class GravityData(BaseData, CoreData): + model_config = ConfigDict( + frozen=True, + arbitrary_types_allowed=True, + ) + mesh: DrapeModel | None + myparam: int = 1 + + data = GravityData( + geoh5 = ws, + data_object = None, + mesh = None, + myparam = 2 + ) + + assert True \ No newline at end of file From 17f30b08bc927d0a7bec89e115169ad81b8d648f Mon Sep 17 00:00:00 2001 From: benjamink Date: Fri, 17 Jan 2025 09:08:52 -0800 Subject: [PATCH 02/21] still working on gravity runtest --- simpeg_drivers/__init__.py | 2 ++ simpeg_drivers/driver.py | 5 ++-- simpeg_drivers/params.py | 26 +++++++++--------- simpeg_drivers/potential_fields/__init__.py | 2 +- .../potential_fields/gravity/__init__.py | 2 +- .../potential_fields/gravity/driver.py | 7 ++--- .../potential_fields/gravity/params.py | 3 ++- tests/params_test.py | 22 +++++++-------- tests/run_tests/driver_grav_test.py | 27 ++++++++++--------- 9 files changed, 52 insertions(+), 44 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index ea8b8e4f..086ca70e 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -19,6 +19,8 @@ from pathlib import Path from simpeg_drivers.constants import default_ui_json + + # from simpeg_drivers.params import InversionBaseParams diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index 5b25cf8d..3ab77133 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -22,6 +22,7 @@ import numpy as np from dask import config as dconf from geoapps_utils.driver.driver import BaseDriver +from geoapps_utils.driver.data import BaseData from geoh5py.data import Data from geoh5py.groups import SimPEGGroup @@ -248,8 +249,8 @@ def params(self) -> InversionBaseParams: return self._params @params.setter - def params(self, val: (InversionBaseParams, SweepParams)): - if not isinstance(val, (InversionBaseParams, SweepParams)): + def params(self, val: BaseInversionData | InversionBaseParams | SweepParams): + if not isinstance(val, (BaseData, InversionBaseParams, SweepParams)): raise TypeError( "Parameters must be of type 'InversionBaseParams' or 'SweepParams'." ) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index f422578d..8b20f689 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -12,22 +12,20 @@ from __future__ import annotations import warnings -from pathlib import Path from copy import deepcopy +from pathlib import Path +from typing import ClassVar from uuid import UUID import numpy as np -from typing import ClassVar -from pydantic import BaseModel, ConfigDict, field_validator, model_validator - from geoapps_utils.driver.data import BaseData from geoapps_utils.driver.params import BaseParams -from geoh5py.data import NumericData, BooleanData +from geoh5py.data import BooleanData, FloatData, NumericData from geoh5py.groups import SimPEGGroup, UIJsonGroup -from geoh5py.objects import Octree, DrapeModel, Points -from geoh5py.data import FloatData +from geoh5py.objects import DrapeModel, 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 from simpeg_drivers import assets_path @@ -40,11 +38,12 @@ class ActiveCellsData(BaseModel): :param topography: Topography data. :param active_model: Topography """ + model_config = ConfigDict( # frozen=True, arbitrary_types_allowed=True, ) - topography_object: Points# | None = None + topography_object: Points # | None = None # topography: FloatData | None = None # active_model: BooleanData | None = None @@ -56,7 +55,6 @@ def at_least_one(cls, data): return data - class CoreData(BaseModel): """ Core parameters shared by inverse and forward operations. @@ -73,6 +71,7 @@ class CoreData(BaseModel): :param topography_object: Topography object used to define the active cells of the model. """ + model_config = ConfigDict( frozen=True, arbitrary_types_allowed=True, @@ -124,7 +123,7 @@ class BaseForwardData(BaseData, CoreData): @property def default_ui_json(self) -> Path: - name = '_'.join(self.title.lower().split()) + name = "_".join(self.title.lower().split()) return assets_path() / "ui_json" / f"{name}_forward.ui.json" @property @@ -272,7 +271,11 @@ class BaseInversionData(BaseData, CoreData): @property def default_ui_json(self) -> Path: - return assets_path() / "ui_json" / f"{'_'.join(self.title.lower().split())}_inversion.ui.json" + return ( + assets_path() + / "ui_json" + / f"{'_'.join(self.title.lower().split())}_inversion.ui.json" + ) def data_channel(self, component: str) -> NumericData | None: """Return the data object associated with the component.""" @@ -313,7 +316,6 @@ def model_norms(self) -> list[float]: ] - class InversionBaseParams(BaseParams): """ Base parameter class for geophysical->property inversion. diff --git a/simpeg_drivers/potential_fields/__init__.py b/simpeg_drivers/potential_fields/__init__.py index 67b0a1b8..6e38763f 100644 --- a/simpeg_drivers/potential_fields/__init__.py +++ b/simpeg_drivers/potential_fields/__init__.py @@ -9,7 +9,7 @@ # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -from .gravity.params import GravityParams +from .gravity.params import GravityForwardParams, GravityInversionParams from .magnetic_scalar.params import MagneticScalarParams from .magnetic_vector.params import MagneticVectorParams diff --git a/simpeg_drivers/potential_fields/gravity/__init__.py b/simpeg_drivers/potential_fields/gravity/__init__.py index 856c8b15..88e122d0 100644 --- a/simpeg_drivers/potential_fields/gravity/__init__.py +++ b/simpeg_drivers/potential_fields/gravity/__init__.py @@ -9,7 +9,7 @@ # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -from .params import GravityParams +from .params import GravityForwardParams, GravityInversionParams # pylint: disable=unused-import # flake8: noqa diff --git a/simpeg_drivers/potential_fields/gravity/driver.py b/simpeg_drivers/potential_fields/gravity/driver.py index 6235d1a1..5c7d2e2a 100644 --- a/simpeg_drivers/potential_fields/gravity/driver.py +++ b/simpeg_drivers/potential_fields/gravity/driver.py @@ -14,12 +14,13 @@ from simpeg_drivers.driver import InversionDriver from .constants import validations -from .params import GravityParams +from .params import GravityForwardParams, GravityInversionParams +from geoapps_utils.driver.data import BaseData class GravityDriver(InversionDriver): - _params_class = GravityParams + _params_class = BaseData _validations = validations - def __init__(self, params: GravityParams): + def __init__(self, params: GravityForwardParams | GravityInversionParams): super().__init__(params) diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index c0827c7d..30268273 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -12,7 +12,6 @@ from __future__ import annotations from typing import ClassVar -from copy import deepcopy from geoh5py.data import FloatData @@ -25,6 +24,7 @@ validations, ) + class GravityForwardParams(BaseForwardData): """ Gravity forward parameters. @@ -40,6 +40,7 @@ class GravityForwardParams(BaseForwardData): :param gzz_channel_bool: gzz channel boolean. """ + class GravityInversionParams(BaseInversionData): """ Gravity inversion parameters. diff --git a/tests/params_test.py b/tests/params_test.py index 3e1edecf..23837aef 100644 --- a/tests/params_test.py +++ b/tests/params_test.py @@ -584,24 +584,27 @@ def test_conductivity_model(ip_params): ): ip_params.conductivity_model = ip_params.geoh5 + def test_active_cells_data(tmp_path): - from simpeg_drivers.params import ActiveCellsData + import numpy as np from geoh5py import Workspace from geoh5py.objects import Points - import numpy as np + + from simpeg_drivers.params import ActiveCellsData ws = Workspace(tmp_path / "test.geoh5") pts = Points.create(ws, vertices=np.random.rand(10, 3)) data = ActiveCellsData(topography_object=pts) assert True -def test_something(tmp_path): +def test_something(tmp_path): from typing import ClassVar + + from geoapps_utils.driver.data import BaseData from geoh5py import Workspace - from geoh5py.objects import Points, Octree + from geoh5py.objects import Octree, Points from pydantic import BaseModel, ConfigDict - from geoapps_utils.driver.data import BaseData ws = Workspace(tmp_path / "test.geoh5") @@ -623,11 +626,6 @@ class GravityData(BaseData, CoreData): mesh: DrapeModel | None myparam: int = 1 - data = GravityData( - geoh5 = ws, - data_object = None, - mesh = None, - myparam = 2 - ) + data = GravityData(geoh5=ws, data_object=None, mesh=None, myparam=2) - assert True \ No newline at end of file + assert True diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py index c97707c9..7e9b7f3f 100644 --- a/tests/run_tests/driver_grav_test.py +++ b/tests/run_tests/driver_grav_test.py @@ -15,7 +15,8 @@ import numpy as np from geoh5py.workspace import Workspace -from simpeg_drivers.potential_fields import GravityParams +from simpeg_drivers.params import ActiveCellsData +from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams from simpeg_drivers.potential_fields.gravity.driver import GravityDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace from simpeg_drivers.utils.utils import get_inversion_output @@ -42,14 +43,16 @@ def test_gravity_fwr_run( refinement=refinement, flatten=False, ) - params = GravityParams( - forward_only=True, + + active = ActiveCellsData(topography_object=topography) + params = GravityForwardParams( geoh5=geoh5, - mesh=model.parent.uid, - topography_object=topography.uid, + mesh=model.parent, + active=active, + topography_object=topography, z_from_topo=False, - data_object=survey.uid, - starting_model=model.uid, + data_object=survey, + starting_model=model, ) fwr_driver = GravityDriver(params) fwr_driver.run() @@ -89,11 +92,11 @@ def test_gravity_run( gz.values = values # Run the inverse - params = GravityParams( + params = GravityInversionParams( geoh5=geoh5, - mesh=mesh.uid, - topography_object=topography.uid, - data_object=gz.parent.uid, + mesh=mesh, + topography_object=topography, + data_object=gz.parent, starting_model=1e-4, reference_model=0.0, s_norm=0.0, @@ -103,7 +106,7 @@ def test_gravity_run( gradient_type="components", gz_channel_bool=True, z_from_topo=False, - gz_channel=gz.uid, + gz_channel=gz, gz_uncertainty=2e-3, lower_bound=0.0, max_global_iterations=max_iterations, From 13ccd2fa1318ab1ccead7a6243199e9c1b0092d0 Mon Sep 17 00:00:00 2001 From: benjamink Date: Fri, 17 Jan 2025 10:30:43 -0800 Subject: [PATCH 03/21] clean out deprecated params, move n_cpu maximining code to params class --- simpeg_drivers/components/data.py | 35 +------------------ simpeg_drivers/driver.py | 3 -- simpeg_drivers/params.py | 33 +++++++++-------- .../potential_fields/gravity/params.py | 2 ++ 4 files changed, 19 insertions(+), 54 deletions(-) diff --git a/simpeg_drivers/components/data.py b/simpeg_drivers/components/data.py index fcc64b31..3ef5976a 100644 --- a/simpeg_drivers/components/data.py +++ b/simpeg_drivers/components/data.py @@ -47,10 +47,6 @@ class InversionData(InversionLocations): Parameters --------- - offset : - Static receivers location offsets. - radar : - Radar channel address used to drape receiver locations over topography. locations : Data locations. mask : @@ -87,8 +83,6 @@ def __init__(self, workspace: Workspace, params: InversionBaseParams): :param: params: Params object containing location based data parameters. """ super().__init__(workspace, params) - self.offset: list[float] | None = None - self.radar: np.ndarray | None = None self.locations: np.ndarray | None = None self.mask: np.ndarray | None = None self.indices: np.ndarray | None = None @@ -113,7 +107,6 @@ def _initialize(self) -> None: self.n_blocks = 3 if self.params.inversion_type == "magnetic vector" else 1 self.components, self.observed, self.uncertainties = self.get_data() self.has_tensor = InversionData.check_tensor(self.components) - self.offset, self.radar = self.params.offset() self.locations = super().get_locations(self.params.data_object) if ( @@ -124,11 +117,7 @@ def _initialize(self) -> None: else: self.mask = np.ones(len(self.locations), dtype=bool) - if self.radar is not None and any(np.isnan(self.radar)): - self.mask[np.isnan(self.radar)] = False - self.observed = self.filter(self.observed) - self.radar = self.filter(self.radar) self.uncertainties = self.filter(self.uncertainties) self.normalizations = self.get_normalizations() @@ -183,11 +172,10 @@ def get_data(self) -> tuple[list, dict, dict]: associated uncertainties. """ - components = self.params.components() data = {} uncertainties = {} - for comp in components: + for comp in self.params.components: data.update({comp: self.params.data(comp)}) uncertainties.update({comp: self.params.uncertainty(comp)}) @@ -273,30 +261,9 @@ def apply_transformations(self, locations: np.ndarray): """Apply all coordinate transformations to locations""" if self.params.z_from_topo: locations = super().set_z_from_topo(locations) - if self.offset is not None: - locations = self.displace(locations, self.offset) - if self.radar is not None: - locations = self.drape(locations, self.radar) return locations - def displace(self, locs: np.ndarray, offset: np.ndarray) -> np.ndarray: - """Offset data locations in all three dimensions.""" - if locs is None: - return None - else: - return locs + offset if offset is not None else 0 - - def drape(self, locs: np.ndarray, radar_offset: np.ndarray) -> np.ndarray: - """Drape data locations using radar channel offsets.""" - - if locs is None: - return None - - radar_offset_pad = np.zeros((len(radar_offset), 3)) - radar_offset_pad[:, 2] = radar_offset - - return self.displace(locs, radar_offset_pad) def normalize( self, data: dict[str, np.ndarray], absolute=False diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index 3ab77133..af799821 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -441,9 +441,6 @@ def configure_dask(self): """Sets Dask config settings.""" if self.params.parallelized: - if self.params.n_cpu is None: - self.params.n_cpu = int(multiprocessing.cpu_count()) - dconf.set({"array.chunk-size": str(self.params.max_chunk_size) + "MiB"}) dconf.set(scheduler="threads", pool=ThreadPool(self.params.n_cpu)) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 8b20f689..54cfe035 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -12,6 +12,7 @@ from __future__ import annotations import warnings +import multiprocessing from copy import deepcopy from pathlib import Path from typing import ClassVar @@ -78,14 +79,26 @@ class CoreData(BaseModel): ) run_command: ClassVar[str] = "simpeg_drivers.driver" conda_environment: str = "simpeg_drivers" + inversion_type: str + physical_property: str data_object: Points + z_from_topo: bool = False mesh: Octree | None starting_model: float | FloatData active: ActiveCellsData tile_spatial: int = 1 + parallelized: bool = True + n_cpu: int | None = None + max_chunk_size: int = 128 out_group: SimPEGGroup | UIJsonGroup | None = None generate_sweep: bool = False + @field_validator("n_cpu", mode="before") + def maximize_cpu_if_none(cls, value): + if value is None: + value = int(multiprocessing.cpu_count()) + return value + @field_validator("mesh", mode="before") @classmethod def mesh_cannot_be_rotated(cls, value: Octree): @@ -464,6 +477,7 @@ def uncertainty(self, component: str) -> np.ndarray | None: else: return None + @property def components(self) -> list[str]: """Retrieve component names used to index channel and uncertainty data.""" comps = [] @@ -482,23 +496,6 @@ def components(self) -> list[str]: return comps - def offset(self) -> tuple[list[float], UUID]: - """Returns offset components as list and drape data.""" - offsets = [ - 0, - 0, - 0 if self.receivers_offset_z is None else self.receivers_offset_z, - ] - is_offset = any((k != 0) for k in offsets) - offsets = offsets if is_offset else None - r = self.receivers_radar_drape - if isinstance(r, str | UUID): - r = UUID(r) if isinstance(r, str) else r - radar = self.geoh5.get_entity(r) - radar = radar[0].values if radar else None - else: - radar = None - return offsets, radar def model_norms(self) -> list[float]: """Returns model norm components as a list.""" @@ -971,6 +968,8 @@ def physical_property(self): @property def n_cpu(self): + if self._n_cpu is None: + self._n_cpu = multiprocessing.cpu_count() return self._n_cpu @n_cpu.setter diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index 30268273..a540102c 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -40,6 +40,8 @@ class GravityForwardParams(BaseForwardData): :param gzz_channel_bool: gzz channel boolean. """ + inversion_type: str = "gravity" + physical_property: str = "density" class GravityInversionParams(BaseInversionData): """ From 5544403c5bd20eb571377d278ae92fe22c231d96 Mon Sep 17 00:00:00 2001 From: benjamink Date: Wed, 22 Jan 2025 09:43:53 -0800 Subject: [PATCH 04/21] switching branches --- simpeg_drivers/__init__.py | 3 +- simpeg_drivers/components/data.py | 7 +- .../components/factories/misfit_factory.py | 2 +- .../components/factories/receiver_factory.py | 6 +- .../components/factories/source_factory.py | 2 +- simpeg_drivers/components/meshes.py | 4 +- simpeg_drivers/components/topography.py | 18 +-- simpeg_drivers/components/windows.py | 2 +- simpeg_drivers/driver.py | 11 +- simpeg_drivers/electricals/driver.py | 4 +- .../electromagnetics/time_domain/driver.py | 10 +- simpeg_drivers/line_sweep/driver.py | 2 +- simpeg_drivers/params.py | 147 +++++++++++++----- .../potential_fields/gravity/driver.py | 24 ++- .../potential_fields/gravity/params.py | 42 +++-- tests/params_test.py | 24 +++ tests/run_tests/driver_grav_test.py | 7 +- 17 files changed, 221 insertions(+), 94 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index 086ca70e..1c1b3f8b 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -49,7 +49,8 @@ def assets_path() -> Path: DRIVER_MAP = { "direct current 3d": ( "simpeg_drivers.electricals.direct_current.three_dimensions.driver", - "DirectCurrent3DDriver", + {"inverse":"DirectCurrent3DDriver", + "forward":"DirectCurrentForward3DDriver"} ), "direct current 2d": ( "simpeg_drivers.electricals.direct_current.two_dimensions.driver", diff --git a/simpeg_drivers/components/data.py b/simpeg_drivers/components/data.py index 3ef5976a..a6877fc0 100644 --- a/simpeg_drivers/components/data.py +++ b/simpeg_drivers/components/data.py @@ -124,7 +124,7 @@ def _initialize(self) -> None: self.observed = self.normalize(self.observed) self.uncertainties = self.normalize(self.uncertainties, absolute=True) self.entity = self.write_entity() - self.params.data_object = self.entity + self.params.mutations["data_object"] = self.entity self.locations = super().get_locations(self.entity) def drape_locations(self, locations: np.ndarray) -> np.ndarray: @@ -460,10 +460,9 @@ def update_params(self, data_dict, uncert_dict): Update pointers to newly created object and data. """ - components = self.params.components() - self.params.data_object = self.entity + self.params.mutations["data_object"] = self.entity - for comp in components: + for comp in self.params.components: if getattr(self.params, "_".join([comp, "channel"]), None) is None: continue diff --git a/simpeg_drivers/components/factories/misfit_factory.py b/simpeg_drivers/components/factories/misfit_factory.py index a32b1269..a18b3b35 100644 --- a/simpeg_drivers/components/factories/misfit_factory.py +++ b/simpeg_drivers/components/factories/misfit_factory.py @@ -128,7 +128,7 @@ def assemble_arguments( # pylint: disable=arguments-differ # treemesh_2_octree(ws, local_sim.mesh) # TODO Parse workers to simulations - local_sim.workers = self.params.distributed_workers + # local_sim.workers = self.params.distributed_workers local_data = data.Data(local_sim.survey) if self.params.forward_only: diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index a2efd10a..a7498282 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -153,9 +153,9 @@ def build( if ( self.factory_type in ["tipper"] - and getattr(self.params.data_object, "base_stations", None) is not None + and getattr(self.params.mutations["data_object"], "base_stations", None) is not None ): - stations = self.params.data_object.base_stations.vertices + stations = self.params.mutations["data_object"].base_stations.vertices if stations is not None: if getattr(self.params.mesh, "rotation", None): rotate_xyz( @@ -165,7 +165,7 @@ def build( ) if stations.shape[0] == 1: - stations = np.tile(stations.T, self.params.data_object.n_vertices).T + stations = np.tile(stations.T, self.params.mutations["data_object"].n_vertices).T receivers.reference_locations = stations[local_index, :] diff --git a/simpeg_drivers/components/factories/source_factory.py b/simpeg_drivers/components/factories/source_factory.py index 8d35f7e4..4b520b39 100644 --- a/simpeg_drivers/components/factories/source_factory.py +++ b/simpeg_drivers/components/factories/source_factory.py @@ -66,7 +66,7 @@ def concrete_object(self): elif "tdem" in self.factory_type: from simpeg.electromagnetics.time_domain import sources - if isinstance(self.params.data_object, LargeLoopGroundTEMReceivers): + if isinstance(self.params.mutations["data_object"], LargeLoopGroundTEMReceivers): return sources.LineCurrent else: return sources.MagDipole diff --git a/simpeg_drivers/components/meshes.py b/simpeg_drivers/components/meshes.py index e66bac48..36b7bf09 100644 --- a/simpeg_drivers/components/meshes.py +++ b/simpeg_drivers/components/meshes.py @@ -118,8 +118,8 @@ def _auto_mesh(self): """Automate meshing based on data and topography objects.""" params = auto_mesh_parameters( - self.params.data_object, - self.params.topography_object, + self.params.mutations["data_object"], + self.params.active.topography_object, inversion_type=self.params.inversion_type, ) driver = OctreeDriver(params) diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index 3c22415a..e9a2c02e 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -70,8 +70,8 @@ def __init__( super().__init__(workspace, params) self.locations: np.ndarray | None = None - if self.params.topography_object is not None: - self.locations = self.get_locations(self.params.topography_object) + if self.params.active.topography_object is not None: + self.locations = self.get_locations(self.params.active.topography_object) def active_cells(self, mesh: InversionMesh, data: InversionData) -> np.ndarray: """ @@ -89,7 +89,7 @@ def active_cells(self, mesh: InversionMesh, data: InversionData) -> np.ndarray: "induced polarization 2d", ] or isinstance(data.entity, LargeLoopGroundEMSurvey) - if isinstance(self.params.active_model, NumericData): + if isinstance(self.params.active.active_model, NumericData): active_cells = InversionModel.obj_2_mesh( self.params.active_model, mesh.entity ) @@ -126,13 +126,13 @@ def get_locations(self, entity: Entity) -> np.ndarray: locs = super().get_locations(entity) - if self.params.topography is not None: - if isinstance(self.params.topography, Entity): - elev = self.params.topography.values - elif isinstance(self.params.topography, int | float): - elev = np.ones_like(locs[:, 2]) * self.params.topography + if self.params.active.topography is not None: + if isinstance(self.params.active.topography, Entity): + elev = self.params.active.topography.values + elif isinstance(self.params.active.topography, int | float): + elev = np.ones_like(locs[:, 2]) * self.params.active.topography else: - elev = self.params.topography.values # Must be FloatData at this point + elev = self.params.active.topography.values # Must be FloatData at this point if not np.all(locs[:, 2] == elev): locs[:, 2] = elev diff --git a/simpeg_drivers/components/windows.py b/simpeg_drivers/components/windows.py index 32454e28..d39eca62 100644 --- a/simpeg_drivers/components/windows.py +++ b/simpeg_drivers/components/windows.py @@ -77,7 +77,7 @@ def window(self): """Get params.window data.""" if self._window is None: if self.is_empty(): - data_object = self.params.data_object + data_object = self.params.mutations["data_object"] if isinstance(data_object, Grid2D): locs = data_object.centroids elif isinstance(data_object, PotentialElectrode): diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index af799821..710136c1 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -122,7 +122,7 @@ def inverse_problem(self): self.optimization, ) - if self.params.initial_beta: + if not self.params.forward_only and self.params.initial_beta: self._inverse_problem.beta = self.params.initial_beta return self._inverse_problem @@ -446,10 +446,18 @@ def configure_dask(self): @classmethod def start(cls, filepath: str | Path, driver_class=None): + _ = driver_class ifile = InputFile.read_ui_json(filepath) + forward_only = ifile.data["forward_only"] inversion_type = ifile.ui_json.get("inversion_type", None) + + + driver_name = (inversion_type + "driver").capitalize() + if forward_only: + driver_name += "Forward" + if inversion_type not in DRIVER_MAP: msg = f"Inversion type {inversion_type} is not supported." msg += f" Valid inversions are: {(*list(DRIVER_MAP),)}." @@ -459,6 +467,7 @@ def start(cls, filepath: str | Path, driver_class=None): module = __import__(mod_name, fromlist=[class_name]) inversion_driver = getattr(module, class_name) driver = BaseDriver.start(filepath, driver_class=inversion_driver) + return driver diff --git a/simpeg_drivers/electricals/driver.py b/simpeg_drivers/electricals/driver.py index f0a87d78..c0329a9b 100644 --- a/simpeg_drivers/electricals/driver.py +++ b/simpeg_drivers/electricals/driver.py @@ -49,9 +49,9 @@ def inversion_mesh(self) -> InversionMesh: def create_drape_mesh(self) -> DrapeModel: """Create a drape mesh for the inversion.""" - current_entity = self.params.data_object.current_electrodes + current_entity = self.params.mutations["data_object"].current_electrodes receiver_locs = np.vstack( - [self.params.data_object.vertices, current_entity.vertices] + [self.params.mutations["data_object"].vertices, current_entity.vertices] ) with fetch_active_workspace(self.workspace): mesh = get_drape_model( diff --git a/simpeg_drivers/electromagnetics/time_domain/driver.py b/simpeg_drivers/electromagnetics/time_domain/driver.py index 4e5ecb6b..514758f1 100644 --- a/simpeg_drivers/electromagnetics/time_domain/driver.py +++ b/simpeg_drivers/electromagnetics/time_domain/driver.py @@ -38,17 +38,17 @@ def get_tiles(self) -> list[np.ndarray]: Second, if the number of groups is less than the number of 'tile_spatial' value, the groups are further divided into groups based on the clustering of receiver locations. """ - if not isinstance(self.params.data_object, LargeLoopGroundTEMReceivers): + if not isinstance(self.params.mutations["data_object"], LargeLoopGroundTEMReceivers): return super().get_tiles() - tx_ids = self.params.data_object.transmitters.tx_id_property.values + tx_ids = self.params.mutations["data_object"].transmitters.tx_id_property.values unique_tile_ids = np.unique(tx_ids) n_groups = np.min([len(unique_tile_ids), self.params.tile_spatial]) locations = [] for uid in unique_tile_ids: locations.append( np.mean( - self.params.data_object.transmitters.vertices[tx_ids == uid], + self.params.mutations["data_object"].transmitters.vertices[tx_ids == uid], axis=0, ) ) @@ -59,7 +59,7 @@ def get_tiles(self) -> list[np.ndarray]: n_groups, method="kmeans", ) - receivers_tx_ids = self.params.data_object.tx_id_property.values + receivers_tx_ids = self.params.mutations["data_object"].tx_id_property.values tiles = [] for _t_id, group in enumerate(tx_tiles): sub_group = [] @@ -74,7 +74,7 @@ def get_tiles(self) -> list[np.ndarray]: largest_group = np.argmax([len(tile) for tile in tiles]) tile = tiles.pop(largest_group) new_tiles = tile_locations( - self.params.data_object.vertices[tile], + self.params.mutations["data_object"].vertices[tile], 2, method="kmeans", ) diff --git a/simpeg_drivers/line_sweep/driver.py b/simpeg_drivers/line_sweep/driver.py index fa7197f6..f131f4e0 100644 --- a/simpeg_drivers/line_sweep/driver.py +++ b/simpeg_drivers/line_sweep/driver.py @@ -186,7 +186,7 @@ def collect_results(self): with open(ws.h5file.parent / "SimPEG.log", "w", encoding="utf8") as f: f.write("".join(log_lines)) - self.pseudo3d_params.data_object.add_data(data) + self.pseudo3d_params.data_entity.add_data(data) if self.pseudo3d_params.mesh is None: return diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 54cfe035..36788dc6 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -26,7 +26,7 @@ from geoh5py.objects import DrapeModel, 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 +from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator from simpeg_drivers import assets_path @@ -45,8 +45,8 @@ class ActiveCellsData(BaseModel): arbitrary_types_allowed=True, ) topography_object: Points # | None = None - # topography: FloatData | None = None - # active_model: BooleanData | None = None + topography: FloatData | None = None + active_model: BooleanData | None = None @model_validator(mode="before") @classmethod @@ -73,9 +73,13 @@ class CoreData(BaseModel): the model. """ + # TODO: Refactor to allow frozen True. Currently params.data_object is + # updated after z_from_topo applied in entity_factory.py. See + # simpeg_drivers/components/data.py ln. 127 model_config = ConfigDict( - frozen=True, + frozen=False, arbitrary_types_allowed=True, + extra="allow" ) run_command: ClassVar[str] = "simpeg_drivers.driver" conda_environment: str = "simpeg_drivers" @@ -90,8 +94,10 @@ class CoreData(BaseModel): parallelized: bool = True n_cpu: int | None = None max_chunk_size: int = 128 + save_sensitivities: bool = False out_group: SimPEGGroup | UIJsonGroup | None = None generate_sweep: bool = False + mutations: dict = Field(default_factory=lambda: {}) @field_validator("n_cpu", mode="before") def maximize_cpu_if_none(cls, value): @@ -106,10 +112,66 @@ def mesh_cannot_be_rotated(cls, value: Octree): raise ValueError( "Rotated meshes are not supported. Please use a mesh with an angle of 0.0." ) + return value + + @model_validator(mode="before") + @classmethod + def out_group_if_none(cls, data) -> SimPEGGroup: + + group = data.get("out_group", None) + + if isinstance(group, UIJsonGroup): + group = SimPEGGroup.create(data["geoh5"], name=group.name) + + elif group is None: + group = SimPEGGroup.create(data["geoh5"], name=cls.title) + + group.metadata = None + data["out_group"] = group + + return data + + @model_validator(mode="after") + def update_out_group_options(self): + self.out_group.options = self.serialize() + return self + + @property + def workpath(self): + return Path(self.geoh5.h5file).parent @property def channels(self) -> list[str]: - return [k for k in self.__dict__ if "channel" in k] + return [k.split("_")[0] for k in self.__dict__ if "channel" in k] + + def data_channel(self, component: str) -> NumericData | None: + """Return the data object associated with the component.""" + return getattr(self, "_".join([component, "channel"]), None) + + def uncertainty_channel(self, component: str) -> NumericData | None: + """Return the uncertainty object associated with the component.""" + return getattr(self, "_".join([component, "uncertainty"]), None) + + def data(self, component: str) -> np.ndarray | None: + """Returns array of data for chosen data component if it exists.""" + data_entity = self.data_channel(component) + if isinstance(data_entity, NumericData): + return data_entity.values.astype(float) + return None + + def uncertainty(self, component: str) -> np.ndarray | None: + """Returns uncertainty for chosen data component if it exists.""" + uncertainty_entity = self.uncertainty_channel(component) + if isinstance(uncertainty_entity, NumericData): + return uncertainty_entity.values.astype(float) + elif self.data(component) is not None: + d = self.data(component) + if isinstance(uncertainty_entity, int | float): + return np.array([float(uncertainty_entity)] * len(d)) + else: + return d * 0.0 + 1.0 # Default + else: + return None @property def padding_cells(self) -> int: @@ -134,17 +196,12 @@ class BaseForwardData(BaseData, CoreData): forward_only: bool = True - @property - def default_ui_json(self) -> Path: - name = "_".join(self.title.lower().split()) - return assets_path() / "ui_json" / f"{name}_forward.ui.json" - @property def components(self) -> list[str]: """Retrieve component names used to index channel and uncertainty data.""" comps = [] for c in self.channels: - if getattr(self, f"{c}_channel_bool", None) is not None: + if getattr(self, f"{c}_channel_bool", False): comps.append(c) return comps @@ -215,7 +272,7 @@ class BaseInversionData(BaseData, CoreData): """ model_config = ConfigDict( - frozen=True, + frozen=False, arbitrary_types_allowed=True, ) @@ -223,15 +280,11 @@ class BaseInversionData(BaseData, CoreData): title: ClassVar[str] = "Geophysical inversion" run_command: ClassVar[str] = "simpeg_drivers.driver" - conda_environment: str = "simpeg_drivers" - reference_model: float | FloatData | None - lower_bound: float | FloatData | None - upper_bound: float | FloatData | None - forward_only: bool = False - - topography: FloatData | None - active_model: BooleanData | None + conda_environment: str = "simpeg_drivers" + reference_model: float | FloatData | None = None + lower_bound: float | FloatData | None = None + upper_bound: float | FloatData | None = None alpha_s: float | FloatData = 1.0 length_scale_x: float | FloatData = 1.0 @@ -258,9 +311,6 @@ class BaseInversionData(BaseData, CoreData): max_cg_iterations: int = 30 tol_cg: float = 1e-4 f_min_change: float = 1e-2 - sens_wts_threshold: float - every_iteration_bool: bool - save_sensitivities: bool sens_wts_threshold: float = 1e-3 every_iteration_bool: bool = True @@ -269,26 +319,29 @@ class BaseInversionData(BaseData, CoreData): tile_spatial: int = 1 store_sensitivities: str = "ram" - parallelized: bool - n_cpu: int - max_chunk_size: int - chunk_by_rows: bool - prctile: float - beta_tol: float - output_tile_files: bool - inversion_style: str - max_ram: float - ga_group: SimPEGGroup - distributed_workers: int - no_data_value: float - - @property - def default_ui_json(self) -> Path: - return ( - assets_path() - / "ui_json" - / f"{'_'.join(self.title.lower().split())}_inversion.ui.json" - ) + beta_tol: float = 0.5 + prctile: float = 95.0 + coolEps_q: bool = True + coolEpsFact: float = 1.2 + beta_search: bool = False + + chunk_by_rows: bool = True + output_tile_files: bool = False + inversion_style: str = "voxel" + max_ram: float | None = None + ga_group: SimPEGGroup | None = None + distributed_workers: int | None = None + no_data_value: float | None = None + + @property + def components(self) -> list[str]: + """Retrieve component names used to index channel and uncertainty data.""" + comps = [] + for c in self.channels: + if getattr(self, f"{c}_channel", False): + comps.append(c) + + return comps def data_channel(self, component: str) -> NumericData | None: """Return the data object associated with the component.""" @@ -431,6 +484,14 @@ def __init__( if "channel_bool" in key and getattr(self, key[:-5], None) is not None: setattr(self, key, True) + @property + def active(self): + return ActiveCellsData( + topography_object=self.topography_object, + topography=self.topography, + active_model=self.active_model, + ) + def data_channel(self, component: str): """Return uuid of data channel.""" return getattr(self, "_".join([component, "channel"]), None) diff --git a/simpeg_drivers/potential_fields/gravity/driver.py b/simpeg_drivers/potential_fields/gravity/driver.py index 5c7d2e2a..ee59a17b 100644 --- a/simpeg_drivers/potential_fields/gravity/driver.py +++ b/simpeg_drivers/potential_fields/gravity/driver.py @@ -16,11 +16,31 @@ from .constants import validations from .params import GravityForwardParams, GravityInversionParams from geoapps_utils.driver.data import BaseData +from geoh5py.ui_json import InputFile +from simpeg_drivers import DRIVER_MAP +class GravityDriverForward(): + _params_class = GravityForwardParams class GravityDriver(InversionDriver): - _params_class = BaseData + _params_class = GravityInversionParams _validations = validations - def __init__(self, params: GravityForwardParams | GravityInversionParams): + def __init__(self, params): super().__init__(params) + # + # @classmethod + # def start(cls, filepath: str | Path, driver_class=None): + # + # + # ifile = InputFile.read_ui_json(filepath) + # with ifile.data["geoh5"].open(mode="r+"): + # params = ( + # GravityForwardParams.build(ifile) + # if ifile.data["forward_only"] + # else GravityInversionParams.build(ifile) + # ) + # driver = cls(params) + # driver.run() + # + # return driver diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index a540102c..a07bd5cf 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -11,19 +11,14 @@ from __future__ import annotations +from pathlib import Path from typing import ClassVar from geoh5py.data import FloatData +from simpeg_drivers import assets_path from simpeg_drivers.params import BaseForwardData, BaseInversionData -from .constants import ( - default_ui_json, - forward_defaults, - inversion_defaults, - validations, -) - class GravityForwardParams(BaseForwardData): """ @@ -40,8 +35,22 @@ class GravityForwardParams(BaseForwardData): :param gzz_channel_bool: gzz channel boolean. """ + name: ClassVar[str] = "Gravity Forward" + title: ClassVar[str] = "Gravity Forward" + default_ui_json: ClassVar[Path] = assets_path() / "uijson/gravity_forward.ui.json" + inversion_type: str = "gravity" physical_property: str = "density" + gx_channel_bool: bool = False + gy_channel_bool: bool = False + gz_channel_bool: bool = True + gxx_channel_bool: bool = False + gxy_channel_bool: bool = False + gxz_channel_bool: bool = False + gyy_channel_bool: bool = False + gyz_channel_bool: bool = False + gzz_channel_bool: bool = False + class GravityInversionParams(BaseInversionData): """ @@ -69,6 +78,7 @@ class GravityInversionParams(BaseInversionData): name: ClassVar[str] = "Gravity Inversion" title: ClassVar[str] = "Gravity Inversion" + default_ui_json: ClassVar[Path] = assets_path() / "uijson/gravity_inversion.ui.json" inversion_type: str = "gravity" physical_property: str = "density" @@ -81,15 +91,15 @@ class GravityInversionParams(BaseInversionData): gyy_channel: FloatData | None = None gyz_channel: FloatData | None = None gzz_channel: FloatData | None = None - gx_uncertainty: FloatData | None = None - gy_uncertainty: FloatData | None = None - gz_uncertainty: FloatData | None = None - gxx_uncertainty: FloatData | None = None - gxy_uncertainty: FloatData | None = None - gxz_uncertainty: FloatData | None = None - gyy_uncertainty: FloatData | None = None - gyz_uncertainty: FloatData | None = None - gzz_uncertainty: FloatData | None = None + gx_uncertainty: FloatData | float | None = None + gy_uncertainty: FloatData | float | None = None + gz_uncertainty: FloatData | float | None = None + gxx_uncertainty: FloatData | float | None = None + gxy_uncertainty: FloatData | float | None = None + gxz_uncertainty: FloatData | float | None = None + gyy_uncertainty: FloatData | float | None = None + gyz_uncertainty: FloatData | float | None = None + gzz_uncertainty: FloatData | float | None = None # class GravityParams(InversionBaseParams): diff --git a/tests/params_test.py b/tests/params_test.py index 23837aef..ad99b027 100644 --- a/tests/params_test.py +++ b/tests/params_test.py @@ -629,3 +629,27 @@ class GravityData(BaseData, CoreData): data = GravityData(geoh5=ws, data_object=None, mesh=None, myparam=2) assert True + +def test_something_else(): + from pydantic import BaseModel, ConfigDict + class MyData(BaseModel): + model_config = ConfigDict(frozen=True, extra="allow") + a: int + b: str + + data = MyData(a=1, b='2') + data.e = 3 + assert data.e == 3 + +def test_something_related(): + from pydantic import BaseModel, ConfigDict, Field, computed_field + class MyData(BaseModel): + model_config = ConfigDict(frozen=True, extra="allow") + a: int + b: str + + + data = MyData(a=1, b="string") + data.c = "other_string" + assert data.b == "string" + assert data.c == "other_string" \ No newline at end of file diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py index 7e9b7f3f..49d75048 100644 --- a/tests/run_tests/driver_grav_test.py +++ b/tests/run_tests/driver_grav_test.py @@ -53,6 +53,7 @@ def test_gravity_fwr_run( z_from_topo=False, data_object=survey, starting_model=model, + gz_channel_bool=True ) fwr_driver = GravityDriver(params) fwr_driver.run() @@ -92,10 +93,11 @@ def test_gravity_run( gz.values = values # Run the inverse + active = ActiveCellsData(topography_object=topography) params = GravityInversionParams( geoh5=geoh5, mesh=mesh, - topography_object=topography, + active=active, data_object=gz.parent, starting_model=1e-4, reference_model=0.0, @@ -115,7 +117,8 @@ def test_gravity_run( store_sensitivities="ram", save_sensitivities=True, ) - params.write_input_file(path=tmp_path, name="Inv_run") + params.write_ui_json(path=tmp_path / "Inv_run.ui.json") + # params.write_input_file(path=tmp_path, name="Inv_run") driver = GravityDriver.start(str(tmp_path / "Inv_run.ui.json")) From 68d0405a9149c7acd267814a9a90c4a882990e80 Mon Sep 17 00:00:00 2001 From: benjamink Date: Wed, 22 Jan 2025 10:49:13 -0800 Subject: [PATCH 05/21] switching branches --- simpeg_drivers/__init__.py | 33 ++++++++++--------- simpeg_drivers/components/data.py | 4 +-- .../components/factories/receiver_factory.py | 6 ++-- .../components/factories/source_factory.py | 2 +- simpeg_drivers/components/meshes.py | 2 +- simpeg_drivers/components/windows.py | 2 +- simpeg_drivers/driver.py | 17 ++++++---- simpeg_drivers/electricals/driver.py | 4 +-- .../electromagnetics/time_domain/driver.py | 10 +++--- simpeg_drivers/params.py | 1 - .../potential_fields/gravity/driver.py | 25 ++++---------- tests/run_tests/driver_grav_test.py | 6 ++-- 12 files changed, 52 insertions(+), 60 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index 1c1b3f8b..0f365821 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -49,57 +49,58 @@ def assets_path() -> Path: DRIVER_MAP = { "direct current 3d": ( "simpeg_drivers.electricals.direct_current.three_dimensions.driver", - {"inverse":"DirectCurrent3DDriver", - "forward":"DirectCurrentForward3DDriver"} + {"inversion": "DirectCurrent3DDriver"} ), "direct current 2d": ( "simpeg_drivers.electricals.direct_current.two_dimensions.driver", - "DirectCurrent2DDriver", + {"inversion": "DirectCurrent2DDriver"}, ), "direct current pseudo 3d": ( "simpeg_drivers.electricals.direct_current.pseudo_three_dimensions.driver", - "DirectCurrentPseudo3DDriver", + {"inversion": "DirectCurrentPseudo3DDriver"}, ), "induced polarization 3d": ( "simpeg_drivers.electricals.induced_polarization.three_dimensions.driver", - "InducedPolarization3DDriver", + {"inversion": "InducedPolarization3DDriver"}, ), "induced polarization 2d": ( "simpeg_drivers.electricals.induced_polarization.two_dimensions.driver", - "InducedPolarization2DDriver", + {"inversion": "InducedPolarization2DDriver"}, ), "induced polarization pseudo 3d": ( "simpeg_drivers.electricals.induced_polarization.pseudo_three_dimensions.driver", - "InducedPolarizationPseudo3DDriver", + {"inversion": "InducedPolarizationPseudo3DDriver"}, ), "joint surveys": ( "simpeg_drivers.joint.joint_surveys.driver", - "JointSurveyDriver", + {"inversion": "JointSurveyDriver"}, ), "fem": ( "simpeg_drivers.electromagnetics.frequency_domain.driver", - "FrequencyDomainElectromagneticsDriver", + {"inversion": "FrequencyDomainElectromagneticsDriver"}, ), "joint cross gradient": ( "simpeg_drivers.joint.joint_cross_gradient.driver", - "JointCrossGradientDriver", + {"inversion": "JointCrossGradientDriver"}, ), "tdem": ( "simpeg_drivers.electromagnetics.time_domain.driver", - "TimeDomainElectromagneticsDriver", + {"inversion": "TimeDomainElectromagneticsDriver"}, ), "magnetotellurics": ( "simpeg_drivers.natural_sources.magnetotellurics.driver", - "MagnetotelluricsDriver", + {"inversion": "MagnetotelluricsDriver"}, ), - "tipper": ("simpeg_drivers.natural_sources.tipper.driver", "TipperDriver"), - "gravity": ("simpeg_drivers.potential_fields.gravity.driver", "GravityDriver"), + "tipper": ("simpeg_drivers.natural_sources.tipper.driver", + {"inversion": "TipperDriver"}), + "gravity": ("simpeg_drivers.potential_fields.gravity.driver", + {"inversion": "GravityDriver", "forward": "GravityForwardDriver"}), "magnetic scalar": ( "simpeg_drivers.potential_fields.magnetic_scalar.driver", - "MagneticScalarDriver", + {"inversion": "MagneticScalarDriver"}, ), "magnetic vector": ( "simpeg_drivers.potential_fields.magnetic_vector.driver", - "MagneticVectorDriver", + {"inversion": "MagneticVectorDriver"}, ), } diff --git a/simpeg_drivers/components/data.py b/simpeg_drivers/components/data.py index a6877fc0..41c78d81 100644 --- a/simpeg_drivers/components/data.py +++ b/simpeg_drivers/components/data.py @@ -124,7 +124,7 @@ def _initialize(self) -> None: self.observed = self.normalize(self.observed) self.uncertainties = self.normalize(self.uncertainties, absolute=True) self.entity = self.write_entity() - self.params.mutations["data_object"] = self.entity + self.params.data_object = self.entity self.locations = super().get_locations(self.entity) def drape_locations(self, locations: np.ndarray) -> np.ndarray: @@ -460,7 +460,7 @@ def update_params(self, data_dict, uncert_dict): Update pointers to newly created object and data. """ - self.params.mutations["data_object"] = self.entity + self.params.data_object = self.entity for comp in self.params.components: if getattr(self.params, "_".join([comp, "channel"]), None) is None: diff --git a/simpeg_drivers/components/factories/receiver_factory.py b/simpeg_drivers/components/factories/receiver_factory.py index a7498282..a2efd10a 100644 --- a/simpeg_drivers/components/factories/receiver_factory.py +++ b/simpeg_drivers/components/factories/receiver_factory.py @@ -153,9 +153,9 @@ def build( if ( self.factory_type in ["tipper"] - and getattr(self.params.mutations["data_object"], "base_stations", None) is not None + and getattr(self.params.data_object, "base_stations", None) is not None ): - stations = self.params.mutations["data_object"].base_stations.vertices + stations = self.params.data_object.base_stations.vertices if stations is not None: if getattr(self.params.mesh, "rotation", None): rotate_xyz( @@ -165,7 +165,7 @@ def build( ) if stations.shape[0] == 1: - stations = np.tile(stations.T, self.params.mutations["data_object"].n_vertices).T + stations = np.tile(stations.T, self.params.data_object.n_vertices).T receivers.reference_locations = stations[local_index, :] diff --git a/simpeg_drivers/components/factories/source_factory.py b/simpeg_drivers/components/factories/source_factory.py index 4b520b39..8d35f7e4 100644 --- a/simpeg_drivers/components/factories/source_factory.py +++ b/simpeg_drivers/components/factories/source_factory.py @@ -66,7 +66,7 @@ def concrete_object(self): elif "tdem" in self.factory_type: from simpeg.electromagnetics.time_domain import sources - if isinstance(self.params.mutations["data_object"], LargeLoopGroundTEMReceivers): + if isinstance(self.params.data_object, LargeLoopGroundTEMReceivers): return sources.LineCurrent else: return sources.MagDipole diff --git a/simpeg_drivers/components/meshes.py b/simpeg_drivers/components/meshes.py index 36b7bf09..494765a1 100644 --- a/simpeg_drivers/components/meshes.py +++ b/simpeg_drivers/components/meshes.py @@ -118,7 +118,7 @@ def _auto_mesh(self): """Automate meshing based on data and topography objects.""" params = auto_mesh_parameters( - self.params.mutations["data_object"], + self.params.data_object, self.params.active.topography_object, inversion_type=self.params.inversion_type, ) diff --git a/simpeg_drivers/components/windows.py b/simpeg_drivers/components/windows.py index d39eca62..32454e28 100644 --- a/simpeg_drivers/components/windows.py +++ b/simpeg_drivers/components/windows.py @@ -77,7 +77,7 @@ def window(self): """Get params.window data.""" if self._window is None: if self.is_empty(): - data_object = self.params.mutations["data_object"] + data_object = self.params.data_object if isinstance(data_object, Grid2D): locs = data_object.centroids elif isinstance(data_object, PotentialElectrode): diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index 710136c1..01f8cb2d 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -453,20 +453,23 @@ def start(cls, filepath: str | Path, driver_class=None): forward_only = ifile.data["forward_only"] inversion_type = ifile.ui_json.get("inversion_type", None) - driver_name = (inversion_type + "driver").capitalize() - if forward_only: - driver_name += "Forward" - if inversion_type not in DRIVER_MAP: msg = f"Inversion type {inversion_type} is not supported." msg += f" Valid inversions are: {(*list(DRIVER_MAP),)}." raise NotImplementedError(msg) - mod_name, class_name = DRIVER_MAP.get(inversion_type) + mod_name, classes = DRIVER_MAP.get(inversion_type) + if forward_only: + class_name = classes.get("forward", "inversion") + else: + class_name = classes.get("inversion") module = __import__(mod_name, fromlist=[class_name]) - inversion_driver = getattr(module, class_name) - driver = BaseDriver.start(filepath, driver_class=inversion_driver) + driver_class = getattr(module, class_name) + with ifile.data["geoh5"].open(mode="r+"): + params = driver_class._params_class.build(ifile) + driver = driver_class(params) + driver.run() return driver diff --git a/simpeg_drivers/electricals/driver.py b/simpeg_drivers/electricals/driver.py index c0329a9b..f0a87d78 100644 --- a/simpeg_drivers/electricals/driver.py +++ b/simpeg_drivers/electricals/driver.py @@ -49,9 +49,9 @@ def inversion_mesh(self) -> InversionMesh: def create_drape_mesh(self) -> DrapeModel: """Create a drape mesh for the inversion.""" - current_entity = self.params.mutations["data_object"].current_electrodes + current_entity = self.params.data_object.current_electrodes receiver_locs = np.vstack( - [self.params.mutations["data_object"].vertices, current_entity.vertices] + [self.params.data_object.vertices, current_entity.vertices] ) with fetch_active_workspace(self.workspace): mesh = get_drape_model( diff --git a/simpeg_drivers/electromagnetics/time_domain/driver.py b/simpeg_drivers/electromagnetics/time_domain/driver.py index 514758f1..4e5ecb6b 100644 --- a/simpeg_drivers/electromagnetics/time_domain/driver.py +++ b/simpeg_drivers/electromagnetics/time_domain/driver.py @@ -38,17 +38,17 @@ def get_tiles(self) -> list[np.ndarray]: Second, if the number of groups is less than the number of 'tile_spatial' value, the groups are further divided into groups based on the clustering of receiver locations. """ - if not isinstance(self.params.mutations["data_object"], LargeLoopGroundTEMReceivers): + if not isinstance(self.params.data_object, LargeLoopGroundTEMReceivers): return super().get_tiles() - tx_ids = self.params.mutations["data_object"].transmitters.tx_id_property.values + tx_ids = self.params.data_object.transmitters.tx_id_property.values unique_tile_ids = np.unique(tx_ids) n_groups = np.min([len(unique_tile_ids), self.params.tile_spatial]) locations = [] for uid in unique_tile_ids: locations.append( np.mean( - self.params.mutations["data_object"].transmitters.vertices[tx_ids == uid], + self.params.data_object.transmitters.vertices[tx_ids == uid], axis=0, ) ) @@ -59,7 +59,7 @@ def get_tiles(self) -> list[np.ndarray]: n_groups, method="kmeans", ) - receivers_tx_ids = self.params.mutations["data_object"].tx_id_property.values + receivers_tx_ids = self.params.data_object.tx_id_property.values tiles = [] for _t_id, group in enumerate(tx_tiles): sub_group = [] @@ -74,7 +74,7 @@ def get_tiles(self) -> list[np.ndarray]: largest_group = np.argmax([len(tile) for tile in tiles]) tile = tiles.pop(largest_group) new_tiles = tile_locations( - self.params.mutations["data_object"].vertices[tile], + self.params.data_object.vertices[tile], 2, method="kmeans", ) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 36788dc6..3ceb187f 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -97,7 +97,6 @@ class CoreData(BaseModel): save_sensitivities: bool = False out_group: SimPEGGroup | UIJsonGroup | None = None generate_sweep: bool = False - mutations: dict = Field(default_factory=lambda: {}) @field_validator("n_cpu", mode="before") def maximize_cpu_if_none(cls, value): diff --git a/simpeg_drivers/potential_fields/gravity/driver.py b/simpeg_drivers/potential_fields/gravity/driver.py index ee59a17b..878be5e6 100644 --- a/simpeg_drivers/potential_fields/gravity/driver.py +++ b/simpeg_drivers/potential_fields/gravity/driver.py @@ -19,28 +19,17 @@ from geoh5py.ui_json import InputFile from simpeg_drivers import DRIVER_MAP -class GravityDriverForward(): +class GravityForwardDriver(InversionDriver): _params_class = GravityForwardParams + _validation = validations -class GravityDriver(InversionDriver): + def __init__(self, params): + super().__init__(params) + +class GravityInversionDriver(InversionDriver): _params_class = GravityInversionParams _validations = validations def __init__(self, params): super().__init__(params) - # - # @classmethod - # def start(cls, filepath: str | Path, driver_class=None): - # - # - # ifile = InputFile.read_ui_json(filepath) - # with ifile.data["geoh5"].open(mode="r+"): - # params = ( - # GravityForwardParams.build(ifile) - # if ifile.data["forward_only"] - # else GravityInversionParams.build(ifile) - # ) - # driver = cls(params) - # driver.run() - # - # return driver + diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py index 49d75048..423e3e84 100644 --- a/tests/run_tests/driver_grav_test.py +++ b/tests/run_tests/driver_grav_test.py @@ -17,7 +17,7 @@ from simpeg_drivers.params import ActiveCellsData from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams -from simpeg_drivers.potential_fields.gravity.driver import GravityDriver +from simpeg_drivers.potential_fields.gravity.driver import GravityForwardDriver, GravityInversionDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace from simpeg_drivers.utils.utils import get_inversion_output @@ -55,7 +55,7 @@ def test_gravity_fwr_run( starting_model=model, gz_channel_bool=True ) - fwr_driver = GravityDriver(params) + fwr_driver = GravityForwardDriver(params) fwr_driver.run() @@ -120,7 +120,7 @@ def test_gravity_run( params.write_ui_json(path=tmp_path / "Inv_run.ui.json") # params.write_input_file(path=tmp_path, name="Inv_run") - driver = GravityDriver.start(str(tmp_path / "Inv_run.ui.json")) + driver = GravityDriverInversion.start(str(tmp_path / "Inv_run.ui.json")) assert driver.params.data_object.uid != gz.parent.uid assert driver.models.upper_bound is np.inf From 8a7da9731f1840aa76937d4df1fa63f6b6a1f1dd Mon Sep 17 00:00:00 2001 From: benjamink Date: Thu, 23 Jan 2025 12:50:50 -0800 Subject: [PATCH 06/21] Gravity runtest passes --- simpeg_drivers/__init__.py | 2 +- simpeg_drivers/params.py | 2 -- tests/run_tests/driver_grav_test.py | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index 0f365821..e2ab207a 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -94,7 +94,7 @@ def assets_path() -> Path: "tipper": ("simpeg_drivers.natural_sources.tipper.driver", {"inversion": "TipperDriver"}), "gravity": ("simpeg_drivers.potential_fields.gravity.driver", - {"inversion": "GravityDriver", "forward": "GravityForwardDriver"}), + {"inversion": "GravityInversionDriver", "forward": "GravityForwardDriver"}), "magnetic scalar": ( "simpeg_drivers.potential_fields.magnetic_scalar.driver", {"inversion": "MagneticScalarDriver"}, diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 3ceb187f..89cd7cf0 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -41,7 +41,6 @@ class ActiveCellsData(BaseModel): """ model_config = ConfigDict( - # frozen=True, arbitrary_types_allowed=True, ) topography_object: Points # | None = None @@ -271,7 +270,6 @@ class BaseInversionData(BaseData, CoreData): """ model_config = ConfigDict( - frozen=False, arbitrary_types_allowed=True, ) diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py index 423e3e84..29077bde 100644 --- a/tests/run_tests/driver_grav_test.py +++ b/tests/run_tests/driver_grav_test.py @@ -118,9 +118,8 @@ def test_gravity_run( save_sensitivities=True, ) params.write_ui_json(path=tmp_path / "Inv_run.ui.json") - # params.write_input_file(path=tmp_path, name="Inv_run") - driver = GravityDriverInversion.start(str(tmp_path / "Inv_run.ui.json")) + driver = GravityInversionDriver.start(str(tmp_path / "Inv_run.ui.json")) assert driver.params.data_object.uid != gz.parent.uid assert driver.models.upper_bound is np.inf From d52b77769c172ddbcc1252eba01c55a7a5f4c976 Mon Sep 17 00:00:00 2001 From: benjamink Date: Fri, 24 Jan 2025 11:37:17 -0800 Subject: [PATCH 07/21] switching branches --- simpeg_drivers/__init__.py | 14 +- simpeg_drivers/driver.py | 2 +- simpeg_drivers/line_sweep/driver.py | 2 +- simpeg_drivers/params.py | 14 +- .../magnetic_scalar/params.py | 3 +- .../magnetic_vector/params.py | 3 +- simpeg_drivers/utils/utils.py | 7 +- tests/data_test.py | 96 +++-------- tests/driver_test.py | 18 ++- tests/params_test.py | 153 +----------------- tests/run_tests/driver_grav_test.py | 7 +- .../driver_joint_cross_gradient_test.py | 12 +- tests/run_tests/driver_joint_surveys_test.py | 44 ++--- tests/run_tests/sensitivity_cutoff_test.py | 18 ++- 14 files changed, 105 insertions(+), 288 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index e2ab207a..ec1b67ea 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -49,7 +49,7 @@ def assets_path() -> Path: DRIVER_MAP = { "direct current 3d": ( "simpeg_drivers.electricals.direct_current.three_dimensions.driver", - {"inversion": "DirectCurrent3DDriver"} + {"inversion": "DirectCurrent3DDriver"}, ), "direct current 2d": ( "simpeg_drivers.electricals.direct_current.two_dimensions.driver", @@ -91,10 +91,14 @@ def assets_path() -> Path: "simpeg_drivers.natural_sources.magnetotellurics.driver", {"inversion": "MagnetotelluricsDriver"}, ), - "tipper": ("simpeg_drivers.natural_sources.tipper.driver", - {"inversion": "TipperDriver"}), - "gravity": ("simpeg_drivers.potential_fields.gravity.driver", - {"inversion": "GravityInversionDriver", "forward": "GravityForwardDriver"}), + "tipper": ( + "simpeg_drivers.natural_sources.tipper.driver", + {"inversion": "TipperDriver"}, + ), + "gravity": ( + "simpeg_drivers.potential_fields.gravity.driver", + {"inversion": "GravityInversionDriver", "forward": "GravityForwardDriver"}, + ), "magnetic scalar": ( "simpeg_drivers.potential_fields.magnetic_scalar.driver", {"inversion": "MagneticScalarDriver"}, diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index 01f8cb2d..ec8ce8b8 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -461,7 +461,7 @@ def start(cls, filepath: str | Path, driver_class=None): mod_name, classes = DRIVER_MAP.get(inversion_type) if forward_only: - class_name = classes.get("forward", "inversion") + class_name = classes.get("forward", classes["inversion"]) else: class_name = classes.get("inversion") module = __import__(mod_name, fromlist=[class_name]) diff --git a/simpeg_drivers/line_sweep/driver.py b/simpeg_drivers/line_sweep/driver.py index f131f4e0..fa7197f6 100644 --- a/simpeg_drivers/line_sweep/driver.py +++ b/simpeg_drivers/line_sweep/driver.py @@ -186,7 +186,7 @@ def collect_results(self): with open(ws.h5file.parent / "SimPEG.log", "w", encoding="utf8") as f: f.write("".join(log_lines)) - self.pseudo3d_params.data_entity.add_data(data) + self.pseudo3d_params.data_object.add_data(data) if self.pseudo3d_params.mesh is None: return diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 89cd7cf0..426fdc93 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -11,8 +11,8 @@ from __future__ import annotations -import warnings import multiprocessing +import warnings from copy import deepcopy from pathlib import Path from typing import ClassVar @@ -43,8 +43,8 @@ class ActiveCellsData(BaseModel): model_config = ConfigDict( arbitrary_types_allowed=True, ) - topography_object: Points # | None = None - topography: FloatData | None = None + topography_object: Points | None = None + topography: FloatData | float | None = None active_model: BooleanData | None = None @model_validator(mode="before") @@ -75,11 +75,7 @@ class CoreData(BaseModel): # TODO: Refactor to allow frozen True. Currently params.data_object is # updated after z_from_topo applied in entity_factory.py. See # simpeg_drivers/components/data.py ln. 127 - model_config = ConfigDict( - frozen=False, - arbitrary_types_allowed=True, - extra="allow" - ) + model_config = ConfigDict(frozen=False, arbitrary_types_allowed=True, extra="allow") run_command: ClassVar[str] = "simpeg_drivers.driver" conda_environment: str = "simpeg_drivers" inversion_type: str @@ -115,7 +111,6 @@ def mesh_cannot_be_rotated(cls, value: Octree): @model_validator(mode="before") @classmethod def out_group_if_none(cls, data) -> SimPEGGroup: - group = data.get("out_group", None) if isinstance(group, UIJsonGroup): @@ -554,7 +549,6 @@ def components(self) -> list[str]: return comps - def model_norms(self) -> list[float]: """Returns model norm components as a list.""" return [ diff --git a/simpeg_drivers/potential_fields/magnetic_scalar/params.py b/simpeg_drivers/potential_fields/magnetic_scalar/params.py index 3f727946..622a2f99 100644 --- a/simpeg_drivers/potential_fields/magnetic_scalar/params.py +++ b/simpeg_drivers/potential_fields/magnetic_scalar/params.py @@ -76,9 +76,10 @@ def __init__(self, input_file=None, forward_only=False, **kwargs): super().__init__(input_file=input_file, forward_only=forward_only, **kwargs) + @property def components(self) -> list[str]: """Retrieve component names used to index channel and uncertainty data.""" - comps = super().components() + comps = super().components if self.forward_only: if len(comps) == 0: comps = ["tmi"] diff --git a/simpeg_drivers/potential_fields/magnetic_vector/params.py b/simpeg_drivers/potential_fields/magnetic_vector/params.py index faf4f9bc..fe45231e 100644 --- a/simpeg_drivers/potential_fields/magnetic_vector/params.py +++ b/simpeg_drivers/potential_fields/magnetic_vector/params.py @@ -76,8 +76,9 @@ def __init__(self, input_file=None, forward_only=False, **kwargs): super().__init__(input_file=input_file, forward_only=forward_only, **kwargs) + @property def components(self) -> list[str]: - comps = super().components() + comps = super().components if self.forward_only: if len(comps) == 0: comps = ["tmi"] diff --git a/simpeg_drivers/utils/utils.py b/simpeg_drivers/utils/utils.py index 63859593..8d79ef97 100644 --- a/simpeg_drivers/utils/utils.py +++ b/simpeg_drivers/utils/utils.py @@ -817,7 +817,12 @@ def simpeg_group_to_driver(group: SimPEGGroup, workspace: Workspace) -> Inversio ui_json["geoh5"] = workspace ifile = InputFile(ui_json=ui_json) - mod_name, class_name = DRIVER_MAP.get(ui_json["inversion_type"]) + forward_only = ui_json["forward_only"] + mod_name, classes = DRIVER_MAP.get(ui_json["inversion_type"]) + if forward_only: + class_name = classes.get("forward", classes["inversion"]) + else: + class_name = classes.get("inversion") module = __import__(mod_name, fromlist=[class_name]) inversion_driver = getattr(module, class_name) params = inversion_driver._params_class( # pylint: disable=W0212 diff --git a/tests/data_test.py b/tests/data_test.py index b548390f..377bb9e2 100644 --- a/tests/data_test.py +++ b/tests/data_test.py @@ -120,29 +120,24 @@ def test_survey_data(tmp_path: Path): ) mesh = treemesh_2_octree(workspace, mesh) - with pytest.warns( - DeprecationWarning, - match="The use of 'receiver_offset_z' will be deprecated in future release.", - ): - params = MagneticVectorParams( - forward_only=False, - geoh5=workspace, - data_object=test_data_object.uid, - topography_object=test_topo_object.uid, - topography=topo, - bxx_channel=bxx_data.uid, - bxx_uncertainty=0.1, - byy_channel=byy_data.uid, - byy_uncertainty=0.2, - bzz_channel=bzz_data.uid, - bzz_uncertainty=0.3, - mesh=mesh.uid, - starting_model=0.0, - tile_spatial=2, - z_from_topo=True, - receivers_offset_z=50.0, - resolution=0.0, - ) + params = MagneticVectorParams( + forward_only=False, + geoh5=workspace, + data_object=test_data_object.uid, + topography_object=test_topo_object.uid, + topography=topo, + bxx_channel=bxx_data.uid, + bxx_uncertainty=0.1, + byy_channel=byy_data.uid, + byy_uncertainty=0.2, + bzz_channel=bzz_data.uid, + bzz_uncertainty=0.3, + mesh=mesh.uid, + starting_model=0.0, + tile_spatial=2, + z_from_topo=True, + resolution=0.0, + ) driver = MagneticVectorDriver(params) @@ -159,10 +154,8 @@ def test_survey_data(tmp_path: Path): np.testing.assert_array_equal( verts[driver.sorting[1], :2], local_survey_b.receiver_locations[:, :2] ) - assert all( - local_survey_a.receiver_locations[:, 2] == 150.0 - ) # 150 = 100 (z_from_topo) + 50 (receivers_offset_z) - assert all(local_survey_b.receiver_locations[:, 2] == 150.0) + assert all(local_survey_a.receiver_locations[:, 2] == 100.0) + assert all(local_survey_b.receiver_locations[:, 2] == 100.0) # test observed data sorting = np.hstack(driver.sorting) @@ -231,55 +224,6 @@ def test_get_uncertainty_component(tmp_path: Path): assert len(unc) == data.entity.n_vertices -def test_displace(tmp_path: Path): - ws, params = setup_params(tmp_path) - locs = params.data_object.vertices - params.update( - { - "window_center_x": np.mean(locs[:, 0]), - "window_center_y": np.mean(locs[:, 1]), - "window_width": 100.0, - "window_height": 100.0, - } - ) - data = InversionData(ws, params) - test_locs = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]) - test_offset = np.array([[1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 0.0, 0.0]]) - expected_locs = np.array([[2.0, 2.0, 3.0], [5.0, 5.0, 6.0], [8.0, 8.0, 9.0]]) - displaced_locs = data.displace(test_locs, test_offset) - assert np.all(displaced_locs == expected_locs) - - test_offset = np.array([[0.0, 1.0, 0.0], [0.0, 1.0, 0.0], [0.0, 1.0, 0.0]]) - expected_locs = np.array([[1.0, 3.0, 3.0], [4.0, 6.0, 6.0], [7.0, 9.0, 9.0]]) - displaced_locs = data.displace(test_locs, test_offset) - assert np.all(displaced_locs == expected_locs) - - test_offset = np.array([[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]]) - expected_locs = np.array([[1.0, 2.0, 4.0], [4.0, 5.0, 7.0], [7.0, 8.0, 10.0]]) - displaced_locs = data.displace(test_locs, test_offset) - assert np.all(displaced_locs == expected_locs) - - -def test_drape(tmp_path: Path): - ws, params = setup_params(tmp_path) - locs = params.data_object.vertices - params.update( - { - "window_center_x": np.mean(locs[:, 0]), - "window_center_y": np.mean(locs[:, 1]), - "window_width": 100.0, - "window_height": 100.0, - } - ) - data = InversionData(ws, params) - test_locs = np.array([[1.0, 2.0, 1.0], [2.0, 1.0, 1.0], [8.0, 9.0, 1.0]]) - radar_ch = np.array([1.0, 2.0, 3.0]) - expected_locs = np.array([[1.0, 2.0, 2.0], [2.0, 1.0, 3.0], [8.0, 9.0, 4.0]]) - draped_locs = data.drape(test_locs, radar_ch) - - assert np.all(draped_locs == expected_locs) - - def test_normalize(tmp_path: Path): ws, params = setup_params(tmp_path) data = InversionData(ws, params) diff --git a/tests/driver_test.py b/tests/driver_test.py index 55363efe..e899e67d 100644 --- a/tests/driver_test.py +++ b/tests/driver_test.py @@ -12,8 +12,9 @@ import numpy as np -from simpeg_drivers.potential_fields import GravityParams -from simpeg_drivers.potential_fields.gravity.driver import GravityDriver +from simpeg_drivers.params import ActiveCellsData +from simpeg_drivers.potential_fields import GravityInversionParams +from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.utils.testing import setup_inversion_workspace @@ -33,11 +34,12 @@ def test_smallness_terms(tmp_path: Path): gz = survey.add_data({"gz": {"values": np.ones(survey.n_vertices)}}) mesh = model.parent - params = GravityParams( + active = ActiveCellsData(topography_object=topography) + params = GravityInversionParams( geoh5=geoh5, - mesh=mesh.uid, - topography_object=topography.uid, - data_object=gz.parent.uid, + mesh=mesh, + active=active, + data_object=gz.parent, starting_model=1e-4, reference_model=0.0, alpha_s=1.0, @@ -45,7 +47,7 @@ def test_smallness_terms(tmp_path: Path): gradient_type="components", gz_channel_bool=True, z_from_topo=False, - gz_channel=gz.uid, + gz_channel=gz, gz_uncertainty=2e-3, lower_bound=0.0, max_global_iterations=1, @@ -54,5 +56,5 @@ def test_smallness_terms(tmp_path: Path): store_sensitivities="ram", ) params.alpha_s = None - driver = GravityDriver(params) + driver = GravityInversionDriver(params) assert driver.regularization.objfcts[0].alpha_s == 0.0 diff --git a/tests/params_test.py b/tests/params_test.py index ad99b027..1cc34f2e 100644 --- a/tests/params_test.py +++ b/tests/params_test.py @@ -85,15 +85,15 @@ def grav_params(tmp_path_factory): flatten=False, ) geoh5.close() - params = GravityParams( + params = GravityInversionParams( **{ "geoh5": geoh5, "data_object": survey, - "topography_object": topography, + "active": {"topography_object": topography}, "mesh": mesh, } ) - params.input_file.geoh5.open() + params.geoh5.open() return params @@ -188,96 +188,6 @@ def test_write_input_file_validation(tmp_path, mvi_params): params.write_input_file(name="test.ui.json", path=tmp_path) -def test_params_initialize(): - for params in [ - MagneticScalarParams(), - MagneticVectorParams(), - GravityParams(), - DirectCurrent3DParams(), - InducedPolarization3DParams(), - ]: - check = [] - for k, v in params.defaults.items(): - if " " in k or k in [ - "starting_model", - "conductivity_model", - "min_value", - "generate_sweep", - ]: - continue - check.append(getattr(params, k) == v) - assert all(check) - - params = MagneticVectorParams(starting_model=1.0) - assert params.starting_model == 1.0 - params = GravityParams(starting_model=1.0) - assert params.starting_model == 1.0 - - -def test_input_file_construction(tmp_path: Path): - params_classes = [ - GravityParams, - MagneticScalarParams, - MagneticVectorParams, - DirectCurrent3DParams, - InducedPolarization3DParams, - ] - - for params_class in params_classes: - filename = "test.ui.json" - for forward_only in [True, False]: - params = params_class(forward_only=forward_only) - params.write_input_file(name=filename, path=tmp_path, validate=False) - ifile = InputFile.read_ui_json(tmp_path / filename, validate=False) - params = params_class(input_file=ifile) - - check = [] - for k, v in params.defaults.items(): - # TODO Need to better handle defaults None to value - if (" " in k) or k in [ - "starting_model", - "reference_model", - "conductivity_model", - "min_value", - "generate_sweep", - ]: - continue - check.append(getattr(params, k) == v) - - assert all(check) - - -def test_default_input_file(tmp_path: Path): - for params_class in [ - MagneticScalarParams, - MagneticVectorParams, - GravityParams, - DirectCurrent3DParams, - InducedPolarization3DParams, - ]: - filename = "test.ui.json" - params = params_class() - params.write_input_file(name=filename, path=tmp_path, validate=False) - ifile = InputFile.read_ui_json(tmp_path / filename, validate=False) - - # check that reads back into input file with defaults - check = [] - for k, v in ifile.data.items(): - if " " in k or requires_value(ifile.ui_json, k): - continue - check.append(v == params.defaults[k]) - assert all(check) - - # check that params constructed from_path is defaulted - params2 = params_class() - check = [] - for k, v in params2.to_dict(ui_json_format=False).items(): - if " " in k or requires_value(ifile.ui_json, k): - continue - check.append(v == ifile.data[k]) - assert all(check) - - def test_update(): new_params = { "starting_model": 99.0, @@ -310,7 +220,7 @@ def test_chunk_validation_mag(tmp_path: Path, mvi_params): def test_chunk_validation_grav(tmp_path: Path, grav_params): test_dict = grav_params.to_dict() - params = GravityParams(**test_dict) # pylint: disable=repeated-keyword + params = GravityInversionParams(**test_dict) # pylint: disable=repeated-keyword params.topography_object = None with pytest.raises( OptionalValidationError, @@ -598,58 +508,3 @@ def test_active_cells_data(tmp_path): assert True -def test_something(tmp_path): - from typing import ClassVar - - from geoapps_utils.driver.data import BaseData - from geoh5py import Workspace - from geoh5py.objects import Octree, Points - from pydantic import BaseModel, ConfigDict - - ws = Workspace(tmp_path / "test.geoh5") - - class CoreData(BaseModel): - model_config = ConfigDict( - frozen=True, - arbitrary_types_allowed=True, - ) - run_command: ClassVar[str] = "simpeg_drivers.driver" - conda_environment: str = "simpeg_drivers" - data_object: Points | None - mesh: Octree | None - - class GravityData(BaseData, CoreData): - model_config = ConfigDict( - frozen=True, - arbitrary_types_allowed=True, - ) - mesh: DrapeModel | None - myparam: int = 1 - - data = GravityData(geoh5=ws, data_object=None, mesh=None, myparam=2) - - assert True - -def test_something_else(): - from pydantic import BaseModel, ConfigDict - class MyData(BaseModel): - model_config = ConfigDict(frozen=True, extra="allow") - a: int - b: str - - data = MyData(a=1, b='2') - data.e = 3 - assert data.e == 3 - -def test_something_related(): - from pydantic import BaseModel, ConfigDict, Field, computed_field - class MyData(BaseModel): - model_config = ConfigDict(frozen=True, extra="allow") - a: int - b: str - - - data = MyData(a=1, b="string") - data.c = "other_string" - assert data.b == "string" - assert data.c == "other_string" \ No newline at end of file diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py index 29077bde..10ee93af 100644 --- a/tests/run_tests/driver_grav_test.py +++ b/tests/run_tests/driver_grav_test.py @@ -17,7 +17,10 @@ from simpeg_drivers.params import ActiveCellsData from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams -from simpeg_drivers.potential_fields.gravity.driver import GravityForwardDriver, GravityInversionDriver +from simpeg_drivers.potential_fields.gravity.driver import ( + GravityForwardDriver, + GravityInversionDriver, +) from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace from simpeg_drivers.utils.utils import get_inversion_output @@ -53,7 +56,7 @@ def test_gravity_fwr_run( z_from_topo=False, data_object=survey, starting_model=model, - gz_channel_bool=True + gz_channel_bool=True, ) fwr_driver = GravityForwardDriver(params) fwr_driver.run() diff --git a/tests/run_tests/driver_joint_cross_gradient_test.py b/tests/run_tests/driver_joint_cross_gradient_test.py index 1a5a6ea2..9f4b08eb 100644 --- a/tests/run_tests/driver_joint_cross_gradient_test.py +++ b/tests/run_tests/driver_joint_cross_gradient_test.py @@ -23,8 +23,8 @@ ) from simpeg_drivers.joint.joint_cross_gradient import JointCrossGradientParams from simpeg_drivers.joint.joint_cross_gradient.driver import JointCrossGradientDriver -from simpeg_drivers.potential_fields import GravityParams, MagneticVectorParams -from simpeg_drivers.potential_fields.gravity.driver import GravityDriver +from simpeg_drivers.potential_fields import GravityInversionParams, MagneticVectorParams +from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.potential_fields.magnetic_vector.driver import MagneticVectorDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace from simpeg_drivers.utils.utils import get_inversion_output @@ -52,7 +52,7 @@ def test_joint_cross_gradient_fwr_run( n_electrodes=n_grid_points, n_lines=n_grid_points, ) - params = GravityParams( + params = GravityInversionParams( forward_only=True, geoh5=geoh5, mesh=model.parent.uid, @@ -62,7 +62,7 @@ def test_joint_cross_gradient_fwr_run( data_object=survey.uid, starting_model=model.uid, ) - fwr_driver_a = GravityDriver(params) + fwr_driver_a = GravityInversionDriver(params) _, _, model, survey, _ = setup_inversion_workspace( tmp_path, @@ -169,7 +169,7 @@ def test_joint_cross_gradient_inv_run( if group.options["inversion_type"] == "gravity": data.values = data.values + np.random.randn(data.values.size) * 1e-2 - params = GravityParams( + params = GravityInversionParams( geoh5=geoh5, mesh=mesh.uid, alpha_s=1.0, @@ -180,7 +180,7 @@ def test_joint_cross_gradient_inv_run( starting_model=0.0, reference_model=0.0, ) - drivers.append(GravityDriver(params)) + drivers.append(GravityInversionDriver(params)) elif group.options["inversion_type"] == "direct current 3d": data.values = data.values + np.random.randn(data.values.size) * 5e-4 params = DirectCurrent3DParams( diff --git a/tests/run_tests/driver_joint_surveys_test.py b/tests/run_tests/driver_joint_surveys_test.py index 6fb15c12..3b506634 100644 --- a/tests/run_tests/driver_joint_surveys_test.py +++ b/tests/run_tests/driver_joint_surveys_test.py @@ -16,10 +16,11 @@ from simpeg_drivers.joint.joint_surveys import JointSurveysParams from simpeg_drivers.joint.joint_surveys.driver import JointSurveyDriver -from simpeg_drivers.potential_fields import GravityParams -from simpeg_drivers.potential_fields.gravity.driver import GravityDriver +from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams +from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace from simpeg_drivers.utils.utils import get_inversion_output +from simpeg_drivers.params import ActiveCellsData # To test the full run and validate the inversion. @@ -42,17 +43,18 @@ def test_joint_surveys_fwr_run( n_electrodes=n_grid_points, n_lines=n_grid_points, ) - params = GravityParams( + active = ActiveCellsData(topography_object=topography) + params = GravityForwardParams( forward_only=True, geoh5=geoh5, - mesh=model.parent.uid, - topography_object=topography.uid, + mesh=model.parent, + active=active, resolution=0.0, z_from_topo=False, - data_object=survey.uid, - starting_model=model.uid, + data_object=survey, + starting_model=model, ) - fwr_driver_a = GravityDriver(params) + fwr_driver_a = GravityInversionDriver(params) fwr_driver_a.out_group.name = "Gravity Forward [0]" # Create local problem B @@ -67,17 +69,18 @@ def test_joint_surveys_fwr_run( geoh5=geoh5, drape_height=10.0, ) - params = GravityParams( + active = ActiveCellsData(topography_object=topography) + params = GravityForwardParams( forward_only=True, geoh5=geoh5, - mesh=model.parent.uid, - topography_object=topography.uid, + mesh=model.parent, + active=active, resolution=0.0, z_from_topo=False, - data_object=survey.uid, - starting_model=model.uid, + data_object=survey, + starting_model=model, ) - fwr_driver_b = GravityDriver(params) + fwr_driver_b = GravityInversionDriver(params) fwr_driver_b.out_group.name = "Gravity Forward [1]" # Force co-location of meshes @@ -124,16 +127,17 @@ def test_joint_surveys_inv_run( active_model = mesh.get_entity("active_cells")[0] gz = survey.get_data("Iteration_0_gz")[0] orig_data.append(gz.values) - params = GravityParams( + active = ActiveCellsData(active_model=active_model) + params = GravityInversionParams( geoh5=geoh5, - mesh=mesh.uid, - active_model=active_model.uid, - data_object=survey.uid, - gz_channel=gz.uid, + mesh=mesh, + active=active, + data_object=survey, + gz_channel=gz, gz_uncertainty=np.var(gz.values) * 2.0, starting_model=0.0, ) - drivers.append(GravityDriver(params)) + drivers.append(GravityInversionDriver(params)) active_model = drivers[0].params.mesh.get_entity("active_cells")[0] # Run the inverse diff --git a/tests/run_tests/sensitivity_cutoff_test.py b/tests/run_tests/sensitivity_cutoff_test.py index 8d170aa5..eaa167ff 100644 --- a/tests/run_tests/sensitivity_cutoff_test.py +++ b/tests/run_tests/sensitivity_cutoff_test.py @@ -15,14 +15,17 @@ import numpy as np from geoh5py.workspace import Workspace + from simpeg_drivers.depth_of_investigation.sensitivity_cutoff.driver import ( SensitivityCutoffDriver, ) from simpeg_drivers.depth_of_investigation.sensitivity_cutoff.params import ( SensitivityCutoffParams, ) -from simpeg_drivers.potential_fields import GravityParams -from simpeg_drivers.potential_fields.gravity.driver import GravityDriver + +from simpeg_drivers.params import ActiveCellsData +from simpeg_drivers.potential_fields import GravityInversionParams +from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.utils.testing import setup_inversion_workspace @@ -43,10 +46,11 @@ def setup_inversion_results( # Run the inverse with save_sensitivities=True gz = survey.add_data({"gz": {"values": np.random.randn(len(survey.vertices))}}) - params = GravityParams( + active = ActiveCellsData(topography_object=topography) + params = GravityInversionParams( geoh5=geoh5, - mesh=mesh.uid, - topography_object=topography.uid, + mesh=mesh, + topography_object=topography, data_object=gz.parent.uid, starting_model=1e-4, reference_model=0.0, @@ -54,7 +58,7 @@ def setup_inversion_results( gradient_type="components", gz_channel_bool=True, z_from_topo=False, - gz_channel=gz.uid, + gz_channel=gz, gz_uncertainty=2e-3, lower_bound=0.0, max_global_iterations=1, @@ -64,7 +68,7 @@ def setup_inversion_results( save_sensitivities=True, ) params.write_input_file(path=tmp_path, name="Inv_run") - GravityDriver.start(str(tmp_path / "Inv_run.ui.json")) + GravityInversionDriver.start(str(tmp_path / "Inv_run.ui.json")) def test_sensitivity_percent_cutoff_run(tmp_path): From 779d05c275f8dd3689bb46c1da72a8b5296731a4 Mon Sep 17 00:00:00 2001 From: benjamink Date: Mon, 27 Jan 2025 13:19:15 -0800 Subject: [PATCH 08/21] tests passing --- simpeg_drivers/components/topography.py | 2 +- simpeg_drivers/params.py | 9 ++- simpeg_drivers/utils/utils.py | 12 +++- tests/params_test.py | 66 ------------------- .../driver_joint_cross_gradient_test.py | 23 ++++--- tests/run_tests/sensitivity_cutoff_test.py | 6 +- 6 files changed, 32 insertions(+), 86 deletions(-) diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index e9a2c02e..b355c4de 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -91,7 +91,7 @@ def active_cells(self, mesh: InversionMesh, data: InversionData) -> np.ndarray: if isinstance(self.params.active.active_model, NumericData): active_cells = InversionModel.obj_2_mesh( - self.params.active_model, mesh.entity + self.params.active.active_model, mesh.entity ) else: active_cells = active_from_xyz( diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 426fdc93..d36a389b 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -114,12 +114,15 @@ def out_group_if_none(cls, data) -> SimPEGGroup: group = data.get("out_group", None) if isinstance(group, UIJsonGroup): - group = SimPEGGroup.create(data["geoh5"], name=group.name) + with fetch_active_workspace(data["geoh5"], mode="r+") as geoh5: + group = SimPEGGroup.create(geoh5, name=group.name) + group.metadata = None elif group is None: - group = SimPEGGroup.create(data["geoh5"], name=cls.title) + with fetch_active_workspace(data["geoh5"], mode="r+") as geoh5: + group = SimPEGGroup.create(geoh5, name=cls.title) + group.metadata = None - group.metadata = None data["out_group"] = group return data diff --git a/simpeg_drivers/utils/utils.py b/simpeg_drivers/utils/utils.py index 8d79ef97..ee05aeb0 100644 --- a/simpeg_drivers/utils/utils.py +++ b/simpeg_drivers/utils/utils.py @@ -45,6 +45,7 @@ from simpeg_drivers.components.data import InversionData from simpeg_drivers.driver import InversionDriver +from geoapps_utils.driver.data import BaseData from simpeg_drivers.utils.surveys import ( compute_alongline_distance, get_intersecting_cells, @@ -825,7 +826,12 @@ def simpeg_group_to_driver(group: SimPEGGroup, workspace: Workspace) -> Inversio class_name = classes.get("inversion") module = __import__(mod_name, fromlist=[class_name]) inversion_driver = getattr(module, class_name) - params = inversion_driver._params_class( # pylint: disable=W0212 - ifile, out_group=group - ) + # TODO: Remove logic when all params classes are converted to BaseData. + if issubclass(inversion_driver._params_class, BaseData): + ifile.set_data_value("out_group", group) + params = inversion_driver._params_class.build(ifile) + else: + params = inversion_driver._params_class( # pylint: disable=W0212 + ifile, out_group=group + ) return inversion_driver(params) diff --git a/tests/params_test.py b/tests/params_test.py index 1cc34f2e..29fa612e 100644 --- a/tests/params_test.py +++ b/tests/params_test.py @@ -74,30 +74,6 @@ def mvi_params(tmp_path_factory): return params -@pytest.fixture(scope="session") -def grav_params(tmp_path_factory): - geoh5, mesh, model, survey, topography = setup_inversion_workspace( - tmp_path_factory.mktemp("gravity"), - background=0.01, - anomaly=10, - n_electrodes=2, - n_lines=2, - flatten=False, - ) - geoh5.close() - params = GravityInversionParams( - **{ - "geoh5": geoh5, - "data_object": survey, - "active": {"topography_object": topography}, - "mesh": mesh, - } - ) - params.geoh5.open() - - return params - - @pytest.fixture(scope="session") def dc_params(tmp_path_factory): geoh5, mesh, model, survey, topography = setup_inversion_workspace( @@ -218,17 +194,6 @@ def test_chunk_validation_mag(tmp_path: Path, mvi_params): params.write_input_file(name="test.ui.json", path=tmp_path) -def test_chunk_validation_grav(tmp_path: Path, grav_params): - test_dict = grav_params.to_dict() - params = GravityInversionParams(**test_dict) # pylint: disable=repeated-keyword - params.topography_object = None - with pytest.raises( - OptionalValidationError, - match="Cannot set a None value to non-optional parameter: topography_object.", - ): - params.write_input_file(name="test.ui.json", path=tmp_path) - - def test_active_set(mvi_params): assert "inversion_type" in mvi_params.active_set() assert "mesh" in mvi_params.active_set() @@ -407,37 +372,6 @@ def test_mag_data(mvi_params, channel): ): setattr(mvi_params, f"{channel}_uncertainty", mvi_params.geoh5) - -def test_gravity_inversion_type(grav_params): - with pytest.raises( - ValueValidationError, match="'inversion_type' is invalid. Must be: 'gravity'" - ): - grav_params.inversion_type = "alskdj" - - -@pytest.mark.parametrize( - "channel", ["gz", "gy", "gz", "guv", "gxy", "gxz", "gyz", "gxx", "gyy", "gzz"] -) -def test_grav_data(grav_params, channel): - with pytest.raises(AssociationValidationError): - setattr(grav_params, f"{channel}_channel", uuid4()) - - with pytest.raises( - TypeValidationError, - match="Must be one of: 'str', 'UUID', 'Entity', 'NoneType'.", - ): - setattr(grav_params, f"{channel}_channel", 4) - - with pytest.raises(AssociationValidationError): - setattr(grav_params, f"{channel}_uncertainty", uuid4()) - - with pytest.raises( - TypeValidationError, - match="Must be one of: 'str', 'UUID', 'int', 'float', 'Entity', 'NoneType'.", - ): - setattr(grav_params, f"{channel}_uncertainty", grav_params.geoh5) - - def test_direct_current_inversion_type(dc_params): with pytest.raises(ValueValidationError, match="Must be: 'direct current 3d'"): dc_params.inversion_type = "alskdj" diff --git a/tests/run_tests/driver_joint_cross_gradient_test.py b/tests/run_tests/driver_joint_cross_gradient_test.py index 9f4b08eb..54497d35 100644 --- a/tests/run_tests/driver_joint_cross_gradient_test.py +++ b/tests/run_tests/driver_joint_cross_gradient_test.py @@ -15,6 +15,7 @@ from geoh5py.groups import SimPEGGroup from geoh5py.workspace import Workspace +from simpeg_drivers.params import ActiveCellsData from simpeg_drivers.electricals.direct_current.three_dimensions import ( DirectCurrent3DParams, ) @@ -23,7 +24,7 @@ ) from simpeg_drivers.joint.joint_cross_gradient import JointCrossGradientParams from simpeg_drivers.joint.joint_cross_gradient.driver import JointCrossGradientDriver -from simpeg_drivers.potential_fields import GravityInversionParams, MagneticVectorParams +from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams, MagneticVectorParams from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.potential_fields.magnetic_vector.driver import MagneticVectorDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace @@ -52,15 +53,16 @@ def test_joint_cross_gradient_fwr_run( n_electrodes=n_grid_points, n_lines=n_grid_points, ) - params = GravityInversionParams( + active = ActiveCellsData(topography_object=topography) + params = GravityForwardParams( forward_only=True, geoh5=geoh5, - mesh=model.parent.uid, - topography_object=topography.uid, + mesh=model.parent, + active=active, resolution=0.0, z_from_topo=False, - data_object=survey.uid, - starting_model=model.uid, + data_object=survey, + starting_model=model, ) fwr_driver_a = GravityInversionDriver(params) @@ -169,13 +171,14 @@ def test_joint_cross_gradient_inv_run( if group.options["inversion_type"] == "gravity": data.values = data.values + np.random.randn(data.values.size) * 1e-2 + active = ActiveCellsData(topography_object=topography) params = GravityInversionParams( geoh5=geoh5, - mesh=mesh.uid, + mesh=mesh, alpha_s=1.0, - topography_object=topography.uid, - data_object=survey.uid, - gz_channel=data.uid, + active=active, + data_object=survey, + gz_channel=data, gz_uncertainty=1e-2, starting_model=0.0, reference_model=0.0, diff --git a/tests/run_tests/sensitivity_cutoff_test.py b/tests/run_tests/sensitivity_cutoff_test.py index eaa167ff..1cdf8698 100644 --- a/tests/run_tests/sensitivity_cutoff_test.py +++ b/tests/run_tests/sensitivity_cutoff_test.py @@ -50,8 +50,8 @@ def setup_inversion_results( params = GravityInversionParams( geoh5=geoh5, mesh=mesh, - topography_object=topography, - data_object=gz.parent.uid, + active=active, + data_object=gz.parent, starting_model=1e-4, reference_model=0.0, s_norm=0.0, @@ -67,7 +67,7 @@ def setup_inversion_results( store_sensitivities="ram", save_sensitivities=True, ) - params.write_input_file(path=tmp_path, name="Inv_run") + params.write_ui_json(path=tmp_path / "Inv_run.ui.json") GravityInversionDriver.start(str(tmp_path / "Inv_run.ui.json")) From 55f41b8fc312b17710a168d15eb0bbb5eb16d8c5 Mon Sep 17 00:00:00 2001 From: benjamink Date: Mon, 27 Jan 2025 13:52:16 -0800 Subject: [PATCH 09/21] pylint fixes --- simpeg_drivers/__init__.py | 4 +--- simpeg_drivers/driver.py | 4 +--- simpeg_drivers/params.py | 6 +++++- .../potential_fields/gravity/driver.py | 18 ++++++++---------- simpeg_drivers/utils/utils.py | 8 ++++---- simpeg_drivers/utils/write_default_uijson.py | 3 --- tests/params_test.py | 16 +--------------- 7 files changed, 20 insertions(+), 39 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index ec1b67ea..7f2e53dd 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -19,9 +19,7 @@ from pathlib import Path from simpeg_drivers.constants import default_ui_json - - -# from simpeg_drivers.params import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams logging.basicConfig(level=logging.INFO) diff --git a/simpeg_drivers/driver.py b/simpeg_drivers/driver.py index ec8ce8b8..415d686c 100644 --- a/simpeg_drivers/driver.py +++ b/simpeg_drivers/driver.py @@ -12,7 +12,6 @@ from __future__ import annotations -import multiprocessing import sys from datetime import datetime, timedelta from multiprocessing.pool import ThreadPool @@ -49,7 +48,7 @@ InversionWindow, ) from simpeg_drivers.components.factories import DirectivesFactory, MisfitFactory -from simpeg_drivers.params import InversionBaseParams +from simpeg_drivers.params import InversionBaseParams, BaseInversionData from simpeg_drivers.utils.utils import tile_locations @@ -446,7 +445,6 @@ def configure_dask(self): @classmethod def start(cls, filepath: str | Path, driver_class=None): - _ = driver_class ifile = InputFile.read_ui_json(filepath) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index d36a389b..615c4ab4 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -31,6 +31,10 @@ from simpeg_drivers import assets_path +# pylint: disable=too-many-lines +# TODO: Remove this disable when all params are BaseData + + class ActiveCellsData(BaseModel): """ Active cells data as a topography surface or 3d model. @@ -94,7 +98,7 @@ class CoreData(BaseModel): generate_sweep: bool = False @field_validator("n_cpu", mode="before") - def maximize_cpu_if_none(cls, value): + def maximize_cpu_if_none(self, value): if value is None: value = int(multiprocessing.cpu_count()) return value diff --git a/simpeg_drivers/potential_fields/gravity/driver.py b/simpeg_drivers/potential_fields/gravity/driver.py index 878be5e6..5a4b5c40 100644 --- a/simpeg_drivers/potential_fields/gravity/driver.py +++ b/simpeg_drivers/potential_fields/gravity/driver.py @@ -11,25 +11,23 @@ from __future__ import annotations -from simpeg_drivers.driver import InversionDriver - -from .constants import validations -from .params import GravityForwardParams, GravityInversionParams from geoapps_utils.driver.data import BaseData from geoh5py.ui_json import InputFile + from simpeg_drivers import DRIVER_MAP +from simpeg_drivers.driver import InversionDriver +from simpeg_drivers.potential_fields.gravity.constants import validations +from simpeg_drivers.potential_fields.gravity.params import ( + GravityForwardParams, + GravityInversionParams, +) + class GravityForwardDriver(InversionDriver): _params_class = GravityForwardParams _validation = validations - def __init__(self, params): - super().__init__(params) class GravityInversionDriver(InversionDriver): _params_class = GravityInversionParams _validations = validations - - def __init__(self, params): - super().__init__(params) - diff --git a/simpeg_drivers/utils/utils.py b/simpeg_drivers/utils/utils.py index ee05aeb0..a6f07c03 100644 --- a/simpeg_drivers/utils/utils.py +++ b/simpeg_drivers/utils/utils.py @@ -38,14 +38,14 @@ from simpeg.survey import BaseSurvey from simpeg.utils import mkvc -from simpeg_drivers import DRIVER_MAP - if TYPE_CHECKING: from simpeg_drivers.components.data import InversionData from simpeg_drivers.driver import InversionDriver from geoapps_utils.driver.data import BaseData + +from simpeg_drivers import DRIVER_MAP from simpeg_drivers.utils.surveys import ( compute_alongline_distance, get_intersecting_cells, @@ -827,9 +827,9 @@ def simpeg_group_to_driver(group: SimPEGGroup, workspace: Workspace) -> Inversio module = __import__(mod_name, fromlist=[class_name]) inversion_driver = getattr(module, class_name) # TODO: Remove logic when all params classes are converted to BaseData. - if issubclass(inversion_driver._params_class, BaseData): + if issubclass(inversion_driver._params_class, BaseData): # pylint: disable=W0212 ifile.set_data_value("out_group", group) - params = inversion_driver._params_class.build(ifile) + params = inversion_driver._params_class.build(ifile) # pylint: disable=W0212 else: params = inversion_driver._params_class( # pylint: disable=W0212 ifile, out_group=group diff --git a/simpeg_drivers/utils/write_default_uijson.py b/simpeg_drivers/utils/write_default_uijson.py index c3e1c916..1eb8fa69 100644 --- a/simpeg_drivers/utils/write_default_uijson.py +++ b/simpeg_drivers/utils/write_default_uijson.py @@ -40,7 +40,6 @@ from simpeg_drivers.joint.joint_surveys import JointSurveysParams from simpeg_drivers.natural_sources import MagnetotelluricsParams, TipperParams from simpeg_drivers.potential_fields import ( - GravityParams, MagneticScalarParams, MagneticVectorParams, ) @@ -69,8 +68,6 @@ def write_default_uijson(path: str | Path): filedict = { - "gravity_inversion.ui.json": GravityParams(validate=False), - "gravity_forward.ui.json": GravityParams(forward_only=True, validate=False), "magnetic_scalar_inversion.ui.json": MagneticScalarParams(validate=False), "magnetic_scalar_forward.ui.json": MagneticScalarParams( forward_only=True, validate=False diff --git a/tests/params_test.py b/tests/params_test.py index 29fa612e..56ca8328 100644 --- a/tests/params_test.py +++ b/tests/params_test.py @@ -372,6 +372,7 @@ def test_mag_data(mvi_params, channel): ): setattr(mvi_params, f"{channel}_uncertainty", mvi_params.geoh5) + def test_direct_current_inversion_type(dc_params): with pytest.raises(ValueValidationError, match="Must be: 'direct current 3d'"): dc_params.inversion_type = "alskdj" @@ -427,18 +428,3 @@ def test_conductivity_model(ip_params): match="Must be one of: 'str', 'UUID', 'int', 'float', 'Entity'.", ): ip_params.conductivity_model = ip_params.geoh5 - - -def test_active_cells_data(tmp_path): - import numpy as np - from geoh5py import Workspace - from geoh5py.objects import Points - - from simpeg_drivers.params import ActiveCellsData - - ws = Workspace(tmp_path / "test.geoh5") - pts = Points.create(ws, vertices=np.random.rand(10, 3)) - data = ActiveCellsData(topography_object=pts) - assert True - - From b95d3961488142dc526982ddec26f94be01f2fa7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 22:00:20 +0000 Subject: [PATCH 10/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- simpeg_drivers/components/data.py | 1 - simpeg_drivers/components/topography.py | 4 +++- simpeg_drivers/potential_fields/gravity/params.py | 2 +- tests/run_tests/driver_joint_cross_gradient_test.py | 8 ++++++-- tests/run_tests/driver_joint_surveys_test.py | 2 +- tests/run_tests/sensitivity_cutoff_test.py | 2 -- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/simpeg_drivers/components/data.py b/simpeg_drivers/components/data.py index 41c78d81..cb55a9be 100644 --- a/simpeg_drivers/components/data.py +++ b/simpeg_drivers/components/data.py @@ -264,7 +264,6 @@ def apply_transformations(self, locations: np.ndarray): return locations - def normalize( self, data: dict[str, np.ndarray], absolute=False ) -> dict[str, np.ndarray]: diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index b355c4de..732ec860 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -132,7 +132,9 @@ def get_locations(self, entity: Entity) -> np.ndarray: elif isinstance(self.params.active.topography, int | float): elev = np.ones_like(locs[:, 2]) * self.params.active.topography else: - elev = self.params.active.topography.values # Must be FloatData at this point + elev = ( + self.params.active.topography.values + ) # Must be FloatData at this point if not np.all(locs[:, 2] == elev): locs[:, 2] = elev diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index a07bd5cf..31d032b9 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -78,7 +78,7 @@ class GravityInversionParams(BaseInversionData): name: ClassVar[str] = "Gravity Inversion" title: ClassVar[str] = "Gravity Inversion" - default_ui_json: ClassVar[Path] = assets_path() / "uijson/gravity_inversion.ui.json" + default_ui_json: ClassVar[Path] = assets_path() / "uijson/gravity_inversion.ui.json" inversion_type: str = "gravity" physical_property: str = "density" diff --git a/tests/run_tests/driver_joint_cross_gradient_test.py b/tests/run_tests/driver_joint_cross_gradient_test.py index 54497d35..377d2941 100644 --- a/tests/run_tests/driver_joint_cross_gradient_test.py +++ b/tests/run_tests/driver_joint_cross_gradient_test.py @@ -15,7 +15,6 @@ from geoh5py.groups import SimPEGGroup from geoh5py.workspace import Workspace -from simpeg_drivers.params import ActiveCellsData from simpeg_drivers.electricals.direct_current.three_dimensions import ( DirectCurrent3DParams, ) @@ -24,7 +23,12 @@ ) from simpeg_drivers.joint.joint_cross_gradient import JointCrossGradientParams from simpeg_drivers.joint.joint_cross_gradient.driver import JointCrossGradientDriver -from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams, MagneticVectorParams +from simpeg_drivers.params import ActiveCellsData +from simpeg_drivers.potential_fields import ( + GravityForwardParams, + GravityInversionParams, + MagneticVectorParams, +) from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.potential_fields.magnetic_vector.driver import MagneticVectorDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace diff --git a/tests/run_tests/driver_joint_surveys_test.py b/tests/run_tests/driver_joint_surveys_test.py index 3b506634..95b42ac5 100644 --- a/tests/run_tests/driver_joint_surveys_test.py +++ b/tests/run_tests/driver_joint_surveys_test.py @@ -16,11 +16,11 @@ from simpeg_drivers.joint.joint_surveys import JointSurveysParams from simpeg_drivers.joint.joint_surveys.driver import JointSurveyDriver +from simpeg_drivers.params import ActiveCellsData from simpeg_drivers.potential_fields import GravityForwardParams, GravityInversionParams from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver from simpeg_drivers.utils.testing import check_target, setup_inversion_workspace from simpeg_drivers.utils.utils import get_inversion_output -from simpeg_drivers.params import ActiveCellsData # To test the full run and validate the inversion. diff --git a/tests/run_tests/sensitivity_cutoff_test.py b/tests/run_tests/sensitivity_cutoff_test.py index 1cdf8698..2e128fb6 100644 --- a/tests/run_tests/sensitivity_cutoff_test.py +++ b/tests/run_tests/sensitivity_cutoff_test.py @@ -15,14 +15,12 @@ import numpy as np from geoh5py.workspace import Workspace - from simpeg_drivers.depth_of_investigation.sensitivity_cutoff.driver import ( SensitivityCutoffDriver, ) from simpeg_drivers.depth_of_investigation.sensitivity_cutoff.params import ( SensitivityCutoffParams, ) - from simpeg_drivers.params import ActiveCellsData from simpeg_drivers.potential_fields import GravityInversionParams from simpeg_drivers.potential_fields.gravity.driver import GravityInversionDriver From d2bbea444c94c23ae6549034be83b5b07fcb5c27 Mon Sep 17 00:00:00 2001 From: benjamink Date: Mon, 27 Jan 2025 14:23:28 -0800 Subject: [PATCH 11/21] fix bug introduced with pylint fixes --- simpeg_drivers/__init__.py | 2 -- simpeg_drivers/params.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/simpeg_drivers/__init__.py b/simpeg_drivers/__init__.py index 7f2e53dd..ccd3b24f 100644 --- a/simpeg_drivers/__init__.py +++ b/simpeg_drivers/__init__.py @@ -19,14 +19,12 @@ from pathlib import Path from simpeg_drivers.constants import default_ui_json -from simpeg_drivers.params import InversionBaseParams logging.basicConfig(level=logging.INFO) __all__ = [ "DRIVER_MAP", - "InversionBaseParams", "assets_path", "default_ui_json", ] diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 615c4ab4..92b9d86e 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -98,7 +98,8 @@ class CoreData(BaseModel): generate_sweep: bool = False @field_validator("n_cpu", mode="before") - def maximize_cpu_if_none(self, value): + @classmethod + def maximize_cpu_if_none(cls, value): if value is None: value = int(multiprocessing.cpu_count()) return value From b9c831ddaddabc48fcd731dbb0cfdc61789ce35a Mon Sep 17 00:00:00 2001 From: benjamink Date: Tue, 28 Jan 2025 09:35:02 -0800 Subject: [PATCH 12/21] Better class inheritance pattern --- simpeg_drivers/params.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 92b9d86e..849dce8f 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -59,7 +59,7 @@ def at_least_one(cls, data): return data -class CoreData(BaseModel): +class CoreData(BaseData): """ Core parameters shared by inverse and forward operations. @@ -186,7 +186,7 @@ def padding_cells(self) -> int: return 4 if self.inversion_type in ["fem", "tdem"] else 6 -class BaseForwardData(BaseData, CoreData): +class BaseForwardData(CoreData): """ Base class for forward parameters. @@ -208,7 +208,7 @@ def components(self) -> list[str]: return comps -class BaseInversionData(BaseData, CoreData): +class BaseInversionData(CoreData): """ Base class for inversion parameters. From a8462e158f90209bdec59fa18a7df2edefe0c6ed Mon Sep 17 00:00:00 2001 From: benjamink Date: Tue, 28 Jan 2025 09:49:43 -0800 Subject: [PATCH 13/21] re-lock files --- .../py-3.10-linux-64-dev.conda.lock.yml | 31 +- environments/py-3.10-linux-64.conda.lock.yml | 16 +- .../py-3.10-win-64-dev.conda.lock.yml | 37 +-- environments/py-3.10-win-64.conda.lock.yml | 22 +- .../py-3.11-linux-64-dev.conda.lock.yml | 33 +- environments/py-3.11-linux-64.conda.lock.yml | 18 +- .../py-3.11-win-64-dev.conda.lock.yml | 39 ++- environments/py-3.11-win-64.conda.lock.yml | 24 +- py-3.10.conda-lock.yml | 300 ++++++++--------- py-3.11.conda-lock.yml | 310 ++++++++---------- 10 files changed, 387 insertions(+), 443 deletions(-) diff --git a/environments/py-3.10-linux-64-dev.conda.lock.yml b/environments/py-3.10-linux-64-dev.conda.lock.yml index af33fccb..115ad151 100644 --- a/environments/py-3.10-linux-64-dev.conda.lock.yml +++ b/environments/py-3.10-linux-64-dev.conda.lock.yml @@ -19,7 +19,7 @@ dependencies: - astroid=3.3.8=py310hff52083_0 - asttokens=3.0.0=pyhd8ed1ab_1 - async-lru=2.0.4=pyhd8ed1ab_1 - - attrs=24.3.0=pyh71513ae_0 + - attrs=25.1.0=pyh71513ae_0 - babel=2.16.0=pyhd8ed1ab_1 - beautifulsoup4=4.12.3=pyha770c72_1 - bleach=6.2.0=pyh29332c3_4 @@ -53,11 +53,10 @@ dependencies: - distributed=2024.6.2=pyhd8ed1ab_0 - docutils=0.19=py310hff52083_1 - empymod=2.2.2=pyhd8ed1ab_0 - - entrypoints=0.4=pyhd8ed1ab_1 - exceptiongroup=1.2.2=pyhd8ed1ab_1 - executing=2.1.0=pyhd8ed1ab_1 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py310h89163eb_0 + - fonttools=4.55.6=py310h89163eb_0 - fqdn=1.5.1=pyhd8ed1ab_1 - freetype=2.12.1=h267a509_2 - fsspec=2022.11.0=pyhd8ed1ab_0 @@ -67,10 +66,10 @@ dependencies: - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py310hacc6608_103 - hdf5=1.14.4=nompi_h2d575fe_105 - - hpack=4.0.0=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 - httpcore=1.0.7=pyh29332c3_1 - httpx=0.28.1=pyhd8ed1ab_0 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hyperframe=6.1.0=pyhd8ed1ab_0 - idna=3.10=pyhd8ed1ab_1 - imagesize=1.4.1=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 @@ -82,7 +81,7 @@ dependencies: - ipython_genutils=0.2.0=pyhd8ed1ab_2 - ipywidgets=7.8.5=pyhd8ed1ab_0 - isoduration=20.11.0=pyhd8ed1ab_1 - - isort=5.13.2=pyhd8ed1ab_1 + - isort=6.0.0=pyhd8ed1ab_0 - jedi=0.19.2=pyhd8ed1ab_1 - jinja2=3.1.5=pyhd8ed1ab_0 - joblib=1.4.2=pyhd8ed1ab_1 @@ -135,7 +134,7 @@ dependencies: - liblzma=5.6.3=hb9d3cd8_1 - libnghttp2=1.64.0=h161d5f1_0 - libnsl=2.0.1=hd590300_0 - - libpng=1.6.45=h943b412_0 + - libpng=1.6.46=h943b412_0 - libsodium=1.0.20=h4ab18f5_0 - libsqlite=3.48.0=hee588c1_1 - libssh2=1.11.1=hf672d98_0 @@ -166,9 +165,9 @@ dependencies: - myst-nb=1.1.2=pyhd8ed1ab_1 - myst-parser=1.0.0=pyhd8ed1ab_0 - nbclient=0.10.2=pyhd8ed1ab_0 - - nbconvert=7.16.5=hd8ed1ab_1 - - nbconvert-core=7.16.5=pyhd8ed1ab_1 - - nbconvert-pandoc=7.16.5=hd8ed1ab_1 + - nbconvert=7.16.6=hb482800_0 + - nbconvert-core=7.16.6=pyh29332c3_0 + - nbconvert-pandoc=7.16.6=hed9df3c_0 - nbformat=5.10.4=pyhd8ed1ab_1 - ncurses=6.5=h2d0b736_2 - nest-asyncio=1.6.0=pyhd8ed1ab_1 @@ -189,7 +188,7 @@ dependencies: - pexpect=4.9.0=pyhd8ed1ab_1 - pickleshare=0.7.5=pyhd8ed1ab_1004 - pillow=10.3.0=py310hebfe307_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - pkgutil-resolve-name=1.3.10=pyhd8ed1ab_2 - platformdirs=4.3.6=pyhd8ed1ab_1 - pluggy=1.5.0=pyhd8ed1ab_1 @@ -202,12 +201,12 @@ dependencies: - pybtex=0.24.0=pyhd8ed1ab_3 - pybtex-docutils=1.0.3=py310hff52083_2 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py310h505e2c1_0 - pydata-sphinx-theme=0.15.4=pyhd8ed1ab_0 - pydiso=0.1.2=py310h7b68af5_0 - pygments=2.19.1=pyhd8ed1ab_0 - - pylint=3.3.3=pyhd8ed1ab_0 + - pylint=3.3.4=pyh29332c3_0 - pymatsolver=0.2.0=ha770c72_3 - pymatsolver-base=0.2.0=pyh44b312d_3 - pyparsing=3.2.1=pyhd8ed1ab_0 @@ -225,7 +224,7 @@ dependencies: - pyzmq=26.2.0=py310h71f11fc_3 - readline=8.2=h8228510_1 - readthedocs-sphinx-ext=2.2.5=pyhd8ed1ab_1 - - referencing=0.36.1=pyhd8ed1ab_0 + - referencing=0.36.2=pyh29332c3_0 - requests=2.32.3=pyhd8ed1ab_1 - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 @@ -297,10 +296,10 @@ dependencies: - zstandard=0.23.0=py310ha39cb0e_1 - zstd=1.5.6=ha6fb4c9_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.10-linux-64.conda.lock.yml b/environments/py-3.10-linux-64.conda.lock.yml index 5926cff6..6400946e 100644 --- a/environments/py-3.10-linux-64.conda.lock.yml +++ b/environments/py-3.10-linux-64.conda.lock.yml @@ -31,15 +31,15 @@ dependencies: - distributed=2024.6.2=pyhd8ed1ab_0 - empymod=2.2.2=pyhd8ed1ab_0 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py310h89163eb_0 + - fonttools=4.55.6=py310h89163eb_0 - freetype=2.12.1=h267a509_2 - fsspec=2022.11.0=pyhd8ed1ab_0 - geoana=0.5.0=py310hcb52e73_4 - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py310hacc6608_103 - hdf5=1.14.4=nompi_h2d575fe_105 - - hpack=4.0.0=pyhd8ed1ab_1 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 + - hyperframe=6.1.0=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 - importlib_metadata=8.6.1=hd8ed1ab_0 - jinja2=3.1.5=pyhd8ed1ab_0 @@ -74,7 +74,7 @@ dependencies: - liblzma=5.6.3=hb9d3cd8_1 - libnghttp2=1.64.0=h161d5f1_0 - libnsl=2.0.1=hd590300_0 - - libpng=1.6.45=h943b412_0 + - libpng=1.6.46=h943b412_0 - libsqlite=3.48.0=hee588c1_1 - libssh2=1.11.1=hf672d98_0 - libstdcxx=14.2.0=hc0a3c3a_1 @@ -104,11 +104,11 @@ dependencies: - pandas=2.2.3=py310h5eaa309_1 - partd=1.4.2=pyhd8ed1ab_0 - pillow=10.3.0=py310hebfe307_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - psutil=6.1.1=py310ha75aee5_0 - pthread-stubs=0.4=hb9d3cd8_1002 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py310h505e2c1_0 - pydiso=0.1.2=py310h7b68af5_0 - pymatsolver=0.2.0=ha770c72_3 @@ -149,10 +149,10 @@ dependencies: - zstandard=0.23.0=py310ha39cb0e_1 - zstd=1.5.6=ha6fb4c9_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.10-win-64-dev.conda.lock.yml b/environments/py-3.10-win-64-dev.conda.lock.yml index 0c9b6854..24ece24f 100644 --- a/environments/py-3.10-win-64-dev.conda.lock.yml +++ b/environments/py-3.10-win-64-dev.conda.lock.yml @@ -17,7 +17,7 @@ dependencies: - astroid=3.3.8=py310h5588dad_0 - asttokens=3.0.0=pyhd8ed1ab_1 - async-lru=2.0.4=pyhd8ed1ab_1 - - attrs=24.3.0=pyh71513ae_0 + - attrs=25.1.0=pyh71513ae_0 - babel=2.16.0=pyhd8ed1ab_1 - beautifulsoup4=4.12.3=pyha770c72_1 - bleach=6.2.0=pyh29332c3_4 @@ -51,11 +51,10 @@ dependencies: - distributed=2024.6.2=pyhd8ed1ab_0 - docutils=0.19=py310h5588dad_1 - empymod=2.2.2=pyhd8ed1ab_0 - - entrypoints=0.4=pyhd8ed1ab_1 - exceptiongroup=1.2.2=pyhd8ed1ab_1 - executing=2.1.0=pyhd8ed1ab_1 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py310h38315fa_0 + - fonttools=4.55.6=py310h38315fa_0 - fqdn=1.5.1=pyhd8ed1ab_1 - freetype=2.12.1=hdaf720e_2 - fsspec=2022.11.0=pyhd8ed1ab_0 @@ -65,10 +64,10 @@ dependencies: - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py310h972678a_103 - hdf5=1.14.4=nompi_hd5d9e70_105 - - hpack=4.0.0=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 - httpcore=1.0.7=pyh29332c3_1 - httpx=0.28.1=pyhd8ed1ab_0 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hyperframe=6.1.0=pyhd8ed1ab_0 - idna=3.10=pyhd8ed1ab_1 - imagesize=1.4.1=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 @@ -81,7 +80,7 @@ dependencies: - ipython_genutils=0.2.0=pyhd8ed1ab_2 - ipywidgets=7.8.5=pyhd8ed1ab_0 - isoduration=20.11.0=pyhd8ed1ab_1 - - isort=5.13.2=pyhd8ed1ab_1 + - isort=6.0.0=pyhd8ed1ab_0 - jedi=0.19.2=pyhd8ed1ab_1 - jinja2=3.1.5=pyhd8ed1ab_0 - joblib=1.4.2=pyhd8ed1ab_1 @@ -123,7 +122,7 @@ dependencies: - libjpeg-turbo=3.0.0=hcfcfb64_1 - liblapack=3.9.0=20_win64_mkl - liblzma=5.6.3=h2466b09_1 - - libpng=1.6.45=had7236b_0 + - libpng=1.6.46=had7236b_0 - libsodium=1.0.20=hc70643c_0 - libsqlite=3.48.0=h67fdade_1 - libssh2=1.11.1=he619c9f_0 @@ -155,9 +154,9 @@ dependencies: - myst-nb=1.1.2=pyhd8ed1ab_1 - myst-parser=1.0.0=pyhd8ed1ab_0 - nbclient=0.10.2=pyhd8ed1ab_0 - - nbconvert=7.16.5=hd8ed1ab_1 - - nbconvert-core=7.16.5=pyhd8ed1ab_1 - - nbconvert-pandoc=7.16.5=hd8ed1ab_1 + - nbconvert=7.16.6=hb482800_0 + - nbconvert-core=7.16.6=pyh29332c3_0 + - nbconvert-pandoc=7.16.6=hed9df3c_0 - nbformat=5.10.4=pyhd8ed1ab_1 - nest-asyncio=1.6.0=pyhd8ed1ab_1 - notebook=7.3.2=pyhd8ed1ab_0 @@ -176,7 +175,7 @@ dependencies: - partd=1.4.2=pyhd8ed1ab_0 - pickleshare=0.7.5=pyhd8ed1ab_1004 - pillow=10.3.0=py310h3e38d90_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - pkgutil-resolve-name=1.3.10=pyhd8ed1ab_2 - platformdirs=4.3.6=pyhd8ed1ab_1 - pluggy=1.5.0=pyhd8ed1ab_1 @@ -189,12 +188,12 @@ dependencies: - pybtex=0.24.0=pyhd8ed1ab_3 - pybtex-docutils=1.0.3=py310h5588dad_2 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py310hc226416_0 - pydata-sphinx-theme=0.15.4=pyhd8ed1ab_0 - pydiso=0.1.2=py310h5da8fee_0 - pygments=2.19.1=pyhd8ed1ab_0 - - pylint=3.3.3=pyhd8ed1ab_0 + - pylint=3.3.4=pyh29332c3_0 - pymatsolver=0.2.0=ha770c72_3 - pymatsolver-base=0.2.0=pyh44b312d_3 - pyparsing=3.2.1=pyhd8ed1ab_0 @@ -213,7 +212,7 @@ dependencies: - pyyaml=6.0.2=py310h38315fa_2 - pyzmq=26.2.0=py310h656833d_3 - readthedocs-sphinx-ext=2.2.5=pyhd8ed1ab_1 - - referencing=0.36.1=pyhd8ed1ab_0 + - referencing=0.36.2=pyh29332c3_0 - requests=2.32.3=pyhd8ed1ab_1 - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 @@ -270,9 +269,9 @@ dependencies: - unicodedata2=16.0.0=py310ha8f682b_0 - uri-template=1.3.0=pyhd8ed1ab_1 - urllib3=2.3.0=pyhd8ed1ab_0 - - vc=14.3=ha32ba9b_23 - - vc14_runtime=14.42.34433=he29a5d6_23 - - vs2015_runtime=14.42.34433=hdffcdeb_23 + - vc=14.3=h5fd82a7_24 + - vc14_runtime=14.42.34433=h6356254_24 + - vs2015_runtime=14.42.34433=hfef2bbc_24 - wcwidth=0.2.13=pyhd8ed1ab_1 - webcolors=24.11.1=pyhd8ed1ab_0 - webencodings=0.5.1=pyhd8ed1ab_3 @@ -291,10 +290,10 @@ dependencies: - zstandard=0.23.0=py310he5e10e1_1 - zstd=1.5.6=h0ea2cb4_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.10-win-64.conda.lock.yml b/environments/py-3.10-win-64.conda.lock.yml index a9e42a1b..6b30765e 100644 --- a/environments/py-3.10-win-64.conda.lock.yml +++ b/environments/py-3.10-win-64.conda.lock.yml @@ -28,15 +28,15 @@ dependencies: - distributed=2024.6.2=pyhd8ed1ab_0 - empymod=2.2.2=pyhd8ed1ab_0 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py310h38315fa_0 + - fonttools=4.55.6=py310h38315fa_0 - freetype=2.12.1=hdaf720e_2 - fsspec=2022.11.0=pyhd8ed1ab_0 - geoana=0.5.0=py310h4856b71_4 - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py310h972678a_103 - hdf5=1.14.4=nompi_hd5d9e70_105 - - hpack=4.0.0=pyhd8ed1ab_1 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 + - hyperframe=6.1.0=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 - importlib_metadata=8.6.1=hd8ed1ab_0 - intel-openmp=2023.2.0=h57928b3_50497 @@ -61,7 +61,7 @@ dependencies: - libjpeg-turbo=3.0.0=hcfcfb64_1 - liblapack=3.9.0=20_win64_mkl - liblzma=5.6.3=h2466b09_1 - - libpng=1.6.45=had7236b_0 + - libpng=1.6.46=had7236b_0 - libsqlite=3.48.0=h67fdade_1 - libssh2=1.11.1=he619c9f_0 - libtiff=4.7.0=h797046b_3 @@ -91,12 +91,12 @@ dependencies: - pandas=2.2.3=py310hb4db72f_1 - partd=1.4.2=pyhd8ed1ab_0 - pillow=10.3.0=py310h3e38d90_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - psutil=6.1.1=py310ha8f682b_0 - pthread-stubs=0.4=hcd874cb_1001 - pthreads-win32=2.9.1=h2466b09_4 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py310hc226416_0 - pydiso=0.1.2=py310h5da8fee_0 - pymatsolver=0.2.0=ha770c72_3 @@ -127,9 +127,9 @@ dependencies: - ucrt=10.0.22621.0=h57928b3_1 - unicodedata2=16.0.0=py310ha8f682b_0 - urllib3=2.3.0=pyhd8ed1ab_0 - - vc=14.3=ha32ba9b_23 - - vc14_runtime=14.42.34433=he29a5d6_23 - - vs2015_runtime=14.42.34433=hdffcdeb_23 + - vc=14.3=h5fd82a7_24 + - vc14_runtime=14.42.34433=h6356254_24 + - vs2015_runtime=14.42.34433=hfef2bbc_24 - wheel=0.45.1=pyhd8ed1ab_1 - win_inet_pton=1.1.0=pyh7428d3b_8 - xorg-libxau=1.0.11=hcd874cb_0 @@ -141,10 +141,10 @@ dependencies: - zstandard=0.23.0=py310he5e10e1_1 - zstd=1.5.6=h0ea2cb4_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.11-linux-64-dev.conda.lock.yml b/environments/py-3.11-linux-64-dev.conda.lock.yml index c7e0c428..c9912dd7 100644 --- a/environments/py-3.11-linux-64-dev.conda.lock.yml +++ b/environments/py-3.11-linux-64-dev.conda.lock.yml @@ -19,7 +19,7 @@ dependencies: - astroid=3.3.8=py311h38be061_0 - asttokens=3.0.0=pyhd8ed1ab_1 - async-lru=2.0.4=pyhd8ed1ab_1 - - attrs=24.3.0=pyh71513ae_0 + - attrs=25.1.0=pyh71513ae_0 - babel=2.16.0=pyhd8ed1ab_1 - beautifulsoup4=4.12.3=pyha770c72_1 - bleach=6.2.0=pyh29332c3_4 @@ -48,17 +48,16 @@ dependencies: - debugpy=1.8.12=py311hfdbb021_0 - decorator=5.1.1=pyhd8ed1ab_1 - defusedxml=0.7.1=pyhd8ed1ab_0 - - deprecated=1.2.15=pyhd8ed1ab_1 + - deprecated=1.2.18=pyhd8ed1ab_0 - dill=0.3.9=pyhd8ed1ab_1 - discretize=0.10.0=py311h92ebd52_1 - distributed=2024.6.2=pyhd8ed1ab_0 - docutils=0.19=py311h38be061_1 - empymod=2.2.2=pyhd8ed1ab_0 - - entrypoints=0.4=pyhd8ed1ab_1 - exceptiongroup=1.2.2=pyhd8ed1ab_1 - executing=2.1.0=pyhd8ed1ab_1 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py311h2dc5d0c_0 + - fonttools=4.55.6=py311h2dc5d0c_0 - fqdn=1.5.1=pyhd8ed1ab_1 - freetype=2.12.1=h267a509_2 - fsspec=2022.11.0=pyhd8ed1ab_0 @@ -68,10 +67,10 @@ dependencies: - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py311h5ed33ec_103 - hdf5=1.14.4=nompi_h2d575fe_105 - - hpack=4.0.0=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 - httpcore=1.0.7=pyh29332c3_1 - httpx=0.28.1=pyhd8ed1ab_0 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hyperframe=6.1.0=pyhd8ed1ab_0 - idna=3.10=pyhd8ed1ab_1 - imagesize=1.4.1=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 @@ -83,7 +82,7 @@ dependencies: - ipython_genutils=0.2.0=pyhd8ed1ab_2 - ipywidgets=7.8.5=pyhd8ed1ab_0 - isoduration=20.11.0=pyhd8ed1ab_1 - - isort=5.13.2=pyhd8ed1ab_1 + - isort=6.0.0=pyhd8ed1ab_0 - jedi=0.19.2=pyhd8ed1ab_1 - jinja2=3.1.5=pyhd8ed1ab_0 - joblib=1.4.2=pyhd8ed1ab_1 @@ -137,7 +136,7 @@ dependencies: - liblzma=5.6.3=hb9d3cd8_1 - libnghttp2=1.64.0=h161d5f1_0 - libnsl=2.0.1=hd590300_0 - - libpng=1.6.45=h943b412_0 + - libpng=1.6.46=h943b412_0 - libsodium=1.0.20=h4ab18f5_0 - libsqlite=3.48.0=hee588c1_1 - libssh2=1.11.1=hf672d98_0 @@ -168,9 +167,9 @@ dependencies: - myst-nb=1.1.2=pyhd8ed1ab_1 - myst-parser=1.0.0=pyhd8ed1ab_0 - nbclient=0.10.2=pyhd8ed1ab_0 - - nbconvert=7.16.5=hd8ed1ab_1 - - nbconvert-core=7.16.5=pyhd8ed1ab_1 - - nbconvert-pandoc=7.16.5=hd8ed1ab_1 + - nbconvert=7.16.6=hb482800_0 + - nbconvert-core=7.16.6=pyh29332c3_0 + - nbconvert-pandoc=7.16.6=hed9df3c_0 - nbformat=5.10.4=pyhd8ed1ab_1 - ncurses=6.5=h2d0b736_2 - nest-asyncio=1.6.0=pyhd8ed1ab_1 @@ -191,7 +190,7 @@ dependencies: - pexpect=4.9.0=pyhd8ed1ab_1 - pickleshare=0.7.5=pyhd8ed1ab_1004 - pillow=10.3.0=py311h82a398c_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - pkgutil-resolve-name=1.3.10=pyhd8ed1ab_2 - platformdirs=4.3.6=pyhd8ed1ab_1 - pluggy=1.5.0=pyhd8ed1ab_1 @@ -204,12 +203,12 @@ dependencies: - pybtex=0.24.0=pyhd8ed1ab_3 - pybtex-docutils=1.0.3=py311h38be061_2 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py311h9e33e62_0 - pydata-sphinx-theme=0.15.4=pyhd8ed1ab_0 - pydiso=0.1.2=py311h979a38d_0 - pygments=2.19.1=pyhd8ed1ab_0 - - pylint=3.3.3=pyhd8ed1ab_0 + - pylint=3.3.4=pyh29332c3_0 - pymatsolver=0.2.0=ha770c72_3 - pymatsolver-base=0.2.0=pyh44b312d_3 - pyparsing=3.2.1=pyhd8ed1ab_0 @@ -227,7 +226,7 @@ dependencies: - pyzmq=26.2.0=py311h7deb3e3_3 - readline=8.2=h8228510_1 - readthedocs-sphinx-ext=2.2.5=pyhd8ed1ab_1 - - referencing=0.36.1=pyhd8ed1ab_0 + - referencing=0.36.2=pyh29332c3_0 - requests=2.32.3=pyhd8ed1ab_1 - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 @@ -300,10 +299,10 @@ dependencies: - zstandard=0.23.0=py311hbc35293_1 - zstd=1.5.6=ha6fb4c9_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.11-linux-64.conda.lock.yml b/environments/py-3.11-linux-64.conda.lock.yml index 57ecdc92..00b691d3 100644 --- a/environments/py-3.11-linux-64.conda.lock.yml +++ b/environments/py-3.11-linux-64.conda.lock.yml @@ -27,20 +27,20 @@ dependencies: - cycler=0.12.1=pyhd8ed1ab_1 - cytoolz=1.0.1=py311h9ecbd09_0 - dask-core=2024.6.2=pyhd8ed1ab_0 - - deprecated=1.2.15=pyhd8ed1ab_1 + - deprecated=1.2.18=pyhd8ed1ab_0 - discretize=0.10.0=py311h92ebd52_1 - distributed=2024.6.2=pyhd8ed1ab_0 - empymod=2.2.2=pyhd8ed1ab_0 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py311h2dc5d0c_0 + - fonttools=4.55.6=py311h2dc5d0c_0 - freetype=2.12.1=h267a509_2 - fsspec=2022.11.0=pyhd8ed1ab_0 - geoana=0.5.0=py311h92ebd52_4 - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py311h5ed33ec_103 - hdf5=1.14.4=nompi_h2d575fe_105 - - hpack=4.0.0=pyhd8ed1ab_1 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 + - hyperframe=6.1.0=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 - importlib_metadata=8.6.1=hd8ed1ab_0 - jinja2=3.1.5=pyhd8ed1ab_0 @@ -76,7 +76,7 @@ dependencies: - liblzma=5.6.3=hb9d3cd8_1 - libnghttp2=1.64.0=h161d5f1_0 - libnsl=2.0.1=hd590300_0 - - libpng=1.6.45=h943b412_0 + - libpng=1.6.46=h943b412_0 - libsqlite=3.48.0=hee588c1_1 - libssh2=1.11.1=hf672d98_0 - libstdcxx=14.2.0=hc0a3c3a_1 @@ -106,11 +106,11 @@ dependencies: - pandas=2.2.3=py311h7db5c69_1 - partd=1.4.2=pyhd8ed1ab_0 - pillow=10.3.0=py311h82a398c_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - psutil=6.1.1=py311h9ecbd09_0 - pthread-stubs=0.4=hb9d3cd8_1002 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py311h9e33e62_0 - pydiso=0.1.2=py311h979a38d_0 - pymatsolver=0.2.0=ha770c72_3 @@ -152,10 +152,10 @@ dependencies: - zstandard=0.23.0=py311hbc35293_1 - zstd=1.5.6=ha6fb4c9_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.11-win-64-dev.conda.lock.yml b/environments/py-3.11-win-64-dev.conda.lock.yml index efeecd43..94545175 100644 --- a/environments/py-3.11-win-64-dev.conda.lock.yml +++ b/environments/py-3.11-win-64-dev.conda.lock.yml @@ -17,7 +17,7 @@ dependencies: - astroid=3.3.8=py311h1ea47a8_0 - asttokens=3.0.0=pyhd8ed1ab_1 - async-lru=2.0.4=pyhd8ed1ab_1 - - attrs=24.3.0=pyh71513ae_0 + - attrs=25.1.0=pyh71513ae_0 - babel=2.16.0=pyhd8ed1ab_1 - beautifulsoup4=4.12.3=pyha770c72_1 - bleach=6.2.0=pyh29332c3_4 @@ -46,17 +46,16 @@ dependencies: - debugpy=1.8.12=py311hda3d55a_0 - decorator=5.1.1=pyhd8ed1ab_1 - defusedxml=0.7.1=pyhd8ed1ab_0 - - deprecated=1.2.15=pyhd8ed1ab_1 + - deprecated=1.2.18=pyhd8ed1ab_0 - dill=0.3.9=pyhd8ed1ab_1 - discretize=0.10.0=py311h12feb9d_1 - distributed=2024.6.2=pyhd8ed1ab_0 - docutils=0.19=py311h1ea47a8_1 - empymod=2.2.2=pyhd8ed1ab_0 - - entrypoints=0.4=pyhd8ed1ab_1 - exceptiongroup=1.2.2=pyhd8ed1ab_1 - executing=2.1.0=pyhd8ed1ab_1 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py311h5082efb_0 + - fonttools=4.55.6=py311h5082efb_0 - fqdn=1.5.1=pyhd8ed1ab_1 - freetype=2.12.1=hdaf720e_2 - fsspec=2022.11.0=pyhd8ed1ab_0 @@ -66,10 +65,10 @@ dependencies: - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py311haea1c80_103 - hdf5=1.14.4=nompi_hd5d9e70_105 - - hpack=4.0.0=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 - httpcore=1.0.7=pyh29332c3_1 - httpx=0.28.1=pyhd8ed1ab_0 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hyperframe=6.1.0=pyhd8ed1ab_0 - idna=3.10=pyhd8ed1ab_1 - imagesize=1.4.1=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 @@ -82,7 +81,7 @@ dependencies: - ipython_genutils=0.2.0=pyhd8ed1ab_2 - ipywidgets=7.8.5=pyhd8ed1ab_0 - isoduration=20.11.0=pyhd8ed1ab_1 - - isort=5.13.2=pyhd8ed1ab_1 + - isort=6.0.0=pyhd8ed1ab_0 - jedi=0.19.2=pyhd8ed1ab_1 - jinja2=3.1.5=pyhd8ed1ab_0 - joblib=1.4.2=pyhd8ed1ab_1 @@ -125,7 +124,7 @@ dependencies: - libjpeg-turbo=3.0.0=hcfcfb64_1 - liblapack=3.9.0=20_win64_mkl - liblzma=5.6.3=h2466b09_1 - - libpng=1.6.45=had7236b_0 + - libpng=1.6.46=had7236b_0 - libsodium=1.0.20=hc70643c_0 - libsqlite=3.48.0=h67fdade_1 - libssh2=1.11.1=he619c9f_0 @@ -157,9 +156,9 @@ dependencies: - myst-nb=1.1.2=pyhd8ed1ab_1 - myst-parser=1.0.0=pyhd8ed1ab_0 - nbclient=0.10.2=pyhd8ed1ab_0 - - nbconvert=7.16.5=hd8ed1ab_1 - - nbconvert-core=7.16.5=pyhd8ed1ab_1 - - nbconvert-pandoc=7.16.5=hd8ed1ab_1 + - nbconvert=7.16.6=hb482800_0 + - nbconvert-core=7.16.6=pyh29332c3_0 + - nbconvert-pandoc=7.16.6=hed9df3c_0 - nbformat=5.10.4=pyhd8ed1ab_1 - nest-asyncio=1.6.0=pyhd8ed1ab_1 - notebook=7.3.2=pyhd8ed1ab_0 @@ -178,7 +177,7 @@ dependencies: - partd=1.4.2=pyhd8ed1ab_0 - pickleshare=0.7.5=pyhd8ed1ab_1004 - pillow=10.3.0=py311h5592be9_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - pkgutil-resolve-name=1.3.10=pyhd8ed1ab_2 - platformdirs=4.3.6=pyhd8ed1ab_1 - pluggy=1.5.0=pyhd8ed1ab_1 @@ -191,12 +190,12 @@ dependencies: - pybtex=0.24.0=pyhd8ed1ab_3 - pybtex-docutils=1.0.3=py311h1ea47a8_2 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py311h533ab2d_0 - pydata-sphinx-theme=0.15.4=pyhd8ed1ab_0 - pydiso=0.1.2=py311h6340b4d_0 - pygments=2.19.1=pyhd8ed1ab_0 - - pylint=3.3.3=pyhd8ed1ab_0 + - pylint=3.3.4=pyh29332c3_0 - pymatsolver=0.2.0=ha770c72_3 - pymatsolver-base=0.2.0=pyh44b312d_3 - pyparsing=3.2.1=pyhd8ed1ab_0 @@ -215,7 +214,7 @@ dependencies: - pyyaml=6.0.2=py311h5082efb_2 - pyzmq=26.2.0=py311h484c95c_3 - readthedocs-sphinx-ext=2.2.5=pyhd8ed1ab_1 - - referencing=0.36.1=pyhd8ed1ab_0 + - referencing=0.36.2=pyh29332c3_0 - requests=2.32.3=pyhd8ed1ab_1 - rfc3339-validator=0.1.4=pyhd8ed1ab_1 - rfc3986-validator=0.1.1=pyh9f0ad1d_0 @@ -272,9 +271,9 @@ dependencies: - unicodedata2=16.0.0=py311he736701_0 - uri-template=1.3.0=pyhd8ed1ab_1 - urllib3=2.3.0=pyhd8ed1ab_0 - - vc=14.3=ha32ba9b_23 - - vc14_runtime=14.42.34433=he29a5d6_23 - - vs2015_runtime=14.42.34433=hdffcdeb_23 + - vc=14.3=h5fd82a7_24 + - vc14_runtime=14.42.34433=h6356254_24 + - vs2015_runtime=14.42.34433=hfef2bbc_24 - wcwidth=0.2.13=pyhd8ed1ab_1 - webcolors=24.11.1=pyhd8ed1ab_0 - webencodings=0.5.1=pyhd8ed1ab_3 @@ -294,10 +293,10 @@ dependencies: - zstandard=0.23.0=py311h53056dc_1 - zstd=1.5.6=h0ea2cb4_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/environments/py-3.11-win-64.conda.lock.yml b/environments/py-3.11-win-64.conda.lock.yml index d105a8fc..187b5eaf 100644 --- a/environments/py-3.11-win-64.conda.lock.yml +++ b/environments/py-3.11-win-64.conda.lock.yml @@ -24,20 +24,20 @@ dependencies: - cycler=0.12.1=pyhd8ed1ab_1 - cytoolz=1.0.1=py311he736701_0 - dask-core=2024.6.2=pyhd8ed1ab_0 - - deprecated=1.2.15=pyhd8ed1ab_1 + - deprecated=1.2.18=pyhd8ed1ab_0 - discretize=0.10.0=py311h12feb9d_1 - distributed=2024.6.2=pyhd8ed1ab_0 - empymod=2.2.2=pyhd8ed1ab_0 - fasteners=0.19=pyhd8ed1ab_1 - - fonttools=4.55.4=py311h5082efb_0 + - fonttools=4.55.6=py311h5082efb_0 - freetype=2.12.1=hdaf720e_2 - fsspec=2022.11.0=pyhd8ed1ab_0 - geoana=0.5.0=py311h12feb9d_4 - h2=4.1.0=pyhd8ed1ab_1 - h5py=3.12.1=nompi_py311haea1c80_103 - hdf5=1.14.4=nompi_hd5d9e70_105 - - hpack=4.0.0=pyhd8ed1ab_1 - - hyperframe=6.0.1=pyhd8ed1ab_1 + - hpack=4.1.0=pyhd8ed1ab_0 + - hyperframe=6.1.0=pyhd8ed1ab_0 - importlib-metadata=8.6.1=pyha770c72_0 - importlib_metadata=8.6.1=hd8ed1ab_0 - intel-openmp=2023.2.0=h57928b3_50497 @@ -63,7 +63,7 @@ dependencies: - libjpeg-turbo=3.0.0=hcfcfb64_1 - liblapack=3.9.0=20_win64_mkl - liblzma=5.6.3=h2466b09_1 - - libpng=1.6.45=had7236b_0 + - libpng=1.6.46=had7236b_0 - libsqlite=3.48.0=h67fdade_1 - libssh2=1.11.1=he619c9f_0 - libtiff=4.7.0=h797046b_3 @@ -93,12 +93,12 @@ dependencies: - pandas=2.2.3=py311hcf9f919_1 - partd=1.4.2=pyhd8ed1ab_0 - pillow=10.3.0=py311h5592be9_1 - - pip=24.3.1=pyh8b19718_2 + - pip=25.0=pyh8b19718_0 - psutil=6.1.1=py311he736701_0 - pthread-stubs=0.4=hcd874cb_1001 - pthreads-win32=2.9.1=h2466b09_4 - pycparser=2.22=pyh29332c3_1 - - pydantic=2.10.5=pyh3cfb1c2_0 + - pydantic=2.10.6=pyh3cfb1c2_0 - pydantic-core=2.27.2=py311h533ab2d_0 - pydiso=0.1.2=py311h6340b4d_0 - pymatsolver=0.2.0=ha770c72_3 @@ -129,9 +129,9 @@ dependencies: - ucrt=10.0.22621.0=h57928b3_1 - unicodedata2=16.0.0=py311he736701_0 - urllib3=2.3.0=pyhd8ed1ab_0 - - vc=14.3=ha32ba9b_23 - - vc14_runtime=14.42.34433=he29a5d6_23 - - vs2015_runtime=14.42.34433=hdffcdeb_23 + - vc=14.3=h5fd82a7_24 + - vc14_runtime=14.42.34433=h6356254_24 + - vs2015_runtime=14.42.34433=hfef2bbc_24 - wheel=0.45.1=pyhd8ed1ab_1 - win_inet_pton=1.1.0=pyh7428d3b_8 - wrapt=1.17.2=py311he736701_0 @@ -144,10 +144,10 @@ dependencies: - zstandard=0.23.0=py311h53056dc_1 - zstd=1.5.6=h0ea2cb4_0 - pip: - - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + - geoapps-utils @ git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 - geoh5py @ git+https://github.com/MiraGeoscience/geoh5py.git@728633f4332d7b5052a4b7e3f8958b287222f26b - mira-simpeg @ git+https://github.com/MiraGeoscience/simpeg.git@0074bae221e775aa3d8abff37de2304a94c411f3 - - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + - octree-creation-app @ git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 - param-sweeps @ git+https://github.com/MiraGeoscience/param-sweeps.git@dbb6a6e2131f4fb6ab26ffe0dcd1bd8adbbbd74d variables: diff --git a/py-3.10.conda-lock.yml b/py-3.10.conda-lock.yml index 05635613..3a8fc6a5 100644 --- a/py-3.10.conda-lock.yml +++ b/py-3.10.conda-lock.yml @@ -353,27 +353,27 @@ package: category: dev optional: true - name: attrs - version: 24.3.0 + version: 25.1.0 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/attrs-24.3.0-pyh71513ae_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/attrs-25.1.0-pyh71513ae_0.conda hash: - md5: 356927ace43302bf6f5926e2a58dae6a - sha256: 750186af694a7130eaf7119fbb56db0d2326d8995ad5b8eae23c622b85fea29a + md5: 2cc3f588512f04f3a0c64b4e9bedc02d + sha256: 1f267886522dfb9ae4e5ebbc3135b5eb13cff27bdbfe8d881a4d893459166ab4 category: dev optional: true - name: attrs - version: 24.3.0 + version: 25.1.0 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/attrs-24.3.0-pyh71513ae_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/attrs-25.1.0-pyh71513ae_0.conda hash: - md5: 356927ace43302bf6f5926e2a58dae6a - sha256: 750186af694a7130eaf7119fbb56db0d2326d8995ad5b8eae23c622b85fea29a + md5: 2cc3f588512f04f3a0c64b4e9bedc02d + sha256: 1f267886522dfb9ae4e5ebbc3135b5eb13cff27bdbfe8d881a4d893459166ab4 category: dev optional: true - name: babel @@ -1319,30 +1319,6 @@ package: sha256: c489c425cb75c30288516c140f47d109b4643ab31f17c3f230be38aae7d464f5 category: main optional: false -- name: entrypoints - version: '0.4' - manager: conda - platform: linux-64 - dependencies: - python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_1.conda - hash: - md5: 3366592d3c219f2731721f11bc93755c - sha256: 80f579bfc71b3dab5bef74114b89e26c85cb0df8caf4c27ab5ffc16363d57ee7 - category: dev - optional: true -- name: entrypoints - version: '0.4' - manager: conda - platform: win-64 - dependencies: - python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_1.conda - hash: - md5: 3366592d3c219f2731721f11bc93755c - sha256: 80f579bfc71b3dab5bef74114b89e26c85cb0df8caf4c27ab5ffc16363d57ee7 - category: dev - optional: true - name: exceptiongroup version: 1.2.2 manager: conda @@ -1416,7 +1392,7 @@ package: category: main optional: false - name: fonttools - version: 4.55.4 + version: 4.55.6 manager: conda platform: linux-64 dependencies: @@ -1427,14 +1403,14 @@ package: python: '>=3.10,<3.11.0a0' python_abi: 3.10.* unicodedata2: '>=15.1.0' - url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.55.4-py310h89163eb_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.55.6-py310h89163eb_0.conda hash: - md5: 004db2be5878321241bd3edb56f124ca - sha256: 07c38660245a9cc20581748c54e7ecae28f406989678b38c1f392dc9219ad0b7 + md5: f9b33873bcc3368c0d29f68d4beeaf8e + sha256: 8324d35aa665eb95f276fbecc697ef2b7a06c0d0a66a8267f929dbb7599e3c91 category: main optional: false - name: fonttools - version: 4.55.4 + version: 4.55.6 manager: conda platform: win-64 dependencies: @@ -1446,10 +1422,10 @@ package: unicodedata2: '>=15.1.0' vc: '>=14.2,<15' vc14_runtime: '>=14.29.30139' - url: https://conda.anaconda.org/conda-forge/win-64/fonttools-4.55.4-py310h38315fa_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/fonttools-4.55.6-py310h38315fa_0.conda hash: - md5: 5540ab10feb766f94475b435c24f4810 - sha256: 585a585df129c64a466285a86b67ed265dc8b1c37db2c85130d74c44069c0765 + md5: c8655d1ca07490bbc237cfe3f49fa013 + sha256: bd1c4cb9ad132af8b36a4a6b5ea21466d0e08fefea263c293493a9835211af51 category: main optional: false - name: fqdn @@ -1731,27 +1707,27 @@ package: category: main optional: false - name: hpack - version: 4.0.0 + version: 4.1.0 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.0.0-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda hash: - md5: 2aa5ff7fa34a81b9196532c84c10d865 - sha256: ec89b7e5b8aa2f0219f666084446e1fb7b54545861e9caa892acb24d125761b5 + md5: 0a802cb9888dd14eeefc611f05c40b6e + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba category: main optional: false - name: hpack - version: 4.0.0 + version: 4.1.0 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.0.0-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda hash: - md5: 2aa5ff7fa34a81b9196532c84c10d865 - sha256: ec89b7e5b8aa2f0219f666084446e1fb7b54545861e9caa892acb24d125761b5 + md5: 0a802cb9888dd14eeefc611f05c40b6e + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba category: main optional: false - name: httpcore @@ -1821,27 +1797,27 @@ package: category: dev optional: true - name: hyperframe - version: 6.0.1 + version: 6.1.0 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.0.1-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda hash: - md5: 566e75c90c1d0c8c459eb0ad9833dc7a - sha256: e91c6ef09d076e1d9a02819cd00fa7ee18ecf30cdd667605c853980216584d1b + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 category: main optional: false - name: hyperframe - version: 6.0.1 + version: 6.1.0 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.0.1-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda hash: - md5: 566e75c90c1d0c8c459eb0ad9833dc7a - sha256: e91c6ef09d076e1d9a02819cd00fa7ee18ecf30cdd667605c853980216584d1b + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 category: main optional: false - name: idna @@ -2188,29 +2164,29 @@ package: category: dev optional: true - name: isort - version: 5.13.2 + version: 6.0.0 manager: conda platform: linux-64 dependencies: python: '>=3.9,<4.0' setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/isort-5.13.2-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/isort-6.0.0-pyhd8ed1ab_0.conda hash: - md5: ef7dc847f19fe4859d5aaa33385bf509 - sha256: 6ebf6e83c2d449760ad5c5cc344711d6404f9e3cf6952811b8678aca5a4ab01f + md5: 5e4f9eef5749c5ce6457321a3f8bd405 + sha256: 6cd5e7e86ec3d674311cbcdd5943a1c1508ff12b0e28006d919f69391f18dd15 category: dev optional: true - name: isort - version: 5.13.2 + version: 6.0.0 manager: conda platform: win-64 dependencies: python: '>=3.9,<4.0' setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/isort-5.13.2-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/isort-6.0.0-pyhd8ed1ab_0.conda hash: - md5: ef7dc847f19fe4859d5aaa33385bf509 - sha256: 6ebf6e83c2d449760ad5c5cc344711d6404f9e3cf6952811b8678aca5a4ab01f + md5: 5e4f9eef5749c5ce6457321a3f8bd405 + sha256: 6cd5e7e86ec3d674311cbcdd5943a1c1508ff12b0e28006d919f69391f18dd15 category: dev optional: true - name: jedi @@ -3644,21 +3620,21 @@ package: category: main optional: false - name: libpng - version: 1.6.45 + version: 1.6.46 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: '>=13' libzlib: '>=1.3.1,<2.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.45-h943b412_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.46-h943b412_0.conda hash: - md5: 85cbdaacad93808395ac295b5667d25b - sha256: b8f5b5ba9a14dedf7c97c01300de492b1b52b68eacbc3249a13fdbfa82349a2f + md5: adcf7bacff219488e29cfa95a2abd8f7 + sha256: a46436dadd12d58155280d68876dba2d8a3badbc8074956d14fe6530c7c7eda6 category: main optional: false - name: libpng - version: 1.6.45 + version: 1.6.46 manager: conda platform: win-64 dependencies: @@ -3666,10 +3642,10 @@ package: ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vc14_runtime: '>=14.29.30139' - url: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.45-had7236b_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.46-had7236b_0.conda hash: - md5: 41fb9e522ec6e0b34a6f23c98b07e1cf - sha256: e39c4f1bc8fee08f6a2eb4a88174d14c3a99dbb4850c98f3a87eb83b4dabbfca + md5: 4ddc2d65b35403e6ed75545f4cb4ec98 + sha256: c866cd79dce3f6478fa3b4bc625d5cbe0512720fd6f8d45718da9537292329cf category: main optional: false - name: libsodium @@ -4577,40 +4553,39 @@ package: category: dev optional: true - name: nbconvert - version: 7.16.5 + version: 7.16.6 manager: conda platform: linux-64 dependencies: - nbconvert-core: 7.16.5 - nbconvert-pandoc: 7.16.5 - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.5-hd8ed1ab_1.conda + nbconvert-core: ==7.16.6 + nbconvert-pandoc: ==7.16.6 + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hb482800_0.conda hash: - md5: 82ffc2974cd09b45182f018b5af731c8 - sha256: 02780c17ea89ff96c229b908201a656affa70c475ebf40a140b7551d016cba31 + md5: aa90ea40c80d4bd3da35cb17ed668f22 + sha256: 5480b7e05bf3079fcb7357a5a15a96c3a1649cc1371d0c468c806898a7e53088 category: dev optional: true - name: nbconvert - version: 7.16.5 + version: 7.16.6 manager: conda platform: win-64 dependencies: - nbconvert-core: 7.16.5 - nbconvert-pandoc: 7.16.5 - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.5-hd8ed1ab_1.conda + nbconvert-core: ==7.16.6 + nbconvert-pandoc: ==7.16.6 + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hb482800_0.conda hash: - md5: 82ffc2974cd09b45182f018b5af731c8 - sha256: 02780c17ea89ff96c229b908201a656affa70c475ebf40a140b7551d016cba31 + md5: aa90ea40c80d4bd3da35cb17ed668f22 + sha256: 5480b7e05bf3079fcb7357a5a15a96c3a1649cc1371d0c468c806898a7e53088 category: dev optional: true - name: nbconvert-core - version: 7.16.5 + version: 7.16.6 manager: conda platform: linux-64 dependencies: beautifulsoup4: '' bleach-with-css: '!=5.0.0' defusedxml: '' - entrypoints: '>=0.2.2' importlib-metadata: '>=3.6' jinja2: '>=3.0' jupyter_core: '>=4.7' @@ -4622,23 +4597,22 @@ package: packaging: '' pandocfilters: '>=1.4.1' pygments: '>=2.4.1' - python: '>=3.9' + python: '' traitlets: '>=5.1' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.5-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda hash: - md5: dd50a122c5b9782b1e9b2695473bfd95 - sha256: 9eed80365c012ab3bbb0f0ed1446af496d6810063dfa07dde33ae4a6d8a392ef + md5: d24beda1d30748afcc87c429454ece1b + sha256: dcccb07c5a1acb7dc8be94330e62d54754c0e9c9cb2bb6865c8e3cfe44cf5a58 category: dev optional: true - name: nbconvert-core - version: 7.16.5 + version: 7.16.6 manager: conda platform: win-64 dependencies: beautifulsoup4: '' bleach-with-css: '!=5.0.0' defusedxml: '' - entrypoints: '>=0.2.2' importlib-metadata: '>=3.6' jinja2: '>=3.0' jupyter_core: '>=4.7' @@ -4652,36 +4626,36 @@ package: pygments: '>=2.4.1' python: '>=3.9' traitlets: '>=5.1' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.5-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda hash: - md5: dd50a122c5b9782b1e9b2695473bfd95 - sha256: 9eed80365c012ab3bbb0f0ed1446af496d6810063dfa07dde33ae4a6d8a392ef + md5: d24beda1d30748afcc87c429454ece1b + sha256: dcccb07c5a1acb7dc8be94330e62d54754c0e9c9cb2bb6865c8e3cfe44cf5a58 category: dev optional: true - name: nbconvert-pandoc - version: 7.16.5 + version: 7.16.6 manager: conda platform: linux-64 dependencies: - nbconvert-core: 7.16.5 + nbconvert-core: ==7.16.6 pandoc: '' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.5-hd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-hed9df3c_0.conda hash: - md5: 593a8fd80968f14f8a7b3a685ddc455e - sha256: ddef467e066125a86bbb748d5cd6a54f7c0b7021461406d1bf7e48823f2eab9d + md5: 5b0afb6c52e74a7eca2cf809a874acf4 + sha256: 1e8923f1557c2ddb7bba915033cfaf8b8c1b7462c745172458102c11caee1002 category: dev optional: true - name: nbconvert-pandoc - version: 7.16.5 + version: 7.16.6 manager: conda platform: win-64 dependencies: - nbconvert-core: 7.16.5 + nbconvert-core: ==7.16.6 pandoc: '' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.5-hd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-hed9df3c_0.conda hash: - md5: 593a8fd80968f14f8a7b3a685ddc455e - sha256: ddef467e066125a86bbb748d5cd6a54f7c0b7021461406d1bf7e48823f2eab9d + md5: 5b0afb6c52e74a7eca2cf809a874acf4 + sha256: 1e8923f1557c2ddb7bba915033cfaf8b8c1b7462c745172458102c11caee1002 category: dev optional: true - name: nbformat @@ -5261,31 +5235,31 @@ package: category: main optional: false - name: pip - version: 24.3.1 + version: '25.0' manager: conda platform: linux-64 dependencies: python: '>=3.9,<3.13.0a0' setuptools: '' wheel: '' - url: https://conda.anaconda.org/conda-forge/noarch/pip-24.3.1-pyh8b19718_2.conda + url: https://conda.anaconda.org/conda-forge/noarch/pip-25.0-pyh8b19718_0.conda hash: - md5: 04e691b9fadd93a8a9fad87a81d4fd8f - sha256: da8c8888de10c1e4234ebcaa1550ac2b4b5408ac20f093fe641e4bc8c9c9f3eb + md5: c2548760a02ed818f92dd0d8c81b55b4 + sha256: 094fa4c825f8b9e8403e0c0b569c3d50892325acdac1010ff43cc3ac65bf62cd category: main optional: false - name: pip - version: 24.3.1 + version: '25.0' manager: conda platform: win-64 dependencies: python: '>=3.9,<3.13.0a0' setuptools: '' wheel: '' - url: https://conda.anaconda.org/conda-forge/noarch/pip-24.3.1-pyh8b19718_2.conda + url: https://conda.anaconda.org/conda-forge/noarch/pip-25.0-pyh8b19718_0.conda hash: - md5: 04e691b9fadd93a8a9fad87a81d4fd8f - sha256: da8c8888de10c1e4234ebcaa1550ac2b4b5408ac20f093fe641e4bc8c9c9f3eb + md5: c2548760a02ed818f92dd0d8c81b55b4 + sha256: 094fa4c825f8b9e8403e0c0b569c3d50892325acdac1010ff43cc3ac65bf62cd category: main optional: false - name: pkgutil-resolve-name @@ -5605,7 +5579,7 @@ package: category: main optional: false - name: pydantic - version: 2.10.5 + version: 2.10.6 manager: conda platform: linux-64 dependencies: @@ -5614,14 +5588,14 @@ package: python: '>=3.9' typing-extensions: '>=4.6.1' typing_extensions: '>=4.12.2' - url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.5-pyh3cfb1c2_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.6-pyh3cfb1c2_0.conda hash: - md5: e8ea30925c8271c4128375810d7d3d7a - sha256: 0f32c30ddc610cd1113335d8b4f311f20f4d72754b7c1a5d0d9493f597cf11d2 + md5: c69f87041cf24dfc8cb6bf64ca7133c7 + sha256: 9a78801a28959edeb945e8270a4e666577b52fac0cf4e35f88cf122f73d83e75 category: main optional: false - name: pydantic - version: 2.10.5 + version: 2.10.6 manager: conda platform: win-64 dependencies: @@ -5630,10 +5604,10 @@ package: python: '>=3.9' typing-extensions: '>=4.6.1' typing_extensions: '>=4.12.2' - url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.5-pyh3cfb1c2_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.6-pyh3cfb1c2_0.conda hash: - md5: e8ea30925c8271c4128375810d7d3d7a - sha256: 0f32c30ddc610cd1113335d8b4f311f20f4d72754b7c1a5d0d9493f597cf11d2 + md5: c69f87041cf24dfc8cb6bf64ca7133c7 + sha256: 9a78801a28959edeb945e8270a4e666577b52fac0cf4e35f88cf122f73d83e75 category: main optional: false - name: pydantic-core @@ -5771,45 +5745,45 @@ package: category: dev optional: true - name: pylint - version: 3.3.3 + version: 3.3.4 manager: conda platform: linux-64 dependencies: astroid: '>=3.3.8,<3.4.0-dev0' colorama: '>=0.4.5' dill: '>=0.3.7' - isort: '>=4.2.5,<6,!=5.13.0' + isort: '>=4.2.5,<7,!=5.13.0' mccabe: '>=0.6,<0.8' platformdirs: '>=2.2.0' - python: '>=3.9' + python: '' tomli: '>=1.1.0' tomlkit: '>=0.10.1' typing_extensions: '>=3.10.0' - url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.3-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.4-pyh29332c3_0.conda hash: - md5: 5842a1fa3b9b4f9fe7069b9ca5ed068d - sha256: a8192c823bfb6cdc57d2e12a8748ac1acb588c960c53e71c763f6359c5602e46 + md5: 3a865c9f5461a1f7b52ed535b03e9285 + sha256: 05016f7826e099b30d6dc7a028169cbc39aa1594da99991311f51516de419310 category: dev optional: true - name: pylint - version: 3.3.3 + version: 3.3.4 manager: conda platform: win-64 dependencies: astroid: '>=3.3.8,<3.4.0-dev0' colorama: '>=0.4.5' dill: '>=0.3.7' - isort: '>=4.2.5,<6,!=5.13.0' + isort: '>=4.2.5,<7,!=5.13.0' mccabe: '>=0.6,<0.8' platformdirs: '>=2.2.0' python: '>=3.9' tomli: '>=1.1.0' tomlkit: '>=0.10.1' typing_extensions: '>=3.10.0' - url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.3-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.4-pyh29332c3_0.conda hash: - md5: 5842a1fa3b9b4f9fe7069b9ca5ed068d - sha256: a8192c823bfb6cdc57d2e12a8748ac1acb588c960c53e71c763f6359c5602e46 + md5: 3a865c9f5461a1f7b52ed535b03e9285 + sha256: 05016f7826e099b30d6dc7a028169cbc39aa1594da99991311f51516de419310 category: dev optional: true - name: pymatsolver @@ -6324,22 +6298,22 @@ package: category: dev optional: true - name: referencing - version: 0.36.1 + version: 0.36.2 manager: conda platform: linux-64 dependencies: attrs: '>=22.2.0' - python: '>=3.9' + python: '' rpds-py: '>=0.7.0' typing_extensions: '>=4.4.0' - url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda hash: - md5: dbb48421efd666ea133c6d5e67291766 - sha256: 55a8c68d75bc70624be9dbd5550d2de0fae295363fb836860a4a5d244a5b088a + md5: 9140f1c09dd5489549c6a33931b943c7 + sha256: e20909f474a6cece176dfc0dc1addac265deb5fa92ea90e975fbca48085b20c3 category: dev optional: true - name: referencing - version: 0.36.1 + version: 0.36.2 manager: conda platform: win-64 dependencies: @@ -6347,10 +6321,10 @@ package: python: '>=3.9' rpds-py: '>=0.7.0' typing_extensions: '>=4.4.0' - url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda hash: - md5: dbb48421efd666ea133c6d5e67291766 - sha256: 55a8c68d75bc70624be9dbd5550d2de0fae295363fb836860a4a5d244a5b088a + md5: 9140f1c09dd5489549c6a33931b943c7 + sha256: e20909f474a6cece176dfc0dc1addac265deb5fa92ea90e975fbca48085b20c3 category: dev optional: true - name: requests @@ -7885,11 +7859,11 @@ package: manager: conda platform: win-64 dependencies: - vc14_runtime: '>=14.38.33135' - url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_23.conda + vc14_runtime: '>=14.40.33810' + url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h5fd82a7_24.conda hash: - md5: 7c10ec3158d1eb4ddff7007c9101adb0 - sha256: 986ddaf8feec2904eac9535a7ddb7acda1a1dfb9482088fdb8129f1595181663 + md5: 00cf3a61562bd53bd5ea99e6888793d0 + sha256: 7ce178cf139ccea5079f9c353b3d8415d1d49b0a2f774662c355d3f89163d7b4 category: main optional: false - name: vc14_runtime @@ -7898,10 +7872,10 @@ package: platform: win-64 dependencies: ucrt: '>=10.0.20348.0' - url: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.42.34433-he29a5d6_23.conda + url: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.42.34433-h6356254_24.conda hash: - md5: 32b37d0cfa80da34548501cdc913a832 - sha256: c483b090c4251a260aba6ff3e83a307bcfb5fb24ad7ced872ab5d02971bd3a49 + md5: 2441e010ee255e6a38bf16705a756e94 + sha256: abda97b8728cf6e3c37df8f1178adde7219bed38b96e392cb3be66336386d32e category: main optional: false - name: vs2015_runtime @@ -7910,10 +7884,10 @@ package: platform: win-64 dependencies: vc14_runtime: '>=14.42.34433' - url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.42.34433-hdffcdeb_23.conda + url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.42.34433-hfef2bbc_24.conda hash: - md5: 5c176975ca2b8366abad3c97b3cd1e83 - sha256: 568ce8151eaae256f1cef752fc78651ad7a86ff05153cc7a4740b52ae6536118 + md5: 117fcc5b86c48f3b322b0722258c7259 + sha256: 09102e0bd283af65772c052d85028410b0c31989b3cd96c260485d28e270836e category: main optional: false - name: wcwidth @@ -8347,12 +8321,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 hash: - sha256: 007da1d142502378a4da9b7760c6b178986368a3 + sha256: 3acc55f9f9a849f6f1537977471913e9f6331125 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 category: main optional: false - name: geoapps-utils @@ -8364,12 +8338,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 hash: - sha256: 007da1d142502378a4da9b7760c6b178986368a3 + sha256: 3acc55f9f9a849f6f1537977471913e9f6331125 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 category: main optional: false - name: geoh5py @@ -8462,12 +8436,12 @@ package: geoh5py: 0.11.0-alpha.1 numpy: '>=1.26.0,<1.27.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 hash: - sha256: f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + sha256: 8a2af2a57144c32419db9335ba623518930b9621 source: type: url - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 category: main optional: false - name: octree-creation-app @@ -8480,12 +8454,12 @@ package: geoh5py: 0.11.0-alpha.1 numpy: '>=1.26.0,<1.27.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 hash: - sha256: f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + sha256: 8a2af2a57144c32419db9335ba623518930b9621 source: type: url - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 category: main optional: false - name: param-sweeps diff --git a/py-3.11.conda-lock.yml b/py-3.11.conda-lock.yml index 3e7d6eef..d0b8c44e 100644 --- a/py-3.11.conda-lock.yml +++ b/py-3.11.conda-lock.yml @@ -351,27 +351,27 @@ package: category: dev optional: true - name: attrs - version: 24.3.0 + version: 25.1.0 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/attrs-24.3.0-pyh71513ae_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/attrs-25.1.0-pyh71513ae_0.conda hash: - md5: 356927ace43302bf6f5926e2a58dae6a - sha256: 750186af694a7130eaf7119fbb56db0d2326d8995ad5b8eae23c622b85fea29a + md5: 2cc3f588512f04f3a0c64b4e9bedc02d + sha256: 1f267886522dfb9ae4e5ebbc3135b5eb13cff27bdbfe8d881a4d893459166ab4 category: dev optional: true - name: attrs - version: 24.3.0 + version: 25.1.0 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/attrs-24.3.0-pyh71513ae_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/attrs-25.1.0-pyh71513ae_0.conda hash: - md5: 356927ace43302bf6f5926e2a58dae6a - sha256: 750186af694a7130eaf7119fbb56db0d2326d8995ad5b8eae23c622b85fea29a + md5: 2cc3f588512f04f3a0c64b4e9bedc02d + sha256: 1f267886522dfb9ae4e5ebbc3135b5eb13cff27bdbfe8d881a4d893459166ab4 category: dev optional: true - name: babel @@ -1149,29 +1149,29 @@ package: category: dev optional: true - name: deprecated - version: 1.2.15 + version: 1.2.18 manager: conda platform: linux-64 dependencies: python: '>=3.9' wrapt: <2,>=1.10 - url: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.15-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.18-pyhd8ed1ab_0.conda hash: - md5: eaef2e94d5bd76f758545d172c1fda67 - sha256: a20ebf2c9b02a6eb32412ceb5c4cffaae49417db7e75414a76417538293a9402 + md5: 0cef44b1754ae4d6924ac0eef6b9fdbe + sha256: d614bcff10696f1efc714df07651b50bf3808401fcc03814309ecec242cc8870 category: main optional: false - name: deprecated - version: 1.2.15 + version: 1.2.18 manager: conda platform: win-64 dependencies: python: '>=3.9' wrapt: <2,>=1.10 - url: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.15-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.2.18-pyhd8ed1ab_0.conda hash: - md5: eaef2e94d5bd76f758545d172c1fda67 - sha256: a20ebf2c9b02a6eb32412ceb5c4cffaae49417db7e75414a76417538293a9402 + md5: 0cef44b1754ae4d6924ac0eef6b9fdbe + sha256: d614bcff10696f1efc714df07651b50bf3808401fcc03814309ecec242cc8870 category: main optional: false - name: dill @@ -1343,30 +1343,6 @@ package: sha256: c489c425cb75c30288516c140f47d109b4643ab31f17c3f230be38aae7d464f5 category: main optional: false -- name: entrypoints - version: '0.4' - manager: conda - platform: linux-64 - dependencies: - python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_1.conda - hash: - md5: 3366592d3c219f2731721f11bc93755c - sha256: 80f579bfc71b3dab5bef74114b89e26c85cb0df8caf4c27ab5ffc16363d57ee7 - category: dev - optional: true -- name: entrypoints - version: '0.4' - manager: conda - platform: win-64 - dependencies: - python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_1.conda - hash: - md5: 3366592d3c219f2731721f11bc93755c - sha256: 80f579bfc71b3dab5bef74114b89e26c85cb0df8caf4c27ab5ffc16363d57ee7 - category: dev - optional: true - name: exceptiongroup version: 1.2.2 manager: conda @@ -1440,7 +1416,7 @@ package: category: main optional: false - name: fonttools - version: 4.55.4 + version: 4.55.6 manager: conda platform: linux-64 dependencies: @@ -1451,14 +1427,14 @@ package: python: '>=3.11,<3.12.0a0' python_abi: 3.11.* unicodedata2: '>=15.1.0' - url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.55.4-py311h2dc5d0c_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.55.6-py311h2dc5d0c_0.conda hash: - md5: dd17b30618f481b074a80a3f3dd4cbcf - sha256: 50cb39e168e5c0514f7c030e9358f04f83209cc2b3e6fae7359007a418d5d8fa + md5: 0f78e44a302c6df16338d5bbcd98de51 + sha256: eb894bdeec6cf249ca003d21575355f79374b04fadab0baf9dfe57b4cc8453b7 category: main optional: false - name: fonttools - version: 4.55.4 + version: 4.55.6 manager: conda platform: win-64 dependencies: @@ -1470,10 +1446,10 @@ package: unicodedata2: '>=15.1.0' vc: '>=14.2,<15' vc14_runtime: '>=14.29.30139' - url: https://conda.anaconda.org/conda-forge/win-64/fonttools-4.55.4-py311h5082efb_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/fonttools-4.55.6-py311h5082efb_0.conda hash: - md5: eb2b603cee631d9b22eb3b68dfba7968 - sha256: 2f3666a6be842814ee5feb690e27b6cc7161de36a98f3e21512a833d5c7a613e + md5: 6ed90b3d7a69451724f0dca418bb90b0 + sha256: e45b356e42b11c00aa245ebffc27e01e4c913460d9981e8867405483f6341d9e category: main optional: false - name: fqdn @@ -1755,27 +1731,27 @@ package: category: main optional: false - name: hpack - version: 4.0.0 + version: 4.1.0 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.0.0-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda hash: - md5: 2aa5ff7fa34a81b9196532c84c10d865 - sha256: ec89b7e5b8aa2f0219f666084446e1fb7b54545861e9caa892acb24d125761b5 + md5: 0a802cb9888dd14eeefc611f05c40b6e + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba category: main optional: false - name: hpack - version: 4.0.0 + version: 4.1.0 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.0.0-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda hash: - md5: 2aa5ff7fa34a81b9196532c84c10d865 - sha256: ec89b7e5b8aa2f0219f666084446e1fb7b54545861e9caa892acb24d125761b5 + md5: 0a802cb9888dd14eeefc611f05c40b6e + sha256: 6ad78a180576c706aabeb5b4c8ceb97c0cb25f1e112d76495bff23e3779948ba category: main optional: false - name: httpcore @@ -1845,27 +1821,27 @@ package: category: dev optional: true - name: hyperframe - version: 6.0.1 + version: 6.1.0 manager: conda platform: linux-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.0.1-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda hash: - md5: 566e75c90c1d0c8c459eb0ad9833dc7a - sha256: e91c6ef09d076e1d9a02819cd00fa7ee18ecf30cdd667605c853980216584d1b + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 category: main optional: false - name: hyperframe - version: 6.0.1 + version: 6.1.0 manager: conda platform: win-64 dependencies: python: '>=3.9' - url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.0.1-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/hyperframe-6.1.0-pyhd8ed1ab_0.conda hash: - md5: 566e75c90c1d0c8c459eb0ad9833dc7a - sha256: e91c6ef09d076e1d9a02819cd00fa7ee18ecf30cdd667605c853980216584d1b + md5: 8e6923fc12f1fe8f8c4e5c9f343256ac + sha256: 77af6f5fe8b62ca07d09ac60127a30d9069fdc3c68d6b256754d0ffb1f7779f8 category: main optional: false - name: idna @@ -2212,29 +2188,29 @@ package: category: dev optional: true - name: isort - version: 5.13.2 + version: 6.0.0 manager: conda platform: linux-64 dependencies: python: '>=3.9,<4.0' setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/isort-5.13.2-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/isort-6.0.0-pyhd8ed1ab_0.conda hash: - md5: ef7dc847f19fe4859d5aaa33385bf509 - sha256: 6ebf6e83c2d449760ad5c5cc344711d6404f9e3cf6952811b8678aca5a4ab01f + md5: 5e4f9eef5749c5ce6457321a3f8bd405 + sha256: 6cd5e7e86ec3d674311cbcdd5943a1c1508ff12b0e28006d919f69391f18dd15 category: dev optional: true - name: isort - version: 5.13.2 + version: 6.0.0 manager: conda platform: win-64 dependencies: python: '>=3.9,<4.0' setuptools: '' - url: https://conda.anaconda.org/conda-forge/noarch/isort-5.13.2-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/isort-6.0.0-pyhd8ed1ab_0.conda hash: - md5: ef7dc847f19fe4859d5aaa33385bf509 - sha256: 6ebf6e83c2d449760ad5c5cc344711d6404f9e3cf6952811b8678aca5a4ab01f + md5: 5e4f9eef5749c5ce6457321a3f8bd405 + sha256: 6cd5e7e86ec3d674311cbcdd5943a1c1508ff12b0e28006d919f69391f18dd15 category: dev optional: true - name: jedi @@ -3695,21 +3671,21 @@ package: category: main optional: false - name: libpng - version: 1.6.45 + version: 1.6.46 manager: conda platform: linux-64 dependencies: __glibc: '>=2.17,<3.0.a0' libgcc: '>=13' libzlib: '>=1.3.1,<2.0a0' - url: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.45-h943b412_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.46-h943b412_0.conda hash: - md5: 85cbdaacad93808395ac295b5667d25b - sha256: b8f5b5ba9a14dedf7c97c01300de492b1b52b68eacbc3249a13fdbfa82349a2f + md5: adcf7bacff219488e29cfa95a2abd8f7 + sha256: a46436dadd12d58155280d68876dba2d8a3badbc8074956d14fe6530c7c7eda6 category: main optional: false - name: libpng - version: 1.6.45 + version: 1.6.46 manager: conda platform: win-64 dependencies: @@ -3717,10 +3693,10 @@ package: ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vc14_runtime: '>=14.29.30139' - url: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.45-had7236b_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.46-had7236b_0.conda hash: - md5: 41fb9e522ec6e0b34a6f23c98b07e1cf - sha256: e39c4f1bc8fee08f6a2eb4a88174d14c3a99dbb4850c98f3a87eb83b4dabbfca + md5: 4ddc2d65b35403e6ed75545f4cb4ec98 + sha256: c866cd79dce3f6478fa3b4bc625d5cbe0512720fd6f8d45718da9537292329cf category: main optional: false - name: libsodium @@ -4628,40 +4604,39 @@ package: category: dev optional: true - name: nbconvert - version: 7.16.5 + version: 7.16.6 manager: conda platform: linux-64 dependencies: - nbconvert-core: 7.16.5 - nbconvert-pandoc: 7.16.5 - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.5-hd8ed1ab_1.conda + nbconvert-core: ==7.16.6 + nbconvert-pandoc: ==7.16.6 + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hb482800_0.conda hash: - md5: 82ffc2974cd09b45182f018b5af731c8 - sha256: 02780c17ea89ff96c229b908201a656affa70c475ebf40a140b7551d016cba31 + md5: aa90ea40c80d4bd3da35cb17ed668f22 + sha256: 5480b7e05bf3079fcb7357a5a15a96c3a1649cc1371d0c468c806898a7e53088 category: dev optional: true - name: nbconvert - version: 7.16.5 + version: 7.16.6 manager: conda platform: win-64 dependencies: - nbconvert-core: 7.16.5 - nbconvert-pandoc: 7.16.5 - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.5-hd8ed1ab_1.conda + nbconvert-core: ==7.16.6 + nbconvert-pandoc: ==7.16.6 + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-7.16.6-hb482800_0.conda hash: - md5: 82ffc2974cd09b45182f018b5af731c8 - sha256: 02780c17ea89ff96c229b908201a656affa70c475ebf40a140b7551d016cba31 + md5: aa90ea40c80d4bd3da35cb17ed668f22 + sha256: 5480b7e05bf3079fcb7357a5a15a96c3a1649cc1371d0c468c806898a7e53088 category: dev optional: true - name: nbconvert-core - version: 7.16.5 + version: 7.16.6 manager: conda platform: linux-64 dependencies: beautifulsoup4: '' bleach-with-css: '!=5.0.0' defusedxml: '' - entrypoints: '>=0.2.2' importlib-metadata: '>=3.6' jinja2: '>=3.0' jupyter_core: '>=4.7' @@ -4675,21 +4650,20 @@ package: pygments: '>=2.4.1' python: '>=3.9' traitlets: '>=5.1' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.5-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda hash: - md5: dd50a122c5b9782b1e9b2695473bfd95 - sha256: 9eed80365c012ab3bbb0f0ed1446af496d6810063dfa07dde33ae4a6d8a392ef + md5: d24beda1d30748afcc87c429454ece1b + sha256: dcccb07c5a1acb7dc8be94330e62d54754c0e9c9cb2bb6865c8e3cfe44cf5a58 category: dev optional: true - name: nbconvert-core - version: 7.16.5 + version: 7.16.6 manager: conda platform: win-64 dependencies: beautifulsoup4: '' bleach-with-css: '!=5.0.0' defusedxml: '' - entrypoints: '>=0.2.2' importlib-metadata: '>=3.6' jinja2: '>=3.0' jupyter_core: '>=4.7' @@ -4703,36 +4677,36 @@ package: pygments: '>=2.4.1' python: '>=3.9' traitlets: '>=5.1' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.5-pyhd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.16.6-pyh29332c3_0.conda hash: - md5: dd50a122c5b9782b1e9b2695473bfd95 - sha256: 9eed80365c012ab3bbb0f0ed1446af496d6810063dfa07dde33ae4a6d8a392ef + md5: d24beda1d30748afcc87c429454ece1b + sha256: dcccb07c5a1acb7dc8be94330e62d54754c0e9c9cb2bb6865c8e3cfe44cf5a58 category: dev optional: true - name: nbconvert-pandoc - version: 7.16.5 + version: 7.16.6 manager: conda platform: linux-64 dependencies: - nbconvert-core: 7.16.5 + nbconvert-core: ==7.16.6 pandoc: '' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.5-hd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-hed9df3c_0.conda hash: - md5: 593a8fd80968f14f8a7b3a685ddc455e - sha256: ddef467e066125a86bbb748d5cd6a54f7c0b7021461406d1bf7e48823f2eab9d + md5: 5b0afb6c52e74a7eca2cf809a874acf4 + sha256: 1e8923f1557c2ddb7bba915033cfaf8b8c1b7462c745172458102c11caee1002 category: dev optional: true - name: nbconvert-pandoc - version: 7.16.5 + version: 7.16.6 manager: conda platform: win-64 dependencies: - nbconvert-core: 7.16.5 + nbconvert-core: ==7.16.6 pandoc: '' - url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.5-hd8ed1ab_1.conda + url: https://conda.anaconda.org/conda-forge/noarch/nbconvert-pandoc-7.16.6-hed9df3c_0.conda hash: - md5: 593a8fd80968f14f8a7b3a685ddc455e - sha256: ddef467e066125a86bbb748d5cd6a54f7c0b7021461406d1bf7e48823f2eab9d + md5: 5b0afb6c52e74a7eca2cf809a874acf4 + sha256: 1e8923f1557c2ddb7bba915033cfaf8b8c1b7462c745172458102c11caee1002 category: dev optional: true - name: nbformat @@ -5314,31 +5288,31 @@ package: category: main optional: false - name: pip - version: 24.3.1 + version: '25.0' manager: conda platform: linux-64 dependencies: python: '>=3.9,<3.13.0a0' setuptools: '' wheel: '' - url: https://conda.anaconda.org/conda-forge/noarch/pip-24.3.1-pyh8b19718_2.conda + url: https://conda.anaconda.org/conda-forge/noarch/pip-25.0-pyh8b19718_0.conda hash: - md5: 04e691b9fadd93a8a9fad87a81d4fd8f - sha256: da8c8888de10c1e4234ebcaa1550ac2b4b5408ac20f093fe641e4bc8c9c9f3eb + md5: c2548760a02ed818f92dd0d8c81b55b4 + sha256: 094fa4c825f8b9e8403e0c0b569c3d50892325acdac1010ff43cc3ac65bf62cd category: main optional: false - name: pip - version: 24.3.1 + version: '25.0' manager: conda platform: win-64 dependencies: python: '>=3.9,<3.13.0a0' setuptools: '' wheel: '' - url: https://conda.anaconda.org/conda-forge/noarch/pip-24.3.1-pyh8b19718_2.conda + url: https://conda.anaconda.org/conda-forge/noarch/pip-25.0-pyh8b19718_0.conda hash: - md5: 04e691b9fadd93a8a9fad87a81d4fd8f - sha256: da8c8888de10c1e4234ebcaa1550ac2b4b5408ac20f093fe641e4bc8c9c9f3eb + md5: c2548760a02ed818f92dd0d8c81b55b4 + sha256: 094fa4c825f8b9e8403e0c0b569c3d50892325acdac1010ff43cc3ac65bf62cd category: main optional: false - name: pkgutil-resolve-name @@ -5658,7 +5632,7 @@ package: category: main optional: false - name: pydantic - version: 2.10.5 + version: 2.10.6 manager: conda platform: linux-64 dependencies: @@ -5667,14 +5641,14 @@ package: python: '>=3.9' typing-extensions: '>=4.6.1' typing_extensions: '>=4.12.2' - url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.5-pyh3cfb1c2_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.6-pyh3cfb1c2_0.conda hash: - md5: e8ea30925c8271c4128375810d7d3d7a - sha256: 0f32c30ddc610cd1113335d8b4f311f20f4d72754b7c1a5d0d9493f597cf11d2 + md5: c69f87041cf24dfc8cb6bf64ca7133c7 + sha256: 9a78801a28959edeb945e8270a4e666577b52fac0cf4e35f88cf122f73d83e75 category: main optional: false - name: pydantic - version: 2.10.5 + version: 2.10.6 manager: conda platform: win-64 dependencies: @@ -5683,10 +5657,10 @@ package: python: '>=3.9' typing-extensions: '>=4.6.1' typing_extensions: '>=4.12.2' - url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.5-pyh3cfb1c2_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pydantic-2.10.6-pyh3cfb1c2_0.conda hash: - md5: e8ea30925c8271c4128375810d7d3d7a - sha256: 0f32c30ddc610cd1113335d8b4f311f20f4d72754b7c1a5d0d9493f597cf11d2 + md5: c69f87041cf24dfc8cb6bf64ca7133c7 + sha256: 9a78801a28959edeb945e8270a4e666577b52fac0cf4e35f88cf122f73d83e75 category: main optional: false - name: pydantic-core @@ -5824,45 +5798,45 @@ package: category: dev optional: true - name: pylint - version: 3.3.3 + version: 3.3.4 manager: conda platform: linux-64 dependencies: astroid: '>=3.3.8,<3.4.0-dev0' colorama: '>=0.4.5' dill: '>=0.3.7' - isort: '>=4.2.5,<6,!=5.13.0' + isort: '>=4.2.5,<7,!=5.13.0' mccabe: '>=0.6,<0.8' platformdirs: '>=2.2.0' python: '>=3.9' tomli: '>=1.1.0' tomlkit: '>=0.10.1' typing_extensions: '>=3.10.0' - url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.3-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.4-pyh29332c3_0.conda hash: - md5: 5842a1fa3b9b4f9fe7069b9ca5ed068d - sha256: a8192c823bfb6cdc57d2e12a8748ac1acb588c960c53e71c763f6359c5602e46 + md5: 3a865c9f5461a1f7b52ed535b03e9285 + sha256: 05016f7826e099b30d6dc7a028169cbc39aa1594da99991311f51516de419310 category: dev optional: true - name: pylint - version: 3.3.3 + version: 3.3.4 manager: conda platform: win-64 dependencies: astroid: '>=3.3.8,<3.4.0-dev0' colorama: '>=0.4.5' dill: '>=0.3.7' - isort: '>=4.2.5,<6,!=5.13.0' + isort: '>=4.2.5,<7,!=5.13.0' mccabe: '>=0.6,<0.8' platformdirs: '>=2.2.0' python: '>=3.9' tomli: '>=1.1.0' tomlkit: '>=0.10.1' typing_extensions: '>=3.10.0' - url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.3-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/pylint-3.3.4-pyh29332c3_0.conda hash: - md5: 5842a1fa3b9b4f9fe7069b9ca5ed068d - sha256: a8192c823bfb6cdc57d2e12a8748ac1acb588c960c53e71c763f6359c5602e46 + md5: 3a865c9f5461a1f7b52ed535b03e9285 + sha256: 05016f7826e099b30d6dc7a028169cbc39aa1594da99991311f51516de419310 category: dev optional: true - name: pymatsolver @@ -6379,7 +6353,7 @@ package: category: dev optional: true - name: referencing - version: 0.36.1 + version: 0.36.2 manager: conda platform: linux-64 dependencies: @@ -6387,14 +6361,14 @@ package: python: '>=3.9' rpds-py: '>=0.7.0' typing_extensions: '>=4.4.0' - url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda hash: - md5: dbb48421efd666ea133c6d5e67291766 - sha256: 55a8c68d75bc70624be9dbd5550d2de0fae295363fb836860a4a5d244a5b088a + md5: 9140f1c09dd5489549c6a33931b943c7 + sha256: e20909f474a6cece176dfc0dc1addac265deb5fa92ea90e975fbca48085b20c3 category: dev optional: true - name: referencing - version: 0.36.1 + version: 0.36.2 manager: conda platform: win-64 dependencies: @@ -6402,10 +6376,10 @@ package: python: '>=3.9' rpds-py: '>=0.7.0' typing_extensions: '>=4.4.0' - url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.1-pyhd8ed1ab_0.conda + url: https://conda.anaconda.org/conda-forge/noarch/referencing-0.36.2-pyh29332c3_0.conda hash: - md5: dbb48421efd666ea133c6d5e67291766 - sha256: 55a8c68d75bc70624be9dbd5550d2de0fae295363fb836860a4a5d244a5b088a + md5: 9140f1c09dd5489549c6a33931b943c7 + sha256: e20909f474a6cece176dfc0dc1addac265deb5fa92ea90e975fbca48085b20c3 category: dev optional: true - name: requests @@ -7940,11 +7914,11 @@ package: manager: conda platform: win-64 dependencies: - vc14_runtime: '>=14.38.33135' - url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-ha32ba9b_23.conda + vc14_runtime: '>=14.40.33810' + url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h5fd82a7_24.conda hash: - md5: 7c10ec3158d1eb4ddff7007c9101adb0 - sha256: 986ddaf8feec2904eac9535a7ddb7acda1a1dfb9482088fdb8129f1595181663 + md5: 00cf3a61562bd53bd5ea99e6888793d0 + sha256: 7ce178cf139ccea5079f9c353b3d8415d1d49b0a2f774662c355d3f89163d7b4 category: main optional: false - name: vc14_runtime @@ -7953,10 +7927,10 @@ package: platform: win-64 dependencies: ucrt: '>=10.0.20348.0' - url: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.42.34433-he29a5d6_23.conda + url: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.42.34433-h6356254_24.conda hash: - md5: 32b37d0cfa80da34548501cdc913a832 - sha256: c483b090c4251a260aba6ff3e83a307bcfb5fb24ad7ced872ab5d02971bd3a49 + md5: 2441e010ee255e6a38bf16705a756e94 + sha256: abda97b8728cf6e3c37df8f1178adde7219bed38b96e392cb3be66336386d32e category: main optional: false - name: vs2015_runtime @@ -7965,10 +7939,10 @@ package: platform: win-64 dependencies: vc14_runtime: '>=14.42.34433' - url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.42.34433-hdffcdeb_23.conda + url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.42.34433-hfef2bbc_24.conda hash: - md5: 5c176975ca2b8366abad3c97b3cd1e83 - sha256: 568ce8151eaae256f1cef752fc78651ad7a86ff05153cc7a4740b52ae6536118 + md5: 117fcc5b86c48f3b322b0722258c7259 + sha256: 09102e0bd283af65772c052d85028410b0c31989b3cd96c260485d28e270836e category: main optional: false - name: wcwidth @@ -8433,12 +8407,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 hash: - sha256: 007da1d142502378a4da9b7760c6b178986368a3 + sha256: 3acc55f9f9a849f6f1537977471913e9f6331125 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 category: main optional: false - name: geoapps-utils @@ -8450,12 +8424,12 @@ package: numpy: '>=1.26.0,<1.27.0' pydantic: '>=2.5.2,<3.0.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 hash: - sha256: 007da1d142502378a4da9b7760c6b178986368a3 + sha256: 3acc55f9f9a849f6f1537977471913e9f6331125 source: type: url - url: git+https://github.com/MiraGeoscience/geoapps-utils.git@007da1d142502378a4da9b7760c6b178986368a3 + url: git+https://github.com/MiraGeoscience/geoapps-utils.git@3acc55f9f9a849f6f1537977471913e9f6331125 category: main optional: false - name: geoh5py @@ -8548,12 +8522,12 @@ package: geoh5py: 0.11.0-alpha.1 numpy: '>=1.26.0,<1.27.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 hash: - sha256: f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + sha256: 8a2af2a57144c32419db9335ba623518930b9621 source: type: url - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 category: main optional: false - name: octree-creation-app @@ -8566,12 +8540,12 @@ package: geoh5py: 0.11.0-alpha.1 numpy: '>=1.26.0,<1.27.0' scipy: '>=1.14.0,<1.15.0' - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 hash: - sha256: f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + sha256: 8a2af2a57144c32419db9335ba623518930b9621 source: type: url - url: git+https://github.com/MiraGeoscience/octree-creation-app.git@f5fe8fd5af50ee1f4252f3ce5eb57adc980a0aa8 + url: git+https://github.com/MiraGeoscience/octree-creation-app.git@8a2af2a57144c32419db9335ba623518930b9621 category: main optional: false - name: param-sweeps From 11ab951cd9aa61d3ffe9f1222372e7b804be9dd1 Mon Sep 17 00:00:00 2001 From: benjamink Date: Tue, 28 Jan 2025 11:10:43 -0800 Subject: [PATCH 14/21] mypy fixes --- simpeg_drivers/params.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 849dce8f..34a35206 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -134,6 +134,7 @@ def out_group_if_none(cls, data) -> SimPEGGroup: @model_validator(mode="after") def update_out_group_options(self): + assert self.out_group is not None self.out_group.options = self.serialize() return self @@ -162,17 +163,19 @@ def data(self, component: str) -> np.ndarray | None: def uncertainty(self, component: str) -> np.ndarray | None: """Returns uncertainty for chosen data component if it exists.""" + uncertainty_entity = self.uncertainty_channel(component) if isinstance(uncertainty_entity, NumericData): return uncertainty_entity.values.astype(float) - elif self.data(component) is not None: - d = self.data(component) + + data = self.data(component) + if data is not None: if isinstance(uncertainty_entity, int | float): - return np.array([float(uncertainty_entity)] * len(d)) + return np.array([float(uncertainty_entity)] * len(data)) else: - return d * 0.0 + 1.0 # Default - else: - return None + return data * 0.0 + 1.0 # type: ignore + + return None @property def padding_cells(self) -> int: @@ -360,26 +363,19 @@ def data(self, component: str) -> np.ndarray | None: def uncertainty(self, component: str) -> np.ndarray | None: """Returns uncertainty for chosen data component if it exists.""" + uncertainty_entity = self.uncertainty_channel(component) if isinstance(uncertainty_entity, NumericData): return uncertainty_entity.values.astype(float) - elif self.data(component) is not None: - d = self.data(component) + + data = self.data(component) + if data is not None: if isinstance(uncertainty_entity, int | float): - return np.array([float(uncertainty_entity)] * len(d)) + return np.array([float(uncertainty_entity)] * len(data)) else: - return d * 0.0 + 1.0 # Default - else: - return None + return data * 0.0 + 1.0 # Default - def model_norms(self) -> list[float]: - """Returns model norm components as a list.""" - return [ - self.s_norm, - self.x_norm, - self.y_norm, - self.z_norm, - ] + return None class InversionBaseParams(BaseParams): From cd66c4c5dbe9bb0338e9c2917249f0bb38113e95 Mon Sep 17 00:00:00 2001 From: benjamink Date: Tue, 28 Jan 2025 11:46:19 -0800 Subject: [PATCH 15/21] cleanup --- .../potential_fields/gravity/params.py | 296 ------------------ 1 file changed, 296 deletions(-) diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index 31d032b9..8ba3fe3a 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -100,299 +100,3 @@ class GravityInversionParams(BaseInversionData): gyy_uncertainty: FloatData | float | None = None gyz_uncertainty: FloatData | float | None = None gzz_uncertainty: FloatData | float | None = None - - -# class GravityParams(InversionBaseParams): -# """ -# Parameter class for gravity->density inversion. -# """ -# -# _physical_property = "density" -# -# def __init__(self, input_file=None, forward_only=False, **kwargs): -# self._default_ui_json = deepcopy(default_ui_json) -# self._forward_defaults = deepcopy(forward_defaults) -# self._inversion_defaults = deepcopy(inversion_defaults) -# self._inversion_type = "gravity" -# self._validations = validations -# self._gz_channel_bool = None -# self._gz_channel = None -# self._gz_uncertainty = None -# self._guv_channel_bool = None -# self._guv_channel = None -# self._guv_uncertainty = None -# self._gxy_channel_bool = None -# self._gxy_channel = None -# self._gxy_uncertainty = None -# self._gxx_channel_bool = None -# self._gxx_channel = None -# self._gxx_uncertainty = None -# self._gyy_channel_bool = None -# self._gyy_channel = None -# self._gyy_uncertainty = None -# self._gzz_channel_bool = None -# self._gzz_channel = None -# self._gzz_uncertainty = None -# self._gxz_channel_bool = None -# self._gxz_channel = None -# self._gxz_uncertainty = None -# self._gyz_channel_bool = None -# self._gyz_channel = None -# self._gyz_uncertainty = None -# self._gx_channel_bool = None -# self._gx_channel = None -# self._gx_uncertainty = None -# self._gy_channel_bool = None -# self._gy_channel = None -# self._gy_uncertainty = None -# self._out_group = None -# -# super().__init__(input_file=input_file, forward_only=forward_only, **kwargs) -# -# def components(self) -> list[str]: -# """Retrieve component names used to index channel and uncertainty data.""" -# comps = super().components() -# if self.forward_only: -# if len(comps) == 0: -# comps = ["gz"] -# return comps -# -# @property -# def gz_channel_bool(self): -# return self._gz_channel_bool -# -# @gz_channel_bool.setter -# def gz_channel_bool(self, val): -# self.setter_validator("gz_channel_bool", val) -# -# @property -# def gz_channel(self): -# return self._gz_channel -# -# @gz_channel.setter -# def gz_channel(self, val): -# self.setter_validator("gz_channel", val, fun=self._uuid_promoter) -# -# @property -# def gz_uncertainty(self): -# return self._gz_uncertainty -# -# @gz_uncertainty.setter -# def gz_uncertainty(self, val): -# self.setter_validator("gz_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def guv_channel_bool(self): -# return self._guv_channel_bool -# -# @guv_channel_bool.setter -# def guv_channel_bool(self, val): -# self.setter_validator("guv_channel_bool", val) -# -# @property -# def guv_channel(self): -# return self._guv_channel -# -# @guv_channel.setter -# def guv_channel(self, val): -# self.setter_validator("guv_channel", val, fun=self._uuid_promoter) -# -# @property -# def guv_uncertainty(self): -# return self._guv_uncertainty -# -# @guv_uncertainty.setter -# def guv_uncertainty(self, val): -# self.setter_validator("guv_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gxy_channel_bool(self): -# return self._gxy_channel_bool -# -# @gxy_channel_bool.setter -# def gxy_channel_bool(self, val): -# self.setter_validator("gxy_channel_bool", val) -# -# @property -# def gxy_channel(self): -# return self._gxy_channel -# -# @gxy_channel.setter -# def gxy_channel(self, val): -# self.setter_validator("gxy_channel", val, fun=self._uuid_promoter) -# -# @property -# def gxy_uncertainty(self): -# return self._gxy_uncertainty -# -# @gxy_uncertainty.setter -# def gxy_uncertainty(self, val): -# self.setter_validator("gxy_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gxx_channel_bool(self): -# return self._gxx_channel_bool -# -# @gxx_channel_bool.setter -# def gxx_channel_bool(self, val): -# self.setter_validator("gxx_channel_bool", val) -# -# @property -# def gxx_channel(self): -# return self._gxx_channel -# -# @gxx_channel.setter -# def gxx_channel(self, val): -# self.setter_validator("gxx_channel", val, fun=self._uuid_promoter) -# -# @property -# def gxx_uncertainty(self): -# return self._gxx_uncertainty -# -# @gxx_uncertainty.setter -# def gxx_uncertainty(self, val): -# self.setter_validator("gxx_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gyy_channel_bool(self): -# return self._gyy_channel_bool -# -# @gyy_channel_bool.setter -# def gyy_channel_bool(self, val): -# self.setter_validator("gyy_channel_bool", val) -# -# @property -# def gyy_channel(self): -# return self._gyy_channel -# -# @gyy_channel.setter -# def gyy_channel(self, val): -# self.setter_validator("gyy_channel", val, fun=self._uuid_promoter) -# -# @property -# def gyy_uncertainty(self): -# return self._gyy_uncertainty -# -# @gyy_uncertainty.setter -# def gyy_uncertainty(self, val): -# self.setter_validator("gyy_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gzz_channel_bool(self): -# return self._gzz_channel_bool -# -# @gzz_channel_bool.setter -# def gzz_channel_bool(self, val): -# self.setter_validator("gzz_channel_bool", val) -# -# @property -# def gzz_channel(self): -# return self._gzz_channel -# -# @gzz_channel.setter -# def gzz_channel(self, val): -# self.setter_validator("gzz_channel", val, fun=self._uuid_promoter) -# -# @property -# def gzz_uncertainty(self): -# return self._gzz_uncertainty -# -# @gzz_uncertainty.setter -# def gzz_uncertainty(self, val): -# self.setter_validator("gzz_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gxz_channel_bool(self): -# return self._gxz_channel_bool -# -# @gxz_channel_bool.setter -# def gxz_channel_bool(self, val): -# self.setter_validator("gxz_channel_bool", val) -# -# @property -# def gxz_channel(self): -# return self._gxz_channel -# -# @gxz_channel.setter -# def gxz_channel(self, val): -# self.setter_validator("gxz_channel", val, fun=self._uuid_promoter) -# -# @property -# def gxz_uncertainty(self): -# return self._gxz_uncertainty -# -# @gxz_uncertainty.setter -# def gxz_uncertainty(self, val): -# self.setter_validator("gxz_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gyz_channel_bool(self): -# return self._gyz_channel_bool -# -# @gyz_channel_bool.setter -# def gyz_channel_bool(self, val): -# self.setter_validator("gyz_channel_bool", val) -# -# @property -# def gyz_channel(self): -# return self._gyz_channel -# -# @gyz_channel.setter -# def gyz_channel(self, val): -# self.setter_validator("gyz_channel", val, fun=self._uuid_promoter) -# -# @property -# def gyz_uncertainty(self): -# return self._gyz_uncertainty -# -# @gyz_uncertainty.setter -# def gyz_uncertainty(self, val): -# self.setter_validator("gyz_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gx_channel_bool(self): -# return self._gx_channel_bool -# -# @gx_channel_bool.setter -# def gx_channel_bool(self, val): -# self.setter_validator("gx_channel_bool", val) -# -# @property -# def gx_channel(self): -# return self._gx_channel -# -# @gx_channel.setter -# def gx_channel(self, val): -# self.setter_validator("gx_channel", val, fun=self._uuid_promoter) -# -# @property -# def gx_uncertainty(self): -# return self._gx_uncertainty -# -# @gx_uncertainty.setter -# def gx_uncertainty(self, val): -# self.setter_validator("gx_uncertainty", val, fun=self._uuid_promoter) -# -# @property -# def gy_channel_bool(self): -# return self._gy_channel_bool -# -# @gy_channel_bool.setter -# def gy_channel_bool(self, val): -# self.setter_validator("gy_channel_bool", val) -# -# @property -# def gy_channel(self): -# return self._gy_channel -# -# @gy_channel.setter -# def gy_channel(self, val): -# self.setter_validator("gy_channel", val, fun=self._uuid_promoter) -# -# @property -# def gy_uncertainty(self): -# return self._gy_uncertainty -# -# @gy_uncertainty.setter -# def gy_uncertainty(self, val): -# self.setter_validator("gy_uncertainty", val, fun=self._uuid_promoter) From 80da7198bcfbacc1fff975864acabeee95f4b04e Mon Sep 17 00:00:00 2001 From: benjamink Date: Tue, 28 Jan 2025 12:05:31 -0800 Subject: [PATCH 16/21] update docstrings --- simpeg_drivers/params.py | 22 +++++++++++++------ .../potential_fields/gravity/params.py | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 34a35206..bce05e75 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -67,13 +67,23 @@ class CoreData(BaseData): command line. :param conda_environment: Name of the conda environment used to run the application with all of its dependencies. + :param inversion_type: Type of inversion. + :param physical_property: Physical property of the model. :param data_object: Data object containing survey geometry and data channels. + :param z_from_topo: If True, the z values of the data object are set to the + topography surface. :param mesh: Mesh object containing models (starting, reference, active, etc..). :param starting_model: Starting model used to start inversion or for simulating data in the forward operation. - :param topography_object: Topography object used to define the active cells of - the model. + :param active: Active cell data as either a topography surface/data or a 3D model. + :param tile_spatial: Number of tiles to split the data. + :param parallelized: Parallelize the inversion/forward operation. + :param n_cpu: Number of CPUs to use if parallelized. If None, all cpu will be used. + :param max_chunk_size: Maximum chunk size used for parallel operations. + :param save_sensitivities: Save sensitivities to file. + :param out_group: Output group to save results. + :param generate_sweep: Generate sweep file instead of running the app. """ # TODO: Refactor to allow frozen True. Currently params.data_object is @@ -193,10 +203,7 @@ class BaseForwardData(CoreData): """ Base class for forward parameters. - :param name: Name of the application. - :param title: Title of the application - :param core: Core parameters for forward (data, mesh, starting model, active). - """ + See CoreData class docstring for addition parameters descriptions.""" forward_only: bool = True @@ -215,7 +222,7 @@ class BaseInversionData(CoreData): """ Base class for inversion parameters. - :param core: Core parameters for inversion (data, mesh, starting model, active). + See CoreData class docstring for addition parameters descriptions. :param reference_model: Reference model. :param lower_bound: Lower bound. @@ -285,6 +292,7 @@ class BaseInversionData(CoreData): forward_only: bool = False conda_environment: str = "simpeg_drivers" + reference_model: float | FloatData | None = None lower_bound: float | FloatData | None = None upper_bound: float | FloatData | None = None diff --git a/simpeg_drivers/potential_fields/gravity/params.py b/simpeg_drivers/potential_fields/gravity/params.py index 8ba3fe3a..26d745e6 100644 --- a/simpeg_drivers/potential_fields/gravity/params.py +++ b/simpeg_drivers/potential_fields/gravity/params.py @@ -41,6 +41,7 @@ class GravityForwardParams(BaseForwardData): inversion_type: str = "gravity" physical_property: str = "density" + gx_channel_bool: bool = False gy_channel_bool: bool = False gz_channel_bool: bool = True @@ -82,6 +83,7 @@ class GravityInversionParams(BaseInversionData): inversion_type: str = "gravity" physical_property: str = "density" + gx_channel: FloatData | None = None gy_channel: FloatData | None = None gz_channel: FloatData | None = None From 99f954523008c8167ce2ceed49014cbe0d49a48d Mon Sep 17 00:00:00 2001 From: benk-mira <81254271+benk-mira@users.noreply.github.com> Date: Wed, 29 Jan 2025 07:37:53 -0800 Subject: [PATCH 17/21] Update simpeg_drivers/params.py Co-authored-by: domfournier --- simpeg_drivers/params.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index bce05e75..874eb6fa 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -128,15 +128,10 @@ def mesh_cannot_be_rotated(cls, value: Octree): def out_group_if_none(cls, data) -> SimPEGGroup: group = data.get("out_group", None) - if isinstance(group, UIJsonGroup): + if isinstance(group, UIJsonGroup | type(None)): + name = cls.title if group is None else group.name with fetch_active_workspace(data["geoh5"], mode="r+") as geoh5: - group = SimPEGGroup.create(geoh5, name=group.name) - group.metadata = None - - elif group is None: - with fetch_active_workspace(data["geoh5"], mode="r+") as geoh5: - group = SimPEGGroup.create(geoh5, name=cls.title) - group.metadata = None + group = SimPEGGroup.create(geoh5, name=name) data["out_group"] = group From 59d70954a0557c1d03d4a7f39dfd76aa36b36d47 Mon Sep 17 00:00:00 2001 From: benk-mira <81254271+benk-mira@users.noreply.github.com> Date: Wed, 29 Jan 2025 07:38:17 -0800 Subject: [PATCH 18/21] Update simpeg_drivers/params.py Co-authored-by: domfournier --- simpeg_drivers/params.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 874eb6fa..8ca9fdab 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -141,6 +141,7 @@ def out_group_if_none(cls, data) -> SimPEGGroup: def update_out_group_options(self): assert self.out_group is not None self.out_group.options = self.serialize() + self.out_group.metadata = None return self @property From 2b44b1e95cb808c9672b9fc62bb12941d04c1028 Mon Sep 17 00:00:00 2001 From: benjamink Date: Wed, 29 Jan 2025 08:46:29 -0800 Subject: [PATCH 19/21] params.active -> params.active_cells --- simpeg_drivers/components/meshes.py | 2 +- simpeg_drivers/components/topography.py | 8 ++++-- simpeg_drivers/params.py | 37 ++----------------------- 3 files changed, 9 insertions(+), 38 deletions(-) diff --git a/simpeg_drivers/components/meshes.py b/simpeg_drivers/components/meshes.py index 494765a1..b02972e1 100644 --- a/simpeg_drivers/components/meshes.py +++ b/simpeg_drivers/components/meshes.py @@ -119,7 +119,7 @@ def _auto_mesh(self): params = auto_mesh_parameters( self.params.data_object, - self.params.active.topography_object, + self.params.active_cells.topography_object, inversion_type=self.params.inversion_type, ) driver = OctreeDriver(params) diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index 732ec860..e974e9fc 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -70,8 +70,10 @@ def __init__( super().__init__(workspace, params) self.locations: np.ndarray | None = None - if self.params.active.topography_object is not None: - self.locations = self.get_locations(self.params.active.topography_object) + if self.params.active_cells.topography_object is not None: + self.locations = self.get_locations( + self.params.active_cells.topography_object + ) def active_cells(self, mesh: InversionMesh, data: InversionData) -> np.ndarray: """ @@ -89,7 +91,7 @@ def active_cells(self, mesh: InversionMesh, data: InversionData) -> np.ndarray: "induced polarization 2d", ] or isinstance(data.entity, LargeLoopGroundEMSurvey) - if isinstance(self.params.active.active_model, NumericData): + if isinstance(self.params.active_cells.active_model, NumericData): active_cells = InversionModel.obj_2_mesh( self.params.active.active_model, mesh.entity ) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index bce05e75..9999b589 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -76,7 +76,7 @@ class CoreData(BaseData): :param mesh: Mesh object containing models (starting, reference, active, etc..). :param starting_model: Starting model used to start inversion or for simulating data in the forward operation. - :param active: Active cell data as either a topography surface/data or a 3D model. + :param active_cells: Active cell data as either a topography surface/data or a 3D model. :param tile_spatial: Number of tiles to split the data. :param parallelized: Parallelize the inversion/forward operation. :param n_cpu: Number of CPUs to use if parallelized. If None, all cpu will be used. @@ -98,7 +98,7 @@ class CoreData(BaseData): z_from_topo: bool = False mesh: Octree | None starting_model: float | FloatData - active: ActiveCellsData + active_cells: ActiveCellsData tile_spatial: int = 1 parallelized: bool = True n_cpu: int | None = None @@ -156,37 +156,6 @@ def workpath(self): def channels(self) -> list[str]: return [k.split("_")[0] for k in self.__dict__ if "channel" in k] - def data_channel(self, component: str) -> NumericData | None: - """Return the data object associated with the component.""" - return getattr(self, "_".join([component, "channel"]), None) - - def uncertainty_channel(self, component: str) -> NumericData | None: - """Return the uncertainty object associated with the component.""" - return getattr(self, "_".join([component, "uncertainty"]), None) - - def data(self, component: str) -> np.ndarray | None: - """Returns array of data for chosen data component if it exists.""" - data_entity = self.data_channel(component) - if isinstance(data_entity, NumericData): - return data_entity.values.astype(float) - return None - - def uncertainty(self, component: str) -> np.ndarray | None: - """Returns uncertainty for chosen data component if it exists.""" - - uncertainty_entity = self.uncertainty_channel(component) - if isinstance(uncertainty_entity, NumericData): - return uncertainty_entity.values.astype(float) - - data = self.data(component) - if data is not None: - if isinstance(uncertainty_entity, int | float): - return np.array([float(uncertainty_entity)] * len(data)) - else: - return data * 0.0 + 1.0 # type: ignore - - return None - @property def padding_cells(self) -> int: """ @@ -489,7 +458,7 @@ def __init__( setattr(self, key, True) @property - def active(self): + def active_cells(self): return ActiveCellsData( topography_object=self.topography_object, topography=self.topography, From c221c599f61195997e09f686a1f45fcde883be8c Mon Sep 17 00:00:00 2001 From: benjamink Date: Wed, 29 Jan 2025 09:01:58 -0800 Subject: [PATCH 20/21] Propagate active rename to tests too --- simpeg_drivers/components/topography.py | 14 +++++++------- tests/driver_test.py | 4 ++-- tests/run_tests/driver_grav_test.py | 8 ++++---- .../run_tests/driver_joint_cross_gradient_test.py | 8 ++++---- tests/run_tests/driver_joint_surveys_test.py | 12 ++++++------ tests/run_tests/sensitivity_cutoff_test.py | 4 ++-- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/simpeg_drivers/components/topography.py b/simpeg_drivers/components/topography.py index e974e9fc..29544202 100644 --- a/simpeg_drivers/components/topography.py +++ b/simpeg_drivers/components/topography.py @@ -93,7 +93,7 @@ def active_cells(self, mesh: InversionMesh, data: InversionData) -> np.ndarray: if isinstance(self.params.active_cells.active_model, NumericData): active_cells = InversionModel.obj_2_mesh( - self.params.active.active_model, mesh.entity + self.params.active_cells.active_model, mesh.entity ) else: active_cells = active_from_xyz( @@ -128,14 +128,14 @@ def get_locations(self, entity: Entity) -> np.ndarray: locs = super().get_locations(entity) - if self.params.active.topography is not None: - if isinstance(self.params.active.topography, Entity): - elev = self.params.active.topography.values - elif isinstance(self.params.active.topography, int | float): - elev = np.ones_like(locs[:, 2]) * self.params.active.topography + if self.params.active_cells.topography is not None: + if isinstance(self.params.active_cells.topography, Entity): + elev = self.params.active_cells.topography.values + elif isinstance(self.params.active_cells.topography, int | float): + elev = np.ones_like(locs[:, 2]) * self.params.active_cells.topography else: elev = ( - self.params.active.topography.values + self.params.active_cells.topography.values ) # Must be FloatData at this point if not np.all(locs[:, 2] == elev): diff --git a/tests/driver_test.py b/tests/driver_test.py index e899e67d..881f80ea 100644 --- a/tests/driver_test.py +++ b/tests/driver_test.py @@ -34,11 +34,11 @@ def test_smallness_terms(tmp_path: Path): gz = survey.add_data({"gz": {"values": np.ones(survey.n_vertices)}}) mesh = model.parent - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityInversionParams( geoh5=geoh5, mesh=mesh, - active=active, + active_cells=active_cells, data_object=gz.parent, starting_model=1e-4, reference_model=0.0, diff --git a/tests/run_tests/driver_grav_test.py b/tests/run_tests/driver_grav_test.py index 10ee93af..f5044cab 100644 --- a/tests/run_tests/driver_grav_test.py +++ b/tests/run_tests/driver_grav_test.py @@ -47,11 +47,11 @@ def test_gravity_fwr_run( flatten=False, ) - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityForwardParams( geoh5=geoh5, mesh=model.parent, - active=active, + active_cells=active_cells, topography_object=topography, z_from_topo=False, data_object=survey, @@ -96,11 +96,11 @@ def test_gravity_run( gz.values = values # Run the inverse - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityInversionParams( geoh5=geoh5, mesh=mesh, - active=active, + active_cells=active_cells, data_object=gz.parent, starting_model=1e-4, reference_model=0.0, diff --git a/tests/run_tests/driver_joint_cross_gradient_test.py b/tests/run_tests/driver_joint_cross_gradient_test.py index 377d2941..d8de878a 100644 --- a/tests/run_tests/driver_joint_cross_gradient_test.py +++ b/tests/run_tests/driver_joint_cross_gradient_test.py @@ -57,12 +57,12 @@ def test_joint_cross_gradient_fwr_run( n_electrodes=n_grid_points, n_lines=n_grid_points, ) - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityForwardParams( forward_only=True, geoh5=geoh5, mesh=model.parent, - active=active, + active_cells=active_cells, resolution=0.0, z_from_topo=False, data_object=survey, @@ -175,12 +175,12 @@ def test_joint_cross_gradient_inv_run( if group.options["inversion_type"] == "gravity": data.values = data.values + np.random.randn(data.values.size) * 1e-2 - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityInversionParams( geoh5=geoh5, mesh=mesh, alpha_s=1.0, - active=active, + active_cells=active_cells, data_object=survey, gz_channel=data, gz_uncertainty=1e-2, diff --git a/tests/run_tests/driver_joint_surveys_test.py b/tests/run_tests/driver_joint_surveys_test.py index 95b42ac5..3e3035d8 100644 --- a/tests/run_tests/driver_joint_surveys_test.py +++ b/tests/run_tests/driver_joint_surveys_test.py @@ -43,12 +43,12 @@ def test_joint_surveys_fwr_run( n_electrodes=n_grid_points, n_lines=n_grid_points, ) - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityForwardParams( forward_only=True, geoh5=geoh5, mesh=model.parent, - active=active, + active_cells=active_cells, resolution=0.0, z_from_topo=False, data_object=survey, @@ -69,12 +69,12 @@ def test_joint_surveys_fwr_run( geoh5=geoh5, drape_height=10.0, ) - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityForwardParams( forward_only=True, geoh5=geoh5, mesh=model.parent, - active=active, + active_cells=active_cells, resolution=0.0, z_from_topo=False, data_object=survey, @@ -127,11 +127,11 @@ def test_joint_surveys_inv_run( active_model = mesh.get_entity("active_cells")[0] gz = survey.get_data("Iteration_0_gz")[0] orig_data.append(gz.values) - active = ActiveCellsData(active_model=active_model) + active_cells = ActiveCellsData(active_model=active_model) params = GravityInversionParams( geoh5=geoh5, mesh=mesh, - active=active, + active_cells=active_cells, data_object=survey, gz_channel=gz, gz_uncertainty=np.var(gz.values) * 2.0, diff --git a/tests/run_tests/sensitivity_cutoff_test.py b/tests/run_tests/sensitivity_cutoff_test.py index 2e128fb6..4a3fd754 100644 --- a/tests/run_tests/sensitivity_cutoff_test.py +++ b/tests/run_tests/sensitivity_cutoff_test.py @@ -44,11 +44,11 @@ def setup_inversion_results( # Run the inverse with save_sensitivities=True gz = survey.add_data({"gz": {"values": np.random.randn(len(survey.vertices))}}) - active = ActiveCellsData(topography_object=topography) + active_cells = ActiveCellsData(topography_object=topography) params = GravityInversionParams( geoh5=geoh5, mesh=mesh, - active=active, + active_cells=active_cells, data_object=gz.parent, starting_model=1e-4, reference_model=0.0, From d04f8ad0fad1b7606722190facdc1b0a7896ba32 Mon Sep 17 00:00:00 2001 From: benjamink Date: Wed, 29 Jan 2025 09:43:40 -0800 Subject: [PATCH 21/21] data, uncertainty methods cannot be moved to BaseInversionData because the driver still pushes forward_only through InversionData which class these. --- simpeg_drivers/params.py | 62 ++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/simpeg_drivers/params.py b/simpeg_drivers/params.py index 8151c5a6..8901b92d 100644 --- a/simpeg_drivers/params.py +++ b/simpeg_drivers/params.py @@ -152,6 +152,37 @@ def workpath(self): def channels(self) -> list[str]: return [k.split("_")[0] for k in self.__dict__ if "channel" in k] + def data_channel(self, component: str) -> NumericData | None: + """Return the data object associated with the component.""" + return getattr(self, "_".join([component, "channel"]), None) + + def data(self, component: str) -> np.ndarray | None: + """Returns array of data for chosen data component if it exists.""" + data_entity = self.data_channel(component) + if isinstance(data_entity, NumericData): + return data_entity.values.astype(float) + return None + + def uncertainty_channel(self, component: str) -> NumericData | None: + """Return the uncertainty object associated with the component.""" + return getattr(self, "_".join([component, "uncertainty"]), None) + + def uncertainty(self, component: str) -> np.ndarray | None: + """Returns uncertainty for chosen data component if it exists.""" + + uncertainty_entity = self.uncertainty_channel(component) + if isinstance(uncertainty_entity, NumericData): + return uncertainty_entity.values.astype(float) + + data = self.data(component) + if data is not None: + if isinstance(uncertainty_entity, int | float): + return np.array([float(uncertainty_entity)] * len(data)) + else: + return data * 0.0 + 1.0 # Default + + return None + @property def padding_cells(self) -> int: """ @@ -319,37 +350,6 @@ def components(self) -> list[str]: return comps - def data_channel(self, component: str) -> NumericData | None: - """Return the data object associated with the component.""" - return getattr(self, "_".join([component, "channel"]), None) - - def uncertainty_channel(self, component: str) -> NumericData | None: - """Return the uncertainty object associated with the component.""" - return getattr(self, "_".join([component, "uncertainty"]), None) - - def data(self, component: str) -> np.ndarray | None: - """Returns array of data for chosen data component if it exists.""" - data_entity = self.data_channel(component) - if isinstance(data_entity, NumericData): - return data_entity.values.astype(float) - return None - - def uncertainty(self, component: str) -> np.ndarray | None: - """Returns uncertainty for chosen data component if it exists.""" - - uncertainty_entity = self.uncertainty_channel(component) - if isinstance(uncertainty_entity, NumericData): - return uncertainty_entity.values.astype(float) - - data = self.data(component) - if data is not None: - if isinstance(uncertainty_entity, int | float): - return np.array([float(uncertainty_entity)] * len(data)) - else: - return data * 0.0 + 1.0 # Default - - return None - class InversionBaseParams(BaseParams): """