pycsamt.models.occam2d#

Python interface to the Occam2DMT inversion workflow.

The pycsamt.models.occam2d subpackage builds, runs, reads, and plots two-dimensional magnetotelluric and CSAMT inversions using the Occam smooth-model approach [1]_, [2]_. The inversion seeks a model that fits the data to a target normalized RMS while minimizing roughness.

\[\begin{split}\phi_d = \sqrt{\\frac{1}{N}\sum_{i=1}^{N} r_i^2}, \qquad \rho_i = 10^{m_i}.\end{split}\]

Typical Workflow#

  1. Load EDI files with pycsamt.site.Sites.

  2. Build input files with InputBuilder.

  3. Run the Fortran executable with OccamRunner.

  4. Load results with InversionResult.

  5. Plot models, responses, pseudosections, and misfit curves.

Examples

>>> from pycsamt.models.occam2d import (
...     InputBuilder, OccamRunner, InversionResult,
... )
>>> from pycsamt.site import Sites
>>> sites = Sites.from_dir("edi")
>>> InputBuilder(sites, workdir="occam_run").build()
>>> OccamRunner("occam_run").run(target_misfit=1.0)
>>> result = InversionResult("occam_run")
>>> result.plot_model()

References

class pycsamt.models.occam2d.InputBuilder(source, workdir='.', config=None, **kwargs)#

Bases: OccamBase

Build the complete input set for an Occam2D inversion.

InputBuilder is the main construction entry point for the v2 Occam2D workflow. It takes one survey source and writes the four files consumed by the Occam2DMT Fortran program:

  • OccamDataFile.dat: observed data and uncertainty rows.

  • Occam2DMesh: finite-element mesh geometry.

  • Occam2DModel: mapping from mesh cells to parameters.

  • Startup: inversion controls and initial model vector.

The build chain follows Occam smooth inversion [1]_, [2]_. The inversion later seeks the smoothest model that reaches a target normalized RMS misfit:

\[\mathrm{RMS} = \sqrt{\frac{1}{N}\sum_{i=1}^N r_i^2}.\]

InputBuilder does not run the inversion. It prepares a self-contained working directory that can be passed to OccamRunner.

Parameters:
  • source (Sites, EDICollection, or iterable) – EDI-derived survey source used to build the Occam data file. Accepted inputs include pycsamt.site.Sites, an EDI collection, or any iterable of site-like objects. Each item must expose frequency, apparent resistivity, and phase arrays. Coordinates are strongly preferred because they allow station offsets to be ordered along profile. When coordinates are absent, fallback spacing is used.

  • workdir (path-like, default ".") – Directory that contains, or will receive, the Occam2D run files. Builders write OccamDataFile.dat, Occam2DMesh, Occam2DModel, and Startup inside this directory. Runners execute the compiled binary from this location and capture standard output and error logs there. The directory is created when output is written.

  • config (OccamConfig, optional) – Configuration object controlling data selection, mesh geometry, startup controls, file names, and executable discovery. It centralizes choices such as modes, error floors, frequency limits, layer counts, cell sizes, target misfit, starting resistivity, and Occam file names. If omitted, a default OccamConfig is created.

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

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Pass an explicit logger when integrating Occam2D objects into an application-level logging setup.

Variables:
  • source (object) – Original survey source passed to the builder. It is kept so repeated build() calls can rebuild outputs with different one-shot overrides.

  • workdir (pathlib.Path) – Output directory where Occam files are written.

  • config (OccamConfig) – Mutable run configuration used by the build steps.

  • data (OccamData or None) – Populated after build(). It stores station names, offsets, frequencies, data-type codes, datum values, and errors.

  • mesh (OccamMesh or None) – Finite-element mesh generated from data.offsets and mesh-related configuration values.

  • model (OccamModel or None) – Model-parameter definition generated from mesh.

  • startup (OccamStartup or None) – Iteration-zero startup object generated from model.

Notes

Keyword overrides supplied to build() update the stored config object before files are written. This makes later calls convenient, but overrides persist unless the caller restores the configuration.

See also

OccamData.from_edi

Convert the survey source into Occam data rows.

OccamMesh.from_data

Build the finite-element mesh from station offsets.

OccamModel.from_mesh

Convert the mesh into an inversion parameter mapping.

OccamStartup.from_model

Build the initial log10-resistivity parameter vector.

OccamRunner

Execute the compiled Occam2DMT binary in workdir.

InversionResult

Load iteration, response, model, mesh, and log outputs.

Examples

Build default TE/TM run files from a directory of EDI files:

>>> from pycsamt.models.occam2d import InputBuilder
>>> from pycsamt.site import Sites
>>> sites = Sites.from_dir("edi")
>>> builder = InputBuilder(sites, workdir="occam_run")
>>> builder.build()
>>> builder.is_ready
True

Build only TM data over a restricted frequency band:

>>> builder = InputBuilder(sites, workdir="occam_tm")
>>> builder.build(
...     modes=["TM"],
...     freq_min=0.1,
...     freq_max=1000.0,
...     title="TM-only Occam2D test",
... )

Use a configuration object for a finer mesh:

>>> from pycsamt.models.occam2d import OccamConfig
>>> cfg = OccamConfig(n_layers=36)
>>> cfg.cell_size_horizontal = 50.0
>>> builder = InputBuilder(sites, workdir="fine_run")
>>> builder.config = cfg
>>> builder.build(error_floor_rho=0.07)

Chain build and summary calls in a script:

>>> summary = InputBuilder(sites, "run").build().summary()
>>> "data pts" in summary
True

References

build(modes=None, n_layers=None, cell_size=None, error_floor_rho=None, error_floor_phase=None, freq_min=None, freq_max=None, title='pycsamt Occam2D run', **kwargs)#

Build and write all required Occam2D input files.

The method executes the input-file pipeline in fixed order: data, mesh, model, then startup. Each step depends on the previous object, so failures usually identify the first bad input in the chain.

The generated files are written using names stored in self.config:

  • config.data_file

  • config.mesh_file

  • config.model_file

  • config.startup_file

One-shot arguments update the builder configuration before writing files. For example, n_layers=40 updates self.config.n_layers and affects mesh, model, and startup objects created by this call.

Parameters:
  • modes (list of str, optional) – Electromagnetic modes written to the data file. Supported values are "TE" for the \(Z_{xy}\) component and "TM" for the \(Z_{yx}\) component. Both apparent resistivity and phase rows are written for each selected mode. If omitted, config.modes is used.

  • n_layers (int, optional) – Number of active subsurface parameter layers in the Occam model. Larger values allow the inversion to represent more vertical structure, but they also increase the number of model parameters and can make the problem less stable without adequate data support.

  • cell_size (float, optional) – Horizontal cell width in metres near station positions. Smaller values provide finer lateral resolution around the profile but increase mesh size and runtime. This value overrides config.cell_size_horizontal for one build only.

  • error_floor_rho (float, optional) – Relative apparent-resistivity error floor used when data built from EDI sources. The value is a fraction, for example 0.05 for five percent. Occam stores apparent resistivity in log10 units, so the floor is converted as \(\sigma_d=\sigma_{\rho}/\ln(10)\). This prevents very small resistivity errors from dominating inversion objective.

  • error_floor_phase (float, optional) – Minimum absolute phase uncertainty in degrees. This value is applied to phase rows when source errors are missing or smaller than the floor. It stabilizes phase weighting data in the Occam objective function.

  • freq_min (float, optional) – Lower frequency limit in hertz. Frequencies below this value are excluded when building data from EDI sources. Use this to remove low-frequency samples that are noisy, poorly sampled, or outside the intended depth range.

  • freq_max (float, optional) – Upper frequency limit in hertz. Frequencies above this value are excluded when building data from EDI sources. Use this to remove high-frequency samples affected by near-surface noise, static effects, or processing limits.

  • title (str, default "pycsamt Occam2D data file") – Free-text title written into the Occam data-file header. Use it to record survey name, processing version, inversion purpose, or other provenance attached to the generated OccamDataFile.dat.

Returns:

Same builder instance, populated with data, mesh, model, and startup objects.

Return type:

InputBuilder

Raises:
  • ValueError – If the survey source cannot produce sites, frequencies, modes, station offsets, or model parameters.

  • OSError – If the output directory or files cannot be written.

See also

OccamData.write

Write the generated data file.

OccamMesh.write

Write the generated mesh file.

OccamModel.write

Write the generated model file.

OccamStartup.write

Write the generated startup file.

Examples

Build a standard run:

>>> from pycsamt.models.occam2d import InputBuilder
>>> from pycsamt.site import Sites
>>> sites = Sites.from_dir("edi")
>>> builder = InputBuilder(sites, workdir="run")
>>> builder.build(modes=["TE", "TM"], n_layers=30)

Build a shallow, high-frequency test:

>>> builder.build(
...     modes=["TE"],
...     freq_min=10.0,
...     freq_max=10000.0,
...     n_layers=18,
...     cell_size=75.0,
... )

Inspect the generated objects without rereading files:

>>> builder.data.n_sites > 0
True
>>> builder.mesh.n_xcells > 0
True
>>> builder.model.n_params == builder.startup.n_params
True
property is_ready: bool#

Return True when all build objects are populated.

summary()#

Return a compact, human-readable build summary.

Return type:

str

class pycsamt.models.occam2d.OccamRunner(workdir='.', binary_path=None, startup_file='Startup', **kwargs)#

Bases: OccamBase

Run the Occam2D Fortran executable from Python.

OccamRunner is the execution layer of the Occam2D workflow. It assumes that an input directory already contains the files written by InputBuilder: OccamDataFile.dat, Occam2DMesh, Occam2DModel, and Startup. The runner resolves a compiled executable, can compile the bundled Fortran source, launches the solver in workdir, and captures standard output and error streams.

Binary discovery follows a deterministic order:

  1. explicit binary_path passed to the constructor;

  2. executable named Occam2D or Occam2D.exe in workdir;

  3. executable found on the system PATH;

  4. bundled _source directory, if automatic compilation is enabled.

The synchronous run() method blocks until Occam2D exits. The asynchronous run_async() method returns a process handle and lets the caller poll is_running or call wait().

Parameters:
  • workdir (path-like, default ".") – Directory containing the Occam2D run files. The binary is executed with this directory as its current working directory, so relative names inside Startup are resolved there. Output logs are also written there.

  • binary_path (path-like, optional) – Explicit path to a compiled Occam2D executable. Use this when the binary is stored outside workdir or is not available on PATH. When omitted, discovery the order described above.

  • startup_file (str, default "Startup") – Name of the startup file passed to the executable. It is resolved relative to workdir.

  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:

