pycsamt.models.modem#

pycsamt.models.modem — Python interface to the ModEM MT inversion code.

ModEM (Modular EM inversion system) supports 2-D and 3-D magnetotelluric inversion using a nonlinear conjugate-gradient (NLCG) algorithm.

References

Egbert, G.D. & Kelbert, A. (2012). Computational recipes for electromagnetic inverse problems. Geophysical Journal International, 189(1), 251-267.

Kelbert, A., Meqbel, N., Egbert, G.D., Tandon, K. (2014). ModEM: A modular system for inversion of electromagnetic geophysical data. Computers & Geosciences, 66, 40-53.

Quick start — 3D#

>>> from pycsamt.models.modem import ModEmConfig, InputBuilder
>>> cfg = ModEmConfig(mode='3d', initial_rho=100.0)
>>> builder = InputBuilder(config=cfg)
>>> builder.build(edi_source, workdir='./modem_run')
>>> from pycsamt.models.modem import ModEmRunner
>>> ModEmRunner(workdir='./modem_run', config=cfg).run()
>>> from pycsamt.models.modem import InversionResult
>>> result = InversionResult(workdir='./modem_run')
>>> result.plot_model().savefig('model.png')
class pycsamt.models.modem.ModEmConfig(mode='3d', component_type='Full_Impedance', sign_convention='exp(+i\\omega t)', units='[mV/km]/[nT]', error_floor_z=0.05, error_floor_z_floor=0.0, freq_min=None, freq_max=None, nx_2d=100, nz_2d=50, n_airlayers_2d=5, cell_size_h_2d=100.0, cell_size_v_top_2d=10.0, depth_scale_2d=1.2, n_padding_x_2d=7, nx=20, ny=20, nz=30, n_airlayers=5, cell_size_h=500.0, cell_size_v_top=10.0, depth_scale=1.2, n_padding_xy=7, smooth_x=0.1, smooth_y=0.1, smooth_z=0.1, n_smooth_iter=2, max_iterations=100, target_rms=1.05, initial_lambda=10.0, lambda_divisor=100.0, initial_alpha=10.0, rms_diff_tol=0.0005, lambda_exit=0.0001, initial_rho=100.0, data_file='ModEMData.dat', model_file='ModEM_Model.rho', covariance_file='ModEM.cov', control_file='ModEM.inv', log_file='Modular_NLCG.log', output_stem='ModEM_out', binary_2d='Mod2DMT', binary_3d='Mod3DMT', use_mpi=False, n_procs=4, mpi_command='mpirun')#

Bases: object

Collect settings that define a ModEM run.

ModEmConfig is the central configuration object for the ModEM v2 subpackage. It is a plain dataclass, so values may be set at construction time, changed before building files, or shared across data, model, covariance, control, runner, and result objects. The class does not perform file I/O or launch the ModEM executable; it records the choices used by those objects.

The configuration covers six workflow areas:

  • dimensionality and data-component selection;

  • impedance units, sign convention, and error floors;

  • 2-D and 3-D starting-model geometry;

  • 3-D covariance smoothing and active-cell behavior;

  • nonlinear inversion-control values;

  • file names, executable names, and MPI launch settings.

The starting-model classes store resistivity in logarithmic form. For a positive half-space resistivity \(\rho_0\), the initial model value is commonly

\[m_0 = \ln(\rho_0).\]

ModEM then updates this model while balancing data fit and regularization [1]_, [2]_.

Dimensionality#

mode{“2d”, “3d”}, default “3d”

Dimensionality of the ModEM workflow. "2d" selects two-dimensional input formats and the Mod2DMT binary. "3d" selects three-dimensional formats, writes a covariance file, and uses the Mod3DMT binary by default. The value also controls which model class is built from survey data.

Data Options#

component_typestr, default “Full_Impedance”

ModEM data component family written to the data file. Typical 2-D choices are "TE_Impedance" and "TM_Impedance". Common 3-D choices include "Full_Impedance", "Off_Diagonal_Impedance", "Determinant_Impedance", and "Full_Vertical_Components". The selected component controls which impedance tensor entries are exported.

sign_conventionstr, default “exp(+i\omega t)”

Time-harmonic sign convention recorded in the ModEM data header. Use "exp(+i\\omega t)" or "exp(-i\\omega t)" to match the convention used by the impedance estimates. A mismatch changes the sign of imaginary components and can lead to inconsistent phase responses.

unitsstr, default “[mV/km]/[nT]”

Impedance units written to the data-file header. The default corresponds to common magnetotelluric field units. Use "[V/m]/[T]" when the impedance tensors are stored in SI units. Unit consistency is important because ModEM interprets data values directly from the file.

error_floor_zfloat, default 0.05

Relative impedance-error floor expressed as a fraction of \(|Z|\). A value of 0.05 enforces a five percent minimum uncertainty on each impedance component. The floor prevents very small formal errors from dominating the objective function and stabilizes inversion weighting.

error_floor_z_floorfloat, default 0.0

Absolute lower bound applied to impedance errors after the relative floor. Use this when some components have very small amplitudes and \(|Z|\)-scaled errors alone would still be too small for a stable inversion.

freq_minfloat, optional

Lower frequency limit in hertz. Frequencies below this value are excluded when building ModEM data from EDI-like sources. Use it to remove low-frequency samples that are noisy, sparsely sampled, or outside the desired depth range.

freq_maxfloat, optional

Upper frequency limit in hertz. Frequencies above this value are excluded when building ModEM data from EDI-like sources. Use it to remove high-frequency samples affected by near-surface noise, instrument limits, or processing artefacts.

2-D Grid Options#

nx_2dint, default 100

Number of core horizontal cells in a 2-D ModEM model. The cells describe the inversion region along profile before lateral padding is added. Larger values can represent more lateral structure but increase model size and run time.

nz_2dint, default 50

Number of active earth layers in a 2-D ModEM model. This count excludes air layers. More layers allow finer depth variation but require enough period coverage to constrain the additional parameters.

n_airlayers_2dint, default 5

Number of air layers placed above the earth in 2-D models. Air layers allow the forward solver to represent the air-earth boundary. Their resistivity is normally fixed to a very high value and is not interpreted geologically.

cell_size_h_2dfloat, default 100.0

Nominal horizontal cell width in metres near the 2-D station zone. Smaller values increase near-station resolution and file size. The value should be chosen with station spacing and shortest useful period in mind.

cell_size_v_top_2dfloat, default 10.0

Thickness in metres of the shallowest earth layer in a 2-D model. Subsequent layers grow geometrically according to depth_scale_2d. Choose a value fine enough to represent shallow sensitivity without over-refining the mesh.

depth_scale_2dfloat, default 1.2

Geometric growth factor for 2-D earth-layer thicknesses. Values slightly greater than one create gradually thicker cells with depth. Larger values reach great depths with fewer layers but reduce vertical resolution.

n_padding_x_2dint, default 7

Number of lateral padding cells added to each side of the 2-D station zone. Padding moves artificial boundaries away from the survey line and helps reduce edge effects in forward responses.

3-D Grid Options#

nxint, default 20

Number of core cells along the ModEM 3-D x direction, commonly local northing. Padding cells are added outside this core region. Increase the value when station coverage or expected structure requires finer north-south detail.

nyint, default 20

Number of core cells along the ModEM 3-D y direction, commonly local easting. Padding cells are added outside this core region. Increase the value when the survey has dense east-west coverage or strong lateral gradients.

nzint, default 30

Number of active earth layers in a 3-D ModEM model. The count excludes air layers. The depth range and vertical resolution are controlled jointly by cell_size_v_top, depth_scale, and this layer count.

n_airlayersint, default 5

Number of air layers placed above the earth in 3-D models. These layers help represent the air-earth boundary in the forward solver and are usually assigned very high resistivity values.

cell_size_hfloat, default 500.0

Nominal horizontal cell width in metres for 3-D core cells in both x and y directions. It should be consistent with station spacing, expected target size, and the shortest periods retained in the data file.

cell_size_v_topfloat, default 10.0

Thickness in metres of the shallowest 3-D earth layer. Deeper layers grow according to depth_scale. Smaller values improve shallow resolution but increase the number of cells needed to reach the same depth.

depth_scalefloat, default 1.2

Geometric growth factor for 3-D earth-layer thicknesses. The thickness of deeper layers approximately follows \(h_k=h_0 s^k\), where \(h_0\) is the top-layer thickness and \(s\) is this scale factor.

n_padding_xyint, default 7

Number of horizontal padding cells added on each side of the 3-D core grid in both x and y directions. Padding expands the computational domain so boundary conditions are farther from the survey area.

Covariance Options#

smooth_xfloat, default 0.1

Smoothing coefficient applied between neighbouring cells in the ModEM x direction. Larger values impose stronger model smoothness along this direction. The value should be balanced with data coverage and expected geological strike.

smooth_yfloat, default 0.1

Smoothing coefficient applied between neighbouring cells in the ModEM y direction. For 3-D inversions this controls lateral regularization perpendicular to smooth_x.

smooth_zfloat, default 0.1

Smoothing coefficient applied between neighbouring cells in depth. Increasing this value discourages rapid vertical resistivity changes, while smaller values allow sharper layering when supported by the data.

n_smooth_iterint, default 2

Number of times ModEM applies the covariance smoothing operator. 0 disables repeated smoothing. Higher values strengthen regularization and can produce smoother, more conservative model updates.

Inversion Control#

max_iterationsint, default 100

Maximum number of nonlinear conjugate-gradient iterations requested in the ModEM control file. The run may stop earlier when the target RMS, lambda-exit threshold, or convergence criteria are reached.

target_rmsfloat, default 1.05

Target normalized root-mean-square misfit. When data errors are realistic, values near \(1\) indicate a fit comparable to the assigned uncertainties. Smaller targets demand tighter data fit and may increase model roughness.

initial_lambdafloat, default 10.0

Initial damping or regularization trade-off parameter used by ModEM. Larger values favour smoother, smaller model updates at the start of inversion. The value is reduced during successful iterations according to lambda_divisor.

lambda_divisorfloat, default 100.0

Factor by which ModEM reduces lambda after successful steps. Larger divisors make lambda decrease faster, while smaller divisors keep stronger regularization for more iterations.

initial_alphafloat, default 10.0

Initial line-search step length used by the inversion control file. It controls the first trial update along the search direction and may be adjusted internally by ModEM during the nonlinear solve.

rms_diff_tolfloat, default 5.0e-4

RMS-change tolerance used as a convergence or restart criterion. When successive RMS values differ by less than this threshold, the inversion is considered to have made little progress.

lambda_exitfloat, default 1.0e-4

Lower lambda threshold used to stop the inversion. Once the regularization trade-off parameter is smaller than this value, additional reductions are unlikely to improve the solution in a stable way.

Initial Model#

initial_rhofloat, default 100.0

Starting half-space resistivity in ohm metres. Builders fill active earth cells with this value before inversion. A positive value is required because model writers store resistivity in logarithmic form for ModEM-compatible files.

File Names#

data_filestr, default “ModEMData.dat”

Default observed-data filename used by workflows that consume configuration file names. The path is interpreted relative to the run working directory unless callers provide an absolute path.

model_filestr, default “ModEM_Model.rho”

Default model filename used by configured runner or result workflows. Builders may override this with mode-specific names such as "m0.ws" or "m0.rho".

covariance_filestr, default “ModEM.cov”

Default 3-D covariance filename. It identifies the file containing smoothing coefficients and active-cell masks.

control_filestr, default “ModEM.inv”

Default inversion-control filename. It stores nonlinear solver settings and output naming controls.

log_filestr, default “Modular_NLCG.log”

Default ModEM nonlinear conjugate-gradient log filename. Result loaders use this name when scanning run output.

output_stemstr, default “ModEM_out”

Stem used by ModEM for generated model, response, and log outputs. It corresponds to the model and data output-name field in the control file. Use a distinctive stem when several inversions share one directory.

Binary And MPI#

binary_2dstr, default “Mod2DMT”

Name or path of the ModEM 2-D executable. If only a name is supplied, the runner searches the working directory and the system PATH. Use an absolute path when the binary is installed in a non-standard location.

binary_3dstr, default “Mod3DMT”

Name or path of the ModEM 3-D executable. If only a name is supplied, the runner searches the working directory and the system PATH. MPI-enabled builds can be launched with use_mpi and n_procs.

use_mpibool, default False

Whether to launch the 3-D executable through an MPI command. This requires a ModEM binary compiled with MPI support. When False, the runner starts the executable directly as a serial process.

n_procsint, default 4

Number of MPI processes requested when use_mpi is true. The value is passed to the MPI launcher and should be compatible with the machine, scheduler allocation, and ModEM build.

