pycsamt.models.mare2dem#

pycsamt.models.mare2dem — Python interface to the MARE2DEM EM inversion code.

MARE2DEM (Modeling with Adaptively Refined Elements for 2.5-D Electromagnetic inversion) implements finite-element MT and CSEM forward modelling and Occam-style regularized inversion. It is an MPI-parallel Fortran code developed by Kerry Key at LDEO, Columbia University.

Because the compiled binary is ~49 MB, the source tree is not bundled in the repository. Use SourceManager to download and build it before running inversions.

Ported MATLAB scripts (complete)#

I/O (a_util/io/ + a_util/data/):

  • .emdata / .EMResp reader + writer

  • .resistivity reader + writer (all anisotropy modes)

  • Triangle .poly PSLG reader + writer

  • .settings parallel-decomposition writer

  • .emdata_group data-group file reader + writer

  • Group-RMS CSV log reader

  • Most-recently-modified file finder

Data management:

  • Data-type code lookup table

  • High-level .emdata builder from MT / CSEM survey configs

  • ZMM impedance file reader + MT data-file builder

  • Synthetic noise addition + make_synthetic_data wrapper

  • Multi-file merge utility

Geometry (a_util/geom/, a_util/mapping/):

  • Topography interpolation + slope angles

  • Line-segment intersections (bounding-box pre-filtered)

  • Douglas-Peucker polyline simplification

  • PSLG polygon simplification (collinear node removal)

  • Area-weighted triangle region centroids

  • Survey-profile line orientation

  • Station-to-profile projection

  • UTM ↔ Lon/Lat conversion (pyproj with pure-Python WGS-84 fallback)

  • Survey area-of-interest estimator

  • Triangle FEM region flood-fill assignment

Model construction:

  • 2-D resistivity grid → MARE2DEM .poly + .resistivity

  • Topography import + profile projection

Model comparison:

  • Log10 (or custom) difference of two .resistivity files

Plotting:

  • RMS convergence curve

  • Survey map (Rx/Tx positions in UTM)

  • Receiver geometry QC (6-panel)

  • Transmitter geometry QC

  • .poly PSLG mesh plot

  • Resistivity section stub (pending full mesh parser)

Quick start#

Step 1 — Download and compile (once per machine):

from pycsamt.models.mare2dem import SourceManager
sm = SourceManager(verbose=1)
sm.download()   # git-clone from Bitbucket
sm.build()      # requires Intel oneAPI + MKL

Step 2 — Create a data file from MT survey parameters:

import numpy as np
from pycsamt.models.mare2dem import MTSurveyConfig, make_data_file
mt = MTSurveyConfig(
    frequencies=np.logspace(-3, 3, 20),
    rx_y=np.linspace(-5000, 5000, 20),
    rx_type='marine', lTE=True, lTM=True,
)
em = make_data_file('survey.emdata', topo=-1000.0, mt=mt)

Step 3 — Prepare a full input set and run:

from pycsamt.models.mare2dem import Mare2DEMConfig, InputBuilder, Mare2DEMRunner
cfg = Mare2DEMConfig(initial_rho=1.0, n_procs=8)
InputBuilder(cfg).build('survey.emdata', workdir='./run')
result = Mare2DEMRunner('./run', cfg).run('mare2dem')
result.print_summary()

References

Key, K. (2016). MARE2DEM: A 2-D inversion code for controlled-source electromagnetic and magnetotelluric data. Geophysical Journal International, 207(1), 571–588. doi:10.1093/gji/ggw290.

class pycsamt.models.mare2dem.Mare2DEMConfig(source_dir=None, fc_compiler=None, cc_compiler=None, binary='MARE2DEM', use_mpi=True, n_procs=4, mpi_command='mpirun', max_iterations=150, target_rms=1.0, initial_rho=1.0, data_file='mare2dem.emdata', resistivity_file='mare2dem.resistivity', settings_file='mare2dem.settings')#

Bases: object

Collect settings that define a MARE2DEM run.

Mare2DEMConfig is the central configuration object for the MARE2DEM wrapper. It is a plain dataclass whose fields cover source management, MPI execution, inversion control, starting model, and default file names.

The configuration is shared by SourceManager, InputBuilder, Mare2DEMRunner, and InversionResult so that all components of a workflow use consistent parameters.

Source Management#

source_dirpath-like or None, default None

Explicit path to the MARE2DEM Fortran source tree. When None, SourceManager applies a four-level fallback: the PYCSAMT_MARE2DEM_SOURCE environment variable, the bundled _source/ directory inside the package (writable dev installs), and finally the platform user-data directory (PyPI installs). Set this field when the source tree lives at an unconventional location.

fc_compilerstr or None, default None

MPI-Fortran compiler used to build MARE2DEM from source. When None, SourceManager.build() auto-detects in the order mpiifort (Intel oneAPI), mpifort (generic OpenMPI/MPICH). Intel compilers are preferred because the MARE2DEM Makefile uses Intel-specific pre-processor flags and the Intel MKL is required.

cc_compilerstr or None, default None

MPI-C compiler used for the Triangle mesh library and ScaLAPACK. Auto-detects mpiicc then mpicc when None.

Binary And MPI#

binarystr, default “MARE2DEM”

Name or absolute path of the compiled MARE2DEM executable. The runner first checks whether the name is on PATH, then looks inside the resolved source directory, and finally checks the user-data directory. Use an absolute path to pin a specific build.

use_mpibool, default True

Whether to launch MARE2DEM through an MPI wrapper. MARE2DEM is an MPI-parallel code; serial execution is not supported by the official distribution. Set to False only when testing with a special single-process build.

n_procsint, default 4

Number of MPI processes requested when use_mpi is True. Each process handles a subset of the spatial wavenumbers. Typical values range from 4 to the number of physical cores available on the node.

mpi_commandstr, default “mpirun”

MPI launcher command. Common alternatives are "mpiexec" and "srun" (SLURM). The value is prepended to the MARE2DEM command line when use_mpi is True.

Inversion Control#

max_iterationsint, default 150

Maximum number of Occam inversion iterations MARE2DEM is allowed to perform before stopping regardless of the misfit target.

target_rmsfloat, default 1.0

Normalized RMS misfit target. MARE2DEM stops iterating when the data misfit falls below this value. Lower values demand a tighter fit and may produce more structured models.

Initial Model#

initial_rhofloat, default 1.0

Starting half-space resistivity in ohm-metres for the initial homogeneous resistivity model. MARE2DEM internally uses log10-resistivity, so the value must be positive.

File Names#

data_filestr, default “mare2dem.emdata”

Default MARE2DEM data filename. The file uses the .emdata extension and records source–receiver geometry, observed data, and data uncertainties for one or more EM methods (MT, CSEM, or combined).

resistivity_filestr, default “mare2dem.resistivity”

Default MARE2DEM resistivity model filename. The file describes the 2-D finite-element mesh and layer resistivities and is the primary input file stem passed to the binary.

settings_filestr, default “mare2dem.settings”

Default MARE2DEM inversion-settings filename. It controls inversion type (Occam vs NLCG), iteration limits, target misfit, output verbosity, and optional regularization parameters.

ivar resistivity_stem:

The stem of resistivity_file without its extension. MARE2DEM receives this stem as its only positional argument and derives the data and settings filenames from it.

vartype resistivity_stem:

str

Notes

MARE2DEM implements 2.5-D finite-element MT and CSEM forward modelling in the frequency domain with an Occam-style regularized inversion [1]_. The inversion minimizes an objective of the form

\[\begin{split}\Phi(m) = \| W_d (F(m) - d) \|_2^2 + \\lambda \| \\nabla m \|_2^2,\end{split}\]

where \(F(m)\) is the 2.5-D FEM forward operator, \(d\) is the observed data vector, and \(W_d\) is the data-weighting operator. The configuration fields target_rms and max_iterations bound the inversion iteration.

Source-Of-Truth Files#

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().

  4. Pass the configuration to SourceManager, InputBuilder, Mare2DEMRunner.

See also

SourceManager

Download and compile the MARE2DEM Fortran source.

InputBuilder

Write MARE2DEM resistivity model, data, and settings files.

Mare2DEMRunner

Launch the MARE2DEM binary subprocess.

InversionResult

Load MARE2DEM inversion output files.

Examples

Create a default configuration:

>>> from pycsamt.models.mare2dem.config import Mare2DEMConfig
>>> cfg = Mare2DEMConfig()
>>> cfg.resistivity_stem
'mare2dem'

Configure a parallel run with 8 MPI processes:

>>> cfg = Mare2DEMConfig(use_mpi=True, n_procs=8)

Point to a custom source directory:

>>> cfg = Mare2DEMConfig(source_dir="/opt/mare2dem_source")

References

source_dir: str | Path | None = None#
fc_compiler: str | None = None#
cc_compiler: str | None = None#
binary: str = 'MARE2DEM'#
use_mpi: bool = True#
n_procs: int = 4#
mpi_command: str = 'mpirun'#
max_iterations: int = 150#
target_rms: float = 1.0#
initial_rho: float = 1.0#
data_file: str = 'mare2dem.emdata'#
resistivity_file: str = 'mare2dem.resistivity'#
settings_file: str = 'mare2dem.settings'#
property resistivity_stem: str#

Return the stem of resistivity_file without extension.

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

Write this configuration as an editable template file.

Parameters:
  • path (path-like, default "mare2dem_config.py") – Destination file.

  • fmt ({"py", "json", "yml", "yaml"}, optional) – Output format. Defaults to .py when the path has no recognized suffix.

Returns:

Path of the generated template.

Return type:

pathlib.Path

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

Write a default editable MARE2DEM configuration file.

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

  • fmt ({"py", "json", "yml", "yaml"}, optional) – Explicit output format.

Returns:

Path of the generated source-of-truth file.

Return type:

pathlib.Path

Examples

>>> from pycsamt.models.mare2dem.config import Mare2DEMConfig
>>> path = Mare2DEMConfig.write_template("mare2dem_config.py")
>>> path.name
'mare2dem_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().

  • strict (bool, default True) – If True, unknown keys raise ValueError.

Returns:

Configuration populated from the edited file.

Return type:

Mare2DEMConfig

Examples

>>> from pycsamt.models.mare2dem.config import Mare2DEMConfig
>>> Mare2DEMConfig.write_template("mare2dem_config.json")
PosixPath('mare2dem_config.json')
>>> cfg = Mare2DEMConfig.from_file("mare2dem_config.json")
>>> cfg.binary
'MARE2DEM'
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().

  • strict (bool, default True) – If True, unknown keys raise ValueError.

Returns:

Configuration populated from the edited file.

Return type:

Mare2DEMConfig

Examples

>>> from pycsamt.models.mare2dem.config import Mare2DEMConfig
>>> Mare2DEMConfig.write_template("mare2dem_config.json")
PosixPath('mare2dem_config.json')
>>> cfg = Mare2DEMConfig.from_file("mare2dem_config.json")
>>> cfg.binary
'MARE2DEM'
Parameters:
  • source_dir (str | Path | None)

  • fc_compiler (str | None)

  • cc_compiler (str | None)

  • binary (str)

  • use_mpi (bool)

  • n_procs (int)

  • mpi_command (str)

  • max_iterations (int)

  • target_rms (float)

  • initial_rho (float)

  • data_file (str)

  • resistivity_file (str)

  • settings_file (str)

class pycsamt.models.mare2dem.SourceManager(config=None, source_dir=None, **kwargs)#

Bases: Mare2DEMBase

Manage the MARE2DEM Fortran source: download, build, and locate.

SourceManager is the entry point for obtaining a working MARE2DEM binary. It separates source management from inversion execution so that users who already have a compiled binary can skip directly to Mare2DEMRunner.

Source-directory resolution#

The directory where sources are stored follows this priority:

  1. source_dir constructor argument.

  2. config.source_dir field.

  3. PYCSAMT_MARE2DEM_SOURCE environment variable.

  4. Bundled _source/ inside the installed package (writable dev installs only).

  5. Platform user-data directory — the safe PyPI fallback:

    • Linux / WSL: ~/.local/share/pycsamt/mare2dem/

    • macOS: ~/Library/Application Support/pycsamt/mare2dem/

    • Windows: %LOCALAPPDATA%\\pycsamt\\mare2dem\\

param config:

Configuration object. Supplies source_dir, fc_compiler, cc_compiler, and binary.

type config:

Mare2DEMConfig, optional

param source_dir:

Explicit path that overrides config.source_dir and the environment variable.

type source_dir:

path-like, optional

param verbose:

Verbosity level. 0 or False keeps the object quiet. Positive values enable diagnostic messages through the instance logger. Larger values may be used to request more detailed run, parsing, or build information.

type verbose:

int or bool, default 0

param logger:

Logger for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Provide a logger when integrating MARE2DEM workflows into an application-wide logging configuration.

type logger:

logging.Logger, optional

Notes

MARE2DEM requires Intel compilers (mpiifort, mpiicc) and the Intel MKL. When Intel oneAPI is installed, source the setvars.sh script before calling build():

source /opt/intel/oneapi/setvars.sh
python -c "
from pycsamt.models.mare2dem import SourceManager
sm = SourceManager(verbose=1)
sm.download()
sm.build()
"

Windows native builds are not supported. Use WSL2.

Examples

Quick-start — download and build:

>>> from pycsamt.models.mare2dem import SourceManager
>>> sm = SourceManager(verbose=1)
>>> sm.download()          # clones from Bitbucket
>>> sm.build()             # compiles with auto-detected compilers

Check status without downloading:

>>> sm.print_status()

Point to sources already on disk:

>>> sm = SourceManager(source_dir="/data/mare2dem_source")
>>> sm.build(inc_file="/data/mare2dem_source/include/habanero.inc")

See also

Mare2DEMRunner

Launch the compiled MARE2DEM executable for inversion.

Mare2DEMConfig

Configuration controlling compiler selection and binary name.

References

REPO_URL: str = 'https://bitbucket.org/mare2dem/mare2dem_source'#
ARCHIVE_URL: str = 'https://bitbucket.org/mare2dem/mare2dem_source/get/master.tar.gz'#
resolve_source_dir()#

Return the directory where MARE2DEM sources should live.

The resolution order is:

  1. Explicit source_dir argument passed to the constructor.

  2. config.source_dir field.

  3. PYCSAMT_MARE2DEM_SOURCE environment variable.

  4. Bundled _source/ inside the package (only when writable — i.e. editable / development installs).

  5. Platform user-data directory (always writable).

Returns:

Resolved directory (created if it does not yet exist).

Return type:

pathlib.Path

resolve_binary()#

Return the path to the compiled MARE2DEM binary or None.

Resolution order:

  1. Binary name found on PATH.

  2. <source_dir>/MARE2DEM.

  3. Platform user-data directory MARE2DEM.

Return type:

Path | None

is_downloaded()#

Return True when the source tree appears populated.

Return type:

bool

is_built()#

Return True when the MARE2DEM binary exists.

Return type:

bool

download(*, method='auto', force=False)#

Download the MARE2DEM source tree.

Parameters:
  • method ({"auto", "git", "archive"}, default "auto") – Download strategy. "auto" tries "git" first and falls back to "archive".

  • force (bool, default False) – Re-download even if the source tree is already present.

Returns:

Source directory containing the downloaded tree.

Return type:

pathlib.Path

Raises:

RuntimeError – When neither git nor requests is available, or when the download fails.

build(*, inc_file=None, fc=None, cc=None, clean_first=False)#

Compile MARE2DEM from the downloaded source.

Parameters:
  • inc_file (path-like or None, default None) – Explicit Make include file. When None, one is auto-generated from the detected compilers and MKL.

  • fc (str or None, default None) – MPI-Fortran compiler override. Falls back to config.fc_compiler then auto-detection.

  • cc (str or None, default None) – MPI-C compiler override. Falls back to config.cc_compiler then auto-detection.

  • clean_first (bool, default False) – Run make clean_all before compiling to start fresh.

Returns:

Path to the compiled MARE2DEM binary.

Return type:

pathlib.Path

Raises:
status()#

Return a summary dictionary of source and build status.

Returns:

Keys: source_dir, downloaded, binary_path, built, fc, cc, mklroot.

Return type:

dict

print_status()#

Print a human-readable source and build status report.

Return type:

None

Parameters:
class pycsamt.models.mare2dem.Mare2DEMFileType(*values)#

Bases: Enum

Enumeration of recognized MARE2DEM file types.

EMDATA = 1#
RESISTIVITY = 2#
POLY = 3#
SETTINGS = 4#
LOG = 5#
RESPONSE = 6#
SENSITIVITY = 7#
UNKNOWN = 8#
pycsamt.models.mare2dem.detect_file_type(path)#

Detect the MARE2DEM file type from the file extension and name.

Parameters:

path (path-like) – Path to the file to classify.

Returns:

Detected file type, or Mare2DEMFileType.UNKNOWN.

Return type:

Mare2DEMFileType

pycsamt.models.mare2dem.is_emdata_file(path)#

Return True when path is a MARE2DEM observed-data file.

Parameters:

path (str | Path)

Return type:

bool

pycsamt.models.mare2dem.is_resistivity_file(path)#

Return True when path is a MARE2DEM resistivity model file.

Parameters:

path (str | Path)

Return type:

bool

pycsamt.models.mare2dem.is_settings_file(path)#

Return True when path is a MARE2DEM settings file.

Parameters:

path (str | Path)

Return type:

bool

pycsamt.models.mare2dem.is_log_file(path)#

Return True when path is a MARE2DEM log file.

Parameters:

path (str | Path)

Return type:

bool

pycsamt.models.mare2dem.is_response_file(path)#

Return True when path is a MARE2DEM predicted-response file.

Parameters:

path (str | Path)

Return type:

bool

pycsamt.models.mare2dem.code_label(code)#

Return "Component Representation" for an integer data code.

Parameters:

code (int) – Integer data-type code from the DATA block of a .emdata file.

Returns:

Human-readable label, e.g. "Zxy (TE) Phase" or "Unknown (code=7)".

Return type:

str

Examples

>>> code_label(104)
'Zxy (TE) — Phase'
>>> code_label(27)
'Ex — Log10 Amplitude'
pycsamt.models.mare2dem.code_component(code)#

Return the EM component name for code, or "" if unknown.

Parameters:

code (int)

Return type:

str

pycsamt.models.mare2dem.code_representation(code)#

Return the representation name for code, or "" if unknown.

Parameters:

code (int)

Return type:

str

pycsamt.models.mare2dem.is_mt_code(code)#

Return True when code belongs to the MT data type range.

Parameters:

code (int)

Return type:

bool

pycsamt.models.mare2dem.is_csem_code(code)#

Return True when code belongs to the CSEM data type range.

Parameters:

code (int)

Return type:

bool

class pycsamt.models.mare2dem.EMDataFile(path=None, format='EMData_2.3', is_response=False, comment='', utm=<factory>, csem=None, mt=None, dc=None, data=<factory>)#

Bases: object

Complete contents of one MARE2DEM .emdata or .EMResp file.