Notes

run() and run_async() do not build input files. Use InputBuilder first when starting from EDI data. The optional max_iter and target_misfit arguments to run() patch the startup file in place before launch.

See also

InputBuilder

Builds the data, mesh, model, and startup files.

OccamStartup

Represents startup and iteration parameter vectors.

InversionResult

Loads results produced by a completed run.

Examples

Run a prepared inversion directory synchronously:

>>> from pycsamt.models.occam2d import OccamRunner
>>> runner = OccamRunner(workdir="occam_run")
>>> code = runner.run(max_iter=80, target_misfit=1.0)

Use an explicit executable path:

>>> runner = OccamRunner(
...     workdir="occam_run",
...     binary_path="/usr/local/bin/Occam2D",
... )
>>> runner.discover_binary(auto_compile=False)

Start a background run and wait for completion:

>>> runner = OccamRunner(workdir="occam_run")
>>> process = runner.run_async()
>>> runner.wait()

References

discover_binary(auto_compile=True)#

Locate or compile the Occam2D executable.

The method resolves the executable path and stores it on binary. It first honors the explicit binary_path constructor argument, then checks workdir, then the system PATH. If those fail and auto_compile is True, it calls compile() for the bundled Fortran source.

Parameters:

auto_compile (bool, default True) – If True, attempt to compile the bundled source when no executable is found. Compilation requires make and a Fortran compiler such as gfortran.

Returns:

Resolved path to the executable.

Return type:

pathlib.Path

Raises:
  • FileNotFoundError – Raised when no executable is found and compilation is disabled or does not produce a binary.

  • RuntimeError – Propagated from compile() when the compiler is missing or make fails.

See also

OccamRunner.compile

Compiles the bundled Fortran source.

OccamRunner.run

Calls this method before launching the solver.

Examples

>>> from pycsamt.models.occam2d import OccamRunner
>>> runner = OccamRunner("occam_run")
>>> binary = runner.discover_binary(False)
compile(fc='gfortran', flags='-O2')#

Compile the bundled Occam2D Fortran source.

Compilation is performed in the package _source directory by invoking make with FC90 and FCFLAGS variables. The resulting executable is expected to be named Occam2D there. This method does not copy the binary into workdir; discover_binary() uses that path directly.

Parameters:
  • fc (str, default "gfortran") – Fortran compiler command passed to make as FC90. Use this to select another compiler that understands the bundled source.

  • flags (str, default "-O2") – Compiler flags passed to make as FCFLAGS. Optimization flags are usually sufficient; debug builds can pass flags such as "-g".

Returns:

Path to the compiled binary inside _source.

Return type:

pathlib.Path

Raises:
  • FileNotFoundError – Raised when the source directory is absent.

  • RuntimeError – Raised when the requested compiler is unavailable, make fails, or no executable is produced.

Examples

>>> from pycsamt.models.occam2d import OccamRunner
>>> runner = OccamRunner("occam_run")
>>> binary = runner.compile("gfortran", "-O2")
run(max_iter=None, target_misfit=None, auto_compile=True)#

Run Occam2D synchronously.

This method blocks until the executable exits. It resolves the binary, optionally patches the startup file, launches Occam2D <startup_file> inside workdir, and writes process streams to occam_stdout.log and occam_stderr.log.

Parameters:
  • max_iter (int, optional) – Temporary override for the Iterations to run field in the startup file. The override is written in place before launch, so the file must be writable.

  • target_misfit (float, optional) – Temporary override for the Target Misfit field in the startup file. This changes the run-control file before launch.

  • auto_compile (bool, default True) – Passed to discover_binary(). If True, missing binaries may trigger compilation.

Returns:

Process exit code. A value of 0 indicates that the executable returned successfully.

Return type:

int

Raises:
  • FileNotFoundError – Raised when the binary or patched startup file cannot be found.

  • RuntimeError – Propagated from compilation if automatic compilation fails.

See also

OccamRunner.run_async

Starts the same executable without blocking.

OccamRunner._patch_startup

Applies max_iter and target_misfit.

InversionResult

Loads output files after a successful run.

Examples

>>> from pycsamt.models.occam2d import OccamRunner
>>> runner = OccamRunner(workdir="occam_run")
>>> code = runner.run(max_iter=100, target_misfit=1.0)
run_async(auto_compile=True)#

Start Occam2D in a background process.

The method resolves the binary and launches the solver with subprocess.Popen. It returns immediately with a process handle. Standard output and standard error are redirected to stdout_log and stderr_log.

Parameters:

auto_compile (bool, default True) – Passed to discover_binary(). If True, missing binaries may trigger compilation.

Returns:

Live process handle for the background run.

Return type:

subprocess.Popen

Raises:

See also

OccamRunner.wait

Blocks until the background process completes.

OccamRunner.is_running

Reports whether the process is still active.

Examples

>>> from pycsamt.models.occam2d import OccamRunner
>>> runner = OccamRunner(workdir="occam_run")
>>> process = runner.run_async()
>>> runner.is_running
wait()#

Block until the asynchronous run finishes.

Returns:

Exit code returned by the background process.

Return type:

int

Raises:

RuntimeError – Raised when no process has been started with run_async().

property is_running: bool#

Whether an asynchronous Occam2D process is active.

class pycsamt.models.occam2d.InversionResult(workdir='.', iteration=None, **kwargs)#

Bases: OccamBase

Load and summarize a completed Occam2D inversion run.

InversionResult is the post-processing access layer for an Occam2D working directory. It scans the directory for input and output files, loads the selected iteration, matches the response file, reads the log, and builds a two-dimensional log10-resistivity grid on the mesh.

The reconstruction maps the iteration parameter vector to model layers and mesh cells. If \(m_j\) is the log10-resistivity value assigned to model parameter \(j\), then the physical resistivity represented by a cell in that parameter group is

\[\rho_j = 10^{m_j}.\]

The stored rho_2d array keeps \(m_j\), not \(\rho_j\), because Occam iteration files store log10-resistivity values.

Parameters:
  • workdir (path-like, default ".") – Directory produced by an Occam2D run. It should contain an Occam2DMesh file, an Occam2DModel file, a data file, a log file, .iter files, and matching .resp files.

  • iteration (int or None, default None) – Iteration number to load. If None, the highest numbered .iter file is selected. If the requested iteration is unavailable, the loader falls back to the last available iteration file.

  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:
  • workdir (pathlib.Path) – Directory scanned by the loader.

  • log (OccamLog or None) – Parsed convergence log when a log file is found.

  • mesh (OccamMesh or None) – Parsed finite-element mesh.

  • model (OccamModel or None) – Parsed model-parameter definition.

  • best_iter (OccamIter or None) – Selected iteration file. The name is kept for backward compatibility; it may be the requested iteration or last available iteration.

  • response (OccamResponse or None) – Response file matching the selected iteration when available. If no exact match exists, the loader falls back to the last response file.

  • data (OccamData or None) – Parsed observed-data file when available.

  • iter_files (list of pathlib.Path) – All .iter files found in workdir, sorted by embedded iteration number.

  • resp_files (list of pathlib.Path) – All .resp files found in workdir, sorted by embedded iteration number.

  • rho_2d (numpy.ndarray of float or None) – Log10-resistivity grid with shape (mesh.n_zcells, mesh.n_xcells). Cells outside the model domain are stored as nan.

Notes

The loader is deliberately tolerant. Missing optional files leave corresponding attributes as None instead of failing immediately. A missing working directory still raises NotADirectoryError because there is no useful scan to perform.

See also

OccamRunner

Runs the executable that produces result files.

OccamLog

Parses convergence information loaded here.

OccamResponse

Parses modeled responses and weighted residuals.

PlotModel

Visualizes the reconstructed model grid.

Examples

Load the latest available iteration:

>>> from pycsamt.models.occam2d import InversionResult
>>> result = InversionResult(workdir="occam_run")
>>> result.final_rms

Load a specific iteration and export the model grid:

>>> result = InversionResult("occam_run", iteration=17)
>>> result.iter2dat("occam_run/final_model.dat")

Access loaded components directly:

>>> result.mesh.n_xcells
>>> result.response.rms

References

iter2dat(output_file)#

Write the selected model as a three-column ASCII file.

The exported file contains one row for each finite cell in rho_2d. Columns are x_center, z_center, and log10_rho. Horizontal coordinates are centered around the profile midpoint and depths are positive downward.

This format is useful for external plotting tools and for workflows that expect Bo Yang-style iter2dat output. The values remain in log10-resistivity units:

\[m = \log_{10}(\rho).\]
Parameters:

output_file (path-like) – Destination path for the exported ASCII model. Parent directories are created when needed.

Returns:

Path to the file that was written.

Return type:

pathlib.Path

Raises:

RuntimeError – Raised when the result is not fully loaded and the mesh or reconstructed grid is unavailable.

See also

InversionResult.rho_2d

Grid used to generate the exported values.

PlotModel

Visualizes the same reconstructed model grid.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> result = InversionResult("occam_run")
>>> out = result.iter2dat("occam_run/final_model.dat")
plot_model(**kwargs)#

Plot the reconstructed 2-D resistivity model.

plot_response(**kwargs)#

Plot observed and modeled response curves.

plot_misfit(**kwargs)#

Plot RMS misfit as a function of iteration.

plot_pseudo(**kwargs)#

Plot an observed-data pseudosection.

property final_rms: float#

RMS misfit of the selected iteration.

property n_iterations: int#

Number of iteration files discovered in workdir.

summary()#

Return a short text summary of the loaded inversion.

Return type:

str

class pycsamt.models.occam2d.OccamData(title='pycsamt Occam2D data file', config=None, **kwargs)#

Bases: OccamBase

Represent an Occam2D magnetotelluric data file.

OccamData stores the station list, profile offsets, global frequency table, data-type codes, datum values, and uncertainty values written to OccamDataFile.dat. The object is both a container for parsed files and the product of EDI conversion by from_edi().

The Occam2D data file uses one row for each datum. Apparent resistivity is stored in logarithmic form, while phase is stored in degrees:

\[d_\rho = \log_{10}(\rho_a), \qquad \sigma_d = \frac{\sigma_\rho}{\ln(10)} .\]

For PyCSAMT EDI arrays, TE mode is taken from \(Z_{xy}\) and TM mode is taken from \(Z_{yx}\). TM phase is shifted by \(180^\circ\) so passive-MT \(Z_{yx}\) phases are written in the first quadrant.

Parameters:
  • title (str, default "pycsamt Occam2D data file") – Free-text title written into the Occam data-file header. Use it to record survey name, processing version, inversion purpose, or other provenance attached to the generated OccamDataFile.dat.

  • config (OccamConfig, optional) – Configuration object controlling data selection, mesh geometry, startup controls, file names, and executable discovery. It centralizes choices such as modes, error floors, frequency limits, layer counts, cell sizes, target misfit, starting resistivity, and Occam file names. If omitted, a default OccamConfig is created.

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

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Pass an explicit logger when integrating Occam2D objects into an application-level logging setup.

Variables:
  • format_str (str) – Occam format tag. The current writer uses "OCCAM2MTDATA_1.0".

  • title (str) – Free-text title written to the data-file header.

  • config (OccamConfig) – Configuration used for default modes, frequency limits, and error floors during EDI conversion.

  • sites (list of str) – Station names ordered along the profile. The same order is used by mesh construction and all one-based site indices.

  • offsets (numpy.ndarray of float, shape (n_sites,)) – Station chainages in metres. Values are sorted from low to high during from_edi().

  • frequencies (numpy.ndarray of float, shape (n_frequencies,)) – Global frequency table in hertz, sorted from high to low as expected by Occam2D.

  • data_blocks (numpy.ndarray of float, shape (n_data, 5)) – Data rows with columns site_index, freq_index, type_code, datum, and error. Indices are one-based because they are written directly to Occam files.

Notes

Occam2D type codes distinguish both data kind and component. The common MT rows are 1 for RhoTE, 2 for PhsTE, 5 for RhoTM, and 6 for PhsTM. Additional impedance and tipper codes are exposed through DATA_TYPE_CODES for readers and future writers.

See also

OccamConfig

Supplies default modes, frequency bounds, and error floors.

OccamMesh.from_data

Builds mesh geometry from station offsets in OccamData.

OccamResponse

Reads modeled responses and residuals for the same rows.

InputBuilder

Coordinates writing data, mesh, model, and startup files.

Examples

Build a data file from EDI sites and write it to disk:

>>> from pycsamt.models.occam2d import OccamData
>>> from pycsamt.site import Sites
>>> sites = Sites.from_dir("edi")
>>> data = OccamData.from_edi(sites, modes=["TE", "TM"])
>>> data.write("occam_run/OccamDataFile.dat")

Create a synthetic container for tests or scripted workflows:

>>> import numpy as np
>>> from pycsamt.models.occam2d import OccamData
>>> data = OccamData(title="synthetic profile")
>>> data.sites = ["S00", "S01"]
>>> data.offsets = np.array([0.0, 1000.0])
>>> data.frequencies = np.array([100.0, 10.0])
>>> data.data_blocks = np.array([[1, 1, 1, 2.0, 0.05]])

Read an existing Occam data file:

>>> from pycsamt.models.occam2d import OccamData
>>> data = OccamData.read("occam_run/OccamDataFile.dat")
>>> data.n_sites, data.n_frequencies, data.n_data

References

classmethod from_edi(source, modes=None, config=None, title='pycsamt Occam2D data file', **kwargs)#

Build an Occam data object from EDI-derived stations.

This constructor normalizes the accepted input source to a list of site-like objects, estimates station chainages, merges all available frequencies into a common descending frequency table, applies frequency limits, and writes TE/TM apparent-resistivity and phase rows using Occam type codes.

The EDI arrays are interpreted with the convention

\[\mathrm{TE} = Z_{xy}, \qquad \mathrm{TM} = Z_{yx} .\]

For each accepted apparent-resistivity value \(\rho_a\), the stored datum is \(\log_{10}(\rho_a)\). The relative resistivity floor is converted to log10 uncertainty by \(\sigma_d=\sigma_\rho/\ln(10)\). Phase rows use degree errors and the TM phase is shifted by \(180^\circ\).

Parameters:
  • source (Sites, EDICollection, or iterable) – EDI-derived survey source used to build the Occam data file. Accepted inputs include pycsamt.site.Sites, an EDI collection, or any iterable of site-like objects. Each item must expose frequency, apparent resistivity, and phase arrays. Coordinates are strongly preferred because they allow station offsets to be ordered along profile. When coordinates are absent, fallback spacing is used.

  • modes (list of str, optional) – Electromagnetic modes written to the data file. Supported values are "TE" for the \(Z_{xy}\) component and "TM" for the \(Z_{yx}\) component. Both apparent resistivity and phase rows are written for each selected mode. If omitted, config.modes is used.

  • config (OccamConfig, optional) – Configuration object controlling data selection, mesh geometry, startup controls, file names, and executable discovery. It centralizes choices such as modes, error floors, frequency limits, layer counts, cell sizes, target misfit, starting resistivity, and Occam file names. If omitted, a default OccamConfig is created.

  • title (str, default "pycsamt Occam2D data file") – Free-text title written into the Occam data-file header. Use it to record survey name, processing version, inversion purpose, or other provenance attached to the generated OccamDataFile.dat.

  • **kwargs – Additional keyword arguments passed to the OccamData constructor. This is commonly used for verbose or logger when progress messages are desired.

Returns:

Populated data object ready to be written as an OCCAM2MTDATA_1.0 file.

Return type:

OccamData

Raises:

ValueError – Raised when the source has no sites, no frequency arrays, no frequencies remain after filtering, or no requested mode is supported.

See also

OccamConfig

Provides default modes, frequency bounds, and error floors.

OccamData.write

Serializes the returned object to OccamDataFile.dat.

OccamMesh.from_data

Uses the returned station offsets to build mesh geometry.

Examples

Build TE and TM rows from a site collection:

>>> from pycsamt.models.occam2d import OccamData
>>> from pycsamt.site import Sites
>>> sites = Sites.from_dir("edi")
>>> data = OccamData.from_edi(sites, modes=["TE", "TM"])

Restrict the frequency range through OccamConfig:

>>> from pycsamt.models.occam2d import OccamConfig
>>> from pycsamt.models.occam2d import OccamData
>>> cfg = OccamConfig(freq_min=0.1, freq_max=1000.0)
>>> data = OccamData.from_edi(sites, config=cfg)

Use only TM data with stronger phase floor:

>>> cfg = OccamConfig(modes=["TM"], error_floor_phase=1.0)
>>> data = OccamData.from_edi(sites, config=cfg)

References

classmethod read(path, **kwargs)#

Read an existing OCCAM2MTDATA_1.0 file.

The parser reads the format tag, title, station names, offsets, frequency table, and numeric data block. Site and frequency indices are kept in the one-based form used by Occam2D so a read-write round trip preserves the original file structure.

Parameters:
  • path (path-like) – Path to an Occam2D input or output file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path. Relative paths are interpreted from the current working directory of the Python process. Readers require the file to exist, while writers create parent directories when the owning method supports output.

  • **kwargs – Additional keyword arguments forwarded to the OccamData constructor before parsed values are attached. Use this for config, verbose, or logger.

Returns:

Parsed data-file container with arrays populated from path.

Return type:

OccamData

Raises:
  • FileNotFoundError – Raised when path does not exist.

  • ValueError – Raised when the format tag is missing or not "OCCAM2MTDATA_1.0".

Examples

>>> from pycsamt.models.occam2d import OccamData
>>> data = OccamData.read("occam_run/OccamDataFile.dat")
>>> data.type_codes
write(path)#

Write this object as an OCCAM2MTDATA_1.0 file.

The writer serializes the current title, station list, offsets, frequency table, and data rows using the Occam2D text layout. Parent directories are created before writing. The method does not modify the object, so it can be used repeatedly for round-trip checks or alternative run directories.

Parameters:

path (path-like) – Path to an Occam2D input or output file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path. Relative paths are interpreted from the current working directory of the Python process. Readers require the file to exist, while writers create parent directories when the owning method supports output.

Returns:

Path to the file that was written.

Return type:

pathlib.Path

See also

OccamData.read

Parses a file written by this method.

InputBuilder.build

Calls this method as part of complete input generation.

Examples

>>> from pycsamt.models.occam2d import OccamData
>>> data = OccamData.read("source/OccamDataFile.dat")
>>> written = data.write("copy/OccamDataFile.dat")
property n_sites: int#
property n_frequencies: int#
property n_data: int#
property type_codes: ndarray#

Unique data-type codes present in this dataset.

class pycsamt.models.occam2d.OccamMesh(config=None, **kwargs)#

Bases: OccamBase

Represent the Occam2D PW2D finite-element mesh.

OccamMesh stores the two-dimensional grid consumed by the Occam2D forward solver. Horizontal cell widths define the profile direction. Vertical widths define air and earth layers, and character rows mark whether cells are fixed, air, or boundary cells in the PW2D mesh format.

Node coordinates are cumulative sums of cell widths:

\[x_j = \sum_{i=0}^{j-1} \Delta x_i, \qquad z_k = \sum_{i=0}^{k-1} \Delta z_i.\]

Depth \(z\) is positive downward. Mesh construction uses station offsets from OccamData, horizontal padding on both profile ends, optional air layers, and a geometrically expanding earth-layer thickness sequence.

Parameters:
  • config (OccamConfig, optional) – Configuration object controlling the number of active layers, number of air layers, near-surface cell sizes, depth scaling, and horizontal padding. If omitted, a default OccamConfig is created.

  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:
  • comment (str) – First line of the mesh file, usually a provenance comment beginning with "MESH FILE".

  • x_widths (numpy.ndarray of float, shape (n_xcells,)) – Horizontal cell widths in metres.

  • z_widths (numpy.ndarray of float, shape (n_zcells,)) – Vertical layer thicknesses in metres.

  • x_nodes (numpy.ndarray of float, shape (n_xcells + 1,)) – Cumulative horizontal node positions in metres.

  • z_nodes (numpy.ndarray of float, shape (n_zcells + 1,)) – Cumulative depth node positions in metres, positive downward.

  • cell_rows (list[str]) – Raw PW2D cell-type rows. Each character encodes the cell type at one horizontal position. The "?" character marks cells that may contribute to free inversion parameters.

  • n_airlayers (int) – Number of rows treated as air layers.

Notes

The mesh file stores widths rather than absolute node coordinates. x_nodes and z_nodes are reconstructed by cumulative summation when reading or building a mesh. The generated mesh uses seven padding cells on each side to match the boundary-column code used by OccamModel.from_mesh().

See also

OccamData

Provides station offsets used to build the mesh.

OccamModel.from_mesh

Converts mesh cells into inversion-parameter columns.

InputBuilder

Builds data, mesh, model, and startup files together.

Examples

Build a mesh from an Occam data file:

>>> from pycsamt.models.occam2d import OccamData
>>> from pycsamt.models.occam2d import OccamMesh
>>> data = OccamData.read("occam_run/OccamDataFile.dat")
>>> mesh = OccamMesh.from_data(data)
>>> mesh.write("occam_run/Occam2DMesh")

Read an existing PW2D mesh:

>>> from pycsamt.models.occam2d import OccamMesh
>>> mesh = OccamMesh.read("occam_run/Occam2DMesh")
>>> mesh.n_xcells, mesh.n_zcells

References

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

Build a PW2D mesh from Occam data offsets.

The method creates a finite-element mesh spanning the profile described by data.offsets. It uses seven padding cells on each side, station-zone cells near the configured horizontal cell size, optional air layers, and geometrically expanding earth layers.

The horizontal padding is chosen to match the boundary columns used by OccamModel.from_mesh(). Interior station-zone cells are adjusted so the number of cells remains compatible with the model parameter grouping.

Parameters:
  • data (OccamData) – Populated data object. Its offsets array must contain station chainages in metres. Offsets are sorted before mesh construction.

  • config (OccamConfig, optional) – Configuration object controlling mesh geometry. The builder uses cell_size_horizontal, n_airlayers, n_layers, cell_size_vertical_top, and depth_scale. If omitted, a default OccamConfig is created.

  • **kwargs – Additional keyword arguments forwarded to the OccamMesh constructor. Use this for verbose or logger.

Returns:

Mesh object ready to be written as Occam2DMesh or passed to OccamModel.from_mesh().

Return type:

OccamMesh

Raises:

ValueError – Raised when the data object contains no station offsets.

See also

OccamData.from_edi

Creates the offsets used by this method.

OccamModel.from_mesh

Builds the inversion-parameter mapping.

Examples

>>> from pycsamt.models.occam2d import OccamData
>>> from pycsamt.models.occam2d import OccamMesh
>>> data = OccamData.read("OccamDataFile.dat")
>>> mesh = OccamMesh.from_data(data)
>>> mesh.n_airlayers
classmethod read(path, **kwargs)#

Read an existing Occam2DMesh PW2D file.

The reader parses the comment line, control line, horizontal widths, vertical widths, air-layer count, and cell-type character rows. Node arrays are rebuilt from cumulative sums of widths.

Parameters:
  • path (path-like) – Path to the mesh file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

  • **kwargs – Additional keyword arguments forwarded to the OccamMesh constructor before parsed values are attached. Use this for config, verbose, or logger.

Returns:

Parsed mesh container with widths, nodes, and cell rows populated.

Return type:

OccamMesh

Raises:
  • FileNotFoundError – Raised when path does not exist.

  • ValueError – Raised when the file is too short or the control line cannot be parsed.

Examples

>>> from pycsamt.models.occam2d import OccamMesh
>>> mesh = OccamMesh.read("occam_run/Occam2DMesh")
>>> mesh.x_nodes.shape
write(path)#

Write this mesh in PW2D format.

The writer serializes the current comment, control values, horizontal widths, vertical widths, and cell-type rows to the native Occam2D mesh format. Parent directories are created before writing.

Parameters:

path (path-like) – Destination path for the mesh file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

Returns:

Path to the file that was written.

Return type:

pathlib.Path

See also

OccamMesh.read

Parses mesh files written by this method.

InputBuilder.build

Calls this method during input-file generation.

Examples

>>> from pycsamt.models.occam2d import OccamMesh
>>> mesh = OccamMesh.read("source/Occam2DMesh")
>>> written = mesh.write("copy/Occam2DMesh")
property n_xcells: int#

Number of horizontal cells.

property n_zcells: int#

Number of vertical layers.

property n_params: int#

Number of free model parameters (cells coded as '?').

class pycsamt.models.occam2d.OccamModel(name='MODEL MADE BY PYCSAMT', description='SMOOTH INVERSION', config=None, **kwargs)#

Bases: OccamBase

Represent the Occam2D model-parameter definition.

OccamModel links a finite-element OccamMesh to the inversion parameter vector used by Occam2D. The model file does not store resistivity values. Instead, it defines how mesh cells are grouped into free or fixed parameters. The startup and iteration files then store one value for each parameter counted by n_params.

Each model layer contains integer column codes. Boundary code 7 marks fixed edge columns tied to the binding value, while active even codes represent free inversion columns [1]_. If \(p_j\) is the code for one model column, then the number of mesh cells represented by that column is encoded by the code value itself. The PyCSAMT builder uses 2 for interior columns and 7 for the two boundary columns:

\[\mathbf{p} = [7,\;2,\;2,\;\ldots,\;2,\;7].\]
Parameters:
  • name (str, default "MODEL MADE BY PYCSAMT") – Model name written to the Model Name header field. Use this for a short label that identifies the model family, processing run, or inversion setup.

  • description (str, default "SMOOTH INVERSION") – Description written to the Description header field. It is intended for human-readable provenance and is preserved when the model is written to disk.

  • config (OccamConfig, optional) – Configuration object used for default file names and related Occam2D settings. If omitted, a default OccamConfig is created.

  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:
  • format_str (str) – Occam model format tag. The writer uses "OCCAM2MTMOD_1.0".

  • name (str) – Model name written to the file header.

  • description (str) – Human-readable model description.

  • config (OccamConfig) – Configuration used by this object.

  • mesh_file (str) – Filename of the associated mesh used by the model file, usually "Occam2DMesh".

  • mesh_type (str) – Mesh type string written to the header. Occam2D PW2D meshes use "PW2D".

  • statics_file (str) – Optional static-shift file. The default "none" means no static correction file is referenced.

  • prejudice_file (str) – Optional prejudice model file. The default "none" means no prejudice file is referenced.

  • binding_offset (float, default 0.0) – Horizontal offset of the binding column. This is the reference value used by boundary columns.

  • n_layers (int) – Number of active model layers after the header. It is normally the number of non-air mesh rows.

  • layers (list of dict) –

    Per-layer parameter specification. Each entry has the following keys:

    n_mergeint

    Number of mesh z-rows merged into this layer.

    n_colsint

    Number of model columns in this layer.

    paramsnumpy.ndarray of int, shape (n_cols,)

    Parameter codes for each model column. Code 7 marks a boundary column; active even values mark free inversion parameters.

  • n_exceptions (int) – Number of exception records at the end of the model file. PyCSAMT currently writes 0.

Notes

n_params is the sum of n_cols over all model layers. This value must match the Param Count in the startup and iteration files. n_free_params excludes boundary columns with code 7.

See also

OccamMesh

Defines finite-element cells grouped by this model.

OccamStartup.from_model

Creates an initial vector with matching size.

InputBuilder

Builds data, mesh, model, and startup files together.

Examples

Build a model definition from an existing mesh:

>>> from pycsamt.models.occam2d import OccamMesh
>>> from pycsamt.models.occam2d import OccamModel
>>> mesh = OccamMesh.read("occam_run/Occam2DMesh")
>>> model = OccamModel.from_mesh(mesh)
>>> model.n_params

Read and write an existing model file:

>>> from pycsamt.models.occam2d import OccamModel
>>> model = OccamModel.read("occam_run/Occam2DModel")
>>> model.write("copy/Occam2DModel")

Create a custom empty container for tests:

>>> from pycsamt.models.occam2d import OccamModel
>>> model = OccamModel(name="SYNTHETIC MODEL")
>>> model.n_layers, model.n_params

References

classmethod from_mesh(mesh, config=None, **kwargs)#

Build a model definition from a populated mesh.

The method converts a finite-element mesh into the column mapping required by OCCAM2MTMOD_1.0. Air rows are ignored. Each remaining earth row becomes one model layer with n_merge = 1. Horizontally, the model uses fixed boundary columns and active interior columns:

\[\mathbf{p} = [7,\;2,\;2,\;\ldots,\;2,\;7].\]

The leading and trailing 7 codes represent seven mesh cells each at the profile boundaries. Interior 2 codes represent two mesh cells per free model column. Therefore the total horizontal cell count is

\[n_x = 7 + 2n_i + 7,\]

where \(n_i\) is the number of interior model columns. Meshes built by OccamMesh.from_data() are constructed to satisfy this layout.

Parameters:
  • mesh (OccamMesh) – Populated mesh object defining horizontal and vertical finite-element cells. It must provide n_xcells, n_zcells, and n_airlayers. Air layers are excluded from the model; all other z-cells become inversion layers.

  • config (OccamConfig, optional) – Configuration object used for file names and related Occam2D defaults. If omitted, a default OccamConfig is created.

  • **kwargs – Additional keyword arguments forwarded to the OccamModel constructor. This is commonly used for name, description, verbose, or logger.

Returns:

Model-definition object ready to be written as an Occam2DModel file. The returned object has n_layers equal to the number of active earth rows and layers populated with parameter-code arrays.

Return type:

OccamModel

Raises:

ValueError – Raised when the mesh has no active earth layers or fewer than fourteen horizontal cells. Fourteen cells are required for the two seven-cell boundary columns.

See also

OccamMesh.from_data

Builds meshes that match this parameterization.

OccamModel.write

Serializes the returned model definition.

OccamStartup.from_model

Creates a startup vector with matching parameter count.

Examples

Build a model from a mesh read from disk:

>>> from pycsamt.models.occam2d import OccamMesh
>>> from pycsamt.models.occam2d import OccamModel
>>> mesh = OccamMesh.read("occam_run/Occam2DMesh")
>>> model = OccamModel.from_mesh(mesh)
>>> model.n_layers

Pass metadata through to the model header:

>>> model = OccamModel.from_mesh(
...     mesh,
...     name="PROFILE A MODEL",
...     description="smooth TE-TM inversion",
... )
classmethod read(path, **kwargs)#

Read an existing OCCAM2MTMOD_1.0 model file.

The reader parses the model header and the per-layer parameter-code blocks. Numeric header values are cast to int or float where appropriate. Layer params arrays are stored as numpy.int32 for comparison with generated model mappings.

Parameters:
  • path (path-like) – Path to an Occam2D model file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

  • **kwargs – Additional keyword arguments forwarded to the OccamModel constructor before parsed values are attached. Use this for config, verbose, or logger.

Returns:

Parsed model-definition container with header fields and layer mappings populated from path.

Return type:

OccamModel

Raises:
  • FileNotFoundError – Raised when path does not exist.

  • ValueError – Raised when the format tag is missing or is not "OCCAM2MTMOD_1.0".

See also

OccamModel.write

Writes model definitions in the same format.

OccamStartup.read

Reads startup or iteration files that depend on the same parameter count.

Examples

>>> from pycsamt.models.occam2d import OccamModel
>>> model = OccamModel.read("occam_run/Occam2DModel")
>>> model.n_layers, model.n_params
write(path)#

Write this model in OCCAM2MTMOD_1.0 format.

The writer serializes the current header fields and layer mappings to the Occam2D model layout. Parent directories are created before writing. The object is not modified, so the same instance can be written to multiple run directories.

Parameters:

path (path-like) – Destination path for the model file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

Returns:

Path to the file that was written.

Return type:

pathlib.Path

See also

OccamModel.read

Parses model files written by this method.

InputBuilder.build

Calls this method during input generation.

Examples

>>> from pycsamt.models.occam2d import OccamModel
>>> model = OccamModel.read("source/Occam2DModel")
>>> written = model.write("copy/Occam2DModel")
property n_params: int#

Total model cells, equal to iter Param Count.

property n_free_params: int#

Number of free (non-boundary) model cells.

class pycsamt.models.occam2d.OccamStartup(config=None, description='startup created by pycsamt', **kwargs)#

Bases: OccamBase

Represent an Occam2D startup control file.

OccamStartup stores the iteration-zero OCCAMITER_FLEX file passed to the Occam2D executable. It defines run controls, file references, inversion options, and the initial model vector. Unlike .iter files produced by the solver, a valid startup file has Iteration: 0.

The startup parameter vector is initialized as a uniform half-space:

\[m_i = \log_{10}(\rho_0), \qquad i = 1, \ldots, N_p.\]

Here \(\rho_0\) is config.initial_rho and \(N_p\) is the number of model parameters defined by OccamModel.

Parameters:
  • config (OccamConfig, optional) – Configuration object providing file names, inversion controls, starting resistivity, target misfit, roughness settings, and debug level. If omitted, a default OccamConfig is created.

  • description (str, default "startup created by pycsamt") – Description written to the Description header. Use it to record the purpose or provenance of the run.

  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:
  • format_str (str) – File format tag, always "OCCAMITER_FLEX".

  • description (str) – Human-readable startup description.

  • model_file (str) – Model file name referenced by the startup file.

  • data_file (str) – Data file name referenced by the startup file.

  • datetime_str (str) – Creation or file timestamp string.

  • max_iterations (int) – Maximum number of iterations requested from Occam2D.

  • target_misfit (float) – Target normalized RMS misfit.

  • roughness_type (int) – Roughness penalty type written to the startup file.

  • diagonal_penalties (int) – Flag controlling diagonal roughness penalties.

  • stepsize_cut_count (int) – Maximum number of step-size cuts in a line search.

  • debug_level (int) – Debug verbosity passed to the Fortran executable.

  • iteration (int) – Always 0 for a valid Startup file.

  • lagrange_value (float) – Initial Lagrange multiplier written as Lagrange Value.

  • roughness_value (float) – Initial roughness value written before the first run.

  • misfit_value (float) – Initial misfit value written before the first run.

  • misfit_reached (bool) – Whether the target misfit has already been reached. Startup files normally use False.

  • n_params (int) – Number of model parameters. This must match the model file and the length of param_values.

  • param_values (numpy.ndarray of float, shape (n_params,)) – Initial log10-resistivity values. Values are uniform after from_model() and equal to log10(config.initial_rho).

Notes

OccamStartup writes the same flexible iteration format that Occam later uses for .iter files. The distinction is semantic: startup files carry Iteration: 0 and are input to the solver, while OccamIter files carry non-zero iteration numbers and are output from the solver.

See also

OccamModel

Provides the parameter count for the startup vector.

OccamIter

Reads iteration files produced after running Occam2D.

OccamRunner

Launches the executable with this startup file.

Examples

Build a startup file from a model definition:

>>> from pycsamt.models.occam2d import OccamModel
>>> from pycsamt.models.occam2d import OccamStartup
>>> model = OccamModel.read("occam_run/Occam2DModel")
>>> startup = OccamStartup.from_model(model)
>>> startup.write("occam_run/Startup")

Read an existing startup file:

>>> from pycsamt.models.occam2d import OccamStartup
>>> startup = OccamStartup.read("occam_run/Startup")
>>> startup.n_params

References

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

Build a startup object from a model definition.

The method uses model.n_params to size the startup vector and fills every entry with the log10 value of starting half-space resistivity:

\[m_i = \log_{10}(\rho_0), \qquad i = 1,\ldots,N_p.\]

This produces the standard smooth-inversion initial model: a homogeneous half-space whose value is later updated by the Occam solver.

Parameters:
  • model (OccamModel) – Populated model-definition object. It must contain at least one parameter so the vector can be sized consistently with the Occam2DModel file.

  • config (OccamConfig, optional) – Configuration object providing initial_rho, model and data file names, iteration controls, and inversion settings. If omitted, a default OccamConfig is created.

  • **kwargs – Additional keyword arguments forwarded to the OccamStartup constructor. Use this for description, verbose, or logger.

Returns:

Startup object with n_params and uniform param_values populated.

Return type:

OccamStartup

Raises:

ValueError – Raised when model.n_params is not positive.

See also

OccamStartup.write

Serializes the generated startup object.

OccamModel

Supplies the parameter count used here.

Examples

>>> from pycsamt.models.occam2d import OccamModel
>>> from pycsamt.models.occam2d import OccamStartup
>>> model = OccamModel.read("occam_run/Occam2DModel")
>>> startup = OccamStartup.from_model(model)
>>> startup.param_values.shape
classmethod read(path, **kwargs)#

Read an Occam2D startup file.

The reader parses an OCCAMITER_FLEX file and then validates that its Iteration header is zero. Use OccamIter.read() for non-zero iteration files produced by the solver.

Parameters:
  • path (path-like) – Path to the startup file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

  • **kwargs – Additional keyword arguments forwarded to the OccamStartup constructor before parsed values are attached.

Returns:

Parsed startup object with header fields and parameter vector populated.

Return type:

OccamStartup

Raises:
  • FileNotFoundError – Raised when path does not exist.

  • ValueError – Raised when the file is not OCCAMITER_FLEX or has a non-zero iteration number.

Examples

>>> from pycsamt.models.occam2d import OccamStartup
>>> startup = OccamStartup.read("occam_run/Startup")
>>> startup.iteration
write(path)#

Write this startup file in OCCAMITER_FLEX format.

Parameters:

path (path-like) – Destination path for the startup file. Parent directories are created when needed.

Returns:

Path to the file that was written.

Return type:

pathlib.Path

See also

OccamStartup.read

Parses files written by this method.

OccamRunner

Passes the written startup file to the executable.

class pycsamt.models.occam2d.OccamIter(**kwargs)#

Bases: OccamBase

Represent an Occam2D iteration file.

OccamIter reads OCCAMITER_FLEX files written by the Occam2D executable after one or more inversion iterations. These files have the same structural format as Startup but carry Iteration values greater than zero and store the accepted model vector.

The parameter vector is stored in log10-resistivity units. Physical resistivity is recovered as

\[\rho_i = 10^{m_i},\]

where \(m_i\) is the stored value for parameter \(i\).

Parameters:
  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:
  • format_str (str) – File format tag, usually "OCCAMITER_FLEX".

  • description (str) – Iteration description written by Occam.

  • model_file (str) – Model file referenced by this iteration.

  • data_file (str) – Data file referenced by this iteration.

  • datetime_str (str) – Date and time string written by Occam.

  • max_iterations (int) – Iteration limit stored in the file.

  • target_misfit (float) – Target normalized RMS misfit.

  • roughness_type (int) – Roughness penalty type.

  • diagonal_penalties (int) – Diagonal penalty flag.

  • stepsize_cut_count (int) – Maximum number of line-search step-size cuts.

  • debug_level (int) – Debug verbosity setting.

  • iteration (int) – Iteration number. Valid .iter files use values greater than zero.

  • lagrange_value (float) – Lagrange multiplier accepted at this iteration.

  • roughness_value (float) – Model roughness value reported by Occam.

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

  • misfit_reached (bool) – True if the target misfit was achieved.

  • n_params (int) – Number of model parameters.

  • param_values (numpy.ndarray of float, shape (n_params,)) – Accepted log10-resistivity values for this iteration.

See also

OccamStartup

Represents the corresponding iteration-zero file.

InversionResult

Selects iteration files from a run directory.

OccamResponse

Reads the response file for the same iteration.

Examples

Read an iteration file and convert to resistivity:

>>> from pycsamt.models.occam2d import OccamIter
>>> iteration = OccamIter.read("occam_run/ITER17.iter")
>>> rho = iteration.to_resistivity()

Inspect log10-resistivity statistics:

>>> iteration.log10_rho_stats

References

classmethod read(path, **kwargs)#

Read an Occam2D .iter file.

The reader parses an OCCAMITER_FLEX file and validates that the Iteration value is non-zero. Startup files should be loaded with OccamStartup.read().

Parameters:
  • path (path-like) – Path to the iteration file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

  • **kwargs – Additional keyword arguments forwarded to the OccamIter constructor before parsed values are attached.

Returns:

Parsed iteration object with header fields and parameter vector populated.

Return type:

OccamIter

Raises:
  • FileNotFoundError – Raised when path does not exist.

  • ValueError – Raised when the file is not OCCAMITER_FLEX or has Iteration: 0.

Examples

>>> from pycsamt.models.occam2d import OccamIter
>>> iteration = OccamIter.read("ITER17.iter")
>>> iteration.misfit_value
write(path)#

Write this iteration in OCCAMITER_FLEX format.

Parameters:

path (path-like) – Destination path for the iteration file. Parent directories are created when needed.

Returns:

Path to the file that was written.

Return type:

pathlib.Path

to_resistivity()#

Return resistivity values from log10 parameters.

Returns:

Resistivity values in ohm metres computed as \(10^m\), where \(m\) is each element of param_values.

Return type:

numpy.ndarray of float

property log10_rho_stats: dict#

Return summary statistics for log10 resistivity.

class pycsamt.models.occam2d.OccamResponse(**kwargs)#

Bases: OccamBase

Represent an Occam2D response file.

