pycsamt.format.adapters.modem3d#

ModEM 3-D -> PCSF adapter (Phase 3 of the PCSF format plan).

Converts a completed pycsamt.models.modem.results.InversionResult (3-D mode) into a backend-neutral PCSFModel with a grid3d geometry — the first genuinely new persisted 3-D volume artifact in the project (see PYCSAMT-PCSF-INVERSION-FORMAT-PLAN.md, §1: nothing else in the codebase currently writes one to disk; the web 3-D view only ever synthesizes a volume at render time from stacked 2-D sections).

Unlike Occam2D, ModEM’s model already carries its own real-world grid centre and rotation when a genuine ModEM run wrote the file — see the origin/rotation_deg attributes added to pycsamt.models.modem.model3d.ModEmModel3D alongside this adapter, which previously parsed and then silently discarded that trailing line.

Functions

modem3d_to_pcsf(result, *[, model, data, ...])

Convert a ModEM 3-D InversionResult to a PCSFModel.

pycsamt.format.adapters.modem3d.modem3d_to_pcsf(result, *, model=None, data=None, station_elevations=None, topo=None, epsg=None, utm_zone=None, latlon=False, on_mismatch='raise', survey=None, created_by='', crs=None, description='')[source]

Convert a ModEM 3-D InversionResult to a PCSFModel.

Parameters:
  • result (InversionResult) – A loaded ModEM working directory (result.mode == "3d").

  • model (ModEmModel3D, optional) – Model to convert. Defaults to result.model_final, falling back to result.model_initial when no final model was parsed.

  • data (ModEmData, optional) – Source of station coordinates. Defaults to result.data_obs, falling back to result.data_pred. None when neither is available (PCSFModel.stations stays None rather than fabricating positions).

  • station_elevations (mapping of str to float, optional) – station_name -> elevation (m), overriding ModEM’s own station z (commonly a flat 0.0 placeholder — a real ModEM .dat file carries no topography). Matched stations also populate PCSFModel.topography; unmatched stations keep their real recorded z as-is (0.0 is a genuine value here, not “unknown”, unlike Occam2D’s equivalent parameter). Superseded per-station by topo when both are given.

  • topo (path-like, TopoTable, Sites/MapData-like, or mapping, optional) – A “smart” real-coordinate source resolved via pycsamt.format.topo_source.resolve_topo() – see pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s identical parameter for the full description. When given, it takes precedence over both station_elevations and the .dat file’s own GG_Lat/GG_Lon for every station it resolves (with a UserWarning if either was also supplied); a station it has no data for keeps its existing value. None (the default) leaves this adapter’s behaviour unaffected.

  • epsg (int | None) – Forwarded to pycsamt.format.topo_source.resolve_topo(); see occam2d_to_pcsf’s identical parameters.

  • utm_zone (Any | None) – Forwarded to pycsamt.format.topo_source.resolve_topo(); see occam2d_to_pcsf’s identical parameters.

  • latlon (bool) – Forwarded to pycsamt.format.topo_source.resolve_topo(); see occam2d_to_pcsf’s identical parameters.

  • on_mismatch (str) – Forwarded to pycsamt.format.topo_source.resolve_topo(); see occam2d_to_pcsf’s identical parameters.

  • survey (SurveyMeta or mapping, optional) – Survey-level metadata, stored the same way as in pycsamt.format.adapters.occam2d.occam2d_to_pcsf().

  • created_by (str, optional) – Passed straight through to PCSFModel.

  • crs (str, optional) – Passed straight through to PCSFModel.

  • description (str, optional) – Passed straight through to PCSFModel.

Returns:

geometry.kind == "grid3d", canonical linear-ohm.m resistivity in PCSFModel.resistivity (model.rho_linear), the original natural-log grid preserved in PCSFModel.resistivity_native, and iteration history (RMS, objective, model norm, Lagrange multiplier, step-size scaling alpha) from InversionResult.log when available. PCSFModel.stations’s lon/lat are populated from data’s own GG_Lat/GG_Lon columns (ModEmData.site_lonlat) when present, so the file is self-sufficiently geo-referenced without needing a separate known_stations match at load time.

Return type:

PCSFModel

Raises:

ValueError – If result is not a 3-D ModEM result, or no model (explicit or resolved from result) is available.

Examples

>>> from pycsamt.models.modem.results import InversionResult
>>> from pycsamt.format.adapters.modem3d import modem3d_to_pcsf
>>> from pycsamt.format import write_pcsf
>>> result = InversionResult("modem_run")
>>> model = modem3d_to_pcsf(result)
>>> write_pcsf(model, "modem3d_run.pcsf")