Variables:
  • path (pathlib.Path or None) – Source file path, if loaded from disk.

  • format (str) – Format string from the file header (e.g. "EMData_2.3").

  • is_response (bool) – True when the file is a response file (8-column DATA block).

  • comment (str) – Optional free-text comment from the file header.

  • utm (UTMOrigin) – UTM origin metadata.

  • csem (CSEMConfig or None) – CSEM configuration section, or None if absent.

  • mt (MTConfig or None) – MT configuration section, or None if absent.

  • dc (DCConfig or None) – DC configuration section, or None if absent.

  • data (numpy.ndarray, shape (n_data, 6) or (n_data, 8)) – DATA block. Columns for observed data: [type, freq#, tx#, rx#, data, std_err]. Response files add [response, residual].

Parameters:
path: Path | None = None#
format: str = 'EMData_2.3'#
is_response: bool = False#
comment: str = ''#
utm: UTMOrigin#
csem: CSEMConfig | None = None#
mt: MTConfig | None = None#
dc: DCConfig | None = None#
data: ndarray#
property n_data: int#

Total number of data rows.

property n_mt_frequencies: int#

Number of MT frequencies.

property n_mt_receivers: int#

Number of MT receivers.

property n_csem_transmitters: int#

Number of CSEM transmitters.

property n_csem_receivers: int#

Number of CSEM receivers.

class pycsamt.models.mare2dem.UTMOrigin(grid=0, hemi='N', north0=0.0, east0=0.0, theta=0.0)#

Bases: object

UTM mapping metadata for the 2-D profile.

Variables:
  • grid (int) – UTM zone number.

  • hemi (str) – Hemisphere letter ('N' or 'S').

  • north0 (float) – Northing of profile origin in metres.

  • east0 (float) – Easting of profile origin in metres.

  • theta (float) – Profile strike direction (degrees).

Parameters:
grid: int = 0#
hemi: str = 'N'#
north0: float = 0.0#
east0: float = 0.0#
theta: float = 0.0#
class pycsamt.models.mare2dem.CSEMConfig(phase_convention='lag', reciprocity_used='', frequencies=<factory>, time_offsets=None, tdem_waveform=None, transmitters=<factory>, transmitter_type=<factory>, transmitter_name=<factory>, receivers=<factory>, receiver_name=<factory>)#

Bases: object

CSEM source–receiver configuration and data parameters.

Variables:
  • phase_convention (str) – 'lag' or 'lead'.

  • reciprocity_used (str) – 'yes', 'no', or ''.

  • frequencies (numpy.ndarray, shape (n_freq,)) – CSEM frequencies in Hz.

  • time_offsets (numpy.ndarray or None) – Time offsets for TDEM modeling.

  • tdem_waveform (numpy.ndarray or None) – TDEM waveform, shape (n_pts, 2).

  • transmitters (numpy.ndarray, shape (n_tx, 7)) – Columns: x, y, z, azimuth, dip, length, solve_corr.

  • transmitter_type (list of str) – Dipole type per transmitter ('edipole' or 'bdipole').

  • transmitter_name (list of str) – Transmitter labels.

  • receivers (numpy.ndarray, shape (n_rx, 8)) – Columns: x, y, z, theta, alpha, beta, length, solve_corr.

  • receiver_name (list of str) – Receiver labels.

Parameters:
phase_convention: str = 'lag'#
reciprocity_used: str = ''#
frequencies: ndarray#
time_offsets: ndarray | None = None#
tdem_waveform: ndarray | None = None#
transmitters: ndarray#
transmitter_type: list[str]#
transmitter_name: list[str]#
receivers: ndarray#
receiver_name: list[str]#
class pycsamt.models.mare2dem.MTConfig(frequencies=<factory>, receivers=<factory>, receiver_name=<factory>)#

Bases: object

MT receiver configuration and frequency list.

Variables:
Parameters:
frequencies: ndarray#
receivers: ndarray#
receiver_name: list[str]#
class pycsamt.models.mare2dem.DCConfig(tx_electrodes=<factory>, rx_electrodes=<factory>, transmitters=<factory>, receivers=<factory>, transmitter_name=<factory>, receiver_name=<factory>)#

Bases: object

DC resistivity electrode and receiver configuration.

Variables:
  • tx_electrodes (numpy.ndarray, shape (n_tx_el, 3)) – Transmitter electrode positions (x, y, z).

  • rx_electrodes (numpy.ndarray, shape (n_rx_el, 3)) – Receiver electrode positions (x, y, z).

  • transmitters (numpy.ndarray, shape (n_tx, 2)) – Integer electrode-index pairs (A, B) for each transmitter.

  • receivers (numpy.ndarray, shape (n_rx, 2)) – Integer electrode-index pairs (M, N) for each receiver.

  • transmitter_name (list of str)

  • receiver_name (list of str)

Parameters:
tx_electrodes: ndarray#
rx_electrodes: ndarray#
transmitters: ndarray#
receivers: ndarray#
transmitter_name: list[str]#
receiver_name: list[str]#
pycsamt.models.mare2dem.read_emdata(path, *, silent=False)#

Read a MARE2DEM .emdata or .EMResp file.

Port of m2d_readEMData2DFile.m.

Parameters:
  • path (path-like) – File to read.

  • silent (bool, default False) – Suppress warnings on unrecognised format strings.

Returns:

Parsed file contents.

Return type:

EMDataFile

Raises:
  • FileNotFoundError – When path does not exist.

  • ValueError – When the format string in the header is not recognised and silent=False.

Examples

>>> from pycsamt.models.mare2dem.iotools.emdata import read_emdata
>>> em = read_emdata("survey.emdata")
>>> em.n_mt_receivers
12
pycsamt.models.mare2dem.write_emdata(em, path)#

Write an EMDataFile to path.

Port of m2d_writeEMData2DFile.m.

Parameters:
  • em (EMDataFile) – Data to write.

  • path (path-like) – Destination .emdata file.

Returns:

Path of the written file.

Return type:

pathlib.Path

Examples

>>> from pycsamt.models.mare2dem.iotools.emdata import write_emdata
>>> write_emdata(em, "survey_out.emdata")
PosixPath('survey_out.emdata')
class pycsamt.models.mare2dem.ResistivityFile(resistivity_file='mare2dem.resistivity', poly_file='mare2dem.poly', data_file='mare2dem.emdata', settings_file='mare2dem.settings', version='mare2dem_1.1', anisotropy='isotropic', target_misfit=1.0, max_iterations=100, iteration=0, log10_lagrange=5.0, roughness=None, misfit=None, date_time='', bounds_transform='bandpass', global_bounds=<factory>, roughness_penalty_method='gradient', yz_penalty_weights=<factory>, penalty_cut_weight=0.1, roughness_with_prejudice=False, beta_mgs=0.0, anisotropy_penalty_weight=None, anisotropy_ratio_roughness_weight=None, debug_level=1, inversion_method='occam', rms_threshold=0.85, converge_slowly='no', resistivity=<factory>, free_parameter=<factory>, bounds=<factory>, prejudice=<factory>, data_group_file='', joint_inv_weight_type='', penalty_file='', fixed_mu_cut=None)#

Bases: object

Contents of one MARE2DEM .resistivity file.

Variables:
  • resistivity_file (str) – Output filename (used when writing).

  • poly_file (str) – Triangle mesh (.poly) file stem referenced by this model.

  • data_file (str) – .emdata file referenced by this model.

  • settings_file (str) – .settings file referenced by this model.

  • version (str) – Format version string (e.g. "mare2dem_1.1").

  • anisotropy (str) – Anisotropy mode: "isotropic" (default), "triaxial", "tix", "tiy", "tiz", "tiz_ratio", "isotropic_ip", "isotropic_complex".

  • target_misfit (float) – Target normalized RMS misfit.

  • max_iterations (int) – Maximum inversion iterations.

  • iteration (int) – Current iteration number (output from inversion).

  • log10_lagrange (float) – Log10 Lagrange (regularization) trade-off value.

  • roughness (float or None) – Model roughness at this iteration.

  • misfit (float or None) – Normalized misfit at this iteration.

  • date_time (str) – Date/time stamp written by MARE2DEM.

  • bounds_transform (str) – Bounds transform type ("bandpass").

  • global_bounds (numpy.ndarray, shape (2,)) – Lower and upper log10-resistivity bounds.

  • roughness_penalty_method (str) – Smoothing type ("gradient" or "first_difference").

  • yz_penalty_weights (numpy.ndarray, shape (2,)) – Smoothing weights (y, z).

  • penalty_cut_weight (float) – Penalty cut weight.

  • roughness_with_prejudice (bool) – Use prejudice in regularization.

  • beta_mgs (float) – Minimum gradient support weight.

  • anisotropy_penalty_weight (float or None) – Anisotropic penalty weight.

  • anisotropy_ratio_roughness_weight (float or None) – Anisotropic ratio roughness weight.

  • debug_level (int) – Verbosity / print level.

  • inversion_method (str) – Inversion method string.

  • rms_threshold (float) – Misfit decrease threshold.

  • converge_slowly (str) – "yes" or "no".

  • resistivity (numpy.ndarray, shape (n_regions, nrho)) – Log10-resistivity per region per component.

  • free_parameter (numpy.ndarray, shape (n_regions, nrho)) – Free-parameter index (0 = fixed, >0 = free parameter number).

  • bounds (numpy.ndarray, shape (n_regions, 2*nrho)) – Lower / upper bounds per region component.

  • prejudice (numpy.ndarray, shape (n_regions, 2*nrho)) – Prejudice value and weight per region component.

Parameters:
  • resistivity_file (str)

  • poly_file (str)

  • data_file (str)

  • settings_file (str)

  • version (str)

  • anisotropy (str)

  • target_misfit (float)

  • max_iterations (int)

  • iteration (int)

  • log10_lagrange (float)

  • roughness (float | None)

  • misfit (float | None)

  • date_time (str)

  • bounds_transform (str)

  • global_bounds (ndarray)

  • roughness_penalty_method (str)

  • yz_penalty_weights (ndarray)

  • penalty_cut_weight (float)

  • roughness_with_prejudice (bool)

  • beta_mgs (float)

  • anisotropy_penalty_weight (float | None)

  • anisotropy_ratio_roughness_weight (float | None)

  • debug_level (int)

  • inversion_method (str)

  • rms_threshold (float)

  • converge_slowly (str)

  • resistivity (ndarray)

  • free_parameter (ndarray)

  • bounds (ndarray)

  • prejudice (ndarray)

  • data_group_file (str)

  • joint_inv_weight_type (str)

  • penalty_file (str)

  • fixed_mu_cut (float | None)

resistivity_file: str = 'mare2dem.resistivity'#
poly_file: str = 'mare2dem.poly'#
data_file: str = 'mare2dem.emdata'#
settings_file: str = 'mare2dem.settings'#
version: str = 'mare2dem_1.1'#
anisotropy: str = 'isotropic'#
target_misfit: float = 1.0#
max_iterations: int = 100#
iteration: int = 0#
log10_lagrange: float = 5.0#
roughness: float | None = None#
misfit: float | None = None#
date_time: str = ''#
bounds_transform: str = 'bandpass'#
global_bounds: ndarray#
roughness_penalty_method: str = 'gradient'#
yz_penalty_weights: ndarray#
penalty_cut_weight: float = 0.1#
roughness_with_prejudice: bool = False#
beta_mgs: float = 0.0#
anisotropy_penalty_weight: float | None = None#
anisotropy_ratio_roughness_weight: float | None = None#
debug_level: int = 1#
inversion_method: str = 'occam'#
rms_threshold: float = 0.85#
converge_slowly: str = 'no'#
resistivity: ndarray#
free_parameter: ndarray#
bounds: ndarray#
prejudice: ndarray#
data_group_file: str = ''#
joint_inv_weight_type: str = ''#
penalty_file: str = ''#
fixed_mu_cut: float | None = None#
property num_regions: int#

Number of resistivity regions.

pycsamt.models.mare2dem.read_resistivity(path, *, no_data=False)#

Read a MARE2DEM .resistivity file.

Port of m2d_readResistivity.m.

Parameters:
  • path (path-like) – File to read.

  • no_data (bool, default False) – When True, stop reading before the region resistivity table. Useful for quickly inspecting header metadata in large iteration output files.

Returns:

Parsed file contents.

Return type:

ResistivityFile

Examples

>>> from pycsamt.models.mare2dem.iotools.resistivity import read_resistivity
>>> rf = read_resistivity("mare2dem.resistivity")
>>> rf.num_regions
1234
pycsamt.models.mare2dem.write_resistivity(rf, path=None)#

Write a ResistivityFile to path.

Port of m2d_writeResistivity.m.

Parameters:
  • rf (ResistivityFile) – Model to write.

  • path (path-like or None) – Destination file. When None, uses rf.resistivity_file.

Returns:

Path of the written file.

Return type:

pathlib.Path

Examples

>>> from pycsamt.models.mare2dem.iotools.resistivity import write_resistivity
>>> write_resistivity(rf, "mare2dem_iter10.resistivity")
PosixPath('mare2dem_iter10.resistivity')
class pycsamt.models.mare2dem.PolyFile#

Bases: object

Contents of one Triangle .poly PSLG file.

Variables:
property n_nodes: int#
property n_segments: int#
property n_holes: int#
property n_regions: int#
pycsamt.models.mare2dem.read_poly(path)#

Read a Triangle .poly PSLG file.

Port of m2d_readPoly.m.

Parameters:

path (path-like) – File to read. If the node count is zero (triangulation already done), the function automatically looks for the companion .node and .ele files in the same directory.

Returns:

Parsed PSLG contents.

Return type:

PolyFile

Examples

>>> from pycsamt.models.mare2dem.iotools.poly import read_poly
>>> poly = read_poly("mare2dem.poly")
>>> poly.n_nodes
4812
pycsamt.models.mare2dem.write_poly(pf, path)#

Write a PolyFile to path.

Port of m2d_writePoly.m.

Parameters:
  • pf (PolyFile) – PSLG data to write.

  • path (path-like) – Destination .poly file.

Returns:

Path of the written file.

Return type:

pathlib.Path

Examples

>>> from pycsamt.models.mare2dem.iotools.poly import write_poly
>>> write_poly(pf, "mare2dem.poly")
PosixPath('mare2dem.poly')
class pycsamt.models.mare2dem.SettingsFile(tolerance=1.0, tx_per_group=10, csem_rx_per_group=40, csem_freq_per_group=1, mt_rx_per_group=40, mt_freq_per_group=1, use_mesh_coarsening=True, use_mt_scattered_field=False, print_adaptive=True, print_decomposition=True)#

Bases: object

Parameters for one MARE2DEM .settings file.

Variables:
  • tolerance (float) – Target solution accuracy in percent.

  • tx_per_group (int) – Maximum transmitters per parallel group (≤ 10 recommended).

  • csem_rx_per_group (int) – CSEM receivers per parallel group.

  • csem_freq_per_group (int) – CSEM frequencies per group (usually 1).

  • mt_rx_per_group (int) – MT receivers per parallel group.

  • mt_freq_per_group (int) – MT frequencies per group (usually 1).

  • use_mesh_coarsening (bool) – Enable moving-window mesh coarsening for long profiles.

  • use_mt_scattered_field (bool) – Use scattered-field MT formulation (for deep-water scenarios).

  • print_adaptive (bool) – Print adaptive refinement iteration stats.

  • print_decomposition (bool) – Print parallel decomposition settings.

Parameters:
  • tolerance (float)

  • tx_per_group (int)

  • csem_rx_per_group (int)

  • csem_freq_per_group (int)

  • mt_rx_per_group (int)

  • mt_freq_per_group (int)

  • use_mesh_coarsening (bool)

  • use_mt_scattered_field (bool)

  • print_adaptive (bool)

  • print_decomposition (bool)

tolerance: float = 1.0#
tx_per_group: int = 10#
csem_rx_per_group: int = 40#
csem_freq_per_group: int = 1#
mt_rx_per_group: int = 40#
mt_freq_per_group: int = 1#
use_mesh_coarsening: bool = True#
use_mt_scattered_field: bool = False#
print_adaptive: bool = True#
print_decomposition: bool = True#
pycsamt.models.mare2dem.write_settings(sf, path, *, overwrite=True)#

Write a MARE2DEM .settings file.

Port of m2d_writeSettingsFile.m.

Parameters:
  • sf (SettingsFile) – Settings to write.

  • path (path-like) – Destination file.

  • overwrite (bool, default True) – If False and the file already exists, return the existing path without writing.

Returns:

Path of the written (or existing) file.

Return type:

pathlib.Path

Examples

>>> from pycsamt.models.mare2dem.iotools.settings import SettingsFile, write_settings
>>> sf = SettingsFile(tx_per_group=5, csem_rx_per_group=20)
>>> write_settings(sf, "mare2dem.settings")
PosixPath('mare2dem.settings')
class pycsamt.models.mare2dem.GroupRMSLog(path=None, headers=<factory>, rms_log=<factory>)#

Bases: object

Contents of one MARE2DEM group-RMS log file.

Variables:
Parameters:
path: Path | None = None#
headers: list[str]#
rms_log: ndarray#
property n_iterations: int#
property n_groups: int#
pycsamt.models.mare2dem.read_group_rms_log(path)#

Read a MARE2DEM group-level RMS log file.

Port of m2d_read_group_rms_log.m.

Parameters:

path (path-like) – CSV-like log file written by MARE2DEM.

Returns:

Parsed log with headers and numeric RMS table.

Return type:

GroupRMSLog

Examples

>>> from pycsamt.models.mare2dem.iotools.group_rms import read_group_rms_log
>>> log = read_group_rms_log("mare2dem_group_rms.log")
>>> log.n_iterations
42
class pycsamt.models.mare2dem.DataGroupFile(path=None, comment='', group_names=<factory>, group_indices=<factory>)#

Bases: object

Contents of one MARE2DEM .emdata_group file.

Variables:
  • path (pathlib.Path or None) – Source file path.

  • comment (str) – Optional free-text comment from the file header.

  • group_names (list of str) – Ordered list of group name strings.

  • group_indices (numpy.ndarray, shape (n_data,)) – 1-based group index for each datum. The value at position i selects the group name at group_names[group_indices[i] - 1].

Parameters:
path: Path | None = None#
comment: str = ''#
group_names: list[str]#
group_indices: ndarray#
property n_groups: int#
property n_data: int#
pycsamt.models.mare2dem.read_data_group(path)#

Read a MARE2DEM .emdata_group file.

Port of m2d_readDataGroupFile.m.

Parameters:

path (path-like) – File to read (Format: EMDataGroup_1.0).

Returns:

Parsed data-group file.

Return type:

DataGroupFile

Raises:

Examples

>>> from pycsamt.models.mare2dem.iotools.data_group import read_data_group
>>> dg = read_data_group("survey.emdata_group")
>>> dg.group_names
['MT', 'Seafloor CSEM', 'Towed CSEM']
pycsamt.models.mare2dem.write_data_group(dg, path)#

Write a DataGroupFile to path.

Port of m2d_writeDataGroupFile.m.

Parameters:
  • dg (DataGroupFile) – Data to write.

  • path (path-like) – Destination file.

Returns:

Path of the written file.

Return type:

pathlib.Path

Raises:

ValueError – When DataGroupFile.group_names is empty or DataGroupFile.group_indices are out of range.

Examples

>>> from pycsamt.models.mare2dem.iotools.data_group import DataGroupFile, write_data_group
>>> import numpy as np
>>> dg = DataGroupFile(group_names=["MT", "CSEM"],
...                    group_indices=np.array([1, 1, 2, 2]))
>>> write_data_group(dg, "survey.emdata_group")
PosixPath('survey.emdata_group')
pycsamt.models.mare2dem.get_most_recent(file_or_keyword, pattern='*.resistivity', *, search_dir='.')#

Return the most recently modified file matching pattern.

Port of m2d_getMostRecent.m.

Parameters:
  • file_or_keyword (str or path-like) – Either a literal file path, or one of the special keywords 'lastiter', 'last', or 'newest'. When a keyword is given the function scans search_dir for files matching pattern and returns the most recently modified one.

  • pattern (str, default “*.resistivity”) – Glob pattern used when a keyword is given.

  • search_dir (path-like, default ".") – Directory to search when a keyword is given.

Returns:

Resolved file path, or None when the keyword is used but no matching files are found.

Return type:

pathlib.Path or None

Examples

Load the latest inversion model:

>>> from pycsamt.models.mare2dem.iotools.most_recent import get_most_recent
>>> path = get_most_recent("newest", "*.resistivity", search_dir="./run")
>>> path
PosixPath('run/mare2dem.0020.resistivity')

Use a literal path (pass-through):

>>> get_most_recent("mare2dem.0010.resistivity")
PosixPath('mare2dem.0010.resistivity')
pycsamt.models.mare2dem.parse_topo(topo, y)#

Interpolate topography to profile positions y.

Port of m2d_parseTopo.m.

Parameters:
  • topo (float or array-like, shape (n_pts, 2)) – Topography input. A single scalar gives a flat surface at constant depth. An (n_pts, 2) array provides piecewise- linear topography with columns [y, z].

  • y (array-like, shape (n,)) – Profile positions at which to interpolate.

Returns:

  • z (numpy.ndarray, shape (n,)) – Depth of the topographic surface at each y position.

  • slope_angle (numpy.ndarray, shape (n,)) – Surface slope angle in degrees, positive clockwise from the +y axis towards +z (down). Zero for flat topography.

  • on_node (numpy.ndarray of bool, shape (n,)) – True where a y position falls exactly on a topography node. The slope is not well-defined at these points.

Return type:

tuple[ndarray, ndarray, ndarray]

Examples

Flat topography at depth 1000 m (e.g. flat seafloor):

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.topo import parse_topo
>>> y = np.array([-5000.0, 0.0, 5000.0])
>>> z, slope, on_node = parse_topo(1000.0, y)
>>> z
array([1000., 1000., 1000.])

Variable topography:

>>> topo_xy = np.array([[0.0, 500.0], [5000.0, 1000.0], [10000.0, 800.0]])
>>> z, slope, on_node = parse_topo(topo_xy, np.array([2500.0, 5000.0]))
pycsamt.models.mare2dem.topo_depth(topo, y)#

Return interpolated topographic depth at positions y.

Convenience wrapper around parse_topo().

Parameters:
Return type:

ndarray

pycsamt.models.mare2dem.topo_slope(topo, y)#

Return topographic slope angle (degrees) at positions y.

Convenience wrapper around parse_topo().

Parameters:
Return type:

ndarray

pycsamt.models.mare2dem.get_intersections(xya, xyb, *, tol=np.float64(2.220446049250313e-13))#

Find intersections between segments in xya and segment xyb.

Port of m2d_getIntersections.m.

Parameters:
  • xya (array-like, shape (n_a, 4)) – Set of line segments. Each row is [x0, x1, y0, y1].

  • xyb (array-like, shape (1, 4) or (4,)) – Single query segment [x0, x1, y0, y1].

  • tol (float) – Interior-point tolerance (intersection on exact endpoint is excluded).

Returns:

  • intersect (numpy.ndarray of int) – Original row indices in xya where an interior intersection with xyb exists.

  • xi (numpy.ndarray of float) – x coordinates of intersection points.

  • yi (numpy.ndarray of float) – y coordinates of intersection points.

  • pa (numpy.ndarray of float, shape (n_a,)) – Parametric position along each segment in xya (-1 for segments not tested).

  • pb (numpy.ndarray of float, shape (n_a,)) – Parametric position along xyb (-1 for untested).

Return type:

tuple[ndarray, ndarray, ndarray, ndarray, ndarray]

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.intersections import get_intersections
>>> segs_a = np.array([[0.0, 2.0, 1.0, 1.0]])   # horizontal segment
>>> seg_b  = np.array([1.0, 1.0, 0.0, 2.0])     # vertical segment
>>> inter, xi, yi, pa, pb = get_intersections(segs_a, seg_b)
>>> xi
array([1.])
>>> yi
array([1.])
pycsamt.models.mare2dem.do_rects_overlap(a_rect, many_rects, *, tol=np.float64(2.220446049250313e-14))#

Return indices of rows in many_rects that overlap a_rect.

Port of the inner doRectsOverlap function in m2d_getIntersections.m.

Parameters:
  • a_rect (array-like, shape (4,)) – Single bounding rectangle [x0, x1, y0, y1].

  • many_rects (array-like, shape (n, 4)) – Array of bounding rectangles, same format.

  • tol (float) – Tolerance for the overlap test.

Returns:

Row indices of many_rects whose bounding boxes overlap a_rect.

Return type:

numpy.ndarray of int

pycsamt.models.mare2dem.dp_simplify(points, tolerance)#

Simplify a polyline using the Douglas-Peucker algorithm.

Port of m2d_dpsimplify.m.

Parameters:
  • points (array-like, shape (n, 2)) – Input polyline vertices.

  • tolerance (float) – Maximum allowable perpendicular deviation. Points whose distance from the simplified segment exceeds this value are retained.

Returns:

Simplified polyline with m <= n vertices.

Return type:

numpy.ndarray, shape (m, 2)

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.simplify import dp_simplify
>>> pts = np.column_stack([np.linspace(0, 10, 100),
...                        np.sin(np.linspace(0, np.pi, 100))])
>>> simplified = dp_simplify(pts, tolerance=0.05)
>>> len(simplified) < 100
True
pycsamt.models.mare2dem.simplify_poly(nodes, adjacency, *, tol=1e-10)#

Remove redundant interior nodes from a PSLG polygon.

Port of m2d_simplify_poly.m.

Parameters:
  • nodes (array-like, shape (n_nodes, 2)) – Node (y, z) coordinates.

  • adjacency (array-like, shape (n_nodes, n_nodes)) – Dense or sparse symmetric adjacency matrix. A non-zero adjacency[i, j] means node i and node j are connected by a segment. Diagonal entries are ignored (self-loops).

  • tol (float, default 1e-10) – Collinearity tolerance used to identify redundant nodes.

Returns:

  • nodes_out (numpy.ndarray, shape (m_nodes, 2)) – Pruned node array with redundant interior nodes removed.

  • adjacency_out (numpy.ndarray, shape (m_nodes, m_nodes)) – Updated adjacency matrix.

Return type:

tuple[ndarray, ndarray]

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.simplify_poly import simplify_poly
>>> nodes = np.array([[0.,0.],[1.,0.],[2.,0.],[3.,0.]])
>>> adj = np.zeros((4,4))
>>> adj[0,1]=adj[1,0]=1; adj[1,2]=adj[2,1]=1; adj[2,3]=adj[3,2]=1
>>> n_out, a_out = simplify_poly(nodes, adj)
>>> len(n_out)   # interior collinear nodes 1 and 2 removed
2
pycsamt.models.mare2dem.get_centroids(nodes, elements, tri_index)#

Compute area-weighted centroids of mesh regions.

Port of m2d_getCentroids.m.

Parameters:
  • nodes (array-like, shape (n_nodes, 2)) – Node (y, z) coordinates.

  • elements (array-like, shape (n_elements, 3)) – Element connectivity (1-based indices accepted).

  • tri_index (array-like, shape (n_elements,)) – Region index for each triangle (1-based).

Returns:

Columns: y_centroid, z_centroid, total_area of each region.

Return type:

numpy.ndarray, shape (n_regions, 3)

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.centroids import get_centroids
>>> nodes = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]])
>>> elems = np.array([[1, 2, 3], [2, 4, 3]])
>>> tri_idx = np.array([1, 1])
>>> get_centroids(nodes, elems, tri_idx)
array([[0.5, 0.5, 1. ]])
pycsamt.models.mare2dem.triangle_centroids(nodes, elements)#

Return the centroid of each triangle element.

Parameters:
  • nodes (array-like, shape (n_nodes, 2)) – Node (y, z) coordinates.

  • elements (array-like, shape (n_elements, 3)) – Element connectivity, 0-based or 1-based node indices. The function detects 1-based indices automatically.

Returns:

Per-element centroid coordinates.

Return type:

numpy.ndarray, shape (n_elements, 2)

pycsamt.models.mare2dem.triangle_areas(nodes, elements)#

Return the signed area of each triangle element.

Parameters:
Returns:

Area of each triangle (absolute value).

Return type:

numpy.ndarray, shape (n_elements,)

pycsamt.models.mare2dem.lonlat_to_utm(lon, lat, *, zone=None, south_hemi=None, ellipsoid='wgs84')#

Convert geographic longitude / latitude to UTM.

Port of LonLat2UTM.m. When pyproj is installed the conversion is delegated to it; otherwise the pure-Python Snyder formulas are used.

Parameters:
  • lon (float or array-like) – Longitude in decimal degrees (−180 to +180).

  • lat (float or array-like) – Latitude in decimal degrees.

  • zone (int, optional) – Force a specific UTM zone. Auto-computed from median longitude when omitted.

  • south_hemi (bool, optional) – Force southern-hemisphere false northing. Auto-detected from median latitude when omitted.

  • ellipsoid (str, default "wgs84") – Ellipsoid name (see ELLIPSOIDS).

Returns:

  • easting (numpy.ndarray) – UTM easting in metres.

  • northing (numpy.ndarray) – UTM northing in metres.

  • zone (int) – UTM zone used.

  • south_hemi (bool) – Hemisphere flag used.

Return type:

tuple[ndarray, ndarray, int, bool]

Examples

>>> from pycsamt.models.mare2dem.geom.utm import lonlat_to_utm
>>> e, n, zone, sh = lonlat_to_utm(-70.0, 42.0)
>>> zone
19
pycsamt.models.mare2dem.utm_to_lonlat(easting, northing, zone, south_hemi=False, *, ellipsoid='wgs84')#

Convert UTM coordinates to geographic longitude / latitude.

Port of UTM2LonLat.m.

Parameters:
  • easting (float or array-like) – UTM easting in metres.

  • northing (float or array-like) – UTM northing in metres.

  • zone (int) – UTM zone number.

  • south_hemi (bool or str, default False) – True / 'S' for southern hemisphere.

  • ellipsoid (str, default "wgs84") – Ellipsoid name (see ELLIPSOIDS).