OccamResponse stores the forward response written by the Occam2D executable for one inversion iteration. The response table has one row per datum and seven columns: site index, frequency index, type code, error-floor value, observed datum, modeled datum, and weighted residual.

The response residual is already weighted by the data uncertainty used by Occam. The global RMS misfit is therefore computed directly from the residual column:

\[\mathrm{RMS} = \sqrt{ \frac{1}{N} \sum_{i=1}^{N} r_i^2 },\]

where \(r_i\) is the weighted residual for datum \(i\) and \(N\) is the number of response rows. Values near one are often consistent with data errors that are neither under-estimated nor over-estimated [1]_.

Parameters:
  • verbose (int or bool, default 0) – Verbosity level inherited from OccamBase. Positive values enable progress messages through the instance logger.

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created.

Variables:
  • data (numpy.ndarray of float, shape (n_data, 7)) – Full raw table from the .resp file. Columns are site_index, freq_index, type_code, error_floor, observed, modeled, and residual.

  • observed (numpy.ndarray of float, shape (n_data,)) – Observed data values from column 4. Values follow the datum convention of OccamData: log10 apparent resistivity for rho rows and degrees for phase rows.

  • modeled (numpy.ndarray of float, shape (n_data,)) – Forward-model predictions from column 5, ordered in the same row order as observed.

  • residuals (numpy.ndarray of float, shape (n_data,)) – Weighted residuals from column 6. These values are the residuals used to compute rms.

  • rms (float) – Root-mean-square weighted residual for all response rows. Empty objects use 0.0.

Notes

Response files do not include a header. The parser accepts any line with seven numeric columns and skips non-numeric lines. Site and frequency indices are one-based to match the Occam data file.

See also

OccamData

Defines the observed data rows and type codes.

InversionResult

Loads the response for a selected iteration.

Plot2D.response

Visualizes observed and modeled response curves.

Examples

Read a response file and inspect its global RMS:

>>> from pycsamt.models.occam2d import OccamResponse
>>> response = OccamResponse.read("occam_run/RESP17.resp")
>>> response.rms

Summarize misfit by station and frequency index:

>>> response.misfit_per_site()
>>> response.misfit_per_frequency()

Select phase rows by Occam type code:

>>> phase_tm = response.data[response.data[:, 2] == 6]
>>> phase_tm.shape[0]

References

classmethod read(path, data_fn=None, **kwargs)#

Read an Occam2D response file.

The reader parses seven-column numeric rows from a response file produced by the Occam2D executable. The first three columns are stored in the raw table as floats because the file itself is numeric text, but convenience properties expose site, frequency, and type codes as integers.

Parameters:
  • path (path-like) – Path to the response file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path.

  • data_fn (path-like, optional) – Optional data-file path reserved for consistency checks between observed data rows and response rows. It is currently accepted for API stability but is not used by the parser.

  • **kwargs – Additional keyword arguments forwarded to the OccamResponse constructor. Use this for verbose or logger.

Returns:

Parsed response container with raw data, observed values, modeled values, residuals, and global RMS populated.

Return type:

OccamResponse

Raises:
  • FileNotFoundError – Raised when path does not exist.

  • ValueError – Raised when no valid seven-column numeric response rows can be parsed.

See also

OccamResponse.misfit_per_site

Computes station-index RMS values from residuals.

OccamResponse.misfit_per_frequency

Computes frequency-index RMS values.

Examples

>>> from pycsamt.models.occam2d import OccamResponse
>>> response = OccamResponse.read("RESP17.resp")
>>> response.n_data
>>> response.type_codes
property n_data: int#
property site_indices: ndarray#

1-based site indices (int).

property freq_indices: ndarray#

1-based frequency indices (int).

property type_codes: ndarray#

Unique data-type codes present in this response.

misfit_per_site()#

Return RMS misfit for each site index.

The returned values are computed from the weighted residual column:

\[\mathrm{RMS}_s = \sqrt{ \frac{1}{N_s} \sum_{i \in s} r_i^2 }.\]
Returns:

Mapping from one-based site index to RMS weighted residual. Empty response objects return an empty dictionary.

Return type:

dict of int to float

Examples

>>> from pycsamt.models.occam2d import OccamResponse
>>> response = OccamResponse.read("RESP17.resp")
>>> per_site = response.misfit_per_site()
>>> per_site[1]
misfit_per_frequency()#

Return RMS misfit for each frequency index.

The returned values group residuals by Occam’s one-based frequency index:

\[\mathrm{RMS}_f = \sqrt{ \frac{1}{N_f} \sum_{i \in f} r_i^2 }.\]
Returns:

Mapping from one-based frequency index to RMS weighted residual. Empty response objects return an empty dictionary.

Return type:

dict of int to float

Examples

>>> from pycsamt.models.occam2d import OccamResponse
>>> response = OccamResponse.read("RESP17.resp")
>>> per_freq = response.misfit_per_frequency()
>>> max(per_freq.values())
class pycsamt.models.occam2d.OccamLog(**kwargs)#

Bases: OccamBase

Represent an Occam2D convergence log.

OccamLog parses the text log written by the Occam2D Fortran executable. The file records one block per inversion iteration, including accepted misfit, model roughness, Lagrange multiplier, and line-search step size. Parsed arrays align by index, so iterations[i], rms[i], roughness[i], lagrange[i], and stepsize[i] describe the same iteration.

The main convergence statistic is the normalized RMS data misfit. If \(r_i\) are weighted residuals for \(N\) data, the reported quantity is commonly interpreted as

\[\phi_d = \sqrt{\frac{1}{N}\sum_{i=1}^N r_i^2} .\]

An inversion is usually considered well weighted when \(\phi_d \approx 1\). The practical target still depends on error estimates and modeling assumptions [1]_.

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

  • logger (logging.Logger, optional) – Logger used for progress and diagnostic messages. If omitted, a class-specific PyCSAMT logger is created automatically. Pass an explicit logger when integrating Occam2D objects into an application-level logging setup.

Variables:
  • iterations (ndarray of int, shape (n_iter,)) – One-based iteration numbers parsed from ** ITERATION blocks. The values are preserved as written by Occam.

  • rms (ndarray of float, shape (n_iter,)) – Accepted normalized RMS misfit for each iteration. When an iteration contains repeated search steps, the parser keeps the last AND IS = value in that block.

  • roughness (ndarray of float, shape (n_iter,)) – Model roughness reported by Occam. The final entry may be nan when a run stops before writing ROUGHNESS IS.

  • lagrange (ndarray of float, shape (n_iter,)) – Accepted Lagrange multiplier, \(\mu\), for each iteration. Values are read from MINIMUM TOL FROM or INTERCEPT IS AT MU lines.

  • stepsize (ndarray of float, shape (n_iter,)) – Accepted step size for each iteration. The final entry may be nan if convergence problems stop the run early.

Notes

The parser is intentionally tolerant of Occam2D log variants. It ignores intermediate TOFMU search lines and keeps the last accepted values in each iteration block. This behavior matches logs where divergence problems trigger repeated Lagrange searches before a step is accepted.

See also

OccamRunner

Produces the log file by launching the executable.

InversionResult

Loads logs with model, iteration, and response files.

Plot2D.misfit

Visualizes RMS convergence from an OccamLog object.

Examples

Read a log and inspect the best iteration:

>>> from pycsamt.models.occam2d import OccamLog
>>> log = OccamLog.read("occam_run/LogFile.logfile")
>>> log.best_iteration

Check whether the inversion reached the common RMS target:

>>> log.converged

Print a compact report for scripts:

>>> log.summary()

References

classmethod read(path, **kwargs)#

Read an Occam2D log file.

The reader scans the file line by line with a small state machine. A ** ITERATION line starts a new block and saves the previous block. Within each block, the last accepted RMS, roughness, Lagrange multiplier, and step size are retained.

This is useful for logs where Occam cuts the step size or repeats the Lagrange search. Intermediate trial values are not stored because they do not describe the accepted model.

Parameters:
  • path (path-like) – Path to an Occam2D input or output file. The value may be a string, pathlib.Path, or any object accepted by pathlib.Path. Relative paths are interpreted from the current working directory of the Python process. Readers require the file to exist, while writers create parent directories when the owning method supports output.

  • **kwargs – Additional keyword arguments forwarded to the OccamLog constructor. Use this for verbose or logger when integrating the parser into a larger workflow.

Returns:

Parsed convergence-log container with one array entry per completed iteration block.

Return type:

OccamLog

Raises:

FileNotFoundError – Raised when path does not exist.

See also

OccamLog.summary

Returns a short text summary of convergence.

OccamLog.best_iteration

Reports the iteration with the lowest finite RMS misfit.

Examples

>>> from pycsamt.models.occam2d import OccamLog
>>> log = OccamLog.read("occam_run/LogFile.logfile")
>>> log.n_iter
>>> log.rms[-1]
property n_iter: int#

Number of parsed iterations.

property converged: bool#

True if any iteration achieved RMS ≤ 1.0 (Occam target).

property best_iteration: int#

1-based iteration number with the lowest finite RMS misfit.

summary()#

Return a one-paragraph convergence summary.

Return type:

str

class pycsamt.models.occam2d.PlotModel(result=None, rho_min=1.0, rho_max=1000.0, depth_max=None, show_stations=True, profile_distance_unit='km', section='inversion', **kwargs)#

Bases: _OccamPlotBase

Plot a two-dimensional Occam resistivity model.

PlotModel displays the selected iteration model from InversionResult as a depth section. It replaces plotOccam2DMT.m, and the companion profile extractor replaces ExtractOccam2DMTProfile.m.

Occam iteration files store model parameters as \(\log_{10}\) resistivity. The plot converts them back to ohm metres before drawing:

\[\rho(x, z) = 10^{m(x, z)}.\]

The mesh is centered around the profile midpoint. Depth is positive downward.

Parameters:
  • result (InversionResult) – Loaded result containing rho_2d and mesh. Station markers are drawn when result.data.offsets is available.

  • rho_min (float, default 1.0, 1000.0) – Color-scale limits in ohm metres. They are passed to matplotlib.colors.LogNorm; both values must be positive.

  • rho_max (float, default 1.0, 1000.0) – Color-scale limits in ohm metres. They are passed to matplotlib.colors.LogNorm; both values must be positive.

  • depth_max (float, optional) – Maximum display depth in metres. If omitted, the full mesh depth is shown.

  • show_stations (bool, default True) – If True, overlay station triangles at the surface using the offsets stored in the data file.

  • profile_distance_unit ({"m", "km"}, default "km") – Unit used on the horizontal axis and by extract_profile().

  • figsize (tuple of float, optional) – Matplotlib figure size. The default suits a profile section.

  • cmap (str, default "jet_r") – Colormap used for the resistivity image.

  • dpi (int, default 100) – Figure resolution in dots per inch.

  • section (str | SectionStyle)

