pycsamt.inversion.data#

Data containers for physics-based EM inversion workflows.

Classes

EMData([method, frequencies, times, rho_a, ...])

Normalized EM observation container.

class pycsamt.inversion.data.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>)[source]#

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)[source]#

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')[source]#

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[source]#

Return the number of primary samples.

property n_stations: int[source]#

Return the number of stations/soundings represented.

property has_mt_response: bool[source]#

Whether apparent resistivity/phase observations are available.

property has_tdem_response: bool[source]#

Whether time-domain EM decay observations are available.

validate()[source]#

Validate basic shape consistency.

Return type:

None

Parameters: