pycsamt.format.adapters.generic#

Generic array-based -> PCSF adapter, for any AI/DL inversion result.

Every other module in pycsamt.format.adapters converts a specific solver’s own in-memory result object (Occam2D’s InversionResult, ModEM’s ModEmModel3D, MARE2DEM’s TriMesh). This module needs none of that: it builds a PCSFModel straight from plain numpy arrays, so a UNet, a GCN, a ResNet, or any third-party AI/DL inversion tool – with zero dependency on pycsamt’s own pycsamt.ai subpackage – can publish its result as a citable, reproducible .pcsf/.pcsm file others can reload and check.

Three functions, one per non-multiline geometry kind:

  • grid2d_to_pcsf() – a regular 2-D section (e.g. a UNet slice).

  • grid3d_to_pcsf() – a regular 3-D volume (e.g. a 3-D CNN/ResNet).

  • mesh_to_pcsf() – a triangular mesh, per-node or per-cell (e.g. a GCN predicting one value per graph vertex).

An AI model producing several 2-D lines with real cross-strike offsets already has a home: pycsamt.format.multiline.build_multiline_pcsf(), whose source_backend is already free text – no changes needed there.

All three functions share the same trailing keyword surface as the solver-specific adapters (station identity/position, elevation/topography via the same smart topo= resolver, an origin/rotation “offset” for placing the result in real-world space, uncertainty/sensitivity, iteration history, and free-form survey/model metadata), so an AI-produced file gets the same spatial richness a real solver’s file gets – see pycsamt.format.provenance for the accompanying ML-provenance convention (architecture/framework/checkpoint/hyperparameters).

Functions

grid2d_to_pcsf(resistivity, x, z, *[, ...])

Build a grid2d PCSFModel from a bare AI/DL prediction.

grid3d_to_pcsf(resistivity, x, y, z, *[, ...])

Build a grid3d PCSFModel from a bare AI/DL prediction.

mesh_to_pcsf(nodes, connectivity, *[, ...])

Build a mesh_unstructured PCSFModel from a bare AI/DL prediction on a triangular mesh.

pycsamt.format.adapters.generic.grid2d_to_pcsf(resistivity, x, z, *, encoding='linear', x_nodes=None, z_nodes=None, origin=None, azimuth_deg=None, uncertainty=None, sensitivity=None, stations=None, topography=None, station_names=None, station_x=None, station_elevations=None, station_lonlat=None, topo=None, epsg=None, utm_zone=None, latlon=False, on_mismatch='raise', history=None, provenance=None, survey=None, source_backend='ai', created_by='', crs=None, description='', metadata=None)[source]

Build a grid2d PCSFModel from a bare AI/DL prediction.

The natural fit for a 2-D model (e.g. a UNet trained on inversion sections): give it its predicted array plus the coordinates it was predicted on, and it becomes the exact same on-disk artifact pycsamt.format.adapters.occam2d.occam2d_to_pcsf() produces for a real Occam2D run – readable by the same pycsamt.format.read_pcsf(), app/mapview, and the web 3-D view.