mpi_commandstr, default “mpirun”

MPI launcher used when use_mpi is true. Common values include "mpirun" and "mpiexec". Cluster environments may require a site-specific wrapper.

ivar is_3d:

Derived property that returns True when mode is "3d" after whitespace stripping and lower-casing.

vartype is_3d:

bool

ivar binary_name:

Derived property returning binary_3d for 3-D mode and binary_2d otherwise.

vartype binary_name:

str

Notes

The dataclass is intentionally permissive. It records user choices but does not validate every field at construction time. Downstream builders, readers, writers, and runners check the subset of fields they need. This keeps quick configuration experiments lightweight while preserving clear failure points near the operation that requires a value.

For 2-D workflows, choose component_type from TE/TM impedance families and use the *_2d grid fields. For 3-D workflows, use full, off-diagonal, determinant, or vertical component families and the 3-D grid/covariance fields.

Source-Of-Truth Files#

Users can generate an editable configuration file before building or running a model. Python is the default format because it supports rich inline comments and can still be read safely by from_file() using literal parsing. YAML files also keep comments. JSON files cannot contain comments, so the generated JSON template stores explanations in a "_schema" metadata block and editable values under "config".

The recommended workflow is:

  1. Generate a template with write_template().

  2. Edit the values in the generated file.

  3. Load the edited file with from_file() or read().

  4. Pass the resulting configuration to builders and runners.

The same reusable configuration I/O layer is designed for other model subpackages, including Occam2D.

See also

InputBuilder

Consumes this configuration while writing ModEM input files.

ModEmData.from_edi

Uses data options to select components, units, error floors, and frequency limits.

ModEmModel2D.halfspace

Uses 2-D grid and initial-resistivity settings.

ModEmModel3D.halfspace

Uses 3-D grid and initial-resistivity settings.

ModEmCovariance.from_model

Uses covariance smoothing settings for 3-D runs.

ModEmControl.from_config

Converts inversion-control fields into a ModEM control object.

ModEmRunner

Uses binary, MPI, mode, and file-name settings.

Examples

Create a default 3-D configuration:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> cfg = ModEmConfig()
>>> cfg.is_3d
True
>>> cfg.binary_name
'Mod3DMT'

Configure a 2-D TE workflow:

>>> cfg = ModEmConfig(
...     mode="2d",
...     component_type="TE_Impedance",
...     nx_2d=120,
...     nz_2d=60,
... )
>>> cfg.binary_name
'Mod2DMT'

Set data weighting and frequency limits:

>>> cfg = ModEmConfig(
...     error_floor_z=0.07,
...     error_floor_z_floor=1e-6,
...     freq_min=0.01,
...     freq_max=1000.0,
... )

Configure an MPI-enabled 3-D run:

>>> cfg = ModEmConfig(
...     mode="3d",
...     use_mpi=True,
...     n_procs=16,
...     binary_3d="Mod3DMT_MPI",
... )

Generate a documented source-of-truth file and read it back:

>>> path = ModEmConfig.write_template("modem_config.py")
>>> cfg = ModEmConfig.from_file(path)
>>> cfg.mode
'3d'

Generate a JSON template for environments where JSON is easier to exchange:

>>> ModEmConfig.write_template("modem_config.json")
PosixPath('modem_config.json')

References

mode: str = '3d'#
component_type: str = 'Full_Impedance'#
sign_convention: str = 'exp(+i\\omega t)'#
units: str = '[mV/km]/[nT]'#
error_floor_z: float = 0.05#
error_floor_z_floor: float = 0.0#
freq_min: float | None = None#
freq_max: float | None = None#
nx_2d: int = 100#
nz_2d: int = 50#
n_airlayers_2d: int = 5#
cell_size_h_2d: float = 100.0#
cell_size_v_top_2d: float = 10.0#
depth_scale_2d: float = 1.2#
n_padding_x_2d: int = 7#
nx: int = 20#
ny: int = 20#
nz: int = 30#
n_airlayers: int = 5#
cell_size_h: float = 500.0#
cell_size_v_top: float = 10.0#
depth_scale: float = 1.2#
n_padding_xy: int = 7#
smooth_x: float = 0.1#
smooth_y: float = 0.1#
smooth_z: float = 0.1#
n_smooth_iter: int = 2#
max_iterations: int = 100#
target_rms: float = 1.05#
initial_lambda: float = 10.0#
lambda_divisor: float = 100.0#
initial_alpha: float = 10.0#
rms_diff_tol: float = 0.0005#
lambda_exit: float = 0.0001#
initial_rho: float = 100.0#
data_file: str = 'ModEMData.dat'#
model_file: str = 'ModEM_Model.rho'#
covariance_file: str = 'ModEM.cov'#
control_file: str = 'ModEM.inv'#
log_file: str = 'Modular_NLCG.log'#
output_stem: str = 'ModEM_out'#
binary_2d: str = 'Mod2DMT'#
binary_3d: str = 'Mod3DMT'#
use_mpi: bool = False#
n_procs: int = 4#
mpi_command: str = 'mpirun'#
property is_3d: bool#

Return True when mode selects 3-D ModEM.

property binary_name: str#

Return the executable name implied by mode.

to_template(path='modem_config.py', *, fmt=None)#

Write this configuration as an editable template.

Parameters:
  • path (path-like, default "modem_config.py") – Destination file. If the path has no suffix, the suffix is inferred from fmt and defaults to .py.

  • fmt ({"py", "json", "yml", "yaml"}, optional) – Template format. Python and YAML templates include comments. JSON templates include a "_schema" documentation block because standard JSON does not support comments.

Returns:

Path of the generated template.

Return type:

pathlib.Path

classmethod write_template(path='modem_config.py', *, fmt=None)#

Write a default editable ModEM configuration file.

Parameters:
  • path (path-like, default "modem_config.py") – Destination file. Suffixes .py, .json, .yml, and .yaml select the output format.

  • fmt ({"py", "json", "yml", "yaml"}, optional) – Explicit output format. When omitted, the suffix of path is used; paths without a suffix produce a Python template.

Returns:

Path of the generated source-of-truth file.

Return type:

pathlib.Path

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> path = ModEmConfig.write_template("modem_config.py")
>>> path.name
'modem_config.py'
classmethod from_file(path, *, strict=True)#

Create a configuration from a source-of-truth file.

Parameters:
  • path (path-like) – Python, JSON, YML, or YAML configuration file generated by write_template() or following the same structure.

  • strict (bool, default True) – If True, unknown editable keys raise ValueError. If False, unknown keys are ignored. Metadata keys starting with "_" are always ignored.

Returns:

Configuration populated from edited file values.

Return type:

ModEmConfig

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> ModEmConfig.write_template("modem_config.json")
PosixPath('modem_config.json')
>>> cfg = ModEmConfig.from_file("modem_config.json")
>>> cfg.binary_name
'Mod3DMT'
classmethod read(path, *, strict=True)#

Create a configuration from a source-of-truth file.

Parameters:
  • path (path-like) – Python, JSON, YML, or YAML configuration file generated by write_template() or following the same structure.

  • strict (bool, default True) – If True, unknown editable keys raise ValueError. If False, unknown keys are ignored. Metadata keys starting with "_" are always ignored.

Returns:

Configuration populated from edited file values.

Return type:

ModEmConfig

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> ModEmConfig.write_template("modem_config.json")
PosixPath('modem_config.json')
>>> cfg = ModEmConfig.from_file("modem_config.json")
>>> cfg.binary_name
'Mod3DMT'
Parameters:
class pycsamt.models.modem.ModEmFileType#

Bases: object

String constants returned by detect_file_type().

DATA = 'data'#
MODEL_2D = 'model_2d'#
MODEL_3D = 'model_3d'#
COVARIANCE = 'covariance'#
CONTROL = 'control'#
LOG = 'log'#
UNKNOWN = 'unknown'#
pycsamt.models.modem.detect_file_type(path)#

Detect the most likely ModEM file category.

The detector applies the public validators in a stable order and returns the first matching ModEmFileType constant. Log and data signatures are checked before model signatures, followed by covariance and control files. If no predicate matches, the file is reported as ModEmFileType.UNKNOWN.

Parameters:

path (path-like) – Candidate ModEM file. Missing files are allowed and return ModEmFileType.UNKNOWN.

Returns:

One of "data", "model_2d", "model_3d", "covariance", "control", "log", or "unknown".

Return type:

str

Examples

>>> from pycsamt.models.modem.validation import detect_file_type
>>> from pycsamt.models.modem.validation import ModEmFileType
>>> detect_file_type("missing.dat") == ModEmFileType.UNKNOWN
True

See also

is_data_file

Validate ModEM observed or predicted data files.

is_model_file

Validate either 2-D or 3-D ModEM model files.

is_control_file

Validate ModEM inversion-control files.

pycsamt.models.modem.is_data_file(path)#

Check whether a file looks like a ModEM data file.

ModEM data files describe observed or predicted electromagnetic responses for a set of stations and periods. The validator uses header signatures rather than a full parse. A file is accepted when its leading lines contain either a known component declaration such as > Full_Impedance or a tabular header containing Period(s), Code, and GG_Lat.

Parameters:

path (path-like) – Candidate file path. The value may be a string or pathlib.Path. Missing files and unreadable files are treated as non-matches.

Returns:

True when the leading file content matches a recognized ModEM data-file signature, otherwise False.

Return type:

bool

Examples

>>> from pycsamt.models.modem.validation import is_data_file
>>> is_data_file("d0.dat")
False

See also

detect_file_type

Return the most likely ModEM file category.

pycsamt.models.modem.is_model_file(path)#

Check whether a file looks like any ModEM model file.

Parameters:

path (path-like) – Candidate 2-D or 3-D model file.

Returns:

True when either is_model_2d_file() or is_model_3d_file() accepts the file.

Return type:

bool

pycsamt.models.modem.is_model_2d_file(path)#

Check whether a file looks like a ModEM 2-D model.

A 2-D ModEM model header begins with two integer cell counts, commonly \(N_x\) and \(N_z\), followed by a resistivity encoding token such as LOGE, LOG10, or LINEAR. This predicate checks only that leading header signature; it does not validate the full number of mesh or resistivity values.

Parameters:

path (path-like) – Candidate model file. Missing or unreadable files return False.

Returns:

True if the file has a 2-D ModEM model header, otherwise False.

Return type:

bool

Examples

>>> from pycsamt.models.modem.validation import is_model_2d_file
>>> is_model_2d_file("m0.rho")
False
pycsamt.models.modem.is_model_3d_file(path)#

Check whether a file looks like a ModEM 3-D model.

A 3-D ModEM model header begins with at least three integer cell counts, commonly \(N_x\), \(N_y\), and \(N_z\), plus a resistivity encoding token. The validator is intentionally lightweight and reads only the first few non-empty lines.

Parameters:

path (path-like) – Candidate model file. Missing or unreadable files return False.

Returns:

True if the file has a 3-D ModEM model header, otherwise False.

Return type:

bool

Examples

>>> from pycsamt.models.modem.validation import is_model_3d_file
>>> is_model_3d_file("m0.ws")
False
pycsamt.models.modem.is_covariance_file(path)#

Check whether a file looks like a ModEM covariance file.

Covariance files describe regularization smoothing and active-cell masks for 3-D inversions. This validator looks for typical header words such as Model Covariance, Autoregression, or the combination of Smoothing and Mask.

Parameters:

path (path-like) – Candidate covariance file. Missing or unreadable files return False.

Returns:

True when the leading lines contain a covariance signature, otherwise False.

Return type:

bool

pycsamt.models.modem.is_control_file(path)#

Check whether a file looks like a ModEM control file.

ModEM control files are key-value text files that define nonlinear inversion settings. The most reliable signatures are the output-stem line, the initial search-step line, or the initial damping parameter \(\lambda\) line.

Parameters:

path (path-like) – Candidate inversion-control file. Missing or unreadable files return False.

Returns:

True when the header contains recognized control parameters, otherwise False.

Return type:

bool

pycsamt.models.modem.is_log_file(path)#

Check whether a file looks like a ModEM run log.

Run logs contain nonlinear conjugate-gradient progress records, including RMS values and damping parameters. The predicate checks for common strings written by ModEM logs, such as NLCG iteration, Completed NLCG, or the combination of Damping parameter lambda and RMS.

Parameters:

path (path-like) – Candidate log file. Missing or unreadable files return False.

Returns:

True when the file has a recognizable ModEM log signature, otherwise False.

Return type:

bool

class pycsamt.models.modem.ModEmData(config=None, **kwargs)#

Bases: ModEmBase

Represent observed or predicted ModEM response data.

