Inversion API#

Physics-based EM inversion API for pyCSAMT.

The pycsamt.inversion package provides a backend-neutral interface for EM inversion. It includes runnable built-in layered-earth inversions for MT/AMT/CSAMT and TDEM soundings, stitched station-by-station 2-D sections, and adapter backends for existing Occam2D and ModEM workflows. SimPEG and pyGIMLi are registered lazily for optional numerical backends.

Examples

>>> from pycsamt.inversion import InversionConfig, InversionWorkflow
>>> cfg = InversionConfig(
...     method="mt",
...     dimension="1d",
...     backend="builtin",
...     data={"freqs": [1, 10], "rho_a": [100, 120], "phase": [45, 47]},
... )
>>> result = InversionWorkflow(cfg).run()
class pycsamt.inversion.EMData(method='mt', frequencies=None, times=None, rho_a=None, phase=None, values=None, errors=None, station_names=<factory>, station_x=None, source=None, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Normalized EM observation container.

EMData is the backend-neutral observation object used by pycsamt.inversion. It keeps natural-source and time-domain EM data in one small shape contract so built-in, optional, and external backends can share the same input API.

Shape convention#

Frequency-domain rho_a and phase arrays may be one-dimensional for a single station or two-dimensional with shape (n_stations, n_frequencies). TDEM values arrays may be one-dimensional for a single sounding or two-dimensional with shape (n_soundings, n_times). Station metadata, when provided, must match the first dimension of these arrays.

param method:

Survey method represented by the observations. The value is normalized to lower case. Natural-source methods require frequency-domain responses; "tdem" requires time-gate decay values.

type method:

{“mt”, “amt”, “csamt”, “emap”, “tdem”}, default “mt”

param frequencies:

Frequency samples in hertz for MT, AMT, CSAMT, and EMAP responses. Values must be strictly positive. The aliases freqs, freq, frequency, and period arrays via periods are accepted by coercion helpers.

type frequencies:

array-like of float, optional

param times:

Time-gate samples in seconds for TDEM data. Values must be strictly positive. Sounding objects may expose these as time_gates, times, or time.

type times:

array-like of float, optional

param rho_a:

Apparent resistivity in ohm metres. One-dimensional arrays represent one station. Two-dimensional arrays represent (n_stations, n_samples); if a response object provides (n_samples, n_stations), coercion transposes it when the frequency count makes the orientation unambiguous. Common aliases include rhoa, app_res, and apparent_resistivity.

type rho_a:

array-like of float, optional

param phase:

Impedance phase in degrees, using the same shape convention as rho_a. The alias phi is accepted by object coercion.

type phase:

array-like of float, optional

param values:

Generic observed values. This is primarily used for TDEM decay data such as dBz_dt/dbdt arrays. One-dimensional arrays represent one sounding; two-dimensional arrays represent (n_soundings, n_times).

type values:

array-like of float, optional

param errors:

Absolute observation uncertainties with the same sample axis as the corresponding data. If omitted, backends derive errors from InversionConfig error floors and component-specific ErrorModel settings.

type errors:

array-like of float, optional

param station_names:

Station or sounding labels. The length must match the number of station rows in the data. Mapping aliases include stations; response-object aliases include station_names, stations, site_names, and names.

type station_names:

sequence of str, optional

param station_x:

Profile-coordinate positions in metres. The length must match the number of station rows. Object coercion also checks aliases such as x, x_stations, easting, longitude, and lon.

type station_x:

array-like of float, optional

param source:

Original data object, collection, survey, or path retained for provenance and backend adapters. It is not modified by EMData.

type source:

object, optional

param metadata:

Free-form provenance metadata. Object readers copy metadata or meta dictionaries when available and add a reader tag describing the coercion path.

type metadata:

dict, optional

Notes

Use EMData.coerce() at API boundaries. It accepts dictionaries, response-like objects, station collections, TDEM sounding collections, and TDEM survey objects exposing to_soundings(). The original input object is kept in source for provenance and backend-specific adapters.

Examples

Build one MT/AMT/CSAMT station from a mapping:

>>> from pycsamt.inversion.data import EMData
>>> data = EMData.from_dict({
...     "method": "mt",
...     "freqs": [1.0, 10.0, 100.0],
...     "rho_a": [100.0, 120.0, 140.0],
...     "phase": [45.0, 47.0, 49.0],
...     "stations": ["S01"],
... })
>>> data.has_mt_response
True

Build a stitched profile from station rows:

>>> from pycsamt.inversion.data import EMData
>>> profile = EMData.coerce({
...     "method": "amt",
...     "freqs": [1.0, 10.0],
...     "rho_a": [[100.0, 120.0], [90.0, 115.0]],
...     "phase": [[45.0, 47.0], [43.0, 46.0]],
...     "station_x": [0.0, 500.0],
...     "station_names": ["A01", "A02"],
... })
>>> profile.n_stations
2

Build TDEM data from time gates and decay values:

>>> from pycsamt.inversion.data import EMData
>>> tdem = EMData.coerce({
...     "method": "tdem",
...     "times": [1e-5, 1e-4, 1e-3],
...     "values": [1e-8, 2e-9, 5e-10],
... })
>>> tdem.has_tdem_response
True

References

method: str = 'mt'#
frequencies: Any = None#
times: Any = None#
rho_a: Any = None#
phase: Any = None#
values: Any = None#
errors: Any = None#
station_names: list[str]#
station_x: Any = None#
source: Any = None#
metadata: dict[str, Any]#
classmethod from_dict(data, **overrides)#

Build EMData from a mapping.

Parameters:
  • data (mapping) – Mapping with observation fields. Keys may include method, freqs/frequencies, periods, rho_a, phase, times, values, errors, stations/station_names, station_x, and metadata.

  • **overrides – Field values that override keys read from data. This is useful when a caller wants to force method or attach metadata while preserving the original observation mapping.

Returns:

Normalized observation container.

Return type:

EMData

Notes

The aliases freqs and stations are normalized to frequencies and station_names. periods are converted to frequency in hertz.

Examples

>>> from pycsamt.inversion.data import EMData
>>> data = EMData.from_dict({
...     "method": "mt",
...     "freqs": [1.0, 10.0],
...     "rho_a": [100.0, 120.0],
...     "phase": [45.0, 47.0],
...     "stations": ["S01"],
... })
>>> data.frequencies.tolist()
[1.0, 10.0]
>>> data.station_names
['S01']
classmethod coerce(data, *, method='mt')#

Return data as an EMData instance.

Parameters:
  • data (EMData, mapping, response object, sounding object, survey object, or sequence) – Input converted to EMData. Supported objects include natural-source response objects with frequency and rho/phase attributes; station collections of such objects; TDEM sounding objects exposing time gates and decay values; and survey objects exposing to_soundings().

  • method (str, default "mt") – Fallback method used when data does not declare its own method. TDEM sounding/survey inputs are automatically promoted to "tdem".

Returns:

Existing EMData instances are returned unchanged. Recognized objects are parsed into normalized arrays. Unrecognized non-null inputs are retained as source on an otherwise empty container so backend adapters can still inspect them.

Return type:

EMData

Raises:

ValueError – If station collections have incompatible frequency counts, TDEM soundings have incompatible time gates, or normalized arrays fail validation.

Examples

Coerce a response-like object:

>>> import numpy as np
>>> from pycsamt.inversion.data import EMData
>>> class Response:
...     freqs = np.array([1.0, 10.0])
...     rho_a = np.array([100.0, 120.0])
...     phase = np.array([45.0, 47.0])
...     station_name = "S01"
>>> data = EMData.coerce(Response(), method="mt")
>>> data.station_names
['S01']

Coerce a small TDEM survey object exposing to_soundings():

>>> import numpy as np
>>> from pycsamt.inversion.data import EMData
>>> class Sounding:
...     station_name = "T01"
...     time_gates = np.array([1e-5, 1e-4])
...     data = np.array([1e-8, 2e-9])
>>> class Survey:
...     def to_soundings(self):
...         return [Sounding()]
>>> tdem = EMData.coerce(Survey())
>>> tdem.method
'tdem'
property n_samples: int#

Return the number of primary samples.

property n_stations: int#

Return the number of stations/soundings represented.

property has_mt_response: bool#

Whether apparent resistivity/phase observations are available.

property has_tdem_response: bool#

Whether time-domain EM decay observations are available.

validate()#

Validate basic shape consistency.

Return type:

None

Parameters:
class pycsamt.inversion.ErrorModel(rho_relative=0.05, rho_absolute=1e-12, phase_absolute=3.0, phase_relative=0.0, tdem_relative=0.05, tdem_absolute=1e-30, impedance_relative=0.05, impedance_absolute=1e-12, min_error=1e-12, masks=<factory>)#

Bases: object

Component-aware data-error settings for inversion backends.

ErrorModel centralizes the floors used when packing objective functions for the built-in, SimPEG, pyGIMLi, Occam2D, and ModEM adapters. It supports component-specific relative/absolute floors and boolean masks used to exclude stations, frequencies, time gates, or individual samples.

Parameters:
  • rho_relative (float, default 0.05) – Relative apparent-resistivity error floor.

  • rho_absolute (float, default 1e-12) – Absolute apparent-resistivity error floor in ohm metres.

  • phase_absolute (float, default 3.0) – Absolute phase error floor in degrees.

  • phase_relative (float, default 0.0) – Optional relative phase error floor.

  • tdem_relative (float, default 0.05) – Relative TDEM decay-value error floor.

  • tdem_absolute (float, default 1e-30) – Absolute TDEM decay-value error floor.

  • impedance_relative (float, default 0.05) – Relative impedance-component error floor.

  • impedance_absolute (float, default 1e-12) – Absolute impedance-component error floor.

  • min_error (float, default 1e-12) – Global lower bound applied to all returned errors.

  • masks (dict, optional) – Component or station masks. Supported keys include component names such as "rho", "phase", "tdem", and station-level keys "station"/"station_mask".

Notes

Configuration helpers read overrides from backend_options and nested backend_options["error_model"] dictionaries. Explicit observed-data errors can still be passed to errors() or component_errors().

Examples

Build an error model directly:

>>> from pycsamt.inversion.objective import ErrorModel
>>> model = ErrorModel(rho_relative=0.05, phase_absolute=2.0)
>>> model.errors([100.0, 200.0], component="rho").tolist()
[5.0, 10.0]

Use component masks to down-weight stations or samples:

>>> from pycsamt.inversion.objective import ErrorModel
>>> model = ErrorModel(masks={"station": [True, False]})
>>> model.mask([[1.0, 2.0], [3.0, 4.0]], component="rho").tolist()
[[True, True], [False, False]]

References

rho_relative: float = 0.05#
rho_absolute: float = 1e-12#
phase_absolute: float = 3.0#
phase_relative: float = 0.0#
tdem_relative: float = 0.05#
tdem_absolute: float = 1e-30#
impedance_relative: float = 0.05#
impedance_absolute: float = 1e-12#
min_error: float = 1e-12#
masks: dict[str, Any]#
errors(values, *, component, explicit=None, relative=False)#

Return data errors for one observed component.

Parameters:
  • values (array-like) – Observed or predicted values used to scale relative error floors.

  • component (str) – Component name. Common aliases include "rho", "rho_a", "phase", "tdem", "dbdt", and "impedance".

  • explicit (array-like, optional) – Explicit absolute errors. When provided, component floor settings are bypassed except for the global min_error lower bound.

  • relative (bool, default False) – If True, return relative errors by dividing absolute errors by abs(values) with min_error protection.

Returns:

Error array with the same shape as values.

Return type:

ndarray

Examples

>>> from pycsamt.inversion.objective import ErrorModel
>>> model = ErrorModel(rho_relative=0.1, rho_absolute=1.0)
>>> model.errors([5.0, 100.0], component="rho").tolist()
[1.0, 10.0]
>>> model.errors([45.0], component="phase").tolist()
[3.0]
mask(values, *, component)#

Return a boolean inclusion mask for one component.

Parameters:
  • values (array-like) – Data array whose shape defines the returned mask shape.

  • component (str) – Component name. Component-specific masks are checked first, then station-level masks under "station" or "station_mask".

Returns:

Boolean mask broadcast to the shape of values.

Return type:

ndarray of bool

Examples

>>> from pycsamt.inversion.objective import ErrorModel
>>> model = ErrorModel(masks={"station": [True, False]})
>>> model.mask([[1.0, 2.0], [3.0, 4.0]], component="rho").tolist()
[[True, True], [False, False]]
class pycsamt.inversion.InversionHistory(records=<factory>, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Common convergence-history container.

InversionHistory stores backend-neutral iteration diagnostics. Built-in solvers record fields such as iteration, phi_d, phi_m, objective, rms, regularization weight, and model norm. Optional or external backends can map native logs into the same record structure.

Parameters:
  • records (list of dict, optional) – One dictionary per iteration or residual evaluation. Numeric fields can be converted to arrays with arrays().

  • metadata (dict, optional) – Free-form provenance metadata such as backend mode or station index.

Examples

Build convergence history from backend records:

>>> from pycsamt.inversion.results import InversionHistory
>>> history = InversionHistory(records=[
...     {"iteration": 0, "objective": 5.0, "rms": 2.0},
...     {"iteration": 1, "objective": 2.5, "rms": 1.2},
... ])
>>> history.arrays()["objective"].tolist()
[5.0, 2.5]

See also

InversionResult.history

Result field that carries convergence diagnostics.

References

records: list[dict[str, Any]]#
metadata: dict[str, Any]#
property n_records: int#

Number of convergence records.

Examples

>>> from pycsamt.inversion.results import InversionHistory
>>> InversionHistory(records=[{"iteration": 0}]).n_records
1
arrays()#

Return numeric history fields as arrays.

Non-numeric fields are skipped. Missing numeric fields are represented by nan so arrays have one value per record.

Returns:

Mapping from numeric history field name to a float array.

Return type:

dict of ndarray

Examples

>>> from pycsamt.inversion.results import InversionHistory
>>> history = InversionHistory(records=[
...     {"iteration": 0, "objective": 5.0},
...     {"iteration": 1, "objective": 2.5},
... ])
>>> history.arrays()["objective"].tolist()
[5.0, 2.5]
class pycsamt.inversion.InversionConfig(method='mt', dimension='1d', backend='builtin', data=None, workdir='pycsamt_inversion', output_dir=None, n_layers=4, starting_model=None, reference_model=None, error_floor=0.05, include_phase=True, phase_error=3.0, regularization='smooth', max_iter=80, tol=1e-05, bounds=<factory>, run_external=False, backend_options=<factory>, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Source-of-truth configuration for pycsamt.inversion.

Parameters:
  • method ({"mt", "amt", "csamt", "emap", "tdem"}, default "mt") – Electromagnetic method to invert. Natural-source methods use frequency, apparent-resistivity, and phase observations. TDEM uses time-gate decay observations. The value is normalized to lower case and is used with dimension to select the backend execution path.

  • dimension ({"1d", "2d", "3d"}, default "1d") – Inversion dimensionality. One-dimensional runs recover layered-earth models. Two-dimensional runs produce section models either by stitched station inversions or by the built-in finite-difference profile mode. Three-dimensional execution is delegated to optional or external engines.

  • backend ({"builtin", "simpeg", "pygimli", "occam2d", "modem"}, default "builtin") – Inversion engine. "builtin" is dependency-light and runnable for local smoke studies. "simpeg" and "pygimli" are optional physics engines imported only when selected. "occam2d" and "modem" prepare, validate, and optionally run external workflows.

  • data (mapping, object, sequence, or path-like, optional) – Observed EM data. Mappings can contain freqs/frequencies, rho_a/phase, or times/values for TDEM. Station collections, response-like objects, and survey objects exposing to_soundings() are coerced through pycsamt.inversion.EMData.

  • workdir (path-like, default "pycsamt_inversion") – Directory used for backend files, logs, and prepared external-run inputs. Local backends store provenance here when they create products. External adapters resolve runner files relative to this folder.

  • n_layers (int, default 4) – Number of layered-earth cells for 1-D style parameterizations, including the final halfspace. Built-in 1-D and stitched 2-D workflows use this value unless a supplied starting model defines its own layer count.

  • starting_model (StartingModel, mapping, or object, optional) – Initial layered model. Resistivities are linear ohm-m values and thicknesses are metres. Mappings may use singular or plural keys such as resistivity/resistivities and thickness/thicknesses.

  • reference_model (StartingModel, mapping, or object, optional) – Model used as the reference for damped or smooth regularization when the selected backend supports it. If omitted, solvers regularize against their starting model or backend-native default.

  • error_floor (float, default 0.05) – Relative error floor for amplitude-like components when explicit errors are unavailable. A value of 0.05 means five percent. More detailed rho, phase, impedance, TDEM, and station-mask rules can be supplied through backend_options["error_model"].

  • include_phase (bool, default True) – Whether built-in natural-source objectives include phase observations in addition to apparent resistivity.

  • phase_error (float, default 3.0) – Absolute phase uncertainty in degrees used by MT/AMT/CSAMT objectives when phase errors are unavailable.

  • regularization ({"none", "smooth", "damped", "blocky"}, default "smooth") – Regularization family used by runnable backends. Shared helpers map this vocabulary to built-in residual penalties, pyGIMLi lam values, and SimPEG weighted least-squares settings where possible.

  • max_iter (int, default 80) – Maximum local optimizer iterations or backend iteration request. External adapters may write this value into native control files or record it as lifecycle metadata depending on the backend.

  • tol (float, default 1e-5) – Local optimizer termination tolerance used by runnable backends.

  • bounds (dict, optional) – Optional parameter bounds. Built-in layered inversions understand log10_rho and log10_thickness bounds. Other engines may interpret backend-specific bound keys through backend_options.

  • run_external (bool, default False) – Whether external adapters are allowed to launch compiled executables. When False, Occam2D and ModEM prepare and validate inputs, assemble commands, and return a ready/prepared result without running the binary.

  • backend_options (dict, optional) – Backend-specific options. Common entries include mesh controls, component selection, profile_mode, error-model overrides, SimPEG/pyGIMLi knobs, and external runner file names or executable settings. Unknown keys are passed through to the selected backend.

  • output_dir (str | None)

  • metadata (dict[str, Any])

Examples

>>> import numpy as np
>>> from pycsamt.inversion import InversionConfig, InversionWorkflow, StartingModel
>>> cfg = InversionConfig(
...     method="mt",
...     dimension="1d",
...     backend="builtin",
...     data={"freqs": np.logspace(-1, 2, 8),
...           "rho_a": np.full(8, 100.0),
...           "phase": np.full(8, 45.0)},
...     starting_model=StartingModel([80.0, 200.0], [500.0]),
...     max_iter=4,
... )
>>> result = InversionWorkflow(cfg).run()
method: str = 'mt'#
dimension: str = '1d'#
backend: str = 'builtin'#
data: Any = None#
workdir: str = 'pycsamt_inversion'#
output_dir: str | None = None#
n_layers: int = 4#
starting_model: Any = None#
reference_model: Any = None#
error_floor: float = 0.05#
include_phase: bool = True#
phase_error: float = 3.0#
regularization: str = 'smooth'#
max_iter: int = 80#
tol: float = 1e-05#
bounds: dict[str, Any]#
run_external: bool = False#
backend_options: dict[str, Any]#
metadata: dict[str, Any]#
property output_path: Path#

Resolved output directory.

validate()#

Validate object state.

Subclasses can override this hook. The base implementation intentionally accepts all states.

Return type:

None

to_backend()#

Instantiate the selected backend.

write_template(path, *, fmt=None)#

Write an editable configuration template.

Parameters:
Return type:

Path

classmethod from_file(path, *, strict=True)#

Load a Python/JSON/YAML configuration file.

Parameters:
Return type:

InversionConfig

classmethod read(path, *, strict=True)#

Load a Python/JSON/YAML configuration file.

Parameters:
Return type:

InversionConfig

class pycsamt.inversion.InversionMesh(dimension='1d', x_centers=None, z_centers=None, native=None, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Lightweight mesh/grid descriptor.

InversionMesh is the common mesh metadata object carried by pycsamt.inversion.results.InversionResult. Numerical engines may keep their real discretization object in native while exposing common profile/depth centers through x_centers and z_centers.

Parameters:
  • dimension ({"1d", "2d", "3d"}, default "1d") – Mesh dimensionality represented by this descriptor.

  • x_centers (array-like of float, optional) – Horizontal/profile cell centers in metres. For 1-D meshes this is usually [0.0].

  • z_centers (array-like of float, optional) – Depth cell centers in metres, positive downward.

  • native (object, optional) – Backend-native mesh/grid object, for example a SimPEG TensorMesh or built-in forward Grid2D.

  • metadata (dict, optional) – Free-form mesh provenance such as builder name, backend engine, padding, or core-cell shape.

Examples

>>> from pycsamt.inversion.mesh import InversionMesh
>>> mesh = InversionMesh.for_1d([25.0, 125.0, 275.0])
>>> mesh.dimension
'1d'
>>> mesh.z_centers.tolist()
[25.0, 125.0, 275.0]

References

dimension: str = '1d'#
x_centers: Any = None#
z_centers: Any = None#
native: Any = None#
metadata: dict[str, Any]#
classmethod for_1d(depths)#

Build a 1-D mesh descriptor from depth centres.

Parameters:

depths (array-like of float) – Positive-downward depth cell centers in metres.

Returns:

Descriptor with dimension="1d", x_centers=[0.0], and the supplied depth centers.

Return type:

InversionMesh

Examples

>>> from pycsamt.inversion.mesh import InversionMesh
>>> InversionMesh.for_1d([10.0, 30.0]).z_centers.tolist()
[10.0, 30.0]
validate()#

Validate object state.

Subclasses can override this hook. The base implementation intentionally accepts all states.

Return type:

None

class pycsamt.inversion.InversionResult(method, dimension, backend, status='success', model=None, mesh=None, data=None, predicted=None, rms=nan, objective=nan, n_iter=0, workdir=None, files=<factory>, native=None, uncertainty=None, history=None, warnings=<factory>, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Backend-neutral post-inversion result.

InversionResult is the common result object returned by every inversion backend. It stores recovered models, predicted responses, misfit diagnostics, uncertainty, convergence history, generated files, backend-native objects, and free-form metadata while exposing conversion hooks for plotting, exporting, and hydrogeophysical interpretation.

Parameters:
  • method (str) – EM method label such as "mt", "amt", "csamt", "emap", or "tdem".

  • dimension (('1d', '2d', '3d')) – Inversion dimensionality.

  • backend (str) – Backend name such as "builtin", "simpeg", "pygimli", "occam2d", or "modem".

  • status (str, default "success") – Backend status. Common values include "success", "converged", "needs_review", "prepared", "ready", and "loaded".

  • model (object, optional) – Recovered model. Accepted conversion forms include a layered model or a dictionary with rho_2d and coordinate arrays.

  • mesh (InversionMesh, optional) – Common mesh descriptor.

  • data (object, optional) – Observed and predicted response containers.

  • predicted (object, optional) – Observed and predicted response containers.

  • rms (float, default nan) – Weighted RMS misfit.

  • objective (float, default nan) – Final objective-function value.

  • n_iter (int, default 0) – Number of backend iterations or residual evaluations.

  • workdir (str, optional) – Backend working directory.

  • files (dict, optional) – Generated or backend-native file paths.

  • native (object, optional) – Backend-native result object retained for advanced users.

  • uncertainty (InversionUncertainty or dict, optional) – Uncertainty diagnostics. Dictionaries are coerced automatically.

  • history (InversionHistory, dict, or list, optional) – Convergence history. Dictionaries and record lists are coerced automatically.

  • warnings (list of str, optional) – Backend warnings and lifecycle messages.

  • metadata (dict, optional) – Free-form result provenance.

Examples

Create a minimal 2-D result and convert it to an interpretation model:

>>> import numpy as np
>>> from pycsamt.inversion.results import InversionResult
>>> result = InversionResult(
...     method="mt",
...     dimension="2d",
...     backend="builtin",
...     model={
...         "rho_2d": np.array([[2.0, 2.2]]),
...         "x_centers": np.array([0.0, 500.0]),
...         "z_centers": np.array([100.0]),
...     },
... )
>>> result.to_resistivity_model().rho_2d.shape
(1, 2)

Summarize a result in logs or notebooks:

>>> from pycsamt.inversion.results import InversionResult
>>> InversionResult("mt", "1d", "builtin", rms=1.2).summary()
"InversionResult(method='mt', dimension='1d', backend='builtin', status='success', rms=1.2)"

See also

pycsamt.inversion.export

Export helpers that consume InversionResult.

pycsamt.inversion.plot

Plotting helpers that consume InversionResult.

pycsamt.interp.ResistivityModel

Interpretation model returned by to_resistivity_model().

References

method: str#
dimension: str#
backend: str#
status: str = 'success'#
model: Any = None#
mesh: InversionMesh | None = None#
data: Any = None#
predicted: Any = None#
rms: float = nan#
objective: float = nan#
n_iter: int = 0#
workdir: str | None = None#
files: dict[str, str]#
native: Any = None#
uncertainty: InversionUncertainty | None = None#
history: InversionHistory | None = None#
warnings: list[str]#
metadata: dict[str, Any]#
property converged: bool#

Whether the backend reported a usable result.

Returns:

True for statuses "success", "converged", "prepared", and "loaded".

Return type:

bool

Examples

>>> from pycsamt.inversion.results import InversionResult
>>> InversionResult("mt", "1d", "builtin", status="converged").converged
True
to_resistivity_model()#

Convert the result to pycsamt.interp.ResistivityModel.

2-D result arrays are passed through directly. A recovered 1-D layered model is expanded to one column so the interpretation API can consume it uniformly.

Returns:

Unified 2-D log10 resistivity model with profile and depth coordinates.

Return type:

pycsamt.interp.ResistivityModel

Raises:

ValueError – If no model is attached or if the attached model cannot be adapted to a resistivity section.

Notes

The conversion accepts three result forms:

  • backend-native Occam-like objects exposing rho_2d;

  • dictionaries containing rho_2d plus coordinate arrays;

  • layered models exposing resistivities and thicknesses.

Examples

>>> import numpy as np
>>> from pycsamt.inversion.results import InversionResult
>>> result = InversionResult(
...     method="mt",
...     dimension="2d",
...     backend="builtin",
...     model={
...         "rho_2d": np.array([[2.0, 2.2]]),
...         "x_centers": np.array([0.0, 500.0]),
...         "z_centers": np.array([100.0]),
...     },
... )
>>> result.to_resistivity_model().n_x
2
summary(*, max_fields=None)#

Return a compact one-line result summary.

Parameters:

max_fields (int, optional) – Reserved for future expanded summaries. Currently ignored.

Returns:

Human-readable summary containing method, dimension, backend, status, and RMS.

Return type:

str

Examples

>>> from pycsamt.inversion.results import InversionResult
>>> InversionResult("mt", "1d", "builtin", rms=1.2).summary()
"InversionResult(method='mt', dimension='1d', backend='builtin', status='success', rms=1.2)"
class pycsamt.inversion.InversionUncertainty(model_std=None, covariance_diag=None, sensitivity=None, confidence=None, station_confidence=None, depth_confidence=None, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Backend-neutral uncertainty and sensitivity diagnostics.

InversionUncertainty stores uncertainty products in a common shape for exports, plots, and interpretation. Built-in solvers currently provide proxy diagnostics from least-squares Jacobians; optional engines may attach richer posterior or sensitivity products over time.

Parameters:
  • model_std (array-like, optional) – Per-model-cell standard-deviation proxy.

  • covariance_diag (array-like, optional) – Diagonal covariance or covariance-like proxy.

  • sensitivity (array-like, optional) – Relative model sensitivity map.

  • confidence (array-like, optional) – Normalized confidence map, typically scaled to [0, 1].

  • station_confidence (array-like, optional) – One confidence value per station.

  • depth_confidence (array-like, optional) – One confidence value per depth cell.

  • metadata (dict, optional) – Free-form uncertainty provenance.

Examples

Store model confidence and sensitivity maps:

>>> from pycsamt.inversion.results import InversionUncertainty
>>> uncertainty = InversionUncertainty(
...     confidence=[[0.9, 0.8]],
...     sensitivity=[[1.0, 0.5]],
... )
>>> uncertainty.confidence.shape
(1, 2)

References

model_std: Any = None#
covariance_diag: Any = None#
sensitivity: Any = None#
confidence: Any = None#
station_confidence: Any = None#
depth_confidence: Any = None#
metadata: dict[str, Any]#
class pycsamt.inversion.InversionWorkflow(config=None, **kw)#

Bases: PyCSAMTObject

Execute a configured EM inversion backend.

InversionWorkflow is the object-oriented entry point for running EM inversions. It owns one normalized pycsamt.inversion.config.InversionConfig and one instantiated backend. Calling run() delegates to that backend and returns a common pycsamt.inversion.results.InversionResult.

Parameters:
  • config (InversionConfig or dict, optional) – Complete inversion configuration. Dictionaries are converted to pycsamt.inversion.config.InversionConfig. Keyword arguments override matching configuration fields. If omitted, keyword arguments are used to build a default configuration.

  • **kw – Configuration fields that override values supplied by config. Common keys include method, dimension, backend, data, starting_model, max_iter, regularization, and backend_options.

Returns:

result – Backend-neutral inversion output. It stores the recovered model, mesh, predicted response, RMS/objective values, files, warnings, native backend objects, uncertainty diagnostics, convergence history, and metadata.

Return type:

InversionResult

Notes

The workflow does not mutate caller-provided data. A per-call data override can be supplied to run(), which is convenient for applying the same configuration to multiple soundings or profiles.

Examples

Run from an explicit configuration object:

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.workflow import InversionWorkflow
>>> cfg = InversionConfig(
...     method="mt",
...     dimension="1d",
...     backend="builtin",
...     data={"freqs": [1.0, 10.0],
...           "rho_a": [100.0, 120.0],
...           "phase": [45.0, 47.0]},
...     max_iter=4,
... )
>>> result = InversionWorkflow(cfg).run()

Run from a dictionary in one line:

>>> from pycsamt.inversion.workflow import run_inversion
>>> result = run_inversion({
...     "method": "tdem",
...     "dimension": "1d",
...     "backend": "builtin",
...     "data": {"times": [1e-5, 1e-4],
...              "values": [1e-8, 2e-9]},
...     "max_iter": 4,
... })

See also

pycsamt.inversion.config.InversionConfig

Configuration consumed by the workflow.

pycsamt.inversion.backends.get_backend

Backend registry used by InversionConfig.to_backend.

pycsamt.inversion.results.InversionResult

Result returned by run().

References

run(data=None)#

Run the selected backend.

Parameters:

data (mapping, object, sequence, or path-like, optional) – Optional data override for this call. When omitted, config.data is used. Accepted values are backend-dependent but normally pass through pycsamt.inversion.data.EMData.coerce.

Returns:

Backend-neutral result containing recovered model, RMS/objective diagnostics, files, warnings, uncertainty, history, and native backend objects when available.

Return type:

InversionResult

Examples

>>> from pycsamt.inversion.workflow import InversionWorkflow
>>> workflow = InversionWorkflow(
...     method="mt",
...     dimension="1d",
...     backend="builtin",
...     max_iter=4,
... )
>>> result = workflow.run({
...     "freqs": [1.0, 10.0],
...     "rho_a": [100.0, 120.0],
...     "phase": [45.0, 47.0],
... })
pycsamt.inversion.ReferenceModel#

alias of StartingModel

class pycsamt.inversion.Regularization(kind='smooth', alpha_s=1.0, alpha_x=1.0, alpha_z=1.0, reference_weight=0.0, metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Backend-neutral regularization settings.

Regularization stores the model-structure penalty vocabulary shared by built-in, SimPEG, and pyGIMLi inversion paths. The residual helpers operate on model-parameter arrays, usually log-domain resistivity values, and return unweighted structure residuals that can be multiplied by a global scalar such as \(\sqrt{\lambda}\).

For a smooth model \(m\), the penalty contains finite differences such as

\[\phi_m = \alpha_x \|\nabla_x m\|_2^2 + \alpha_z \|\nabla_z m\|_2^2 .\]

For damped/reference regularization, a smallness term \(\alpha_s\|m-m_{ref}\|_2^2\) is added. For "blocky" models, the finite differences are normalized by \(\sqrt{(\Delta m)^2 + \epsilon^2}\) to reduce sensitivity to sharp edges.

Parameters:
  • kind ({"none", "smooth", "damped", "blocky"}, default "smooth") – Regularization family. "none" disables the penalty, "smooth" penalizes model roughness, "damped" combines smallness/reference and roughness terms, and "blocky" applies an edge-preserving normalized gradient penalty.

  • alpha_s (float, default 1.0) – Smallness or reference-model weight. This controls residual terms of the form \(m - m_{ref}\) when damping/reference regularization is active.

  • alpha_x (float, default 1.0) – Lateral roughness weight applied along the profile or X axis.

  • alpha_z (float, default 1.0) – Vertical roughness weight applied along the depth or Z axis.

  • reference_weight (float, default 0.0) – Extra multiplier for the reference-model term. When a reference model is provided, values below one are promoted to one for damped/smallness terms.

  • metadata (dict, optional) – Free-form provenance metadata attached to the regularization settings.

Notes

This class stores relative penalty settings only. The scalar objective weight is read separately by regularization_weight(), while pyGIMLi-specific lambda handling is read by pygimli_lambda().

Examples

Build a smoothness penalty for a 2-D log-resistivity model:

>>> import numpy as np
>>> from pycsamt.inversion.regularization import Regularization
>>> from pycsamt.inversion.regularization import regularization_residual
>>> reg = Regularization(kind="smooth", alpha_x=2.0, alpha_z=1.0)
>>> residual = regularization_residual(np.ones((3, 4)), regularization=reg)
>>> residual.size
17

Read shared settings from an inversion config:

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.regularization import regularization_from_config
>>> cfg = InversionConfig(regularization="damped",
...     backend_options={"alpha_s": 0.5, "regularization_weight": 2.0})
>>> regularization_from_config(cfg).alpha_s
0.5

References

kind: str = 'smooth'#
alpha_s: float = 1.0#
alpha_x: float = 1.0#
alpha_z: float = 1.0#
reference_weight: float = 0.0#
metadata: dict[str, Any]#
validate()#

Validate regularization kind and non-negative weights.

Raises:

ValueError – If kind is not one of "none", "smooth", "damped", or "blocky", or if any alpha/reference weight is negative.

Return type:

None

Examples

>>> from pycsamt.inversion.regularization import Regularization
>>> Regularization(kind="smooth", alpha_x=1.0).validate() is None
True
class pycsamt.inversion.StartingModel(resistivities, thicknesses, name='', metadata=<factory>)#

Bases: PyCSAMTObject, MetadataMixin

Starting or recovered layered-earth model.

Resistivities are linear ohm-m values. The final layer is a halfspace, so len(thicknesses) must equal len(resistivities) - 1.

ReferenceModel is currently an alias of StartingModel. Use it when the same layer container is being supplied as a regularization reference rather than as an optimizer starting point.

Parameters:
  • resistivities (array-like of float) – Layer resistivities in ohm metres. Values must be strictly positive. The last value represents the bottom halfspace.

  • thicknesses (array-like of float) – Layer thicknesses in metres. Values must be strictly positive and the array length must be len(resistivities) - 1 because the final layer is a halfspace.

  • name (str, optional) – Human-readable model label recorded with the object and passed to forward model adapters where supported.

  • metadata (dict, optional) – Free-form provenance metadata attached to the model.

Notes

The model is deliberately small and backend-neutral. Built-in solvers optimize log10(resistivity) and log10(thickness) internally, but this public container stores physical linear values in ohm metres and metres.

Examples

Build a three-layer model with a conductive target over a resistive basement:

>>> from pycsamt.inversion.model import StartingModel
>>> start = StartingModel([100.0, 30.0, 800.0], [200.0, 900.0])
>>> start.n_layers
3
>>> start.depths.tolist()
[0.0, 200.0, 1100.0]

Coerce a mapping supplied in a configuration file:

>>> from pycsamt.inversion.model import StartingModel
>>> start = StartingModel.coerce({
...     "resistivities": [80.0, 250.0],
...     "thicknesses": [500.0],
... })
>>> start.resistivities.tolist()
[80.0, 250.0]

References

resistivities: Any#
thicknesses: Any#
name: str = ''#
metadata: dict[str, Any]#
classmethod default(n_layers=4)#

Return a conservative layered starting model.

Parameters:

n_layers (int, default 4) – Number of layers, including the bottom halfspace.

Returns:

Default model with 100 ohm-m layers and geometrically increasing thicknesses between 100 m and 2000 m.

Return type:

StartingModel

Raises:

ValueError – If n_layers < 2.

Examples

>>> from pycsamt.inversion.model import StartingModel
>>> start = StartingModel.default(n_layers=3)
>>> start.resistivities.tolist()
[100.0, 100.0, 100.0]
>>> start.thicknesses.size
2
classmethod from_dict(data)#

Build from singular or plural mapping keys.

Parameters:

data (mapping) – Model mapping. Accepted keys are resistivity or resistivities for layer resistivity, thickness or thicknesses for layer thickness, plus optional name and metadata.

Returns:

Validated layered-earth model.

Return type:

StartingModel

Examples

>>> from pycsamt.inversion.model import StartingModel
>>> start = StartingModel.from_dict({
...     "resistivity": [100.0, 500.0],
...     "thickness": [250.0],
...     "name": "two_layer",
... })
>>> start.name
'two_layer'
classmethod coerce(value, *, n_layers=4)#

Return value as a StartingModel.

Parameters:
  • value (StartingModel, mapping, object, or None) – Input model. Existing StartingModel instances are returned unchanged. Mappings are read by from_dict(). Generic objects may expose resistivity/resistivities and thickness/thicknesses attributes.

  • n_layers (int, default 4) – Number of layers used only when value is None and a default model must be created.

Returns:

Validated layered-earth model.

Return type:

StartingModel

Examples

>>> from pycsamt.inversion.model import StartingModel
>>> StartingModel.coerce(None, n_layers=2).n_layers
2
>>> StartingModel.coerce({
...     "resistivities": [80.0, 250.0],
...     "thicknesses": [500.0],
... }).depths.tolist()
[0.0, 500.0]
property n_layers: int#
property depths: ndarray#

Top-of-layer depths in metres.

Examples

>>> from pycsamt.inversion.model import StartingModel
>>> StartingModel([100.0, 300.0, 800.0], [50.0, 150.0]).depths.tolist()
[0.0, 50.0, 200.0]
to_layered_model()#

Return the existing pycsamt.forward.LayeredModel.

This adapter lets inversion starting/recovered models reuse the forward modelling API without duplicating layer containers.

Returns:

Forward-model-compatible layered earth.

Return type:

pycsamt.forward.LayeredModel

Examples

>>> from pycsamt.inversion.model import StartingModel
>>> layered = StartingModel([100.0, 300.0], [500.0]).to_layered_model()
>>> layered.n_layers
2
validate()#

Validate layer shape and positivity.

Raises:

ValueError – If resistivities or thicknesses are not 1-D, if fewer than two resistivity layers are supplied, if thickness count does not equal len(resistivities) - 1, or if any value is non-positive.

Return type:

None

Examples

>>> from pycsamt.inversion.model import StartingModel
>>> StartingModel([100.0, 300.0], [500.0]).validate() is None
True
pycsamt.inversion.available_backends()#

Return registered backend names.

Return type:

list[str]

class pycsamt.inversion.MT1DInversion(data=None, **kwargs)#

Bases: ConfiguredInversionWorkflow

Built-in 1-D MT inversion workflow.

Parameters:
method: str = 'mt'#
dimension: str = '1d'#
backend: str = 'builtin'#
class pycsamt.inversion.MT2DInversion(data=None, **kwargs)#

Bases: ConfiguredInversionWorkflow

Built-in stitched 2-D MT inversion workflow.

Parameters:
method: str = 'mt'#
dimension: str = '2d'#
backend: str = 'builtin'#
class pycsamt.inversion.MT3DInversion(data=None, **kwargs)#

Bases: ConfiguredInversionWorkflow

ModEM 3-D MT inversion workflow.

Parameters:
method: str = 'mt'#
dimension: str = '3d'#
backend: str = 'modem'#
class pycsamt.inversion.SimPEGMT3DInversion(data=None, **kwargs)#

Bases: ConfiguredInversionWorkflow

SimPEG 3-D MT inversion workflow.

Parameters:
method: str = 'mt'#
dimension: str = '3d'#
backend: str = 'simpeg'#
pycsamt.inversion.build_1d_tensor_mesh(start, options, tensor_mesh_cls)#

Build a 1-D TensorMesh-like object and positive-downward centres.

This helper centralizes the depth discretization used by optional engines such as SimPEG. The caller supplies the actual TensorMesh class so this module stays free of optional dependencies.

Parameters:
  • start (object) – Starting model exposing n_layers, resistivities, and thicknesses.

  • options (dict, optional) – Mesh controls. Recognized keys include n_cells, depth_max, origin, min_cell_size, and growth_factor.

  • tensor_mesh_cls (type) – TensorMesh-like constructor accepting ([widths], origin=...).

Returns:

  • mesh (object) – Backend-native 1-D tensor mesh.

  • z_centers (ndarray) – Positive-downward depth cell centers in metres.

Return type:

tuple[Any, ndarray]

Examples

>>> import numpy as np
>>> from pycsamt.inversion.mesh import build_1d_tensor_mesh
>>> from pycsamt.inversion.model import StartingModel
>>> class TensorMesh:
...     def __init__(self, widths, origin="0"):
...         self.widths = widths
...         self.origin = origin
>>> start = StartingModel([100.0, 300.0], [500.0])
>>> mesh, z = build_1d_tensor_mesh(
...     start, {"n_cells": 2, "depth_max": 100.0, "growth_factor": 1.0}, TensorMesh
... )
>>> np.round(z, 1).tolist()
[25.0, 75.0]
pycsamt.inversion.build_3d_tensor_mesh(station_x, station_y, options, tensor_mesh_cls)#

Build a 3-D TensorMesh-like object around station coordinates.

The helper constructs uniform horizontal cells around the station footprint and geometrically growing depth cells. It is used by optional 3-D physics paths while keeping the native mesh class injectable.

Parameters:
  • station_x (array-like of float) – Station coordinates in metres.

  • station_y (array-like of float) – Station coordinates in metres.

  • options (dict, optional) – Mesh controls. Recognized keys include x_pad, y_pad, depth_max, nx, ny, nz, min_cell_size, and growth_factor.

  • tensor_mesh_cls (type) – TensorMesh-like constructor accepting ([hx, hy, hz], origin=...).

Returns:

  • mesh (object) – Backend-native 3-D tensor mesh.

  • centers (dict of ndarray) – Cell-center arrays with keys "x", "y", "z", and "z_depth". z follows the native mesh coordinate with depth negative; z_depth is positive downward.

Return type:

tuple[Any, dict[str, ndarray]]

Examples

>>> from pycsamt.inversion.mesh import build_3d_tensor_mesh
>>> class TensorMesh:
...     def __init__(self, widths, origin=None):
...         self.widths = widths
...         self.origin = origin
>>> mesh, centers = build_3d_tensor_mesh(
...     [0.0, 100.0], [0.0, 50.0],
...     {"nx": 2, "ny": 2, "nz": 2, "depth_max": 100.0}, TensorMesh
... )
>>> sorted(centers)
['x', 'y', 'z', 'z_depth']
pycsamt.inversion.build_fd2d_grid(start, station_x, options, grid_cls, *, make_padding_func=None)#

Build the finite-difference 2-D grid used by built-in inversion.

This builder creates the starting Grid2D-like object for the built-in finite-difference MT/AMT/CSAMT profile inversion. It shifts station coordinates into the grid coordinate system, adds optional lateral/depth padding, and expands the layered starting model into a 2-D resistivity array.

Parameters:
  • start (object) – Starting model exposing resistivities and thicknesses.

  • station_x (array-like of float) – Station positions along profile in metres. At least two distinct stations are required.

  • options (dict, optional) – Grid controls. Recognized keys include nx/fd2d_nx, n_pad/fd2d_n_pad, pad_factor, x_margin, x_max, and halfspace_thickness.

  • grid_cls (type) – Grid2D-like constructor accepting dx, dz, resistivity, x_stations, n_pad, and name.

  • make_padding_func (callable, optional) – Padding-width function. If omitted, pycsamt.forward.make_padding() is imported lazily.

Returns:

  • grid (object) – Built finite-difference grid.

  • core_shape (tuple of int) – (nz_core, nx_core) shape of the unpadded inversion core.

Return type:

tuple[Any, tuple[int, int]]

Examples

>>> from pycsamt.inversion.mesh import build_fd2d_grid
>>> from pycsamt.inversion.model import StartingModel
>>> class Grid:
...     def __init__(self, dx, dz, resistivity, x_stations, n_pad, name):
...         self.dx = dx
...         self.dz = dz
...         self.resistivity = resistivity
...         self.x_stations = x_stations
>>> start = StartingModel([100.0, 300.0], [500.0])
>>> grid, core_shape = build_fd2d_grid(
...     start, [0.0, 1000.0], {"nx": 2, "n_pad": 0}, Grid
... )
>>> core_shape
(2, 2)
pycsamt.inversion.component_errors(values, cfg, *, component, explicit=None, relative=False)#

Return errors for one data component using config settings.

Parameters:
  • values (array-like) – Data values used for scaling.

  • cfg (object) – Inversion config-like object accepted by error_model_from_config().

  • component (str) – Component name or alias.

  • explicit (array-like, optional) – Explicit data errors.

  • relative (bool, default False) – Return relative errors instead of absolute errors.

Returns:

Component error array.

Return type:

ndarray

Examples

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.objective import component_errors
>>> cfg = InversionConfig(error_floor=0.05, phase_error=2.0)
>>> component_errors([100.0, 200.0], cfg, component="rho").tolist()
[5.0, 10.0]
>>> component_errors([45.0], cfg, component="phase").tolist()
[2.0]
pycsamt.inversion.component_mask(values, cfg, *, component)#

Return a boolean mask for one component using config mask settings.

Parameters:
  • values (array-like) – Data array whose shape defines the returned mask shape.

  • cfg (object) – Inversion config-like object accepted by error_model_from_config().

  • component (str) – Component name or alias.

Returns:

Boolean inclusion mask.

Return type:

ndarray of bool

Examples

>>> import numpy as np
>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.objective import component_mask
>>> cfg = InversionConfig(backend_options={"masks": {"station": [True, False]}})
>>> component_mask(np.ones((2, 2)), cfg, component="rho").tolist()
[[True, True], [False, False]]
pycsamt.inversion.core_rho_from_start(start, nz, nx)#

Expand a layered starting model into a 2-D core resistivity grid.

Parameters:
  • start (object) – Starting model exposing resistivities.

  • nz (int) – Number of vertical and horizontal core cells.

  • nx (int) – Number of vertical and horizontal core cells.

Returns:

Resistivity grid with shape (nz, nx). If nz is larger than the number of supplied layers, the final layer resistivity is repeated.

Return type:

ndarray

Examples

>>> from pycsamt.inversion.mesh import core_rho_from_start
>>> from pycsamt.inversion.model import StartingModel
>>> start = StartingModel([100.0, 300.0], [500.0])
>>> core_rho_from_start(start, 3, 2).tolist()
[[100.0, 100.0], [300.0, 300.0], [300.0, 300.0]]
pycsamt.inversion.depth_widths(depth_max, n_cells, options=None)#

Return geometrically growing positive depth cell widths.

Parameters:
  • depth_max (float) – Total target depth in metres. The returned widths sum to this value.

  • n_cells (int) – Number of depth cells.

  • options (dict, optional) – Mesh options. Recognized keys are min_cell_size and growth_factor. Defaults are chosen conservatively from depth_max and n_cells.

Returns:

Positive cell widths in metres.

Return type:

ndarray

Raises:

ValueError – If depth_max, n_cells, min_cell_size, or growth_factor are not positive.

Examples

>>> from pycsamt.inversion.mesh import depth_widths
>>> depth_widths(100.0, 4, {"growth_factor": 1.0}).round(2).tolist()
[25.0, 25.0, 25.0, 25.0]

References

pycsamt.inversion.error_model_from_config(cfg)#

Build an ErrorModel from inversion config options.

Parameters:

cfg (object) – Inversion config-like object exposing error_floor, phase_error, and optional backend_options. Overrides may be placed directly in backend_options or inside backend_options["error_model"].

Returns:

Component-aware error model.

Return type:

ErrorModel

Examples

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.objective import error_model_from_config
>>> cfg = InversionConfig(error_floor=0.1, phase_error=2.0)
>>> model = error_model_from_config(cfg)
>>> model.rho_relative
0.1
>>> model.phase_absolute
2.0
pycsamt.inversion.get_backend(name)#

Return the backend class for name using lazy imports.

Parameters:

name (str)

pycsamt.inversion.pygimli_lambda(cfg, *, default=20.0)#

Return the pyGIMLi lambda value using shared option names.

Parameters:
  • cfg (object) – Inversion config-like object with optional backend_options.

  • default (float, default 20.0) – Fallback value when no lambda-like option is configured.

Returns:

Value from lam, lambda, or regularization_weight in that priority order.

Return type:

float

Examples

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.regularization import pygimli_lambda
>>> cfg = InversionConfig(backend_options={"lam": 7.0})
>>> pygimli_lambda(cfg)
7.0
pycsamt.inversion.regularization_from_config(cfg)#

Build backend-neutral controls from a config object.

Parameters:

cfg (object) – Inversion config-like object exposing regularization and optional backend_options. Recognized backend options include alpha_s, alpha_model, alpha_x, alpha_lateral, alpha_z, alpha_vertical, reference_weight, and regularization_metadata.

Returns:

Parsed regularization settings.

Return type:

Regularization

Examples

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.regularization import regularization_from_config
>>> cfg = InversionConfig(regularization="blocky",
...     backend_options={"alpha_x": 2.0, "alpha_z": 0.5})
>>> reg = regularization_from_config(cfg)
>>> (reg.kind, reg.alpha_x, reg.alpha_z)
('blocky', 2.0, 0.5)
pycsamt.inversion.regularization_residual(values, *, reference=None, regularization=None, blocky_eps=0.01, axes=None)#

Return unweighted residual terms for smooth/damped/blocky penalties.

values are normally log-domain model parameters. The returned vector already contains the square-root alpha factors; callers can multiply by a global scalar such as sqrt(regularization_weight).

Parameters:
  • values (array-like) – Model parameter array. One-dimensional arrays are treated as depth profiles. Two-dimensional arrays are treated as (z, x) sections.

  • reference (array-like, optional) – Reference model with the same shape as values or broadcastable to that shape.

  • regularization (Regularization, optional) – Regularization settings. If omitted, Regularization() is used.

  • blocky_eps (float, default 1e-2) – Stabilization value in the blocky normalized-gradient penalty.

  • axes (tuple of {"x", "z"}, optional) – Axes on which to compute roughness. Defaults to ("z",) for 1-D arrays and ("x", "z") for 2-D or higher arrays.

Returns:

Concatenated residual vector. Empty when kind="none" or all active penalty terms have zero weight.

Return type:

ndarray

Examples

>>> import numpy as np
>>> from pycsamt.inversion.regularization import Regularization
>>> from pycsamt.inversion.regularization import regularization_residual
>>> reg = Regularization(kind="damped", alpha_s=1.0, alpha_z=1.0)
>>> residual = regularization_residual(np.array([1.0, 2.0, 4.0]),
...     reference=np.ones(3), regularization=reg)
>>> residual.size
5

References

pycsamt.inversion.regularization_weight(cfg, *, default=0.0)#

Return the scalar penalty weight for least-squares backends.

Parameters:
  • cfg (object) – Inversion config-like object with optional backend_options.

  • default (float, default 0.0) – Value returned when no shared weight is configured.

Returns:

Value from backend_options["regularization_weight"] or backend_options["reg_weight"].

Return type:

float

Examples

>>> from pycsamt.inversion.config import InversionConfig
>>> from pycsamt.inversion.regularization import regularization_weight
>>> cfg = InversionConfig(backend_options={"regularization_weight": 3.0})
>>> regularization_weight(cfg)
3.0
pycsamt.inversion.run_inversion(config=None, **kw)#

Run an inversion in one call.

This convenience function is equivalent to InversionWorkflow(config, **kw).run(). It is useful in scripts, notebooks, tests, and demos where the workflow object does not need to be reused.

Parameters:
Returns:

Backend-neutral inversion result.

Return type:

InversionResult

Examples

>>> from pycsamt.inversion.workflow import run_inversion
>>> result = run_inversion(
...     method="mt",
...     dimension="1d",
...     backend="builtin",
...     data={"freqs": [1.0, 10.0],
...           "rho_a": [100.0, 120.0],
...           "phase": [45.0, 47.0]},
...     max_iter=4,
... )

Core Modules#

pycsamt.inversion.config

Configuration for physics-based EM inversion workflows.

pycsamt.inversion.workflow

High-level inversion workflow entry point.

pycsamt.inversion.data

Data containers for physics-based EM inversion workflows.

pycsamt.inversion.model

Model containers used by pycsamt.inversion.

pycsamt.inversion.mesh

Mesh descriptions and builders for EM inversion workflows.

pycsamt.inversion.objective

Objective-function helpers for inversion backends.

pycsamt.inversion.regularization

Regularization controls for inversion workflows.

pycsamt.inversion.results

Unified inversion result container.

pycsamt.inversion.export

Export helpers for pycsamt.inversion results.

pycsamt.inversion.plot

Plotting helpers for pycsamt.inversion results.

Backend Modules#

pycsamt.inversion.backends

Backend registry for pycsamt.inversion.

pycsamt.inversion.backends.builtin

Built-in dependency-light EM inversion backend.

pycsamt.inversion.backends.occam2d

Occam2D adapter backend.

pycsamt.inversion.backends.modem

ModEM adapter backend.

pycsamt.inversion.backends.simpeg

SimPEG backend for physics-based EM inversion.

pycsamt.inversion.backends.pygimli

pyGIMLi backend for EM inversion.

Method Modules#

pycsamt.inversion.mt.inv1d

1-D MT inversion convenience wrapper.

pycsamt.inversion.mt.inv2d

2-D MT inversion convenience wrapper.

pycsamt.inversion.mt.inv3d

3-D MT inversion convenience wrappers.

pycsamt.inversion.amt.inv1d

1-D AMT inversion convenience wrapper.

pycsamt.inversion.amt.inv2d

2-D AMT inversion convenience wrapper.

pycsamt.inversion.emap.inv2d

2-D EMAP inversion convenience wrapper.

pycsamt.inversion.tdem.inv1d

1-D TDEM inversion convenience wrapper.

pycsamt.inversion.tdem.inv2d

2-D TDEM inversion convenience wrapper.