Returns:

  • lon (numpy.ndarray) – Longitude in decimal degrees.

  • lat (numpy.ndarray) – Latitude in decimal degrees.

Return type:

tuple[ndarray, ndarray]

Examples

>>> from pycsamt.models.mare2dem.geom.utm import utm_to_lonlat
>>> lon, lat = utm_to_lonlat(330000.0, 4650000.0, 19, False)
pycsamt.models.mare2dem.estimate_area_of_interest(em)#

Estimate the y and z limits for display or mesh generation.

Port of m2d_estimateAreaOfInterest.m.

Parameters:

em (EMDataFile) – Survey data file supplying MT, CSEM, and DC receiver / transmitter positions.

Returns:

  • ylim (numpy.ndarray, shape (2,) or None) – [y_min, y_max] recommended profile extent in metres. None when no survey geometry is available.

  • zlim (numpy.ndarray, shape (2,) or None) – [z_min, z_max] recommended depth extent in metres. None when no survey geometry is available.

Return type:

tuple[ndarray | None, ndarray | None]

Examples

>>> from pycsamt.models.mare2dem import read_emdata
>>> from pycsamt.models.mare2dem.geom.area_of_interest import estimate_area_of_interest
>>> em = read_emdata("survey.emdata")
>>> ylim, zlim = estimate_area_of_interest(em)
>>> ylim
array([-5500.,  5500.])
pycsamt.models.mare2dem.get_triangle_regions(points, triangles, segments, region_seeds=None)#

Assign each triangle to a numbered region.

Port of m2d_getTriangleRegions.m.

Parameters:
  • points (array-like, shape (n_nodes, 2)) – Node (y, z) coordinates.

  • triangles (array-like, shape (n_tri, 3)) – Triangle connectivity, 1-based node indices.

  • segments (array-like, shape (n_segs, 2)) – Boundary segment node-index pairs (1-based) that separate regions.

  • region_seeds (array-like, shape (n_seeds, 2) or None) – One seed point per pre-defined region. Each seed is a (y, z) coordinate inside a region. Pass None if no pre-defined seeds are given; all regions are then discovered automatically.

Returns:

  • tri_index (numpy.ndarray, shape (n_tri,)) – Region index for each triangle (1-based).

  • region_map (numpy.ndarray, shape (n_new_regions,)) – Maps new region indices back to input seed indices (1-based); 0 for regions with no corresponding seed.

Return type:

tuple[ndarray, ndarray]

Notes

The algorithm builds a sparse adjacency matrix from the boundary segments, zeros out neighbour links that cross boundaries, then performs a BFS flood fill from each seed (or from untouched triangles after the seed pass).

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.triangle_regions import get_triangle_regions
>>> pts = np.array([[0.,0.],[1.,0.],[0.5,1.]])
>>> tris = np.array([[1,2,3]])
>>> segs = np.array([[1,2]])
>>> tri_index, region_map = get_triangle_regions(pts, tris, segs)
>>> tri_index
array([1])
pycsamt.models.mare2dem.get_line_orientation(northings, eastings)#

Estimate the survey profile orientation from station UTM positions.

Port of m2d_getLineOrientation.m.

The function fits a line to the input (northing, easting) pairs and returns its bearing. The result is in the range 0–180°:

  • 0° / 180° → N–S profile

  • 90° → E–W profile

Parameters:
  • northings (array-like, shape (n,)) – UTM northing coordinates in metres.

  • eastings (array-like, shape (n,)) – UTM easting coordinates in metres.

Returns:

Line orientation in degrees clockwise from geographic north (0 ≤ result ≤ 180).

Return type:

float

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.geom.line_orientation import get_line_orientation
>>> northings = np.array([0.0, 1000.0, 2000.0])
>>> eastings  = np.array([0.0, 0.0, 0.0])
>>> get_line_orientation(northings, eastings)   # N-S profile
0.0
pycsamt.models.mare2dem.project_onto_line(northings, eastings, utm0_north, utm0_east, line_orientation)#

Project UTM (northing, easting) positions onto a survey profile.

Parameters:
  • northings (array-like) – Station UTM northings in metres.

  • eastings (array-like) – Station UTM eastings in metres.

  • utm0_north (float) – Profile origin northing in metres.

  • utm0_east (float) – Profile origin easting in metres.

  • line_orientation (float) – Profile orientation in degrees clockwise from north.

Returns:

  • x (numpy.ndarray) – Cross-profile (x) offset in metres.

  • y (numpy.ndarray) – Along-profile (y) offset in metres.

Return type:

tuple[ndarray, ndarray]

class pycsamt.models.mare2dem.MTSurveyConfig(frequencies=<factory>, rx_y=<factory>, rx_type='marine', rx_z=None, rx_z_offset=None, rx_beta=None, rx_name=None, lTE=True, lTM=True, lZDet=False, lTipper=False, lTipperRealImag=False, lMTFields=False)#

Bases: object

MT receiver and data-selection configuration.

Parameters:
  • frequencies (array-like) – MT frequencies in Hz.

  • rx_y (array-like) – Receiver y positions along the 2-D profile.

  • rx_type (str) – Receiver placement mode: 'land', 'marine', or 'amphibious'.

  • rx_z (array-like or None) – Override receiver depth positions. When supplied, slope- based tilt angles are not computed.

  • rx_z_offset (float or array-like or None) – Offset from topography (< 0 above, > 0 below). Overrides the rx_type depth rule.

  • rx_beta (float or array-like or None) – Override receiver beta (y-tilt) angles in degrees.

  • rx_name (list of str or None) – Station names.

  • lTE (bool) – Include log10 apparent resistivity and phase (TE mode).

  • lTM (bool) – Include log10 apparent resistivity and phase (TM mode).

  • lZDet (bool) – Include impedance-determinant apparent resistivity and phase.

  • lTipper (bool) – Include TE tipper amplitude and phase.

  • lTipperRealImag (bool) – Include TE tipper real and imaginary parts.

  • lMTFields (bool) – Include TE and TM field vectors (Ex, Ey, Ez, Hx, Hy, Hz).

frequencies: ndarray#
rx_y: ndarray#
rx_type: str = 'marine'#
rx_z: ndarray | None = None#
rx_z_offset: float | ndarray | None = None#
rx_beta: float | ndarray | None = None#
rx_name: list[str] | None = None#
lTE: bool = True#
lTM: bool = True#
lZDet: bool = False#
lTipper: bool = False#
lTipperRealImag: bool = False#
lMTFields: bool = False#
class pycsamt.models.mare2dem.CSEMSurveyConfig(frequencies=<factory>, tx_y=<factory>, rx_y=None, rx_r=None, tx_z=None, tx_z_offset=None, rx_z=None, rx_z_offset=None, rx_type='marine', tx_type='edipole', tx_azimuth=None, tx_dip=None, tx_length=None, rx_length=None, rx_beta=None, tx_name=None, rx_name=None, phase_convention='lag', min_range=None, max_range=None, lEx=True, lEy=False, lEz=False, lBx=False, lBy=False, lBz=False)#

Bases: object

CSEM source–receiver and data-selection configuration.

Parameters:
  • frequencies (array-like) – CSEM frequencies in Hz.

  • tx_y (array-like) – Transmitter y positions.

  • rx_y (array-like or None) – Receiver y positions. Mutually exclusive with rx_r.

  • rx_r (array-like or None) – Towed receiver offsets from transmitter positions.

  • tx_z (array-like or None) – Override transmitter depth positions.

  • tx_z_offset (float or array-like or None) – Transmitter offset relative to topography.

  • rx_z (array-like or None) – Override receiver depth positions.

  • rx_z_offset (float or array-like or None) – Receiver offset relative to topography.

  • rx_type (str) – Receiver placement mode.

  • tx_type (str) – Dipole type: 'edipole' or 'bdipole'.

  • tx_azimuth (float or array-like or None) – Transmitter azimuth (degrees from x towards y).

  • tx_dip (float or array-like or None) – Transmitter dip (degrees positive down).

  • tx_length (float or array-like or None) – Electric dipole length in metres.

  • rx_length (float or array-like or None) – Receiver dipole length in metres.

  • rx_beta (float or array-like or None) – Receiver beta (y-tilt) angles in degrees.

  • tx_name (list of str or None)

  • rx_name (list of str or None)

  • phase_convention (str) – 'lag' (default) or 'lead'.

  • min_range (float or None) – Minimum Tx–Rx range to include in data file.

  • max_range (float or None) – Maximum Tx–Rx range.

  • lEx (bool) – Include Ex log10 amplitude and phase.

  • lEy (bool)

  • lEz (bool)

  • lBx (bool)

  • lBy (bool)

  • lBz (bool)

frequencies: ndarray#
tx_y: ndarray#
rx_y: ndarray | None = None#
rx_r: ndarray | None = None#
tx_z: ndarray | None = None#
tx_z_offset: float | ndarray | None = None#
rx_z: ndarray | None = None#
rx_z_offset: float | ndarray | None = None#
rx_type: str = 'marine'#
tx_type: str = 'edipole'#
tx_azimuth: float | ndarray | None = None#
tx_dip: float | ndarray | None = None#
tx_length: float | ndarray | None = None#
rx_length: float | ndarray | None = None#
rx_beta: float | ndarray | None = None#
tx_name: list[str] | None = None#
rx_name: list[str] | None = None#
phase_convention: str = 'lag'#
min_range: float | None = None#
max_range: float | None = None#
lEx: bool = True#
lEy: bool = False#
lEz: bool = False#
lBx: bool = False#
lBy: bool = False#
lBz: bool = False#
pycsamt.models.mare2dem.make_data_file(out_file, topo, *, mt=None, csem=None, file_type='forward', comment='Created by pycsamt make_data_file', utm=None)#

Create a MARE2DEM .emdata file from survey parameters.

Port of m2d_makeDataFile.m.

Parameters:
  • out_file (path-like) – Output .emdata filename.

  • topo (float or array-like (n, 2)) – Topography: scalar depth (flat) or [y, z] table.

  • mt (MTSurveyConfig, optional) – MT receiver/data configuration.

  • csem (CSEMSurveyConfig, optional) – CSEM transmitter/receiver/data configuration.

  • file_type (str, default "forward") – "forward" or "inversion" (inversion data not yet implemented).

  • comment (str) – Optional comment written on the second line of the file.

  • utm (UTMOrigin, optional) – UTM mapping metadata.

Returns:

The constructed data object (also written to out_file).

Return type:

EMDataFile

Examples

MT forward dataset at 10 frequencies, 20 land stations:

>>> import numpy as np
>>> from pycsamt.models.mare2dem.survey import MTSurveyConfig, make_data_file
>>> freqs = np.logspace(-3, 3, 10)
>>> rx_y  = np.linspace(-10000, 10000, 20)
>>> mt_cfg = MTSurveyConfig(frequencies=freqs, rx_y=rx_y, rx_type="land", lTE=True, lTM=True)
>>> em = make_data_file("survey.emdata", topo=0.0, mt=mt_cfg)
>>> em.n_mt_receivers
20
class pycsamt.models.mare2dem.ZMMStation(name='', latitude=0.0, longitude=0.0, declination=0.0, periods=<factory>, apres_te=<factory>, phase_te=<factory>, apres_te_se=<factory>, phase_te_se=<factory>, apres_tm=<factory>, phase_tm=<factory>, apres_tm_se=<factory>, phase_tm_se=<factory>, tipper_zy=None, tipper_zy_se=None, x_profile=0.0, y_profile=0.0, z_profile=0.0)#

Bases: object

Impedance tensor data from one .zmm file.

Variables:
  • name (str) – Station name.

  • latitude (float) – Geographic latitude in decimal degrees.

  • longitude (float) – Geographic longitude in decimal degrees.

  • declination (float) – Geomagnetic declination to apply (degrees).

  • periods (numpy.ndarray) – Period samples in seconds.

  • apres_te (numpy.ndarray) – TE-mode apparent resistivity (Ω·m).

  • phase_te (numpy.ndarray) – TE-mode phase (degrees).

  • apres_te_se (numpy.ndarray) – TE apparent resistivity standard error.

  • phase_te_se (numpy.ndarray) – TE phase standard error (degrees).

  • apres_tm (numpy.ndarray) – TM-mode apparent resistivity.

  • phase_tm (numpy.ndarray) – TM-mode phase.

  • apres_tm_se (numpy.ndarray)

  • phase_tm_se (numpy.ndarray)

  • tipper_zy (numpy.ndarray or None) – Complex TE tipper values.

  • tipper_zy_se (numpy.ndarray or None) – Tipper standard errors.