ModEmData stores the ModEM ASCII data-file structure used by both 2-D and 3-D workflows. A file is composed of one or more component blocks. Each block starts with > metadata lines describing the component family, time convention, units, rotation, origin, and counts. Data rows then store period, station code, local coordinates, component name, complex value, and uncertainty.

The complex impedance tensor is commonly written as

\[\begin{split}\mathbf{Z} = \begin{bmatrix} Z_{xx} & Z_{xy} \\ Z_{yx} & Z_{yy} \end{bmatrix},\end{split}\]

with each selected component stored as real and imaginary columns. The data builder applies an error floor

\[\sigma_Z = \max(\sigma_{src}, \epsilon |Z|_{max}, \sigma_{min}),\]

where \(\epsilon\) is config.error_floor_z and \(\sigma_<built-in function min>\) is config.error_floor_z_floor.

Parameters:
  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • config (ModEmConfig) – Configuration object used for sign convention, units, component selection, frequency limits, and error floors.

  • comment (str, optional) – Free-text comment written near the top of a ModEM data file. Use it to record survey name, processing version, data-selection rules, or other provenance that should travel with the exported inversion input.

  • blocks (list of dict) – Parsed or assembled ModEM component rows. Each block stores period, station, coordinates, component name, real value, imaginary value, and error. The block structure is used internally by readers, writers, result loaders, and response plotting helpers.

  • site_names (sequence of str) – Ordered station names used in the data file and in plots. The order must match rows in site_coords and station indices in the component blocks. Stable names make it easier to compare observed data, predicted data, and model responses across inversion iterations.

  • site_coords (dict[str, tuple]) – Mapping from station name to (x_m, y_m, z_m) local coordinates. The x coordinate is local northing, the y coordinate is local easting, and z is elevation in metres.

  • periods (array-like of float) – Periods in seconds represented by the data object. Periods are the inverse of frequency, \(T=1/f\), and are used by ModEM to order response blocks. Values should be positive and should correspond to the impedance samples stored in the component rows.

Notes

Supported component families include:

  • "TE_Impedance" and "TM_Impedance" for 2-D profile workflows;

  • "Full_Impedance" for ZXX, ZXY, ZYX, and ZYY;

  • "Off_Diagonal_Impedance" for ZXY and ZYX;

  • "Determinant_Impedance" for determinant-style data;

  • "Full_Vertical_Components" for tipper-like components;

  • "Phase_Tensor" for phase-tensor component names.

from_edi currently builds impedance component rows from z and z_err arrays. Component families whose values require derived calculations, such as determinant or phase tensor responses, may need additional preprocessing before they can be represented fully.

See also

ModEmConfig

Supplies component, unit, sign, frequency, and error settings.

InputBuilder

Builds ModEM data and the matching model/control files.

ModEmModel2D

Uses station coordinates from data to build 2-D models.

ModEmModel3D

Uses station coordinates from data to build 3-D models.

ModEmRunner

Passes observed data files to the ModEM executable.

Examples

Read an existing data file:

>>> from pycsamt.models.modem.data import ModEmData
>>> data = ModEmData.read("data.dat")
>>> data.n_sites > 0
True

Build data from EDI-like station objects:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> cfg = ModEmConfig(component_type="Off_Diagonal_Impedance")
>>> data = ModEmData.from_edi(sites, config=cfg)
>>> data.component_types
['Off_Diagonal_Impedance']

Write a ModEM data file:

>>> path = data.write("modem_run/data.dat")
>>> path.name
'data.dat'

References

property n_sites: int#

Number of stations represented by the data object.

property n_periods: int#

Number of unique periods represented by the object.

property offsets: ndarray#

Return station easting offsets in metres.

property x_coords: ndarray#

Return station northing coordinates in metres.

property y_coords: ndarray#

Return station easting coordinates in metres.

property component_types: list[str]#

Return component-type names present in the data blocks.

property has_lonlat: bool#

Whether real geographic coordinates were found in the file.

lonlat_for(name)#

Return (lon, lat) for name, or None if unavailable.

Parameters:

name (str)

Return type:

tuple[float, float] | None

classmethod read(path, **kwargs)#

Parse an existing ModEM data file.

Parameters:
  • path (path-like) – Path to a ModEM ASCII data file. The file may contain one or more > component blocks and optional # comment lines.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmData, commonly config, verbose, or logger.

Returns:

Parsed data object with comment, blocks, station names, station coordinates, and unique periods populated.

Return type:

ModEmData

Raises:

FileNotFoundError – If path does not exist.

Examples

>>> from pycsamt.models.modem.data import ModEmData
>>> data = ModEmData.read("data.dat")
>>> data.n_sites > 0
True
write(path)#

Write data to path in ModEM ASCII format.

Parameters:

path (path-like) – Destination data file. Parent directories are created before writing. Existing files are overwritten.

Returns:

Path passed to the writer, converted to pathlib.Path.

Return type:

pathlib.Path

Notes

Latitude/longitude columns are written from site_lonlat when available (e.g. parsed from a real ModEM file, or built via from_edi()), else as zeros. Model builders and runners use the local X(m), Y(m), and Z(m) columns exclusively; lat/lon is metadata only.

Examples

>>> from pycsamt.models.modem.data import ModEmData
>>> data = ModEmData.read("data.dat")
>>> path = data.write("copy.dat")
>>> path.name
'copy.dat'
classmethod from_edi(source, config=None, **kwargs)#

Build a ModEM data file from EDI sites.

The builder accepts a collection of site-like objects and writes one ModEM component block according to config.component_type. Frequencies are merged across stations with a relative tolerance, converted to periods, and stored in descending period order. Impedance errors are floored using both relative and absolute thresholds from config.

Parameters:
  • source (iterable of duck-typed site objects) –

    Each item must expose:

    • name (str)

    • coords (lat, lon, elev) or lat/lon/elev

    • freq (array, Hz)

    • z (array, shape (n_freq, 2, 2), complex): impedance tensor in units matching config.units.

    • z_err (array, same shape): error estimate on Z (absolute, same units); or None for floor-only errors

    For 2-D data, z[:,0,1] = Z_TE, z[:,1,0] = Z_TM.

  • config (ModEmConfig, optional) – Configuration controlling component selection, sign convention, units, frequency limits, and impedance error floors. If omitted, defaults are used.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmData.

Returns:

Populated data object ready to be written with write() or passed to model builders.

Return type:

ModEmData

Raises:

ValueError – If source is empty, contains no valid positive frequencies, or selects an unknown component type.

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.data import ModEmData
>>> cfg = ModEmConfig(component_type="Full_Impedance")
>>> data = ModEmData.from_edi(sites, config=cfg)
>>> data.component_types
['Full_Impedance']
class pycsamt.models.modem.ModEmModel2D(config=None, **kwargs)#

Bases: ModEmBase

Represent a ModEM two-dimensional resistivity model.

ModEmModel2D stores the model grid and resistivity values used by the ModEM 2-D executable. The horizontal axis follows the survey profile, while the vertical axis contains air layers and active earth layers. Resistivity values are stored internally as natural logarithms, so a linear resistivity \(\rho\) is represented as

\[m = \ln(\rho).\]

The ASCII file format contains a header with nx, nz, and log encoding, followed by horizontal cell widths, vertical layer thicknesses, a block count, and the resistivity grid.

Parameters:
  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • config (ModEmConfig) – Configuration object used when constructing half-space models.

  • x_widths (numpy.ndarray, shape (nx,)) – Horizontal cell widths in metres. The array includes lateral padding and station-zone cells.

  • z_widths (numpy.ndarray, shape (nz,)) – Vertical layer thicknesses in metres. The array includes air layers followed by active earth layers.

  • rho_loge (numpy.ndarray, shape (nz, nx)) – Natural-log resistivity values. Earth cells in a default half-space are initialized as \(\ln(\rho_0)\), where \(\rho_0\) is config.initial_rho.

  • log_type (str, default "LOGE") – Encoding label written to the ModEM file header. "LOGE" is the standard internal representation used by this class. Readers also accept "LOG10" and "LINEAR" and convert them to natural logarithms.

  • Properties (Derived)

  • ------------------

  • nx (int) – Number of horizontal cells.

  • nz (int) – Number of vertical layers, including air layers.

  • x_nodes (numpy.ndarray, shape (nx + 1,)) – Cumulative horizontal node coordinates in metres.

  • z_nodes (numpy.ndarray, shape (nz + 1,)) – Cumulative vertical node depths in metres.

  • rho_linear (numpy.ndarray, shape (nz, nx)) – Resistivity values in linear ohm metres, obtained as \(\exp(\mathtt{rho\_loge})\).

Notes

The halfspace() constructor creates a conservative starting model. Air layers are assigned a very high resistivity, while earth cells are assigned config.initial_rho. Horizontal padding grows away from the station zone so artificial boundaries are moved away from the profile.

See also

ModEmConfig

Supplies 2-D grid and initial-resistivity settings.

ModEmData

Provides station offsets used by halfspace().

InputBuilder

Builds and writes a 2-D starting model automatically.

ModEmRunner

Passes the written model file to the ModEM executable.

Examples

Build a 2-D half-space model:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.model2d import ModEmModel2D
>>> cfg = ModEmConfig(mode="2d", initial_rho=100.0)
>>> model = ModEmModel2D.halfspace(data, config=cfg)
>>> model.rho_loge.shape == (model.nz, model.nx)
True

Read and write a ModEM model file:

>>> model = ModEmModel2D.read("m0.rho")
>>> path = model.write("m0_copy.rho")
>>> path.name
'm0_copy.rho'

Inspect linear resistivity:

>>> rho = model.rho_linear
>>> rho.shape == model.rho_loge.shape
True

References

property nx: int#

Number of horizontal model cells.

property nz: int#

Number of vertical layers, including air layers.

property x_nodes: ndarray#

Cumulative horizontal node coordinates in metres.

property z_nodes: ndarray#

Cumulative vertical node depths in metres.

property rho_linear: ndarray#

Return resistivity in linear ohm metres.

classmethod halfspace(data, config=None, **kwargs)#

Build a uniform half-space starting model.

The method derives the horizontal grid from station offsets in a ModEmData object. It fills earth cells with config.initial_rho and assigns air layers a high fixed resistivity. Resistivity is stored internally as natural logarithm values.

Parameters:
  • data (ModEmData) – Populated data object. The builder uses data.offsets to determine the station-zone width and to place lateral padding cells.

  • config (ModEmConfig, optional) – Configuration supplying 2-D grid dimensions, padding, layer growth, air-layer count, and starting half-space resistivity. If omitted, a default ModEmConfig is used.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmModel2D.

Returns:

Populated 2-D model object ready to be written as a ModEM model file.

Return type:

ModEmModel2D

Examples

>>> from pycsamt.models.modem.model2d import ModEmModel2D
>>> model = ModEmModel2D.halfspace(data, config=cfg)
>>> model.rho_loge.shape == (model.nz, model.nx)
True

Notes

The station-zone cell widths are derived from gaps between sorted station offsets. If only one station is present, one station-zone cell is created using config.cell_size_h_2d. Padding cells grow by powers of two away from the station zone.

classmethod read(path, **kwargs)#

Parse an existing ModEM 2-D model file.

Parameters:
  • path (path-like) – Path to a ModEM 2-D model file. The file may store resistivity as LOGE, LOG10, or LINEAR; values are converted to natural-log resistivity internally.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmModel2D.

Returns:

Parsed model with cell widths, layer thicknesses, natural-log resistivity, and log-type metadata.

Return type:

ModEmModel2D

Raises:

FileNotFoundError – If path does not exist.

Examples

>>> from pycsamt.models.modem.model2d import ModEmModel2D
>>> model = ModEmModel2D.read("m0.rho")
>>> model.rho_loge.shape == (model.nz, model.nx)
True
write(path)#

Write the model to path in ModEM 2-D format.

Parameters:

path (path-like) – Destination model file. Parent directories are created before writing. Existing files are overwritten.

Returns:

Path passed to the writer, converted to pathlib.Path.

Return type:

pathlib.Path

Notes

The writer emits one parameter block and writes the values stored in rho_loge. The log_type header is written from the object, so callers should keep it consistent with the numerical encoding of rho_loge.

Examples

>>> from pycsamt.models.modem.model2d import ModEmModel2D
>>> model = ModEmModel2D.halfspace(data, config=cfg)
>>> path = model.write("m0.rho")
>>> path.name
'm0.rho'
class pycsamt.models.modem.ModEmModel3D(config=None, **kwargs)#

Bases: ModEmBase

Represent a ModEM three-dimensional resistivity model.

ModEmModel3D stores the grid and resistivity values used by the ModEM 3-D executable. The model contains x, y, and z cell widths, a count of air layers at the top of the mesh, and a resistivity volume with shape (nz, ny, nx). Resistivity is stored internally as natural logarithms, so a linear resistivity \(\rho\) is represented as