Parameters:
  • resistivity (array-like, shape (n_z, n_x)) – The model’s predicted resistivity, in whatever encoding it was trained/predicted in.

  • x (array-like) – Cell-centre coordinates (metres) matching Grid2DGeometry.

  • z (array-like) – Cell-centre coordinates (metres) matching Grid2DGeometry.

  • encoding ({"linear", "log10", "ln"}, default "linear") – Encoding of resistivity. Many DL models predict log-resistivity for training stability; when not "linear", the given array is kept verbatim as resistivity_native and the canonical linear resistivity is derived automatically.

  • x_nodes (Any) – Forwarded to Grid2DGeometry. origin/azimuth_deg are this geometry’s own “offset” – the real-world placement of an otherwise locally-referenced section.

  • z_nodes (Any) – Forwarded to Grid2DGeometry. origin/azimuth_deg are this geometry’s own “offset” – the real-world placement of an otherwise locally-referenced section.

  • origin (Any) – Forwarded to Grid2DGeometry. origin/azimuth_deg are this geometry’s own “offset” – the real-world placement of an otherwise locally-referenced section.

  • azimuth_deg (float | None) – Forwarded to Grid2DGeometry. origin/azimuth_deg are this geometry’s own “offset” – the real-world placement of an otherwise locally-referenced section.

  • uncertainty (array-like, optional) – Same shape as resistivity – a direct fit for a predictive standard deviation from an MC-dropout/Bayesian model.

  • sensitivity (array-like, optional) – Same shape as resistivity – a direct fit for a predictive standard deviation from an MC-dropout/Bayesian model.

  • stations (StationTable, optional) – A pre-built table, used as-is when given (bypasses every station_*/topo parameter below).

  • topography (TopographyPerStation or TopographyRaster, optional) – A pre-built topography, used as-is when given – e.g. a DEM raster from pycsamt.format.topography.topography_from_grid(), which no station_elevations/topo combination below can produce.

  • station_names (sequence, optional) – Station identity and along-profile chainage (same frame as x).

  • station_x (sequence, optional) – Station identity and along-profile chainage (same frame as x).

  • station_elevations (Mapping[str, float] | None) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • station_lonlat (Mapping[str, tuple[float, float]] | None) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • topo (Any) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • epsg (int | None) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • utm_zone (Any | None) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • latlon (bool) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • on_mismatch (str) – Identical to pycsamt.format.adapters.occam2d.occam2d_to_pcsf()’s own parameters of the same name – see that function’s docstring for the full description of the smart topo= resolver.

  • history (mapping of str to array-like, optional) – Per-iteration/per-epoch series (e.g. training/validation loss).

  • provenance (ModelProvenance or mapping, optional) – Folded into metadata["model_provenance"] – see pycsamt.format.provenance.

  • survey (Any | Mapping[str, Any] | None) – Passed through to PCSFModel; source_backend defaults to "ai" but any free-text string is accepted (e.g. "unet", "gcn", "resnet", a third party’s own name).

  • source_backend (str) – Passed through to PCSFModel; source_backend defaults to "ai" but any free-text string is accepted (e.g. "unet", "gcn", "resnet", a third party’s own name).

  • created_by (str) – Passed through to PCSFModel; source_backend defaults to "ai" but any free-text string is accepted (e.g. "unet", "gcn", "resnet", a third party’s own name).

  • crs (str | None) – Passed through to PCSFModel; source_backend defaults to "ai" but any free-text string is accepted (e.g. "unet", "gcn", "resnet", a third party’s own name).

  • description (str) – Passed through to PCSFModel; source_backend defaults to "ai" but any free-text string is accepted (e.g. "unet", "gcn", "resnet", a third party’s own name).

  • metadata (Mapping[str, Any] | None) – Passed through to PCSFModel; source_backend defaults to "ai" but any free-text string is accepted (e.g. "unet", "gcn", "resnet", a third party’s own name).

Return type:

PCSFModel

Examples

>>> import numpy as np
>>> from pycsamt.format.adapters.generic import grid2d_to_pcsf
>>> model = grid2d_to_pcsf(
...     resistivity=np.array([[2.0, 2.1], [1.7, 1.8]]),
...     x=np.array([0.0, 100.0]), z=np.array([10.0, 50.0]),
...     encoding="log10", source_backend="unet",
... )
>>> model.kind, model.source_backend
('grid2d', 'unet')
pycsamt.format.adapters.generic.grid3d_to_pcsf(resistivity, x, y, z, *, encoding='linear', x_nodes=None, y_nodes=None, z_nodes=None, origin=None, rotation_deg=0.0, n_air=0, uncertainty=None, sensitivity=None, stations=None, topography=None, station_names=None, station_x=None, station_y=None, station_z=None, station_elevations=None, station_lonlat=None, topo=None, epsg=None, utm_zone=None, latlon=False, on_mismatch='raise', history=None, provenance=None, survey=None, source_backend='ai', created_by='', crs=None, description='', metadata=None)[source]

Build a grid3d PCSFModel from a bare AI/DL prediction.

The natural fit for a volumetric model (a 3-D CNN/ResNet-style architecture predicting a full tensor volume): the resulting file is the same artifact pycsamt.format.adapters.modem3d.modem3d_to_pcsf() produces for a real ModEM 3-D run.