Parameters:
name: str = ''#
latitude: float = 0.0#
longitude: float = 0.0#
declination: float = 0.0#
periods: ndarray#
apres_te: ndarray#
phase_te: ndarray#
apres_te_se: ndarray#
phase_te_se: ndarray#
apres_tm: ndarray#
phase_tm: ndarray#
apres_tm_se: ndarray#
phase_tm_se: ndarray#
tipper_zy: ndarray | None = None#
tipper_zy_se: ndarray | None = None#
x_profile: float = 0.0#
y_profile: float = 0.0#
z_profile: float = 0.0#
pycsamt.models.mare2dem.read_zmm(path)#

Read one EMTF .zmm impedance file.

Parameters:

path (path-like) – File to read.

Returns:

Parsed station data.

Return type:

ZMMStation

Raises:

FileNotFoundError – When path does not exist.

Notes

The reader parses the ZMM 2-column-per-component format:

Period ZXX.r ZXX.i ZXY.r ZXY.i ZYX.r ZYX.i ZYY.r ZYY.i

TZX.r TZX.i TZY.r TZY.i Coh_XY Coh_YX

Apparent resistivities and phases are derived from the complex impedance components ZXY (TE) and ZYX (TM) using:

ρ_a = |Z|² / (ω · μ₀) φ = atan2(Z.imag, Z.real)

where ω = / T and μ₀ = × 10⁻⁷ H/m.

pycsamt.models.mare2dem.make_mt_data_from_zmm(zmm_files, out_file, *, output_modes='all', error_floor_te=0.0, error_floor_tm=0.0, error_floor_tipper=0.0, omit_periods=None, line_orientation=None, declination=0.0, utm0=None, utm_zone='', topo=0.0, rx_z_offset=-0.1)#

Create a MARE2DEM MT data file from a list of .zmm files.

Port of m2d_makeMTDataFromZmm.m.

Parameters:
  • zmm_files (list of path-like) – .zmm impedance files in profile order.

  • out_file (path-like) – Output .emdata filename.

  • output_modes (str, default "all") – Comma-separated data types to include: "TE", "TM", "tipper", "TE+tipper", "all impedance", or "all" (TE + TM + tipper).

  • error_floor_te (float) – Relative error floor for TE (e.g. 0.05 = 5 %).

  • error_floor_tm (float) – Relative error floor for TM.

  • error_floor_tipper (float) – Absolute tipper error floor.

  • omit_periods (array-like, shape (n, 2) or None) – Period bands to omit: each row is [T_min, T_max] in seconds.

  • line_orientation (float or None) – Profile orientation in degrees clockwise from North. Auto-fit from station positions when None.

  • declination (float, default 0.0) – Geomagnetic declination correction in degrees.

  • utm0 ((float, float) or None) – Profile UTM origin (northing, easting) in metres.

  • utm_zone (str, default "") – UTM zone string, e.g. "19N". Auto-detected when empty.

  • topo (float or array-like) – Topography for receiver placement (see parse_topo()).

  • rx_z_offset (float, default -0.1) – Vertical offset of receivers relative to topography (m). Negative → above (marine), positive → below (land).

Returns:

Constructed data file (also written to out_file).

Return type:

EMDataFile

Examples

>>> from pycsamt.models.mare2dem.zmm import make_mt_data_from_zmm
>>> em = make_mt_data_from_zmm(
...     ["S001.zmm", "S002.zmm"],
...     "line1_mt.emdata",
...     output_modes="TE+tipper",
...     error_floor_te=0.05,
... )
>>> em.n_mt_receivers
2
pycsamt.models.mare2dem.make_mt_data_from_stations(stations, out_file, *, output_modes='all', error_floor_te=0.0, error_floor_tm=0.0, error_floor_tipper=0.0, omit_periods=None, line_orientation=None, declination=0.0, utm0=None, utm_zone='', topo=0.0, rx_z_offset=-0.1)#

Create a MARE2DEM MT data file from prepared ZMMStation objects.

Backend shared by make_mt_data_from_zmm() (stations parsed from .zmm files) and pycsamt.models.mare2dem.edi.make_mt_data_from_edi() (stations converted from EDI impedances). See make_mt_data_from_zmm() for the parameter documentation; the only difference is that stations are supplied directly.

Parameters:
Return type:

EMDataFile

pycsamt.models.mare2dem.stations_from_edi(source, *, default_rel_error=0.05, confidence_weighting=False, confidence_method='composite', confidence_weights=None, confidence_min=0.05, confidence_power=1.0)#

Convert an EDI source into ZMMStation objects.

Parameters:
  • source (path-like, Sites, or EDI collection) – Anything accepted by pycsamt.emtools._core.ensure_sites().

  • default_rel_error (float, default 0.05) – Relative impedance error assumed when the EDIs carry no error block (5 %). Error floors applied later can only raise it.

  • confidence_weighting (bool, default False) – If True, inflate the relative impedance errors by the frequency-level confidence ratio (CR) before apparent-resistivity and phase standard errors are computed.

  • confidence_method (str) – Passed to pycsamt.emtools.qc.frequency_confidence_table().

  • confidence_weights (Mapping[str, float] | None) – Passed to pycsamt.emtools.qc.frequency_confidence_table().

  • confidence_min (float, default 0.05) – Lower bound applied to CR before inverting it. This prevents one severely degraded datum from producing infinite uncertainty.

  • confidence_power (float, default 1.0) – Exponent in the uncertainty multiplier (1 / max(CR, confidence_min)) ** confidence_power.

Returns:

One station per EDI with valid impedance, coordinates, and a frequency table matching the first station’s. TE is Zxy, TM is Zyx; apparent resistivity uses the field-units convention ρ_a = 0.2 |Z|² / f and TM phase is wrapped by +180° into the first quadrant (same conventions as read_zmm()).

Return type:

list of ZMMStation

Raises:

ValueError – When no station yields usable impedance + coordinates.

pycsamt.models.mare2dem.make_mt_data_from_edi(source, out_file, *, output_modes='all', error_floor_te=0.05, error_floor_tm=0.05, error_floor_tipper=0.0, default_rel_error=0.05, confidence_weighting=False, confidence_method='composite', confidence_weights=None, confidence_min=0.05, confidence_power=1.0, **kwargs)#

Create a MARE2DEM MT .emdata file from EDI data.

Parameters:
  • source (path-like, Sites, or EDI collection) – Anything accepted by pycsamt.emtools._core.ensure_sites().

  • out_file (path-like) – Output .emdata filename.

  • output_modes (str) – See make_mt_data_from_zmm().

  • error_floor_te (float) – See make_mt_data_from_zmm().

  • error_floor_tm (float) – See make_mt_data_from_zmm().

  • error_floor_tipper (float) – See make_mt_data_from_zmm().

  • default_rel_error (float, default 0.05) – Assumed relative impedance error when the EDIs carry none.

  • confidence_weighting (bool, default False) – If enabled, CR-derived uncertainty inflation is applied before MARE2DEM data weights are written. The propagated errors are sigma_rho = 2 rho sigma_Z/|Z| and sigma_phi = degrees(sigma_Z/|Z|) after multiplying the relative impedance error by (1 / max(CR, confidence_min)) ** confidence_power.

  • **kwargs (Any) – Remaining keyword arguments of make_mt_data_from_stations() (omit_periods, line_orientation, utm0, utm_zone, topo, rx_z_offset, declination).

  • confidence_method (str)

  • confidence_weights (Mapping[str, float] | None)

  • confidence_min (float)

  • confidence_power (float)

  • **kwargs

Returns:

Constructed data file (also written to out_file).

Return type:

EMDataFile

Examples

>>> from pycsamt.models.mare2dem.edi import make_mt_data_from_edi
>>> em = make_mt_data_from_edi(
...     "data/AMT/WILLY_DATA/L22PLT",
...     "run/mare2dem.emdata",
...     error_floor_te=0.05, error_floor_tm=0.05,
... )
>>> em.n_mt_receivers
25
class pycsamt.models.mare2dem.NoiseConfig(mt_rel_noise=0.05, mt_rel_noise_tipper=0.01, mt_abs_noise_tipper=0.01, csem_rel_noise_e=0.05, csem_rel_noise_b=0.05, max_sigma_factor=2.0)#

Bases: object

Per-data-type noise specifications.

Variables:
  • mt_rel_noise (float) – Relative noise for MT apparent resistivity (e.g. 0.05 = 5 %). Phase noise is mt_rel_noise / 2.

  • mt_rel_noise_tipper (float) – Relative noise for tipper real/imaginary components.

  • mt_abs_noise_tipper (float) – Absolute noise floor for tipper. Tipper data with amplitude below this value are dropped (NaN).

  • csem_rel_noise_e (float) – Relative noise for CSEM electric-field responses.

  • csem_rel_noise_b (float) – Relative noise for CSEM magnetic-field responses.

  • max_sigma_factor (float, default 2.0) – Clip noise at this many standard deviations to avoid unrealistically large random draws (matches MATLAB abs(randn) > 2 clipping).

Parameters:
  • mt_rel_noise (float)

  • mt_rel_noise_tipper (float)

  • mt_abs_noise_tipper (float)

  • csem_rel_noise_e (float)

  • csem_rel_noise_b (float)

  • max_sigma_factor (float)

mt_rel_noise: float = 0.05#
mt_rel_noise_tipper: float = 0.01#
mt_abs_noise_tipper: float = 0.01#
csem_rel_noise_e: float = 0.05#
csem_rel_noise_b: float = 0.05#
max_sigma_factor: float = 2.0#
pycsamt.models.mare2dem.add_synthetic_noise(em, noise, *, seed=None)#

Add synthetic Gaussian noise to MARE2DEM response data.

Port of m2d_addSyntheticNoise.m.

The function reads predicted responses from column 7 of the 8-column DATA block (is_response=True), adds noise according to noise, and stores the result in columns 5 and 6 (data, std_err). The output DATA block has 6 columns (observed-data format).

Parameters:
  • em (EMDataFile) – Response file with 8-column DATA block (Format: EMResp_2.3).

  • noise (NoiseConfig) – Noise specification.

  • seed (int or None, default None) – Random-number generator seed for reproducibility.

Returns:

New EMDataFile with 6-column DATA block containing the noisy synthetic data and standard errors.

Return type:

EMDataFile

Raises:

ValueError – When em.data does not have 8 columns (not a response file).

Examples

>>> from pycsamt.models.mare2dem import read_emdata
>>> from pycsamt.models.mare2dem.noise import NoiseConfig, add_synthetic_noise
>>> resp = read_emdata("forward.EMResp")
>>> nc = NoiseConfig(mt_rel_noise=0.05)
>>> noisy = add_synthetic_noise(resp, nc, seed=42)
>>> noisy.n_data
200
pycsamt.models.mare2dem.make_synthetic_data(in_file, out_file, noise, *, seed=None)#

Read a MARE2DEM response file, add noise, and write a data file.

Port of m2d_makeSyntheticData.m.

Parameters:
  • in_file (path-like) – MARE2DEM response file (.EMResp) with 8-column DATA block.

  • out_file (path-like) – Output .emdata file with 6-column noisy DATA block.

  • noise (NoiseConfig) – Noise specification.

  • seed (int or None, default None) – RNG seed for reproducibility.

Returns:

The noisy data object (also written to out_file).

Return type:

EMDataFile

Examples

>>> from pycsamt.models.mare2dem.noise import NoiseConfig, make_synthetic_data
>>> nc = NoiseConfig(mt_rel_noise=0.05, csem_rel_noise_e=0.05)
>>> em = make_synthetic_data("forward.EMResp", "synthetic.emdata", nc, seed=0)
pycsamt.models.mare2dem.merge_data_files(files_to_merge, out_file, *, keep_duplicate_rx=False)#

Merge MARE2DEM .emdata files and write the result.

Port of m2d_mergeDataFiles.m.

Parameters:
  • files_to_merge (list of path-like) – At least two .emdata files to merge. Include the full path if files are not in the current directory.

  • out_file (path-like) – Output .emdata filename.

  • keep_duplicate_rx (bool, default False) – Keep identical receiver locations (needed for towed CSEM arrays).