\[m = \ln(\rho).\]

The ASCII .ws format contains a header with nx, ny, nz, optional air-layer count, and log encoding. It then stores cell widths followed by the resistivity volume written layer by layer.

Parameters:
  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • config (ModEmConfig) – Configuration object used when constructing half-space models.

  • x_widths (numpy.ndarray, shape (nx,)) – Cell widths in metres along the ModEM x direction.

  • y_widths (numpy.ndarray, shape (ny,)) – Cell widths in metres along the ModEM y direction.

  • z_widths (numpy.ndarray, shape (nz,)) – Vertical layer thicknesses in metres. The array includes air layers followed by active earth layers.

  • rho_loge (numpy.ndarray, shape (nz, ny, nx)) – Natural-log resistivity values. Earth cells in a default half-space are initialized as \(\ln(\rho_0)\), where \(\rho_0\) is config.initial_rho.

  • n_air (int) – Number of air layers included at the top of the model.

  • log_type (str, default "LOGE") – Encoding label written to the ModEM file header. "LOGE" is the standard internal representation used by this class. Readers also accept "LOG10" and "LINEAR" and convert them to natural logarithms.

  • Properties (Derived)

  • ------------------

  • nz (nx, ny,) – Number of cells in the x, y, and z directions.

  • z_nodes (x_nodes, y_nodes,) – Cumulative node coordinates in metres for each direction.

  • rho_linear (numpy.ndarray, shape (nz, ny, nx)) – Resistivity values in linear ohm metres, obtained as \(\exp(\mathtt{rho\_loge})\).

  • shape (tuple of int) – Convenience tuple (nz, ny, nx) matching rho_loge.shape.

Notes

The halfspace() constructor creates a uniform starting model. Air layers are assigned a very high resistivity, while earth cells are assigned config.initial_rho. Horizontal padding grows away from the station footprint in both x and y directions so artificial boundaries are moved away from the survey.

See also

ModEmConfig

Supplies 3-D grid and initial-resistivity settings.

ModEmData

Provides station coordinates used by halfspace().

ModEmCovariance

Uses this model geometry to build 3-D covariance masks.

InputBuilder

Builds and writes a 3-D starting model automatically.

ModEmRunner

Passes the written model file to the ModEM executable.

Examples

Build a 3-D half-space model:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.model3d import ModEmModel3D
>>> cfg = ModEmConfig(mode="3d", initial_rho=100.0)
>>> model = ModEmModel3D.halfspace(data, config=cfg)
>>> model.shape == model.rho_loge.shape
True

Read and write a ModEM .ws model file:

>>> model = ModEmModel3D.read("m0.ws")
>>> path = model.write("m0_copy.ws")
>>> path.name
'm0_copy.ws'

Inspect linear resistivity:

>>> rho = model.rho_linear
>>> rho.shape == model.shape
True

References

property nx: int#

Number of model cells along the x direction.

property ny: int#

Number of model cells along the y direction.

property nz: int#

Number of vertical layers, including air layers.

property x_nodes: ndarray#

Cumulative x-node coordinates in metres.

property y_nodes: ndarray#

Cumulative y-node coordinates in metres.

property z_nodes: ndarray#

Cumulative vertical node depths in metres.

property rho_linear: ndarray#

Return resistivity in linear ohm metres.

property shape: tuple[int, int, int]#

Return (nz, ny, nx) for the resistivity grid.

classmethod halfspace(data, config=None, **kwargs)#

Build a uniform half-space starting model.

The method derives the horizontal x and y grids from station coordinates in a ModEmData object. It fills earth cells with config.initial_rho and assigns air layers a high fixed resistivity. Resistivity is stored internally as natural logarithm values.

Parameters:
  • data (ModEmData) – Populated data object. The builder uses data.x_coords and data.y_coords to define the station-zone grid in the horizontal plane.

  • config (ModEmConfig, optional) – Configuration supplying 3-D grid dimensions, padding, vertical growth, air-layer count, and starting half-space resistivity. If omitted, a default ModEmConfig is used.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmModel3D.

Returns:

Populated 3-D model object ready to be written as a ModEM .ws model file.

Return type:

ModEmModel3D

Examples

>>> from pycsamt.models.modem.model3d import ModEmModel3D
>>> model = ModEmModel3D.halfspace(data, config=cfg)
>>> model.shape == model.rho_loge.shape
True

Notes

The station-zone widths are derived separately for x and y from sorted unique station coordinates. If only one coordinate exists in a direction, one station-zone cell is created using config.cell_size_h. Padding cells grow by powers of two away from the station zone.

classmethod read(path, **kwargs)#

Parse an existing ModEM 3-D model file.

Parameters:
  • path (path-like) – Path to a ModEM 3-D .ws model file. The file may store resistivity as LOGE, LOG10, or LINEAR; values are converted to natural-log resistivity internally.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmModel3D.

Returns:

Parsed model with x, y, and z cell widths, natural-log resistivity, air-layer count, and log-type metadata.

Return type:

ModEmModel3D

Raises:

FileNotFoundError – If path does not exist.

Examples

>>> from pycsamt.models.modem.model3d import ModEmModel3D
>>> model = ModEmModel3D.read("m0.ws")
>>> model.rho_loge.shape == model.shape
True
write(path)#

Write the model to path in ModEM 3-D format.

Parameters:

path (path-like) – Destination model file. Parent directories are created before writing. Existing files are overwritten.

Returns:

Path passed to the writer, converted to pathlib.Path.

Return type:

pathlib.Path

Notes

The writer emits the WinGLink/ModEM .ws style grid: header, x widths, y widths, z widths, then nz * ny rows of nx resistivity values. It writes the values stored in rho_loge and the encoding label stored in log_type.

Examples

>>> from pycsamt.models.modem.model3d import ModEmModel3D
>>> model = ModEmModel3D.halfspace(data, config=cfg)
>>> path = model.write("m0.ws")
>>> path.name
'm0.ws'
class pycsamt.models.modem.ModEmCovariance(config=None, **kwargs)#

Bases: ModEmBase

Represent a ModEM 3-D covariance and smoothing file.

ModEmCovariance stores the regularization information used by ModEM 3-D inversions. The covariance file defines earth-only grid dimensions, per-layer horizontal smoothing coefficients, one vertical smoothing coefficient, optional smoothing exceptions between mask regions, and integer mask blocks that divide the model into smoothing domains.

In ModEM’s regularized objective, covariance controls the model regularization term:

\[\Phi_m(m) = \| W_m (m - m_0) \|_2^2 ,\]

where \(W_m\) is shaped by smoothing weights and region masks from this file. Larger smoothing values generally favour models that vary more gradually in the corresponding direction. Mask exceptions can reduce or disable smoothing across geological boundaries, air, or ocean regions [1]_, [2]_.

Parameters:
  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • config (ModEmConfig) – Configuration object used to initialize smoothing defaults.

  • nx_earth (int) – Number of earth cells along the ModEM x direction. Air layers are excluded from this dimension.

  • ny_earth (int) – Number of earth cells along the ModEM y direction. Air layers are excluded from this dimension.

  • nz_earth (int) – Number of earth layers represented by the covariance file. This is normally model.nz - model.n_air.

  • smooth_x (numpy.ndarray, shape (nz_earth,)) – Per-layer smoothing coefficients in the x direction.

  • smooth_y (numpy.ndarray, shape (nz_earth,)) – Per-layer smoothing coefficients in the y direction.

  • smooth_z (float, default 0.1) – Smoothing coefficient applied between neighbouring cells in depth. Increasing this value discourages rapid vertical resistivity changes, while smaller values allow sharper layering when supported by the data.

  • n_smooth_iter (int, default 2) – Number of times ModEM applies the covariance smoothing operator. 0 disables repeated smoothing. Higher values strengthen regularization and can produce smoother, more conservative model updates.

  • exceptions (list of tuple of int, int, float) – Smoothing overrides between two mask identifiers. A tuple (a, b, value) sets the smoothing across the boundary between mask regions a and b. Values of 0 turn off smoothing across that boundary.

  • mask_blocks (list of dict) – Layer-group masks. Each block contains "layer_start", "layer_end", and "mask". Layer indices are one-based and inclusive, matching the ModEM text format. Each mask array has shape (nx_earth, ny_earth).

Notes

The covariance file begins with a 16-line explanatory header, then stores the earth-grid dimensions, smoothing arrays, vertical smoothing value, number of smoothing iterations, exception rows, and one or more mask blocks.

Mask values follow the ModEM convention:

  • 0 is reserved for air;

  • 9 is reserved for ocean;

  • 1 through 8 are user-defined model regions.

Smoothing involving air and ocean is disabled by ModEM automatically. Additional boundaries can be controlled through exceptions.

See also

ModEmConfig

Supplies default smoothing and iteration values.

ModEmModel3D

Provides the grid dimensions used by from_model().

InputBuilder

Creates a covariance file automatically for 3-D builds.

ModEmRunner

Passes the covariance file to the ModEM 3-D executable.

Examples

Create a uniform covariance object from a 3-D model:

>>> from pycsamt.models.modem.covariance import ModEmCovariance
>>> cov = ModEmCovariance.from_model(model, config=cfg)
>>> cov.nz_earth == model.nz - model.n_air
True
>>> cov.mask_blocks[0]["layer_start"]
1

Disable smoothing between two user-defined regions:

>>> cov.exceptions.append((1, 2, 0.0))
>>> cov.write("ModEM.cov")
PosixPath('ModEM.cov')

Read an existing covariance file:

>>> loaded = ModEmCovariance.read("ModEM.cov")
>>> loaded.n_smooth_iter >= 0
True

References

classmethod from_model(model, config=None, **kwargs)#

Build a uniform covariance object from a 3-D model.

The generated object assigns one active earth region with mask value 1 over all earth layers and uses the smoothing values stored in config. Air layers are excluded from the covariance grid because the ModEM covariance dimensions are earth-only.

Parameters:
  • model (ModEmModel3D) – Populated 3-D model used to determine earth-grid dimensions. The model must expose nx, ny, nz, and n_air. The number of covariance layers is computed as model.nz - model.n_air.

  • config (ModEmConfig, optional) – Configuration supplying smooth_x, smooth_y, smooth_z, and n_smooth_iter. If omitted, a default ModEmConfig is used.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmCovariance, commonly verbose or logger.

Returns:

Covariance object with one mask block spanning all earth layers.

Return type:

ModEmCovariance

Examples

>>> from pycsamt.models.modem.covariance import ModEmCovariance
>>> cov = ModEmCovariance.from_model(model, config=cfg)
>>> cov.nz_earth == model.nz - model.n_air
True
>>> len(cov.mask_blocks)
1

Notes

from_model creates a simple uniform regularization region. Users who need geological domains, ocean masks, or smoothing exceptions can edit mask_blocks and exceptions before calling write().

classmethod read(path, **kwargs)#

Parse an existing ModEM covariance file.

Parameters:
  • path (path-like) – Path to a ModEM covariance file. The file must contain the standard header, earth-grid dimensions, smoothing rows, exception count, and one or more mask blocks.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmCovariance.

Returns:

Parsed covariance object with smoothing arrays, exception tuples, and mask blocks populated.

Return type:

ModEmCovariance

Raises:

FileNotFoundError – If path does not exist.

Examples

>>> from pycsamt.models.modem.covariance import ModEmCovariance
>>> cov = ModEmCovariance.read("ModEM.cov")
>>> cov.smooth_x.shape == (cov.nz_earth,)
True
write(path)#

Write the covariance object to a ModEM file.

Parameters:

path (path-like) – Destination covariance file. Parent directories are created before writing. Existing files are overwritten.

Returns:

Path passed to the writer, converted to pathlib.Path.

Return type:

pathlib.Path

Raises:

KeyError – If a mask block lacks "layer_start", "layer_end", or "mask".

Examples

>>> from pycsamt.models.modem.covariance import ModEmCovariance
>>> cov = ModEmCovariance.from_model(model, config=cfg)
>>> path = cov.write("covariance.cov")
>>> path.name
'covariance.cov'

Notes

The writer preserves the mask-block orientation used by this module: each mask array is shaped (nx_earth, ny_earth) and is written row by row.

class pycsamt.models.modem.ModEmControl(config=None, **kwargs)#

Bases: ModEmBase

Represent a ModEM inversion-control file.

ModEmControl stores the small key-value .inv file used by ModEM to control nonlinear inversion. The same container is used for 2-D and 3-D runs. It records the output file stem, lambda damping parameters, line-search starting step, convergence thresholds, target misfit, and maximum number of iterations. The object can be created directly from ModEmConfig, read from an existing control file, or written as part of an InputBuilder workflow.