Parameters:
  • resistivity (array-like, shape (n_z, n_y, n_x)) – The model’s predicted resistivity (see resistivity_shape for this axis order – ModEM’s own native convention).

  • x (array-like) – Cell-centre coordinates (metres).

  • y (array-like) – Cell-centre coordinates (metres).

  • z (array-like) – Cell-centre coordinates (metres).

  • encoding ({"linear", "log10", "ln"}, default "linear") – See grid2d_to_pcsf()’s identical parameter.

  • x_nodes (Any) – Forwarded to Grid3DGeometry. origin/rotation_deg are this geometry’s “offset” – real-world placement and bearing of an otherwise locally-referenced volume.

  • y_nodes (Any) – Forwarded to Grid3DGeometry. origin/rotation_deg are this geometry’s “offset” – real-world placement and bearing of an otherwise locally-referenced volume.

  • z_nodes (Any) – Forwarded to Grid3DGeometry. origin/rotation_deg are this geometry’s “offset” – real-world placement and bearing of an otherwise locally-referenced volume.

  • origin (Any) – Forwarded to Grid3DGeometry. origin/rotation_deg are this geometry’s “offset” – real-world placement and bearing of an otherwise locally-referenced volume.

  • rotation_deg (float) – Forwarded to Grid3DGeometry. origin/rotation_deg are this geometry’s “offset” – real-world placement and bearing of an otherwise locally-referenced volume.

  • n_air (int) – Forwarded to Grid3DGeometry. origin/rotation_deg are this geometry’s “offset” – real-world placement and bearing of an otherwise locally-referenced volume.

  • uncertainty (Any)

  • sensitivity (Any)

  • stations (StationTable | None)

  • topography (TopographyPerStation | TopographyRaster | None)

  • station_names (Sequence[str] | None)

  • station_x (Sequence[float] | None)

  • station_y (Sequence[float] | None)

  • station_z (Sequence[float] | None)

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

  • station_lonlat (Mapping[str, tuple[float, float]] | None)

  • topo (Any)

  • epsg (int | None)

  • utm_zone (Any | None)

  • latlon (bool)

  • on_mismatch (str)

  • history (Mapping[str, Any] | None)

  • provenance (ModelProvenance | Mapping[str, Any] | None)

  • survey (Any | Mapping[str, Any] | None)

  • source_backend (str)

  • created_by (str)

  • crs (str | None)

  • description (str)

  • metadata (Mapping[str, Any] | None)

Return type:

PCSFModel

:param : :param station_x: :param station_y: :param station_z: :param station_elevations: :param station_lonlat: :param : :param topo: :param epsg: :param utm_zone: :param latlon: :param on_mismatch: :param history: :param provenance: :param survey: :param : :param source_backend: Same meaning as grid2d_to_pcsf()’s identical parameters

(station_y/station_z additionally accepted here, matching a native 3-D station table).

Parameters:
  • created_by (str) – Same meaning as grid2d_to_pcsf()’s identical parameters (station_y/station_z additionally accepted here, matching a native 3-D station table).

  • crs (str | None) – Same meaning as grid2d_to_pcsf()’s identical parameters (station_y/station_z additionally accepted here, matching a native 3-D station table).

  • description (str) – Same meaning as grid2d_to_pcsf()’s identical parameters (station_y/station_z additionally accepted here, matching a native 3-D station table).

  • metadata (Mapping[str, Any] | None) – Same meaning as grid2d_to_pcsf()’s identical parameters (station_y/station_z additionally accepted here, matching a native 3-D station table).

  • resistivity (Any)

  • x (Any)

  • y (Any)

  • z (Any)

  • encoding (str)

  • x_nodes (Any)

  • y_nodes (Any)

  • z_nodes (Any)

  • origin (Any)

  • rotation_deg (float)

  • n_air (int)

  • uncertainty (Any)

  • sensitivity (Any)

  • stations (StationTable | None)

  • topography (TopographyPerStation | TopographyRaster | None)

  • station_names (Sequence[str] | None)

  • station_x (Sequence[float] | None)

  • station_y (Sequence[float] | None)

  • station_z (Sequence[float] | None)

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

  • station_lonlat (Mapping[str, tuple[float, float]] | None)

  • topo (Any)

  • epsg (int | None)

  • utm_zone (Any | None)

  • latlon (bool)

  • on_mismatch (str)

  • history (Mapping[str, Any] | None)

  • provenance (ModelProvenance | Mapping[str, Any] | None)

  • survey (Any | Mapping[str, Any] | None)

  • source_backend (str)