Returns:

Merged file contents (also written to out_file).

Return type:

EMDataFile

Examples

>>> from pycsamt.models.mare2dem.merge import merge_data_files
>>> em = merge_data_files(["mt.emdata", "csem.emdata"], "joint.emdata")
>>> em.n_data
3200
pycsamt.models.mare2dem.merge_emdata(files, *, keep_duplicate_rx=False, comment='')#

Merge a list of EMDataFile objects into one.

Parameters:
  • files (list of EMDataFile) – At least two files to merge.

  • keep_duplicate_rx (bool, default False) – When True, identical receiver locations are kept separate (needed for towed CSEM arrays with identical offsets).

  • comment (str) – Comment written into the merged output file header.

Returns:

Merged data file (not yet written to disk).

Return type:

EMDataFile

Raises:

ValueError – When fewer than two files are given, or when UTM origins differ.

pycsamt.models.mare2dem.grid_to_mare2dem(Y, Z, Rho, *, padding_y=50000.0, padding_z=50000.0, out_dir='.', model_name='mare2dem', data_file='mare2dem.emdata', target_misfit=1.0, max_iterations=100)#

Create a MARE2DEM model from a regular 2-D resistivity grid.

Port of m2d_gridToM2D.m.

Parameters:
  • Y (array-like, shape (nz, ny)) – y-coordinates (along-profile) of grid cell centres in metres. Values must vary along columns; all rows for the same column share the same y value.

  • Z (array-like, shape (nz, ny)) – Depth coordinates of grid cell centres in metres (positive down). Values must vary along rows; all columns for the same row share the same z value.

  • Rho (array-like, shape (nz, ny)) – Resistivity at each cell centre in Ω·m.

  • padding_y (float, default 50000.0) – Lateral padding in metres added outside the grid.

  • padding_z (float, default 50000.0) – Vertical padding in metres added below and above the grid.

  • out_dir (path-like, default ".") – Output directory.

  • model_name (str, default "mare2dem") – Stem name used for all output files.

  • data_file (str, default "mare2dem.emdata") – Name of the associated data file written into the model header.

  • target_misfit (float, default 1.0) – Target normalized RMS misfit.

  • max_iterations (int, default 100) – Maximum inversion iterations.

Returns:

Keys "resistivity", "poly", "settings".

Return type:

dict[str, pathlib.Path]

Examples

>>> import numpy as np
>>> from pycsamt.models.mare2dem.grid_to_m2d import grid_to_mare2dem
>>> y1d = np.linspace(-5000, 5000, 21)
>>> z1d = np.linspace(0, 3000, 11)
>>> Y, Z = np.meshgrid(y1d, z1d)
>>> Rho = np.ones_like(Y) * 10.0      # 10 Ω·m half-space
>>> files = grid_to_mare2dem(Y, Z, Rho, out_dir="/tmp/m2d_grid_test")
>>> files["resistivity"].exists()
True
class pycsamt.models.mare2dem.TopoConfig(topo_file='', col_longitude=None, col_latitude=None, col_elevation_m=None, col_depth_m=None, col_distance_km=None, col_distance_m=None)#

Bases: object

Configuration for loading one topography file.

Variables:
  • topo_file (str or path-like) – Path to the topography file (whitespace-separated columns).

  • col_longitude (int or None) – 1-based column index for longitude. Required when the file has geographic coordinates.

  • col_latitude (int or None) – 1-based column index for latitude.

  • col_elevation_m (int or None) – 1-based column for elevation in metres (positive up). Mutually exclusive with col_depth_m.

  • col_depth_m (int or None) – 1-based column for depth in metres (positive down).

  • col_distance_km (int or None) – 1-based column for along-profile distance in km.

  • col_distance_m (int or None) – 1-based column for along-profile distance in metres.

Parameters:
  • topo_file (str | Path)

  • col_longitude (int | None)

  • col_latitude (int | None)

  • col_elevation_m (int | None)

  • col_depth_m (int | None)

  • col_distance_km (int | None)

  • col_distance_m (int | None)

topo_file: str | Path = ''#
col_longitude: int | None = None#
col_latitude: int | None = None#
col_elevation_m: int | None = None#
col_depth_m: int | None = None#
col_distance_km: int | None = None#
col_distance_m: int | None = None#
class pycsamt.models.mare2dem.TopoProfile(y_topo, z_topo, northings=None, eastings=None)#

Bases: object

Loaded and projected topography profile.

Variables:
  • y_topo (numpy.ndarray) – Along-profile position in metres (MARE2DEM y axis).

  • z_topo (numpy.ndarray) – Depth in metres, positive down (MARE2DEM z axis).

  • northings (numpy.ndarray or None) – UTM northing (m) — present when converted from Lon/Lat.

  • eastings (numpy.ndarray or None) – UTM easting (m) — present when converted from Lon/Lat.

Parameters:
y_topo: ndarray#
z_topo: ndarray#
northings: ndarray | None = None#
eastings: ndarray | None = None#
pycsamt.models.mare2dem.import_topo(cfg, *, utm_north0=0.0, utm_east0=0.0, utm_theta=0.0, utm_zone=None, south_hemi=False, orientation_tol=5.0)#

Import a topography file and project it onto the survey profile.

Port of m2d_importTopo.m.

Parameters:
  • cfg (TopoConfig) – Column layout and file path.

  • utm_north0 (float) – Profile UTM origin northing (metres).

  • utm_east0 (float) – Profile UTM origin easting (metres).

  • utm_theta (float) – Profile UTM theta angle (degrees) — the stUTM.theta field from the .emdata UTM block. Note: the survey-line direction is theta + 90°.

  • utm_zone (int or None) – UTM zone number. Required only when Lon/Lat input is used.

  • south_hemi (bool, default False) – Southern-hemisphere flag for UTM conversion.

  • orientation_tol (float, default 5.0) – Maximum allowed angle (degrees) between the topography profile orientation and the survey line orientation.

Returns:

Projected topography (y, z) in MARE2DEM coordinates.

Return type:

TopoProfile

Raises:
  • FileNotFoundError – When the topography file does not exist.

  • ValueError – When the topography and survey orientations differ by more than orientation_tol degrees.

Examples

>>> from pycsamt.models.mare2dem.import_topo import TopoConfig, import_topo
>>> cfg = TopoConfig(topo_file="topo.txt", col_distance_km=1, col_depth_m=2)
>>> prof = import_topo(cfg, utm_north0=0.0, utm_east0=0.0)
>>> prof.y_topo
array([0., ...])
pycsamt.models.mare2dem.diff_resistivity(file1, file2, out_file, *, diff_fn=None)#

Difference two MARE2DEM resistivity files and write the result.

Port of diffMARE2DEM_Resistivity.m.

Parameters:
  • file1 (path-like) – First .resistivity file (minuend, or reference model).

  • file2 (path-like) – Second .resistivity file (subtrahend, or inverted model).

  • out_file (path-like) – Destination .resistivity file for the difference model.

  • diff_fn (callable or None, default None) –

    Function (A, B) -> C applied element-wise to the resistivity arrays. Both A and B have shape (n_regions, nrho). The default is:

    lambda A, B: np.log10(A) - np.log10(B)
    

    Custom alternatives:

    • Absolute percentage difference: lambda A, B: np.abs((A - B) / A * 100)

    • Linear difference: lambda A, B: A - B

Returns:

The difference resistivity model (also written to out_file).

Return type:

ResistivityFile

Raises:

ValueError – When the two files have different numbers of regions.

Examples

Default log10 difference:

>>> from pycsamt.models.mare2dem.diff import diff_resistivity
>>> dm = diff_resistivity(
...     "mare2dem_iter00.resistivity",
...     "mare2dem_iter20.resistivity",
...     "mare2dem_diff.resistivity",
... )
>>> dm.num_regions
4812

Percentage change:

>>> dm = diff_resistivity(
...     "iter00.resistivity",
...     "iter20.resistivity",
...     "pct_change.resistivity",
...     diff_fn=lambda A, B: np.abs((A - B) / A * 100),
... )
class pycsamt.models.mare2dem.EMData(path=None, **kwargs)#

Bases: object

Thin wrapper around EMDataFile for backwards compatibility.

Provides the same path, header, data, and write() interface as the original stub while delegating to the full parser.

Parameters:

path (path-like, optional) – Source file. Read immediately when provided.

property header: dict[str, Any]#
property data: ndarray | None#
property n_data: int#
write(path)#

Write the stored .emdata to path.

Parameters:

path (str | Path)

Return type:

Path

class pycsamt.models.mare2dem.ResistivityModel(path=None, **kwargs)#

Bases: object

Thin wrapper around ResistivityFile for backwards compatibility.

Parameters:

path (path-like, optional) – Source .resistivity file.

property header: dict[str, Any]#
property n_elements: int#
property n_nodes: int#
write(path)#

Write the model to path.

Parameters:

path (str | Path)

Return type:

Path

classmethod halfspace(log10_rho=0.0, *, n_nodes=0)#

Return a homogeneous half-space resistivity model stub.

Parameters:
Return type:

ResistivityModel

class pycsamt.models.mare2dem.PolyMesh(path=None, **kwargs)#

Bases: object

Thin wrapper around PolyFile for backwards compatibility.

Parameters:

path (path-like, optional) – Source .poly file.

property vertices: ndarray | None#
property segments: ndarray | None#
property holes: ndarray | None#
write(path)#
Parameters:

path (str | Path)

Return type:

Path

class pycsamt.models.mare2dem.Mare2DEMLog(path)#

Bases: object

Parse the MARE2DEM per-iteration OccamLog.2012.0 log file.

MARE2DEM writes one block per completed iteration containing Model Misfit, Roughness, and Optimal Mu lines. This parser extracts those values and exposes them as IterationRecord objects.

Parameters:

path (path-like) – Path to the log file (usually *.logfile or *.log).

Variables:
property final_rms: float | None#

RMS at the last logged iteration.

property n_iterations: int#

Number of completed iterations in the log.

rms_history()#

Return per-iteration RMS values in order.

Return type:

list[float]

class pycsamt.models.mare2dem.IterationRecord(iteration, rms, roughness, lambda_)#

Bases: object

One completed iteration from a MARE2DEM log file.

Variables:
  • iteration (int) – Iteration number.

  • rms (float) – Normalized RMS misfit at this iteration.

  • roughness (float) – Model roughness.

  • lambda (float) – Log10 of the Lagrange (regularization) multiplier.

Parameters:
iteration: int#
rms: float#
roughness: float#
lambda_: float#
class pycsamt.models.mare2dem.InversionResult(workdir, config=None, **kwargs)#

Bases: Mare2DEMBase

Load and expose MARE2DEM inversion output files.

InversionResult scans a MARE2DEM run directory after the binary has finished and loads the iteration log, final resistivity model, observed-data file, and predicted-response file.

Parameters:
  • workdir (path-like) – Directory to scan for MARE2DEM output files.

  • config (Mare2DEMConfig, optional) – Configuration providing default file stems. When omitted, the scanner looks for any .log, .resistivity, .emdata, and *_MARE2DEM.emdata files.

  • **kwargs – Forwarded to Mare2DEMBase.

Variables:
  • workdir (pathlib.Path) – Absolute path of the scanned run directory.

  • config (Mare2DEMConfig) – Configuration used for file-name hints.

  • log (Mare2DEMLog or None) – Parsed iteration log.

  • model (ResistivityModel or None) – Final inverted resistivity model.

  • data (EMData or None) – Observed data file.

  • response (EMData or None) – Predicted-response file (*_MARE2DEM.emdata).

Examples

>>> from pycsamt.models.mare2dem import InversionResult
>>> result = InversionResult("./mare2dem_run")
>>> result.log.final_rms
0.98
>>> result.log.converged
True
property converged: bool#

True when the log reports successful convergence.

property final_rms: float | None#

Final normalized RMS from the log, or None.

property n_iterations: int#

Number of completed inversion iterations.

summary()#

Return a human-readable summary string.

Return type:

str

print_summary()#

Print summary() to stdout.

Return type:

None

class pycsamt.models.mare2dem.Mare2DEMRunner(workdir, config=None, **kwargs)#

Bases: Mare2DEMBase

Launch MARE2DEM inversion subprocesses.