The control parameters guide the regularized nonlinear solve. A typical ModEM objective can be written as

\[\Phi(m) = \| W_d (F(m) - d) \|_2^2 + \lambda \| W_m (m - m_0) \|_2^2 ,\]

where \(m\) is the current model, \(F(m)\) is the forward response, \(d\) is the observed data vector, \(W_d\) and \(W_m\) are weighting operators, and \(\lambda\) is the damping factor written to this file. The target RMS controls when the data-fit part is considered adequate for the assigned uncertainties.

Parameters:
  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • config (ModEmConfig) – Configuration object used to initialize the control values. It is retained so callers can inspect the source settings used to create the control file.

  • output_stem (str, default "ModEM_out") – Stem used by ModEM for generated model, response, and log outputs. It corresponds to the model and data output-name field in the control file. Use a distinctive stem when several inversions share one directory.

  • initial_lambda (float, default 10.0) – Initial damping or regularization trade-off parameter used by ModEM. Larger values favour smoother, smaller model updates at the start of inversion. The value is reduced during successful iterations according to lambda_divisor.

  • lambda_divisor (float, default 100.0) – Factor by which ModEM reduces lambda after successful steps. Larger divisors make lambda decrease faster, while smaller divisors keep stronger regularization for more iterations.

  • initial_alpha (float, default 10.0) – Initial line-search step length used by the inversion control file. It controls the first trial update along the search direction and may be adjusted internally by ModEM during the nonlinear solve.

  • rms_diff_tol (float, default 5.0e-4) – RMS-change tolerance used as a convergence or restart criterion. When successive RMS values differ by less than this threshold, the inversion is considered to have made little progress.

  • target_rms (float, default 1.05) – Target normalized root-mean-square misfit. When data errors are realistic, values near \(1\) indicate a fit comparable to the assigned uncertainties. Smaller targets demand tighter data fit and may increase model roughness.

  • lambda_exit (float, default 1.0e-4) – Lower lambda threshold used to stop the inversion. Once the regularization trade-off parameter is smaller than this value, additional reductions are unlikely to improve the solution in a stable way.

  • max_iterations (int, default 100) – Maximum number of nonlinear conjugate-gradient iterations requested in the ModEM control file. The run may stop earlier when the target RMS, lambda-exit threshold, or convergence criteria are reached.

Notes

The ModEM control file is a plain text file with one colon-separated key-value pair per line. The canonical labels written by this class are:

  • Model and data output file name;

  • Initial damping factor lambda;

  • To update lambda divide by;

  • Initial search step in model units;

  • Restart when rms diff is less than;

  • Exit search when rms is less than;

  • Exit when lambda is less than;

  • Maximum number of iterations.

The reader is intentionally tolerant: fields that cannot be parsed retain their current defaults, and unrecognized lines are skipped. This allows the loader to handle control files with comments or minor executable-specific additions.

See also

ModEmConfig

Supplies the inversion-control values used here.

InputBuilder

Writes a control file as part of a complete ModEM input set.

ModEmRunner

Passes the written control file to the ModEM executable.

InversionResult

Loads the control file found in a completed run directory.

Examples

Create a control file from configuration values:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.control import ModEmControl
>>> cfg = ModEmConfig(max_iterations=80, target_rms=1.05)
>>> ctrl = ModEmControl.from_config(cfg)
>>> ctrl.max_iterations
80

Write and read a control file:

>>> path = ctrl.write("ModEM.inv")
>>> loaded = ModEmControl.read(path)
>>> loaded.target_rms == ctrl.target_rms
True

Tune lambda controls before writing:

>>> ctrl.initial_lambda = 20.0
>>> ctrl.lambda_divisor = 50.0
>>> ctrl.write("strong_start.inv")
PosixPath('strong_start.inv')

References

classmethod from_config(config=None, **kwargs)#

Build a control object from a ModEmConfig.

Parameters:
  • config (ModEmConfig, optional) – Configuration object supplying output stem, lambda controls, target RMS, convergence thresholds, and maximum iteration count. If omitted, a default ModEmConfig is used.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmControl, commonly verbose or logger inherited from ModEmBase.

Returns:

Control-file container initialized from config.

Return type:

ModEmControl

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.control import ModEmControl
>>> cfg = ModEmConfig(max_iterations=50, target_rms=1.03)
>>> ctrl = ModEmControl.from_config(cfg)
>>> ctrl.max_iterations
50
classmethod read(path, **kwargs)#

Parse an existing ModEM inversion-control file.

The reader scans the key-value labels recognized by ModEM and maps them to object attributes. Unknown lines are ignored so comments or executable-specific additions do not prevent the standard fields from loading.

Parameters:
  • path (path-like) – Path to an existing ModEM .inv control file. The file must contain colon-separated key-value rows such as Initial damping factor lambda and Maximum number of iterations.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmControl.

Returns:

Parsed control object. Fields not found in the file retain their default values from ModEmConfig.

Return type:

ModEmControl

Raises:

FileNotFoundError – If path does not exist.

Examples

>>> from pycsamt.models.modem.control import ModEmControl
>>> ctrl = ModEmControl.read("ModEM.inv")
>>> ctrl.target_rms > 0
True
write(path)#

Write the control object to a ModEM .inv file.

Parameters:

path (path-like) – Destination file. Parent directories are created before writing. Existing files are overwritten.

Returns:

Path passed to the writer, converted to pathlib.Path.

Return type:

pathlib.Path

Notes

Floating-point values are written with compact %.4g formatting. This matches the simple key-value style expected by ModEM while keeping files readable in version control.

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.control import ModEmControl
>>> ctrl = ModEmControl.from_config(ModEmConfig())
>>> path = ctrl.write("control.inv")
>>> path.name
'control.inv'
class pycsamt.models.modem.ModEmLog(**kwargs)#

Bases: ModEmBase

Represent a parsed ModEM NLCG iteration log.

ModEmLog stores the convergence history written by ModEM during nonlinear conjugate-gradient inversion. It extracts the initial START record and completed iteration records, then exposes each tracked quantity as a NumPy array. The object is used directly by result loaders and plotting helpers to inspect misfit reduction and inversion progress.

Each parsed record corresponds to a line with values similar to f, m2, rms, lambda, and alpha. These values summarize the trade-off between data fit and regularization:

\[\Phi(m) = \Phi_d(m) + \lambda \Phi_m(m),\]

where \(\Phi_d\) measures data misfit, \(\Phi_m\) measures model roughness or size, and \(\lambda\) is the damping parameter reported by the log.

Parameters:
  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • iterations (numpy.ndarray, shape (n_iter,)) – Parsed iteration numbers. The first record is often 0 from the START line. Some ModEM logs can contain restarts, so iteration numbers are not guaranteed to be unique or strictly increasing.

  • rms (numpy.ndarray, shape (n_iter,)) – Normalized root-mean-square misfit for each parsed record. Values near one indicate data fit comparable to the assigned errors when uncertainties are realistic.

  • objective (numpy.ndarray, shape (n_iter,)) – Total objective-function value f reported by ModEM.

  • model_norm (numpy.ndarray, shape (n_iter,)) – Model roughness or model norm m2 reported by ModEM.

  • lagrange (numpy.ndarray, shape (n_iter,)) – Lambda damping values used during inversion.

  • alpha (numpy.ndarray, shape (n_iter,)) – Line-search step length values reported by ModEM.

Notes

final_rms returns the last parsed RMS value, while best_iter returns the iteration number associated with the lowest parsed RMS value. If no records are parsed, final_rms is nan and best_iter is 0.

The parser is intentionally focused on the standard lines used by the ModEM examples and common NLCG outputs. Additional log messages are ignored.

See also

InversionResult

Loads

class:ModEmLog while scanning a run directory.

PlotMisfit

Plots RMS history from a parsed log.

ModEmControl

Defines target RMS and lambda controls used by the run.

ModEmRunner

Launches the ModEM executable that writes the log.

Examples

Read a ModEM log and inspect convergence:

>>> from pycsamt.models.modem.log import ModEmLog
>>> log = ModEmLog.read("Modular_NLCG.log")
>>> log.n_iter > 0
True
>>> log.best_iter in set(log.iterations)
True

Use the RMS history for plotting:

>>> rms = log.rms
>>> rms.shape == log.iterations.shape
True

References

property n_iter: int#

Number of parsed log records.

property final_rms: float#

Final parsed RMS value, or nan for an empty log.

property best_iter: int#

Iteration number with the lowest parsed RMS value.

classmethod read(path, **kwargs)#

Parse a ModEM NLCG log file.

Parameters:
  • path (path-like) – Path to a ModEM log file, commonly "Modular_NLCG.log" for bundled examples or "inverse.log" for some 3-D runs.

  • **kwargs (dict) – Additional keyword arguments forwarded to ModEmLog, commonly verbose or logger.

Returns:

Parsed log object containing iteration numbers, RMS values, objective values, model norms, lambda values, and line-search step lengths.

Return type:

ModEmLog

Raises:

FileNotFoundError – If path does not exist.

Examples

>>> from pycsamt.models.modem.log import ModEmLog
>>> log = ModEmLog.read("Modular_NLCG.log")
>>> log.n_iter > 0
True
>>> log.final_rms == log.rms[-1]
True
class pycsamt.models.modem.InversionResult(workdir, config=None, load_log=True, load_control=True, load_covariance=True, load_models=True, load_data=True, **kwargs)#

Bases: ModEmBase

Aggregate the files produced by a ModEM inversion run.

InversionResult scans one ModEM working directory, detects whether it contains two-dimensional or three-dimensional model files, and loads every recognized artefact into a single Python object. It is intended for post-processing, plotting, quality control, and workflow scripts that need a consistent view of logs, control files, models, data, and covariance settings after a run has finished.

The main scalar quality measure exposed by the class is the root-mean-square data misfit. For \(N\) weighted data residuals, the value reported by ModEM is commonly read as

\[\mathrm{RMS} = \sqrt{\frac{1}{N} \sum_{i=1}^N \left(\frac{d_i^{obs} - d_i^{pred}} {\sigma_i}\right)^2}.\]

Here \(d_i^{obs}\) and \(d_i^{pred}\) are observed and predicted data values, and \(\sigma_i\) is the data uncertainty used for weighting. The exact composition of the sum depends on the component family selected in the ModEM data file [1]_.

Parameters:
  • workdir (path-like, default ".") – Directory that contains, or will receive, a ModEM run. The builder writes the data file, starting model, covariance file, and inversion-control file here. The runner executes the ModEM binary from this directory so relative file names in command-line arguments and control files refer to the same run folder. The directory is created before output is written.

  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • **kwargs (dict) – Additional keyword arguments passed to ModEmBase. Typical values include logging and verbosity options shared by the ModEM wrapper classes.

  • load_log (bool)

  • load_control (bool)

  • load_covariance (bool)

  • load_models (bool)

  • load_data (bool)

Variables:
  • workdir (pathlib.Path) – Resolved directory scanned for ModEM artefacts. The directory must exist before the result object is created.

  • mode ({"2d", "3d", "unknown"}) – Detected inversion dimensionality. A directory containing *.ws files is treated as 3-D, a directory containing *.rho files is treated as 2-D, and an empty or unrecognized directory remains "unknown".

  • log (ModEmLog or None) – Parsed run log containing iteration numbers, objective values, model norms, trade-off parameters, and RMS history. The attribute is None when no readable log file is present.

  • control (ModEmControl or None) – Parsed inversion-control file, usually read from the first *.inv file found in workdir. It records nonlinear solver limits, target misfit, lambda controls, and output naming settings.

  • model_initial (ModEmModel2D or ModEmModel3D, optional) – Initial model loaded from the run directory. It represents the starting half-space or user-supplied model before inversion updates were applied.

  • model_final (ModEmModel2D or ModEmModel3D, optional) – Final model loaded from the run directory. When several iteration models are present, this is the highest-numbered or otherwise final model detected by the result scanner.

  • models (dict) – Mapping from iteration labels to parsed ModEM model objects. The dictionary allows callers to inspect model evolution across iterations rather than only the final inversion result.

  • data_obs (ModEmData, optional) – Observed data loaded from the run directory. Response and pseudo-section plots compare this object with predicted data when both are available.

  • data_pred (ModEmData, optional) – Predicted response data loaded from ModEM output. It should share stations, periods, and component choices with data_obs so residuals and response plots are meaningful.

  • covariance (ModEmCovariance or None) – Parsed covariance file for 3-D runs. The object contains smoothing weights, smoothing iteration count, and active masks when a readable *.cov file is available.

Notes

The scanner is deliberately tolerant. If a recognized file is missing or cannot be parsed, the corresponding attribute is left as None and scanning continues. This makes the class useful for inspecting incomplete, interrupted, or partially copied run directories.