Return type:

PCSFModel

Examples

>>> import numpy as np
>>> from pycsamt.format.adapters.generic import grid3d_to_pcsf
>>> model = grid3d_to_pcsf(
...     resistivity=np.full((2, 2, 2), 100.0),
...     x=np.array([0.0, 100.0]), y=np.array([0.0, 100.0]),
...     z=np.array([10.0, 50.0]), source_backend="resnet",
... )
>>> model.kind
'grid3d'
pycsamt.format.adapters.generic.mesh_to_pcsf(nodes, connectivity, *, region_ids=None, resistivity=None, resistivity_by_node=None, resistivity_by_region=None, encoding='linear', plane='xz', uncertainty=None, sensitivity=None, stations=None, topography=None, station_names=None, station_x=None, station_y=None, station_z=None, station_elevations=None, station_lonlat=None, topo=None, epsg=None, utm_zone=None, latlon=False, on_mismatch='raise', history=None, provenance=None, survey=None, source_backend='ai', created_by='', crs=None, description='', metadata=None)[source]

Build a mesh_unstructured PCSFModel from a bare AI/DL prediction on a triangular mesh.

The natural fit for a graph-based model (a GCN predicting one value per mesh vertex/graph node), but also works for any model that already predicts per-triangle or per-region values on a mesh it did not itself generate (e.g. a caller-supplied mesh from pycsamt.models.mare2dem.tri_mesh.tri_mesh_from_poly()).

Parameters:
  • nodes (array-like, shape (n, 2) or (n, 3)) – Mesh node coordinates, metres.

  • connectivity (array-like, shape (m, 3), int) – Triangle node indices.

  • region_ids (array-like, shape (m,), int, optional) – Per-triangle region id. Defaults to all-zeros (a single, generic region – “no region structure”) when omitted.

  • resistivity (array-like, optional) – At least one is required. resistivity is per-triangle/per-cell (shape (m,)); resistivity_by_node is per-vertex (shape (n,), the natural GCN output); resistivity_by_region is a compact per-region table (shape (n_regions,)). Precedence when more than one is given: resistivity > resistivity_by_node > resistivity_by_region – the first present is treated as the canonical source (encoding applies to it), and the canonical per-triangle resistivity is derived from it: taken as-is, or averaged from its 3 vertex values per triangle (documented arithmetic mean, see _node_values_to_triangles()), or expanded via 0-based region_ids (see _expand_region_resistivity()). Any of the other two tables also given alongside the canonical source is stored as-is, assumed already linear ohm.m.

  • resistivity_by_node (array-like, optional) – At least one is required. resistivity is per-triangle/per-cell (shape (m,)); resistivity_by_node is per-vertex (shape (n,), the natural GCN output); resistivity_by_region is a compact per-region table (shape (n_regions,)). Precedence when more than one is given: resistivity > resistivity_by_node > resistivity_by_region – the first present is treated as the canonical source (encoding applies to it), and the canonical per-triangle resistivity is derived from it: taken as-is, or averaged from its 3 vertex values per triangle (documented arithmetic mean, see _node_values_to_triangles()), or expanded via 0-based region_ids (see _expand_region_resistivity()). Any of the other two tables also given alongside the canonical source is stored as-is, assumed already linear ohm.m.

  • resistivity_by_region (array-like, optional) – At least one is required. resistivity is per-triangle/per-cell (shape (m,)); resistivity_by_node is per-vertex (shape (n,), the natural GCN output); resistivity_by_region is a compact per-region table (shape (n_regions,)). Precedence when more than one is given: resistivity > resistivity_by_node > resistivity_by_region – the first present is treated as the canonical source (encoding applies to it), and the canonical per-triangle resistivity is derived from it: taken as-is, or averaged from its 3 vertex values per triangle (documented arithmetic mean, see _node_values_to_triangles()), or expanded via 0-based region_ids (see _expand_region_resistivity()). Any of the other two tables also given alongside the canonical source is stored as-is, assumed already linear ohm.m.

  • encoding ({"linear", "log10", "ln"}, default "linear") – Encoding of whichever of the three resistivity arrays above is the canonical source (see precedence above).

  • plane ({"xz", "xy", "3d"}, default "xz") – Forwarded to UnstructuredMeshGeometry.

  • uncertainty (array-like, optional) – Same shape as the canonical per-triangle resistivity.

  • sensitivity (array-like, optional) – Same shape as the canonical per-triangle resistivity.

  • stations (StationTable | None)

  • topography (TopographyPerStation | TopographyRaster | None)

  • station_names (Sequence[str] | None)

  • station_x (Sequence[float] | None)

  • station_y (Sequence[float] | None)

  • station_z (Sequence[float] | None)

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

  • station_lonlat (Mapping[str, tuple[float, float]] | None)

  • topo (Any)

  • epsg (int | None)

  • utm_zone (Any | None)

  • latlon (bool)

  • on_mismatch (str)

  • history (Mapping[str, Any] | None)

  • provenance (ModelProvenance | Mapping[str, Any] | None)

  • survey (Any | Mapping[str, Any] | None)

  • source_backend (str)

  • created_by (str)

  • crs (str | None)

  • description (str)

  • metadata (Mapping[str, Any] | None)