Returns:

Figure containing the resistivity model section.

Return type:

matplotlib.figure.Figure

Raises:

RuntimeError – If the result does not contain rho_2d.

plot()#

Return the model section as a Matplotlib figure.

extract_profile(x0, x1)#

Extract centered coordinates, depth centers, and the log10-resistivity grid between x0 and x1.

Parameters:
Return type:

tuple

See also

InversionResult

Reconstructs rho_2d from Occam output files.

PlotSounding1D

Extracts model columns at station positions.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotModel
>>> result = InversionResult("occam_run")
>>> fig = PlotModel(result, depth_max=2000).plot()
>>> plotter = PlotModel(result)
>>> x, z, log_rho = plotter.extract_profile(-1.0, 1.0)

References

plot()#

Return a pcolormesh Figure of the 2-D resistivity model.

Return type:

matplotlib.figure.Figure

extract_profile(x0, x1)#

Extract (x_centers, z_centers, rho_subset) between x0 and x1.

Coordinates use profile_distance_unit. x0 and x1 are in the centered profile frame.

Returns:

(x_centers, z_centers, rho_2d_subset) where rho_2d_subset has shape (n_zcells, n_cols_in_range).

Return type:

tuple

Parameters:
class pycsamt.models.occam2d.PlotResponse(result=None, stations=None, modes=None, period_axis=True, max_stations=9, **kwargs)#

Bases: _OccamPlotBase

Plot observed and modeled Occam response curves.

PlotResponse compares observed data from the Occam file with modeled values from an Occam .resp file. It replaces plotOccam2DMTResponse.m.

Apparent-resistivity rows are stored as log10 values. They are converted before plotting:

\[\rho_a = 10^{d_\rho}.\]

Phase rows are plotted in degrees. The frequency index in the table is mapped back to physical frequency when corresponding OccamData object is available.

Parameters:
  • result (InversionResult) – Loaded result containing response and ideally data. The response must expose the seven-column table.

  • stations (list of str, list of int, or None, default None) – Stations to plot. Strings are matched against result.data.sites. Integers are one-based site indices when names are unavailable. If None, stations are sampled from the response table.

  • modes (list of str, optional) – Electromagnetic modes to draw. Supported values are "TE" and "TM".

  • period_axis (bool, default True) – Reserved for interface clarity. The implementation uses period when frequencies are available and indices otherwise.

  • max_stations (int, default 9) – Maximum number of station columns when stations is None.

  • figsize (tuple of float, optional) – Figure size. If omitted, width scales with station count.

  • cmap (str, default "jet_r") – Stored for a consistent interface. It is not used by this curve plot.

  • dpi (int, default 100) – Figure resolution in dots per inch.

Returns:

Figure with apparent-resistivity and phase panels.

Return type:

matplotlib.figure.Figure

Raises:

RuntimeError – If response data are missing, modes are absent, or no stations can be selected.

See also

PlotResponseGrid

Compact version designed for many stations.

OccamResponse

Reader for the .resp file used by this plot.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotResponse
>>> result = InversionResult("occam_run")
>>> fig = PlotResponse(result, modes=["TM"]).plot()

References

plot()#

Return a Figure with rho_a / phase subplots per station.

Return type:

matplotlib.figure.Figure

class pycsamt.models.occam2d.PlotPseudo(result=None, mode='TM', data_type='rho', **kwargs)#

Bases: _OccamPlotBase

Plot an Occam observed-data pseudosection.

PlotPseudo displays one data component from the Occam data file as a station-period view. It is the Python replacement for plotOccam2DMTPseudo.m.

The horizontal axis is station offset in kilometres when offsets are available. The vertical axis is \(\log_{10}(T)\), where \(T = 1/f\) is period in seconds. Apparent resistivity is converted from log10 storage to ohm metres; phase data remain in degrees.

Parameters:
  • result (InversionResult) – Loaded result containing an OccamData object with data blocks, offsets, and frequencies.

  • mode ({"TE", "TM"}, default "TM") – Electromagnetic mode to display. "TE" maps to codes 1 and 2; "TM" maps to codes 5 and 6.

  • data_type ({"rho", "phase"}, default "rho") – Quantity to display. "rho" selects apparent resistivity; "phase" selects phase.

  • figsize (tuple of float, optional) – Matplotlib figure size.

  • cmap (str, default "jet_r") – Colormap used for the pseudosection.

  • dpi (int, default 100) – Figure resolution in dots per inch.

Returns:

Pseudosection figure.

Return type:

matplotlib.figure.Figure

Raises:
  • RuntimeError – If no data blocks are available or the selected type is not present.

  • ValueError – If mode and data_type are unsupported.

See also

OccamData

Provides the data block for the pseudosection.

PlotSiteMisfit

Builds a residual pseudosection from response values.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotPseudo
>>> result = InversionResult("occam_run")
>>> fig = PlotPseudo(result, mode="TE").plot()
plot()#

Return a pseudosection pcolormesh Figure.

Return type:

matplotlib.figure.Figure

class pycsamt.models.occam2d.PlotMisfit(result=None, show_roughness=True, show_lagrange=False, target_line=True, **kwargs)#

Bases: _OccamPlotBase

Plot Occam2D convergence metrics by iteration.

PlotMisfit visualizes the convergence history stored in an OccamLog attached to an InversionResult. It replaces the MATLAB plotOccamIterMisfit.m view.

The main curve is the normalized root-mean-square data misfit:

\[\mathrm{RMS} = \sqrt{\frac{1}{N}\sum_{i=1}^{N} r_i^2},\]

Here \(r_i\) is the weighted residual for datum i. A run is commonly acceptable when the RMS approaches the target value of 1.0 [1]_.

Parameters:
  • result (InversionResult) – Loaded inversion result. It must expose log with iterations, rms, roughness, lagrange, and n_iter attributes.

  • show_roughness (bool, default True) – If True, add a secondary y-axis for roughness. Roughness is plotted on a log scale because it can vary by several orders of magnitude.

  • show_lagrange (bool, default False) – If True, add a lower panel for the accepted Lagrange multiplier at each iteration.

  • target_line (bool, default True) – If True, draw a dashed line at RMS equal to 1.0.

  • figsize (tuple of float, optional) – Matplotlib figure size passed through the shared base. If omitted, the number of panels controls the size.

  • cmap (str, default "jet_r") – Stored for consistency with other plot classes. It is not used by this line plot.

  • dpi (int, default 100) – Figure resolution in dots per inch.

Returns:

Figure containing the convergence plot.

Return type:

matplotlib.figure.Figure

Raises:

RuntimeError – If result.log is missing or has no iterations.

See also

OccamLog

Parses convergence values from the Occam log file.

InversionResult.plot_misfit

Convenience wrapper that instantiates this class.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotMisfit
>>> result = InversionResult("occam_run")
>>> fig = PlotMisfit(result, show_lagrange=True).plot()

References

plot()#

Return a convergence Figure (RMS ± roughness vs iteration).

Return type:

matplotlib.figure.Figure

class pycsamt.models.occam2d.PlotSounding1D(result=None, stations=None, max_stations=16, depth_max=None, rho_min=1.0, rho_max=1000.0, overlay=False, **kwargs)#

Bases: _OccamPlotBase

Plot station-centered 1-D profiles from a 2-D Occam model.

PlotSounding1D samples the reconstructed 2-D resistivity grid at the mesh column nearest each station. The result is a set of resistivity-depth curves to compare vertical structure below stations.

The plotted resistivity is converted from the log10 grid:

\[\rho(z) = 10^{m(z)}.\]

Air layers are omitted using result.mesh.n_airlayers.

Parameters:
  • result (InversionResult) – Loaded result containing rho_2d, mesh, and data.offsets.

  • stations (list of str or None, default None) – Station names to plot. If None, stations are sampled from all available offsets.

  • max_stations (int, default 16) – Maximum station profiles when stations is None.

  • depth_max (float, optional) – Maximum plotted depth. If omitted, mesh depth controls the lower limit.

  • rho_min (float, default 1.0, 1000.0) – Horizontal resistivity-axis limits in ohm metres.

  • rho_max (float, default 1.0, 1000.0) – Horizontal resistivity-axis limits in ohm metres.

  • overlay (bool, default False) – If True, draw selected profiles on one axis. If False, draw one panel per station.

  • figsize (tuple of float, optional) – Figure size. Defaults depend on station count.

  • cmap (str, default "jet_r") – Stored for interface consistency. Overlay plots use a tabular Matplotlib colormap internally.

  • dpi (int, default 100) – Figure resolution in dots per inch.

Returns:

Resistivity-depth profile figure.

Return type:

matplotlib.figure.Figure

Raises:

RuntimeError – If rho_2d is missing, station offsets are missing, or station selection is empty.

See also

PlotModel.extract_profile

Extracts a horizontal interval from the same grid.

InversionResult

Provides the reconstructed model grid.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotSounding1D
>>> result = InversionResult("occam_run")
>>> fig = PlotSounding1D(result, overlay=True).plot()
plot()#

Return a Figure of 1-D ρ–depth soundings.

Return type:

matplotlib.figure.Figure

class pycsamt.models.occam2d.PlotSiteMisfit(result=None, modes=None, show_residual_map=True, rms_target=1.0, **kwargs)#

Bases: _OccamPlotBase

Plot per-site Occam response misfit diagnostics.

PlotSiteMisfit summarizes the fit between observed and modeled values at each station. The top panel is a bar chart of RMS residual by station and data type. The optional lower panel is a residual pseudosection.

Residuals are normalized by the error column in the Occam response table:

\[r_i = \frac{d_i^{obs} - d_i^{pred}}{\sigma_i}.\]

Per-site RMS values use these normalized residuals. If a response error is non-positive, that residual is ignored.

Parameters:
  • result (InversionResult) – Loaded result containing response. Station labels and frequencies come from result.data.

  • modes (list of str, optional) – Modes included in the summary. Supported values are "TE" and "TM". If omitted, both are used.

  • show_residual_map (bool, default True) – If True, draw the normalized residual map under the bar chart.

  • rms_target (float, default 1.0) – Target RMS value drawn in the bar panel. Use None to omit the target line.

  • figsize (tuple of float, optional) – Figure size. Defaults scale with station count.

  • cmap (str, default "jet_r") – Stored for the shared interface. The residual map uses a diverging colormap.

  • dpi (int, default 100) – Figure resolution in dots per inch.