Model files are keyed by their file stem. The initial model is selected from m0 when present. The final model is selected from mi when present; otherwise the highest numbered m<N> model is used.

Examples

Load a finished inversion directory and inspect the misfit:

>>> from pycsamt.models.modem.results import InversionResult
>>> result = InversionResult("modem_run")
>>> result.mode in {"2d", "3d", "unknown"}
True
>>> float(result.final_rms) == result.final_rms
True

Access model and data products when they were loaded:

>>> if result.model_final is not None:
...     rho = result.model_final.rho_linear
...     rho.ndim in (2, 3)
... else:
...     rho = None

Compare the best and final RMS values:

>>> if result.rms_history.size:
...     result.best_rms <= result.final_rms
... else:
...     result.n_iter == 0
True

See also

ModEmLog

Parser for ModEM iteration logs and RMS histories.

ModEmData

Reader and writer for observed and predicted data files.

ModEmModel2D

Two-dimensional ModEM resistivity model container.

ModEmModel3D

Three-dimensional ModEM resistivity model container.

ModEmControl

Reader and writer for ModEM inversion-control files.

ModEmCovariance

Reader and writer for 3-D covariance smoothing files.

References

property n_iter: int#

Total number of inversion iterations parsed from the log.

property final_rms: float#

Final root-mean-square data misfit reported by ModEM.

Returns:

Last parsed RMS value. If no log was loaded, the value is nan so callers can use numpy.isfinite() to check availability.

Return type:

float

property rms_history: ndarray#

RMS misfit values for each parsed inversion iteration.

property best_rms: float#

Minimum RMS value reached by the inversion history.

property iteration_numbers: ndarray#

Iteration numbers associated with rms_history.

class pycsamt.models.modem.ModEmRunner(workdir, config=None, **kwargs)#

Bases: ModEmBase

Launch ModEM inversion and forward-modeling subprocesses.

ModEmRunner is the execution layer of the ModEM wrapper. It does not build input files itself; instead it receives model, data, control, and optional covariance files created by InputBuilder or by user code, selects the configured ModEM executable, launches the process from workdir, and can load the finished run into an InversionResult.

For inversion runs the command has the logical form

Mod3DMT -I NLCG model.ws data.dat control.inv covariance.cov

or, when MPI execution is requested,

mpirun -np 8 Mod3DMT -I NLCG model.ws data.dat control.inv

The 2-D runner uses config.binary_2d and 2-D model files, whereas the 3-D runner uses config.binary_3d and can pass a covariance file. The forward-only path uses the -F flag and requires only model and data files.

Parameters:
  • workdir (path-like, default ".") – Directory that contains, or will receive, a ModEM run. The builder writes the data file, starting model, covariance file, and inversion-control file here. The runner executes the ModEM binary from this directory so relative file names in command-line arguments and control files refer to the same run folder. The directory is created before output is written.

  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • **kwargs (dict) – Additional keyword arguments passed to ModEmBase, including logging and verbosity options.

Variables:
  • workdir (pathlib.Path) – Directory from which the subprocess is launched. Relative file names in ModEM command lines are interpreted from this directory.

  • config (ModEmConfig) – Configuration used to choose mode, executable names, MPI command, process count, and result-loading behavior.

Notes

Executable resolution is intentionally small and predictable. The runner first accepts a name found on PATH. It then checks workdir / name and local source-build locations under workdir / "_source" / "3D" and workdir / "_source" / "2D". Use an absolute executable path in the configuration when running against a system installation outside the run folder.

The runner delegates process execution to subprocess.run(). Standard output and standard error are inherited from the calling process unless the surrounding application redirects them. A non-zero exit status is converted to subprocess.CalledProcessError by check_returncode.

Examples

Create a runner for a serial 3-D inversion:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.runner import ModEmRunner
>>> cfg = ModEmConfig(mode="3d", use_mpi=False)
>>> runner = ModEmRunner("modem_run", config=cfg)
>>> cmd = runner.command("m0.ws", "d0.dat", "control.inv")
>>> "-I NLCG" in cmd
True

Run a forward response calculation from an existing model:

>>> runner = ModEmRunner("modem_run", config=cfg)
>>> result = runner.run_forward("mi.ws", "d0.dat")

See also

InputBuilder

Build ModEM model, data, covariance, and control files.

ModEmConfig

Store executable names, MPI settings, and inversion options shared by the runner.

InversionResult

Load logs, models, data, and covariance after a run.

References

run(model, data, control, covariance=None, *, mode=None, use_mpi=None, n_procs=None, extra_args=None, timeout=None, load_result=True)#

Run a nonlinear ModEM inversion subprocess.

This method builds the command line for an inversion run, launches it with subprocess.run(), checks the process return code, and optionally scans workdir into an InversionResult. The executable is called with the inversion flag sequence -I NLCG so the run uses ModEM’s nonlinear conjugate gradient inversion mode.

Parameters:
  • model (path-like) – Starting or current ModEM model file passed to the runner. The path may be absolute or relative to workdir. In 2-D runs it usually points to a .rho file; in 3-D runs it usually points to a .ws model file.

  • data (path-like) – Observed-data file passed to ModEM. The file should match the dimensionality, component selection, sign convention, period list, and units expected by the selected executable and control settings.

  • control (path-like) – ModEM inversion-control file passed to inversion runs. It contains iteration limits, target misfit, lambda controls, output stem, line-search settings, and related nonlinear solver parameters.

  • covariance (path-like, optional) – ModEM covariance file passed to 3-D inversion runs. The file describes smoothing strengths, smoothing iteration count, and active-cell masks. It is commonly omitted for 2-D workflows.

  • mode ({"2d", "3d"}, optional) – Dimensionality override for this invocation. If omitted, config.mode is used. The value selects config.binary_2d or config.binary_3d and should match the model and data file formats.

  • use_mpi (bool, optional) – MPI override for this invocation. If omitted, config.use_mpi is used. When true, the command is prefixed by config.mpi_command -np <n_procs>.

  • n_procs (int, optional) – Number of MPI processes requested for this invocation. If omitted, config.n_procs is used. The value is ignored when MPI execution is disabled.

  • extra_args (sequence of str, optional) – Additional command-line arguments appended to the ModEM executable invocation. Use this for advanced executable flags while keeping standard file handling under the runner.

  • timeout (float, optional) – Maximum run time in seconds for the ModEM process. If the process exceeds this duration, it is terminated by the caller. Leave as None for no Python-side timeout.

  • load_result (bool, default True) – Whether to scan workdir and return an InversionResult after the executable finishes. Set to False when the caller only needs process completion.

Returns:

Parsed result object when load_result is true. Otherwise None is returned after the subprocess completes successfully.

Return type:

InversionResult or None

Raises:

Notes

Relative paths are passed to ModEM exactly as supplied while the subprocess working directory is set to workdir. This mirrors the way ModEM control files and examples are usually written: model, data, control, and covariance file names are interpreted relative to the run directory.

Examples

Run a serial 3-D inversion and load the result:

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.runner import ModEmRunner
>>> cfg = ModEmConfig(mode="3d", use_mpi=False)
>>> runner = ModEmRunner("modem_run", config=cfg)
>>> result = runner.run(
...     model="m0.ws",
...     data="d0.dat",
...     control="control.inv",
...     covariance="covariance.cov",
... )

Run with MPI and defer result loading:

>>> cfg = ModEmConfig(mode="3d", use_mpi=True, n_procs=8)
>>> runner = ModEmRunner("modem_run", config=cfg)
>>> runner.run(
...     "m0.ws",
...     "d0.dat",
...     "control.inv",
...     covariance="covariance.cov",
...     load_result=False,
... )

See also

command

Build the same inversion command without executing it.

run_forward

Execute a forward-only ModEM response calculation.

InversionResult

Loader for logs, models, data, and covariance outputs.

run_forward(model, data, *, mode=None, use_mpi=None, n_procs=None, timeout=None, load_result=True)#

Run a forward-only ModEM response calculation.

Forward mode evaluates predicted responses for an existing model and data file without updating the model. The executable is called with the -F flag. This is useful for checking a starting model, computing synthetic responses, or re-evaluating a final model after editing data weights.

Parameters:
  • model (path-like) – Starting, current, or final ModEM model file used for response calculation. The path may be absolute or relative to workdir.

  • data (path-like) – Data file that defines the stations, periods, components, and errors for which responses are calculated.

  • mode ({"2d", "3d"}, optional) – Dimensionality override for this invocation. If omitted, config.mode selects the executable.

  • use_mpi (bool, optional) – MPI override for this invocation. If omitted, config.use_mpi is used.

  • n_procs (int, optional) – Number of MPI processes requested when MPI execution is enabled. If omitted, config.n_procs is used.

  • timeout (float, optional) – Maximum run time in seconds for the ModEM process. Leave as None for no Python-side timeout.

  • load_result (bool, default True) – Whether to scan workdir and return an InversionResult after the executable finishes.

Returns:

Parsed result object when load_result is true. Otherwise None is returned after successful process completion.

Return type:

InversionResult or None

Raises:

Examples

>>> from pycsamt.models.modem.runner import ModEmRunner
>>> runner = ModEmRunner("modem_run")
>>> result = runner.run_forward("mi.ws", "d0.dat")
command(model, data, control, covariance=None, *, mode=None, use_mpi=None, n_procs=None)#

Return the inversion command without executing ModEM.

This helper is a dry-run view of run(). It applies the same mode, MPI, process-count, and file-name choices, but it does not resolve the executable or start a subprocess.

Parameters:
  • model (path-like) – Starting or current ModEM model file to include in the command string.

  • data (path-like) – Observed-data file to include in the command string.

  • control (path-like) – Inversion-control file to include in the command string.

  • covariance (path-like, optional) – Covariance file appended to the command when supplied.

  • mode ({"2d", "3d"}, optional) – Dimensionality override for the command string.

  • use_mpi (bool, optional) – MPI override for the command string.

  • n_procs (int, optional) – MPI process-count override.

Returns:

Shell-quoted command string suitable for display, logging, or copying into a terminal.

Return type:

str

Examples

>>> from pycsamt.models.modem.config import ModEmConfig
>>> from pycsamt.models.modem.runner import ModEmRunner
>>> cfg = ModEmConfig(mode="3d", use_mpi=True, n_procs=4)
>>> runner = ModEmRunner("modem_run", config=cfg)
>>> "mpirun" in runner.command("m0.ws", "d0.dat", "c.inv")
True
class pycsamt.models.modem.PlotMisfit(result=None, show_best=True, **kwargs)#

Bases: _ModEmPlotBase

Plot RMS misfit as a function of inversion iteration.

PlotMisfit visualizes the convergence history parsed from ModEmLog. The plot shows normalized RMS misfit against iteration number and, optionally, marks the lowest RMS value. A reference line at \(RMS=1\) is included because values near one generally indicate a data fit comparable to the assigned errors.

Parameters:
  • result (InversionResult, optional) – Loaded ModEM inversion result. The result must contain a parsed log attribute.

  • show_best (bool, default True) – Whether to mark the iteration with the lowest parsed RMS value.

Examples

>>> from pycsamt.models.modem.results import InversionResult
>>> from pycsamt.models.modem.plot import PlotMisfit
>>> result = InversionResult("modem_run")
>>> fig = PlotMisfit(result=result).plot()
plot()#

Return a matplotlib figure containing the RMS curve.

Returns:

Figure containing one axes with RMS history.

Return type:

matplotlib.figure.Figure

Raises:

ValueError – If no result is attached or the result has no parsed log.

class pycsamt.models.modem.PlotModel2D(result=None, which='final', depth_max=None, rho_min=1.0, rho_max=1000.0, cmap='jet_r', section='inversion', figsize=None, show_stations=True, **kwargs)#

Bases: _ModEmPlotBase

Plot a 2-D ModEM resistivity cross-section.

The plot displays either the initial or final 2-D model as a depth section. Resistivity is shown on a logarithmic colour scale because magnetotelluric models commonly span several orders of magnitude.

Parameters:
  • result (InversionResult, optional) – Loaded inversion result containing model_initial or model_final.

  • which ({"final", "initial"}, default "final") – Which model to display.

  • depth_max (float, optional) – Maximum depth in metres to display. If omitted, all layers are plotted.

  • rho_min (float, default 1.0, 1000.0) – Resistivity colour-scale limits in ohm metres.

  • rho_max (float, default 1.0, 1000.0) – Resistivity colour-scale limits in ohm metres.

  • cmap (str, default "jet_r") – Matplotlib colourmap name.

  • section (str | SectionStyle)

  • figsize (tuple[float, float] | None)

  • show_stations (bool)