Return type:

PCSFModel

:param : :param station_elevations: :param station_lonlat: :param topo: :param epsg: :param utm_zone: :param latlon: :param : :param on_mismatch: :param history: :param provenance: :param survey: :param source_backend: :param created_by: :param : :param crs: Same meaning as grid3d_to_pcsf()’s identical parameters. A

mesh’s own node coordinates already carry real position – these are for naming/geo-referencing discrete receivers distinct from the mesh nodes (mirrors pycsamt.format.adapters.mare2dem.mare2dem_to_pcsf()’s own caller-supplied stations).

Parameters:
  • description (str) – Same meaning as grid3d_to_pcsf()’s identical parameters. A mesh’s own node coordinates already carry real position – these are for naming/geo-referencing discrete receivers distinct from the mesh nodes (mirrors pycsamt.format.adapters.mare2dem.mare2dem_to_pcsf()’s own caller-supplied stations).

  • metadata (Mapping[str, Any] | None) – Same meaning as grid3d_to_pcsf()’s identical parameters. A mesh’s own node coordinates already carry real position – these are for naming/geo-referencing discrete receivers distinct from the mesh nodes (mirrors pycsamt.format.adapters.mare2dem.mare2dem_to_pcsf()’s own caller-supplied stations).

  • nodes (Any)

  • connectivity (Any)

  • region_ids (Any)

  • resistivity (Any)

  • resistivity_by_node (Any)

  • resistivity_by_region (Any)

  • encoding (str)

  • plane (str)

  • uncertainty (Any)

  • sensitivity (Any)

  • stations (StationTable | None)

  • topography (TopographyPerStation | TopographyRaster | None)

  • station_names (Sequence[str] | None)

  • station_x (Sequence[float] | None)

  • station_y (Sequence[float] | None)

  • station_z (Sequence[float] | None)

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

  • station_lonlat (Mapping[str, tuple[float, float]] | None)

  • topo (Any)

  • epsg (int | None)

  • utm_zone (Any | None)

  • latlon (bool)

  • on_mismatch (str)

  • history (Mapping[str, Any] | None)

  • provenance (ModelProvenance | Mapping[str, Any] | None)

  • survey (Any | Mapping[str, Any] | None)

  • source_backend (str)

  • created_by (str)

  • crs (str | None)

Return type:

PCSFModel

Raises:

ValueError – If none of resistivity/resistivity_by_node/resistivity_by_region is given, or region_ids falls outside the resistivity-by-region table’s range.

Examples

>>> import numpy as np
>>> from pycsamt.format.adapters.generic import mesh_to_pcsf
>>> nodes = np.array([[0., 0.], [1., 0.], [0., 1.], [1., 1.]])
>>> connectivity = np.array([[0, 1, 2], [1, 3, 2]])
>>> node_values = np.array([1.0, 2.0, 3.0, 4.0])  # log10, one per node
>>> model = mesh_to_pcsf(
...     nodes, connectivity, resistivity_by_node=node_values,
...     encoding="log10", source_backend="gcn",
... )
>>> model.kind
'mesh_unstructured'