Mare2DEMRunner is the execution layer of the MARE2DEM wrapper. It receives the stem of a .resistivity file prepared by InputBuilder, selects the configured MARE2DEM executable, and launches the MPI process from workdir. After the run it optionally loads output into an InversionResult.

The command has the logical form:

mpirun -np 8 MARE2DEM mare2dem

where mare2dem is the stem of mare2dem.resistivity.

Parameters:
  • workdir (path-like, default ".") – Directory that contains, or will receive, a MARE2DEM run. The builder writes the resistivity model, data, and settings files here. The runner executes the MARE2DEM binary from this directory so the input file stem is resolved relative to the run folder. The directory is created before output is written.

  • config (Mare2DEMConfig, optional) – Configuration object controlling the resistivity model, data component selection, inversion parameters, source management, executable name, and MPI settings. If omitted, a default Mare2DEMConfig is created. Pass an explicit configuration when several MARE2DEM objects must share exactly the same run parameters.

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

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

Variables:
  • workdir (pathlib.Path) – Directory from which the subprocess is launched.

  • config (Mare2DEMConfig) – Configuration used for binary name, MPI, and source management.

Notes

Binary resolution is performed by _resolve_binary(), which first checks PATH, then delegates to SourceManager.resolve_binary() for locally compiled binaries.

See also

SourceManager

Download and compile the MARE2DEM binary.

InputBuilder

Write the resistivity model, data, and settings files.

InversionResult

Load MARE2DEM output after the run.

References

run(resistivity_stem, *, use_mpi=None, n_procs=None, extra_args=None, timeout=None, load_result=True)#

Run a MARE2DEM inversion subprocess.

MARE2DEM receives one positional argument: the stem of the .resistivity file. It derives the data filename by replacing the extension with .emdata and the settings filename with .settings.

Parameters:
  • resistivity_stem (path-like) – Stem or full path to the .resistivity file. MARE2DEM strips the extension itself; you may pass either "run" or "run.resistivity". Relative paths are interpreted from workdir.

  • use_mpi (bool, optional) – MPI override. Falls back to config.use_mpi.

  • n_procs (int, optional) – Number of MPI processes. Falls back to config.n_procs.

  • extra_args (sequence of str, optional) – Additional command-line arguments appended to the MARE2DEM invocation.

  • timeout (float, optional) – Maximum run time in seconds. None means no timeout.

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

Returns:

Parsed result object when load_result is True. None otherwise.

Return type:

InversionResult or None

Raises:

Examples

Serial run (special single-process build):

>>> from pycsamt.models.mare2dem import Mare2DEMConfig, Mare2DEMRunner
>>> cfg = Mare2DEMConfig(use_mpi=False)
>>> runner = Mare2DEMRunner("./mare2dem_run", config=cfg)
>>> result = runner.run("mare2dem")

MPI run with 8 processes:

>>> cfg = Mare2DEMConfig(use_mpi=True, n_procs=8)
>>> runner = Mare2DEMRunner("./mare2dem_run", config=cfg)
>>> result = runner.run("mare2dem")
command(resistivity_stem, *, use_mpi=None, n_procs=None)#

Return the MARE2DEM command string without executing it.

Parameters:
  • resistivity_stem (path-like) – Resistivity file stem passed to MARE2DEM.

  • use_mpi (bool, optional) – MPI override.

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

Returns:

Shell-quoted command string for display or logging.

Return type:

str

Examples

>>> from pycsamt.models.mare2dem import Mare2DEMConfig, Mare2DEMRunner
>>> cfg = Mare2DEMConfig(use_mpi=True, n_procs=4)
>>> runner = Mare2DEMRunner("./run", config=cfg)
>>> "mpirun" in runner.command("mare2dem")
True
class pycsamt.models.mare2dem.InputBuilder(config=None, **kwargs)#

Bases: Mare2DEMBase

Prepare a MARE2DEM working directory from survey parameters.

InputBuilder produces the three required input files for a MARE2DEM inversion run:

  • the .emdata observed-data file;

  • the starting .resistivity model;

  • the .settings parallel-decomposition control file.

Parameters:
  • config (Mare2DEMConfig, optional) – Configuration for inversion parameters and file names.

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

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

Examples

Build from an existing .emdata file:

>>> from pycsamt.models.mare2dem import Mare2DEMConfig, InputBuilder
>>> cfg = Mare2DEMConfig(initial_rho=1.0, max_iterations=100)
>>> builder = InputBuilder(config=cfg)
>>> files = builder.build("survey.emdata", workdir="./run")

Build from MTSurveyConfig:

>>> import numpy as np
>>> from pycsamt.models.mare2dem.survey import MTSurveyConfig
>>> mt = MTSurveyConfig(
...     frequencies=np.logspace(-3, 3, 10),
...     rx_y=np.linspace(-5000, 5000, 20),
...     rx_type="marine", lTE=True, lTM=True,
... )
>>> files = builder.build(None, workdir="./run", mt=mt)

See also

Mare2DEMRunner

Launch MARE2DEM on the written input files.

make_data_file

Low-level data file generator.

write_settings(workdir='.', *, filename=None, **sf_kwargs)#

Write the MARE2DEM .settings file.

Parameters:
  • workdir (path-like, default ".") – Target directory.

  • filename (str, optional) – Override the settings filename.

  • **sf_kwargs – Extra keyword arguments forwarded to SettingsFile.

Returns:

Path of the written file.

Return type:

pathlib.Path

write_resistivity(workdir='.', *, filename=None, poly_file=None)#

Write a homogeneous half-space .resistivity file.

Parameters:
  • workdir (path-like, default ".") – Target directory.

  • filename (str, optional) – Override the resistivity filename.

  • poly_file (str, optional) – Poly file reference written into the model header.

Returns:

Path of the written file.

Return type:

pathlib.Path

build(source, workdir='.', *, topo=0.0, mt=None, csem=None, data_filename=None, model_filename=None, settings_filename=None)#

Write a MARE2DEM input set to workdir.

Parameters:
  • source (path-like, EMDataFile, or None) – Existing .emdata file (copied to workdir) or None (generate from mt/csem config objects).

  • workdir (path-like, default ".") – Target directory.

  • topo (float or array-like) – Topography for receiver/transmitter placement (used only when source is None).

  • mt (MTSurveyConfig, optional) – MT survey config (used when source is None).

  • csem (CSEMSurveyConfig, optional) – CSEM survey config (used when source is None).

  • data_filename (str, optional) – Override data file name.

  • model_filename (str, optional) – Override resistivity model file name.

  • settings_filename (str, optional) – Override settings file name.

Returns:

Keys: "data", "model", "settings".

Return type:

dict[str, pathlib.Path]

class pycsamt.models.mare2dem.PlotConvergence(log_or_result, **kwargs)#

Bases: Mare2DEMBase

Plot RMS misfit convergence from a MARE2DEM log.

Parameters:

log_or_result (Mare2DEMLog or InversionResult) – Source of iteration records.

Examples

>>> from pycsamt.models.mare2dem import InversionResult, PlotConvergence
>>> result = InversionResult("./run")
>>> pc = PlotConvergence(result)
>>> fig = pc.plot()
plot(ax=None, *, savefig=None, dpi=150, target_rms=None)#

Draw the RMS-vs-iteration convergence curve.

Parameters:
Return type:

matplotlib.figure.Figure

class pycsamt.models.mare2dem.PlotSurveyLayout(em, **kwargs)#

Bases: Mare2DEMBase

Plot survey receiver and transmitter positions on a map.

Port of plotMARE2DEM_SurveyLayout.m (map view only; GUI removed).

Parameters:
  • em (EMDataFile) – Data file supplying receiver / transmitter positions and the UTM origin metadata.

  • **kwargs – Forwarded to Mare2DEMBase.

Examples

>>> from pycsamt.models.mare2dem import read_emdata
>>> from pycsamt.models.mare2dem.plot import PlotSurveyLayout
>>> em = read_emdata("survey.emdata")
>>> fig = PlotSurveyLayout(em).plot()
plot(ax=None, *, savefig=None, dpi=150, units='km')#

Draw the survey map: receivers and transmitters in UTM.

Parameters:
  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • savefig (path-like, optional) – Save figure to this path.

  • dpi (int, default 150) – DPI for the saved figure.

  • units ({"m", "km"}, default "km") – Display units for axes labels.

Return type:

matplotlib.figure.Figure

class pycsamt.models.mare2dem.PlotRxParams(em, **kwargs)#

Bases: Mare2DEMBase

Plot receiver geometry parameters (x, y, z, θ, α, β).

Port of the plotRxParams sub-function in plotMARE2DEM_SurveyLayout.m.

Parameters:
  • em (EMDataFile) – Survey data file.

  • **kwargs – Forwarded to Mare2DEMBase.

plot(*, fig=None, savefig=None, dpi=150, units='km')#

Draw 6-panel receiver parameter overview.

Parameters:
Return type:

matplotlib.figure.Figure

class pycsamt.models.mare2dem.PlotTxParams(em, **kwargs)#

Bases: Mare2DEMBase

Plot CSEM transmitter geometry parameters (x, y, z, azimuth, dip).

Port of the plotTxParams sub-function in plotMARE2DEM_SurveyLayout.m.

Parameters:

em (Any)

plot(*, fig=None, savefig=None, dpi=150, units='km')#

Draw transmitter parameter overview.

Parameters:
Return type:

matplotlib.figure.Figure

pycsamt.models.mare2dem.plot_poly(poly_file, ax=None, *, linewidth=1.0, color='k', savefig=None, dpi=150)#

Plot a Triangle .poly PSLG mesh file.

Port of m2d_plot_poly.m.

Parameters:
  • poly_file (path-like) – Path to the .poly file.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • linewidth (float, default 1.0)

  • color (str, default "k")

  • savefig (path-like, optional)

  • dpi (int, default 150)

Returns:

The axes with the PSLG drawn.

Return type:

matplotlib.axes.Axes

Examples

>>> from pycsamt.models.mare2dem.plot import plot_poly
>>> ax = plot_poly("mare2dem.poly")
class pycsamt.models.mare2dem.PlotModel(model_or_result, **kwargs)#

Bases: Mare2DEMBase

Plot the log10-resistivity 2-D section.

Renders a colour-filled triangular mesh via matplotlib.axes.Axes.tripcolor() when Triangle mesh output files (.node + .ele) are found next to the .resistivity file. Falls back to a histogram of region resistivity values when no mesh is present.

Parameters:
plot(ax=None, *, savefig=None, dpi=150, cmap='turbo_r', vmin=None, vmax=None)#

Plot the 2-D resistivity section.

When Triangle mesh output files (.node + .ele) are found next to the .resistivity file, a colour-filled triangular section is rendered. Otherwise a histogram of resistivity values is shown.

Parameters:
  • ax (matplotlib.axes.Axes, optional) – Target axes. When None a new figure is created.

  • savefig (path-like, optional) – Save the figure to this path.

  • dpi (int, default 150) – Output resolution in dots per inch.

  • cmap (str, default "turbo_r") – Colour map for the resistivity section.

  • vmin (float, optional) – Lower log10-rho bound for the colour axis.

  • vmax (float, optional) – Upper log10-rho bound for the colour axis.

Return type:

matplotlib.figure.Figure

class pycsamt.models.mare2dem.PlotResponse(result, **kwargs)#

Bases: Mare2DEMBase

Compare observed and predicted MT responses.

Generates a per-receiver grid of subplots overlaying TE and TM apparent resistivity and phase versus period.

Parameters:
  • result (InversionResult) – Inversion output containing observed data and MARE2DEM predicted response.

  • **kwargs – Forwarded to Mare2DEMBase.

plot(ax=None, *, savefig=None, dpi=150, station=None, max_rx=4, figsize=None)#

Plot observed vs predicted MT responses.

One figure row per receiver, two columns: apparent resistivity on the left and phase on the right.

Parameters:
  • ax (matplotlib.axes.Axes, optional) – Ignored – the method creates its own figure.

  • savefig (path-like, optional) – Save the figure to this path.

  • dpi (int, default 150) – Output resolution in dots per inch.

  • station (str, optional) – Plot only this receiver by name. When None, the first max_rx receivers are plotted.

  • max_rx (int, default 4) – Maximum number of receivers when station is None.

  • figsize ((float, float), optional) – Figure size in inches.

Return type:

matplotlib.figure.Figure

Raises:

ValueError – When the result contains no MT data.