Examples

>>> from pycsamt.models.modem.plot import PlotModel2D
>>> fig = PlotModel2D(result=result, depth_max=5000).plot()
plot()#

Return a matplotlib figure containing the model section.

class pycsamt.models.modem.PlotModel3D(result=None, depths=None, which='final', rho_min=1.0, rho_max=1000.0, cmap='jet_r', n_cols=2, section='inversion', show_stations=True, **kwargs)#

Bases: _ModEmPlotBase

Plot horizontal slices through a 3-D ModEM model.

PlotModel3D extracts model layers nearest to requested depths and renders each as an x-y resistivity map. The selected depths are interpreted in metres below the model top, including the depth coordinate convention stored in the model object.

Parameters:
  • result (InversionResult, optional) – Loaded inversion result containing a 3-D model.

  • depths (sequence of float, optional) – Depths in metres at which to extract slices. If omitted, the first four active earth-layer centres are used.

  • which ({"final", "initial"}, default "final") – Which model to display.

  • rho_min (float, default 1.0, 1000.0) – Resistivity colour-scale limits in ohm metres.

  • rho_max (float, default 1.0, 1000.0) – Resistivity colour-scale limits in ohm metres.

  • cmap (str, default "jet_r") – Matplotlib colourmap name.

  • n_cols (int, default 2) – Number of columns in the subplot grid.

  • section (str | SectionStyle)

  • show_stations (bool)

plot()#

Return a matplotlib figure containing model slices.

class pycsamt.models.modem.PlotResponse(result=None, stations=None, max_stations=4, show_tipper=False, period_min=None, period_max=None, figsize=None, style='modem', **kwargs)#

Bases: _ModEmPlotBase

Per-station MT response in MTPy style.

Plots apparent resistivity and phase for all four impedance components (Z_xx, Z_xy, Z_yx, Z_yy) of each selected station. Each station occupies 4 columns (one per component) built with GridSpecFromSubplotSpec so the ρ_a panel is exactly twice the height of the φ panel with zero whitespace between them.

Observed data is drawn with error bars using component colours from PYCSAMT_STYLE. When the result contains predicted data (result.data_pred), the modelled response is overlaid as a dotted line in the same colour. The component RMS misfit is shown in each subplot title.

Parameters:
  • result (InversionResult, optional) – Loaded inversion result.

  • stations (sequence of str, optional) – Station names to plot. Defaults to the first max_stations stations in result.data_obs.

  • max_stations (int, default 4) – Maximum number of stations to show.

  • show_tipper (bool, default False) – Whether to add a third row for tipper (Re/Im Tx and Ty).

  • period_min (float, optional) – Period range in seconds to display.

  • period_max (float, optional) – Period range in seconds to display.

  • figsize (tuple of float, optional) – Figure size in inches. Derived automatically if omitted.

  • style (str)

Examples

>>> from pycsamt.models.modem.results import InversionResult
>>> from pycsamt.models.modem.plot import PlotResponse
>>> result = InversionResult("modem_run")
>>> fig = PlotResponse(result=result, stations=["23-18-010U"]).plot()
plot()#

Return a matplotlib figure with the per-station response panels.

class pycsamt.models.modem.PlotPseudo(result=None, component='TE', rho_min=1.0, rho_max=1000.0, cmap='jet_r', **kwargs)#

Bases: _ModEmPlotBase

Plot apparent-resistivity and phase pseudo-sections.

PlotPseudo selects one component from observed data and arranges apparent resistivity and phase on station offset versus period grids. This is a quick survey-scale view of lateral and period-dependent response variation.

Parameters:
  • result (InversionResult, optional) – Loaded result containing observed data.

  • component (str) – Data component to display (e.g. 'TE', 'ZXY').

  • rho_min (float, default 1.0, 1000.0) – Apparent-resistivity colour-scale limits in ohm metres.

  • rho_max (float, default 1.0, 1000.0) – Apparent-resistivity colour-scale limits in ohm metres.

  • cmap (str, default "jet_r") – Matplotlib colourmap used for apparent resistivity.

plot()#

Return a matplotlib figure containing pseudo-sections.

class pycsamt.models.modem.InputBuilder(config=None, **kwargs)#

Bases: ModEmBase

Build and write a complete ModEM input set.

InputBuilder is the main preparation object for the ModEM v2 workflow. It turns a survey source into the files required by the ModEM executable: an observed-data file, a half-space starting model, a covariance file for 3-D runs, and an inversion-control file. The builder does not launch ModEM. Instead, it creates a consistent working directory that can be passed to ModEmRunner.

The build sequence is deterministic:

  1. Convert the survey source to ModEmData.

  2. Build a 2-D or 3-D half-space starting model.

  3. Derive a 3-D covariance file when config.mode == "3d".

  4. Write the ModEM inversion-control file.

For a uniform starting resistivity \(\rho_0\), model writers store logarithmic resistivity values, commonly

\[m_0 = \ln(\rho_0).\]

These files are then used by ModEM to solve a regularized nonlinear inverse problem for the subsurface resistivity distribution [1]_, [2]_.

Parameters:
  • config (ModEmConfig, optional) – Configuration object controlling dimensionality, data components, error floors, grid geometry, covariance smoothing, inversion controls, file names, executable names, and MPI settings. If omitted, a default ModEmConfig is created. Pass an explicit configuration when several ModEM objects must use exactly the same run parameters.

  • verbose (int or bool, default 0) – Verbosity level used for progress reporting. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used by callers to request more detailed run, parsing, or export information.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating ModEM workflows into an application-wide logging configuration.

Variables:
  • config (ModEmConfig) – Mutable run configuration used by all build steps. It selects dimensionality, component type, error floors, model geometry, covariance smoothing, control values, and default executable/file names.

  • data (ModEmData or None) – Data object generated by build() or supplied through build_from_data(). It stores station coordinates, periods, component rows, complex values, and errors.

  • model (ModEmModel2D or ModEmModel3D or None) – Starting model generated from data and config. The concrete class depends on config.mode.

  • covariance (ModEmCovariance or None) – Covariance object generated only for 3-D runs. It stores smoothing controls and active-cell masks derived from the starting model.

  • control (ModEmControl or None) – Inversion-control object generated from config.

  • Parameters (Build)

  • ----------------

  • source (iterable of site-like objects) – Survey source used to build a ModEM data file. Each item must expose station name, coordinates, frequency samples, impedance tensor values, and impedance errors in the form accepted by ModEmData.from_edi(). EDI collections, site containers, and custom objects with compatible attributes can be used. Coordinates are required for building station locations in the ModEM coordinate system.

  • workdir (path-like, default ".") – Directory that contains, or will receive, a ModEM run. The builder writes the data file, starting model, covariance file, and inversion-control file here. The runner executes the ModEM binary from this directory so relative file names in command-line arguments and control files refer to the same run folder. The directory is created before output is written.

  • data_filename (str, default "data.dat") – Name of the observed-data file written by InputBuilder.build(). The name is resolved relative to workdir. Use a descriptive value when several data selections or component sets are written into the same parent directory.

  • model_filename (str, optional) – Name of the starting-model file written by the builder. If omitted, the builder selects "m0.ws" for 3-D runs and "m0.rho" for 2-D runs. The extension should remain compatible with the selected ModEM executable and model writer.

  • cov_filename (str, default "covariance.cov") – Name of the covariance file written for 3-D inversions. The file stores smoothing weights, smoothing iteration count, and active-cell masks derived from the starting model. It is not written for 2-D builder workflows.

  • ctrl_filename (str, default "control.inv") – Name of the ModEM inversion-control file written by the builder. The file contains nonlinear solver settings, target RMS, lambda controls, and output-stem information derived from ModEmConfig.

Notes

InputBuilder writes a half-space model by design. This is the standard starting point for many ModEM inversions and gives the solver a stable initial model. Users who need a custom starting model can write it separately and pass that file to the runner while still using this builder for data, covariance, and control-file generation.

The 2-D builder path writes data, model, and control files. The 3-D path additionally writes a covariance file because ModEM 3-D inversions use explicit smoothing and mask definitions.

See also

ModEmData.from_edi

Convert EDI-like station objects into ModEM data rows.

ModEmModel2D.halfspace

Build a 2-D half-space model from station geometry.

ModEmModel3D.halfspace

Build a 3-D half-space model from station geometry.

ModEmCovariance.from_model

Derive 3-D smoothing and active-cell masks from a model.

ModEmControl.from_config

Build inversion controls from ModEmConfig.

ModEmRunner

Execute ModEM with the generated input files.

Examples

Build the default 3-D ModEM files:

>>> from pycsamt.models.modem.builder import InputBuilder
>>> from pycsamt.models.modem.config import ModEmConfig
>>> cfg = ModEmConfig(mode="3d", initial_rho=100.0)
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build(sites, workdir="modem_run")
>>> sorted(files)
['control', 'covariance', 'data', 'model']

Build a 2-D TE input set:

>>> cfg = ModEmConfig(
...     mode="2d",
...     component_type="TE_Impedance",
...     nz_2d=60,
... )
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build(sites, workdir="modem_te")
>>> "covariance" in files
False

Reuse an already assembled data object:

>>> from pycsamt.models.modem.data import ModEmData
>>> data = ModEmData.from_edi(sites, config=cfg)
>>> data.write("modem_te/data.dat")
>>> files = builder.build_from_data(data, workdir="modem_te")
>>> sorted(files)
['control', 'model']

Use custom file names for a test run:

>>> cfg = ModEmConfig(mode="3d", output_stem="trial")
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build(
...     sites,
...     workdir="trial_run",
...     data_filename="obs_trial.dat",
...     model_filename="start_trial.ws",
...     cov_filename="smooth_trial.cov",
...     ctrl_filename="trial.inv",
... )
>>> files["control"].name
'trial.inv'

References

build(source, workdir='.', *, data_filename='data.dat', model_filename=None, cov_filename='covariance.cov', ctrl_filename='control.inv')#

Write the complete ModEM input set to workdir.

The method is the normal entry point for preparing a new ModEM inversion from EDI-like survey data. It first converts source to ModEmData, then builds a uniform half-space starting model with the geometry defined by self.config. For 3-D runs it also derives a covariance file from the model grid. Finally, it writes the inversion-control file.

The generated file set is:

  • observed data, usually data.dat;

  • starting model, m0.ws in 3-D or m0.rho in 2-D;

  • covariance file for 3-D runs only;

  • inversion-control file, usually control.inv.

Parameters:
  • source (iterable of site-like objects) – Survey source accepted by ModEmData.from_edi(). Each item should provide a station name, coordinates, frequency samples, a complex impedance tensor, and impedance errors. The builder consumes the iterable immediately, so generators are supported but cannot be reused after the call.

  • workdir (path-like, default ".") – Output directory that will contain the ModEM input files. The directory is created if it does not exist. Relative paths are resolved from the current Python working directory.

  • data_filename (str, default "data.dat") – Name of the observed-data file written in workdir. Use this to keep several component selections or frequency bands in the same parent folder.

  • model_filename (str, optional) – Name of the starting-model file. If omitted, "m0.ws" is used for 3-D runs and "m0.rho" is used for 2-D runs.

  • cov_filename (str, default "covariance.cov") – Name of the covariance file written for 3-D runs. The value is ignored for 2-D runs because the current 2-D builder path does not write a covariance file.

  • ctrl_filename (str, default "control.inv") – Name of the inversion-control file written in workdir.

Returns:

Mapping from output role to resolved pathlib.Path. The mapping always contains "data", "model", and "control". It also contains "covariance" for 3-D runs.

Return type:

dict

Raises:

ValueError – Raised by ModEmData.from_edi() when source is empty or cannot provide the required station and impedance information.

Examples

Build a standard 3-D input set from EDI-like stations:

>>> from pycsamt.models.modem.builder import InputBuilder
>>> from pycsamt.models.modem.config import ModEmConfig
>>> cfg = ModEmConfig(mode="3d", initial_rho=100.0)
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build(sites, workdir="modem_3d")
>>> sorted(files)
['control', 'covariance', 'data', 'model']

Build a 2-D TE inversion input set with custom names:

>>> cfg = ModEmConfig(
...     mode="2d",
...     component_type="TE_Impedance",
... )
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build(
...     sites,
...     workdir="modem_2d_te",
...     data_filename="te_data.dat",
...     model_filename="te_start.rho",
...     ctrl_filename="te_control.inv",
... )
>>> "covariance" in files
False
build_from_data(data, workdir='.', *, model_filename=None, cov_filename='covariance.cov', ctrl_filename='control.inv')#

Write run files from an existing ModEmData.