Returns:

Figure containing per-site RMS diagnostics.

Return type:

matplotlib.figure.Figure

Raises:

RuntimeError – If response data are missing or requested type codes are absent.

See also

OccamResponse.misfit_per_site

Returns a simpler per-site RMS dictionary.

PlotResponseGrid

Shows observed and modeled curves for many stations.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotSiteMisfit
>>> result = InversionResult("occam_run")
>>> fig = PlotSiteMisfit(result).plot()
plot()#

Return a per-site misfit Figure.

Return type:

matplotlib.figure.Figure

class pycsamt.models.occam2d.PlotResponseGrid(result=None, stations=None, n_cols=5, modes=None, max_stations=25, **kwargs)#

Bases: _OccamPlotBase

Plot a compact grid of observed and modeled responses.

PlotResponseGrid is designed to scan many stations. Each station uses two axes: apparent resistivity above and phase below. Observed values are drawn as points and modeled values as lines. Titles include per-site RMS when response errors are available.

Apparent-resistivity values are converted from log10 Occam storage before plotting:

\[\rho_a = 10^{d_\rho}.\]
Parameters:
  • result (InversionResult) – Loaded result with response and ideally data.

  • stations (list of str or None, default None) – Station names to include. If omitted, station indices sampled from the response table.

  • n_cols (int, default 5) – Maximum number of station columns in each grid row.

  • modes (list of str, optional) – Modes to draw. Use "TE", "TM", or both.

  • max_stations (int, default 25) – Maximum station count included when stations is None.

  • figsize (tuple of float, optional) – Figure size. Defaults scale with columns and rows.

  • cmap (str, default "jet_r") – Stored for interface consistency. It is unused by this curve plot.

  • dpi (int, default 100) – Figure resolution in dots per inch.

Returns:

Compact response-grid figure.

Return type:

matplotlib.figure.Figure

Raises:

RuntimeError – If response data or station choices are missing.

See also

PlotResponse

Larger response panels for a smaller station subset.

PlotSiteMisfit

Per-site residual summary from the response table.

Examples

>>> from pycsamt.models.occam2d import InversionResult
>>> from pycsamt.models.occam2d import PlotResponseGrid
>>> result = InversionResult("occam_run")
>>> fig = PlotResponseGrid(result, n_cols=4).plot()
plot()#

Return a compact response-grid Figure.

Return type:

matplotlib.figure.Figure

class pycsamt.models.occam2d.OccamConfig(modes=<factory>, error_floor_rho=0.05, error_floor_phase=0.5, freq_min=None, freq_max=None, n_layers=30, n_airlayers=5, cell_size_horizontal=100.0, cell_size_vertical_top=10.0, depth_scale=1.2, n_padding_x=7, max_iterations=100, target_misfit=1.0, roughness_type=1, diagonal_penalties=0, stepsize_cut_count=8, debug_level=1, initial_rho=100.0, lagrange_start=5.0, data_file='OccamDataFile.dat', mesh_file='Occam2DMesh', model_file='Occam2DModel', startup_file='Startup', binary_name='Occam2D')#

Bases: object

Collect settings that define an Occam2D run.

OccamConfig groups the options shared by the Occam2D builder, file containers, runner, and result loaders. It is a plain dataclass, so users may set fields at construction time or mutate them before calling InputBuilder.

The configuration controls four parts of the workflow:

  • data selection and error floors;

  • mesh geometry and depth discretization;

  • startup and inversion-control values;

  • file names and executable discovery.

Data Options#

modeslist of str, default [“TE”, “TM”]

Electromagnetic modes written to the Occam data file. "TE" selects the \(Z_{xy}\) component and "TM" selects \(Z_{yx}\). Each selected mode writes apparent-resistivity and phase rows.

error_floor_rhofloat

Relative apparent-resistivity error floor. A value of 0.05 means five percent. Because Occam stores apparent resistivity as \(\log_{10}(\rho_a)\), the builder converts this floor before writing data.

error_floor_phasefloat

Absolute phase error floor in degrees. This keeps phase rows with unrealistically small source errors from dominating the normalized data misfit.

freq_minfloat or None

Lower frequency limit in hertz. Frequencies below this value are excluded when built from EDI sources. None leaves the lower bound open.

freq_maxfloat or None

Upper frequency limit in hertz. Frequencies above this value are excluded when built from EDI sources. None leaves the upper bound open.

Mesh Options#

n_layersint

Number of active earth layers below the air layers. Larger values represent more vertical structure but increase the parameter count.

n_airlayersint

Number of air layers above the earth model. These layers stabilize finite-element boundaries near the surface.

cell_size_horizontalfloat

Target horizontal cell width in metres near stations. Smaller values give finer lateral detail and bigger meshes.

cell_size_vertical_topfloat

Thickness, in metres, of the top earth layer and air layers used by the current mesh builder.

depth_scalefloat

Geometric multiplier applied to layer thickness with depth. Values greater than 1 make layers progressively thicker.

n_padding_xint

Number of horizontal padding cells added on each side. Padding moves side boundaries away from the survey profile.

Startup Options#

max_iterationsint

Maximum number of Occam iterations requested in the startup file.

target_misfitfloat

Target normalized RMS misfit. Values near 1.0 are typical when data errors are realistic.

roughness_typeint

Roughness penalty type passed to Occam. A value of 1 selects the standard gradient penalty; 2 selects curvature when supported by the executable.

diagonal_penaltiesint

Flag controlling diagonal roughness penalties in the startup file. 0 disables them.

stepsize_cut_countint

Maximum number of Lagrange step-size reductions allowed during a line-search stage.

debug_levelint

Debug verbosity passed to the Occam executable.

initial_rhofloat

Starting half-space resistivity in ohm metres. The startup vector is initialized as \(\log_{10}\) of this value.

lagrange_startfloat

Initial Lagrange multiplier written to startup.

File Options#

data_filestr

Data filename written inside the run directory.

mesh_filestr

Mesh filename written inside the run directory.

model_filestr

Model filename written inside the run directory.

startup_filestr

Startup filename passed to the Occam executable.

binary_namestr

Executable name searched by OccamRunner.

Notes

InputBuilder.build accepts one-shot overrides for common data and mesh fields. Overrides update the same OccamConfig instance stored on the builder.

Source-Of-Truth Files#

Users can generate an editable configuration file before building an Occam2D run. Python is the default template format because it supports rich inline comments and can be read safely by from_file() using literal parsing. YAML templates also keep comments. JSON templates store explanations in a "_schema" metadata block and editable values under "config" because standard JSON has no comment syntax.

The recommended workflow is:

  1. Generate a template with write_template().

  2. Edit values in the generated file.

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

  4. Pass the resulting configuration to builders and runners.

See also

InputBuilder

Consumes this configuration while writing input files.

OccamData.from_edi

Uses data options to select modes, frequencies, and errors.

OccamMesh.from_data

Uses mesh options to build finite-element geometry.

OccamStartup.from_model

Uses startup options to initialize inversion controls.

OccamRunner

Uses file and binary settings during execution.

Examples

Create a standard configuration for the builder:

>>> from pycsamt.models.occam2d import OccamConfig
>>> from pycsamt.models.occam2d import InputBuilder
>>> cfg = OccamConfig(n_layers=32, target_misfit=1.0)
>>> cfg.error_floor_rho = 0.07
>>> builder = InputBuilder([], workdir="run", config=cfg)

Restrict the frequency band and use only TM mode:

>>> cfg = OccamConfig(modes=["TM"])
>>> cfg.freq_min = 0.1
>>> cfg.freq_max = 1000.0

Configure a finer near-station mesh:

>>> cfg = OccamConfig()
>>> cfg.cell_size_horizontal = 50.0
>>> cfg.cell_size_vertical_top = 5.0
>>> cfg.depth_scale = 1.15

Generate a documented source-of-truth template:

>>> path = OccamConfig.write_template("occam2d_config.py")
>>> cfg = OccamConfig.from_file(path)
>>> cfg.binary_name
'Occam2D'

Use YAML when the configuration will be edited outside Python:

>>> OccamConfig.write_template("occam2d_config.yml")
PosixPath('occam2d_config.yml')

References

modes: list[str]#
error_floor_rho: float = 0.05#
error_floor_phase: float = 0.5#
freq_min: float | None = None#
freq_max: float | None = None#
n_layers: int = 30#
n_airlayers: int = 5#
cell_size_horizontal: float = 100.0#
cell_size_vertical_top: float = 10.0#
depth_scale: float = 1.2#
n_padding_x: int = 7#
max_iterations: int = 100#
target_misfit: float = 1.0#
roughness_type: int = 1#
diagonal_penalties: int = 0#
stepsize_cut_count: int = 8#
debug_level: int = 1#
initial_rho: float = 100.0#
lagrange_start: float = 5.0#
data_file: str = 'OccamDataFile.dat'#
mesh_file: str = 'Occam2DMesh'#
model_file: str = 'Occam2DModel'#
startup_file: str = 'Startup'#
binary_name: str = 'Occam2D'#
to_template(path='occam2d_config.py', *, fmt=None)#

Write this configuration as an editable template.

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

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

Returns:

Path of the generated source-of-truth file.

Return type:

pathlib.Path

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

Write a default editable Occam2D configuration file.

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

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

Returns:

Path of the generated template.

Return type:

pathlib.Path

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

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

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

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

Returns:

Configuration populated from edited file values.

Return type:

OccamConfig

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

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

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

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

Returns:

Configuration populated from edited file values.

Return type:

OccamConfig

Parameters:
  • modes (list[str])

  • error_floor_rho (float)

  • error_floor_phase (float)

  • freq_min (float | None)

  • freq_max (float | None)

  • n_layers (int)

  • n_airlayers (int)

  • cell_size_horizontal (float)

  • cell_size_vertical_top (float)

  • depth_scale (float)

  • n_padding_x (int)

  • max_iterations (int)

  • target_misfit (float)

  • roughness_type (int)

  • diagonal_penalties (int)

  • stepsize_cut_count (int)

  • debug_level (int)

  • initial_rho (float)

  • lagrange_start (float)

  • data_file (str)

  • mesh_file (str)

  • model_file (str)

  • startup_file (str)

  • binary_name (str)