This method is useful when the observed-data object has already been assembled, filtered, edited, or written by a caller. It uses the supplied data to build the starting model, derives a covariance file for 3-D workflows, and writes the inversion-control file. It does not write the data file itself, so callers should write data to the run directory when the ModEM executable will need it.

Parameters:
  • data (ModEmData) – Populated data object used to derive station extents, periods, and model geometry. The object is retained as self.data after the method returns.

  • workdir (path-like, default ".") – Output directory for the generated starting model, optional covariance file, and control file. The directory is created if it does not exist.

  • model_filename (str, optional) – Name of the starting-model file. If omitted, "m0.ws" is used for 3-D runs and "m0.rho" is used for 2-D runs.

  • cov_filename (str, default "covariance.cov") – Name of the covariance file written for 3-D runs. Ignored for 2-D workflows.

  • ctrl_filename (str, default "control.inv") – Name of the inversion-control file written in workdir.

Returns:

Mapping from output role to resolved pathlib.Path. The mapping contains "model" and "control" for all modes, and also "covariance" for 3-D runs.

Return type:

dict

Examples

Reuse a data object that was prepared elsewhere:

>>> from pycsamt.models.modem.builder import InputBuilder
>>> from pycsamt.models.modem.data import ModEmData
>>> data = ModEmData.from_edi(sites, config=cfg)
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build_from_data(data, workdir="run")
>>> sorted(files)
['control', 'covariance', 'model']
pycsamt.models.modem.interp_model3d(source, target, bg_rho=1000.0)#

Interpolate a 3-D resistivity model onto a new grid.

Equivalent to interpCond_3D(newgrid, oldCond, bg) in MATLAB. Trilinear interpolation is used; cells outside the source domain are filled with bg_rho.

Parameters:
  • source (ModEmModel3D) – Model to interpolate from.

  • target (ModEmModel3D) – Model whose grid specifies the destination. Only its grid attributes (x_widths, y_widths, z_widths, n_air) are used; the rho_loge array is overwritten in the returned copy.

  • bg_rho (float or array-like) – Background resistivity in Ω·m used to fill cells outside the source domain. Scalar applies to all layers; a 1-D array of length target.nz applies per layer.

Returns:

New model on the target grid with interpolated values.

Return type:

ModEmModel3D

Raises:

ImportError – If SciPy is not installed.

pycsamt.models.modem.interp_z3d(imp, new_site_loc, new_site_names=None, pct_error=None)#

Interpolate 3-D MT impedance data to new site locations.

Equivalent to interpZ_3D(data, siteLoc, siteChar, pererr) in MATLAB. Cubic scattered interpolation is applied independently to the real and imaginary parts of each component and each period.

Parameters:
  • imp (ImpedanceFile) – Source impedance data.

  • new_site_loc (array-like, shape (n_new, 2) or (n_new, 3)) – Target site locations. Columns 0 and 1 are X and Y in metres.

  • new_site_names (list of str, optional) – Site codes for the new locations. Auto-generated as S000, S001, … if not given.

  • pct_error (float, optional) – If provided, replace error estimates with this percentage of |Z| (e.g. pct_error=5 → 5 % error). Mirrors the ADD_NOISE branch of the MATLAB function.

Returns:

New data file with impedances at the target locations.

Return type:

ImpedanceFile

Raises:

ImportError – If SciPy is not installed.

pycsamt.models.modem.write_meshtools3d(model, path)#

Export a ModEmModel3D to MeshTools3D mesh and conductivity files.

Equivalent to write_meshtools3d_model(fname, Cond) in MATLAB. The model is converted from LOGE resistivity to linear conductivity before writing. Air layers (the first model.n_air z-layers) are excluded from the export.

Parameters:
  • model (ModEmModel3D) – Source model. rho_loge values are expected as ln(Ω·m).

  • path (str or Path) – Base path for output. The .msh and .con extensions are appended automatically. Any existing extension is stripped.

Returns:

  • msh_path (Path) – Path to the mesh file.

  • con_path (Path) – Path to the conductivity file.

Return type:

tuple[Path, Path]

Examples

>>> msh, con = write_meshtools3d(model, "output/my_model")
pycsamt.models.modem.skin_depth(period, rho=100.0)#

Electromagnetic skin depth δ in metres.

Equivalent to the skindepth.m script:

δ = √(2ρ / (ω μ₀))

where ω = 2π/T.

Parameters:
  • period (float or array-like) – Period in seconds.

  • rho (float or array-like, optional) – Resistivity in Ω·m. Defaults to 100 Ω·m.

Returns:

Skin depth in metres.

Return type:

float or ndarray

Examples

>>> skin_depth(1.0)          # 1 s period, 100 Ω·m
503.292...
>>> skin_depth([1.0, 10.0, 100.0], rho=10.0)
array([159.154..., 503.292..., 1591.549...])
pycsamt.models.modem.imp_units_factor(from_units, to_units)#

Return the multiplicative conversion factor between impedance unit strings.

Equivalent to ImpUnits(from, to) called implicitly in readZ_3D.m. In the ModEM context only SI and [mV/km]/[nT] are common; both map to the same numerical value so the factor is always 1.0 for the supported units.

Parameters:
  • from_units (str) – Unit strings (case-insensitive). Recognised values: '[V/m]/[T]', '[mV/km]/[nT]', 'Ohm'.

  • to_units (str) – Unit strings (case-insensitive). Recognised values: '[V/m]/[T]', '[mV/km]/[nT]', 'Ohm'.

Return type:

float

Raises:

ValueError – If either unit string is not recognised.

pycsamt.models.modem.loge_to_log10(rho_loge)#

Convert ln(ρ) to log₁₀(ρ).

Parameters:

rho_loge (ndarray)

Return type:

ndarray

pycsamt.models.modem.log10_to_loge(rho_log10)#

Convert log₁₀(ρ) to ln(ρ).

Parameters:

rho_log10 (ndarray)

Return type:

ndarray

pycsamt.models.modem.loge_to_linear(rho_loge)#

Convert ln(ρ) to linear resistivity (Ω·m).

Parameters:

rho_loge (ndarray)

Return type:

ndarray

pycsamt.models.modem.linear_to_loge(rho)#

Convert linear resistivity (Ω·m) to ln(ρ).

Parameters:

rho (ndarray)

Return type:

ndarray

pycsamt.models.modem.read_mackie2d(path)#

Read a 2D Mackie resistivity model file.

Equivalent to readCond_2D(fname) in MATLAB. Ten synthetic air layers are prepended to the vertical grid (matching the MATLAB wrapper).

Parameters:

path (str or Path) – Path to the Mackie 2D model file (typically *.rho).

Returns:

Populated model object with n_air set to 10.

Return type:

ModEmModel2D

pycsamt.models.modem.write_mackie2d(model, path, n_air=None, log_type='LOGE')#

Write a ModEmModel2D in Mackie 2D format.

Equivalent to writeCond_2D(fname, cond) in MATLAB. Only the earth layers are written; air layers are stripped first.

Parameters:
  • model (ModEmModel2D)

  • path (str or Path) – Output file path.

  • n_air (int, optional) – Number of air layers at the top of the model grid. If None, uses model.n_air if present, otherwise auto-detects from rho values.

  • log_type ({'LOGE', 'LINEAR', 'LOG10'}) – Encoding to use in the file. Defaults to 'LOGE'.

Returns:

Resolved output path.

Return type:

Path

pycsamt.models.modem.read_mackie3d(path)#

Read a 3D Mackie resistivity model file.

Equivalent to readCond_3D(fname, format=1) in MATLAB.

Parameters:

path (str or Path) – Path to the Mackie 3D model file.

Returns:

Populated model object.

Return type:

ModEmModel3D

pycsamt.models.modem.write_mackie3d(model, path, log_type='LOGE', origin=(0.0, 0.0, 0.0), rotation=0.0)#

Write a ModEmModel3D in Mackie 3D format.

Equivalent to writeCond_3D(fname, cond, format=1) in MATLAB. Each depth layer is written as a separate block with a single integer index on its own line.

Parameters:
  • model (ModEmModel3D)

  • path (str or Path) – Output file path.

  • log_type ({'LOGE', 'LINEAR', 'LOG10'}) – Encoding to use. Defaults to 'LOGE'.

  • origin (sequence of 3 floats) – Grid centre (x, y, z) in metres. Written as km.

  • rotation (float) – Grid rotation angle in degrees.

Returns:

Resolved output path.

Return type:

Path

class pycsamt.models.modem.ZBlock(period, site_names, site_loc, comp_names, Z, Zerr, mode='', lat=None, lon=None)#

Bases: object

One transmitter (period) block of impedance data.

Variables:
  • period (float) – Period in seconds.

  • site_names (list of str) – Site codes, length n_sites.

  • site_loc (ndarray, shape (n_sites, 3)) – Site locations in metres: [X, Y, Z].

  • comp_names (list of str) – Complex component names, e.g. ['ZXX', 'ZXY', 'ZYX', 'ZYY'].

  • Z (ndarray, shape (n_sites, n_comp), complex) – Impedance values.

  • Zerr (ndarray, shape (n_sites, n_comp), float) – Impedance error estimates (standard deviations).

  • mode (str) – 'TE', 'TM', or '' (3-D).

  • lon (lat,) – Geographic coordinates (optional).

Parameters:
period: float#
site_names: list[str]#
site_loc: ndarray#
comp_names: list[str]#
Z: ndarray#
Zerr: ndarray#
mode: str = ''#
lat: ndarray | None = None#
lon: ndarray | None = None#
property n_sites: int#
property n_comp: int#
class pycsamt.models.modem.ImpedanceFile(description='ModEM impedance data', units='[V/m]/[T]', sign=-1, blocks=<factory>, origin=(0.0, 0.0, 0.0), orientation=0.0)#

Bases: object

Container for an impedance data file (old or new format).

Variables:
  • description (str) – Free-text description from the file header.

  • units (str) – Impedance units, e.g. '[V/m]/[T]' or 'Ohm'.

  • sign (int) – Time-variation sign convention: -1 for exp(-iωt), +1 otherwise.

  • blocks (list of ZBlock) – One entry per period.

  • origin (tuple of 3 floats) – Grid origin (x, y, z) in metres.

  • orientation (float) – Grid orientation angle in degrees.

Parameters:
description: str = 'ModEM impedance data'#
units: str = '[V/m]/[T]'#
sign: int = -1#
blocks: list[ZBlock]#
origin: tuple[float, float, float] = (0.0, 0.0, 0.0)#
orientation: float = 0.0#
property periods: ndarray#
property n_periods: int#
pycsamt.models.modem.read_z3d_old(path)#

Read an old-format (pre-2011) 3D impedance file.

Equivalent to readZ_3D(cfile) / readZ_3D_old(cfile) in MATLAB (the 2008 version).

Parameters:

path (str or Path)

Return type:

ImpedanceFile

pycsamt.models.modem.write_z3d_old(imp, path)#

Write an old-format (pre-2011) 3D impedance file.

Equivalent to writeZ_3D(cfile, allData, info, units, isign) in MATLAB (the 2008 version).

Parameters:
Return type:

Path

pycsamt.models.modem.read_z2d_old(path)#

Read an old-format (pre-2011) 2D impedance file.

Equivalent to readZ_2D(cfile) (the 2008 version) in MATLAB.

Parameters:

path (str or Path)

Return type:

ImpedanceFile

pycsamt.models.modem.write_z2d_old(imp, path)#

Write an old-format (pre-2011) 2D impedance file.

Equivalent to writeZ_2D(cfile, allData, ...) (the 2008 version).

Parameters:
Return type:

Path

pycsamt.models.modem.write_z3d_list(imp, path)#

Write impedance data in the current ModEM 3D list format.

Equivalent to writeZ_3D(cfile, allData, ...) (the 2011 version). Each datum is one line: period code lat lon X Y Z comp Re Im err

Parameters:
Return type:

Path

pycsamt.models.modem.write_z2d_list(imp, path)#

Write impedance data in the current ModEM 2D list format.

Equivalent to writeZ_2D(cfile, allData, ...) (the 2011 version). TE and TM blocks are written separately.

Parameters:
Return type:

Path

pycsamt.models.modem.convert_z3d(old_path, new_path)#

Convert old 3D impedance format to current ModEM list format.

Mirrors writeZ_old2list_3D.m.

Parameters:
  • old_path (str or Path) – Input file in old (pre-2011) format.

  • new_path (str or Path) – Output file in current ModEM list format.

Return type:

Path

pycsamt.models.modem.convert_z2d(old_path, new_path)#

Convert old 2D impedance format to current ModEM list format.

Mirrors writeZ_old2list_2D.m.

Parameters:
  • old_path (str or Path) – Input file in old (pre-2011) format.

  • new_path (str or Path) – Output file in current ModEM list format.

Return type:

Path