pycsamt.format.regrid#

Regridded grid2d convenience export for mesh_unstructured models.

Design principle 6 (SPEC.md section 2) deliberately keeps a mesh_unstructured file’s own triangular mesh un-regridded by default – MARE2DEM’s mesh stays a mesh. A reader wanting a rectilinear approximation instead (a quick-look plot, a pipeline stage that only understands grid2d) previously had to write that interpolation itself; this module closes that gap with one function, mesh_to_grid2d().

It is not a second interpolation scheme: it reuses the exact matplotlib.tri.Triangulation point-location machinery pycsamt.map.inversion.load_pcsf_lines() already uses to slice a per-station curtain through a mesh_unstructured model, evaluated on a regular grid instead of at station positions. A query point outside the mesh returns nan, never an extrapolated or fabricated value – the same convention that curtain slicer already follows.

The result is explicitly marked synthesized (in description and metadata), matching design principle 5’s rule that a derived view must never be mistaken for a native inversion output: no resistivity_native, no resistivity_by_region survive the regrid, since neither concept applies to an interpolated value.

Functions

mesh_to_grid2d(model, *[, nx, nz])

Regrid a mesh_unstructured PCSF model onto a rectilinear grid2d approximation.

pycsamt.format.regrid.mesh_to_grid2d(model, *, nx=200, nz=150)[source]

Regrid a mesh_unstructured PCSF model onto a rectilinear grid2d approximation.

Parameters:
  • model (PCSFModel) – A model with geometry.kind == "mesh_unstructured" and per-cell resistivity (shape (n_triangles,) – every pycsamt.format.adapters writer already produces this; a region-collapsed (n_regions,) array must be expanded onto each triangle’s region id first).

  • nx (int, default 200, 150) – Grid resolution. Chosen independently of the source mesh’s own resolution – there is no natural rectilinear resolution to inherit from an unstructured mesh – the same kind of pragmatic, documented default the rest of this format already makes (cf. PCSM’s row-width cap, the per-station curtain’s n_z default) rather than leaving it unbounded.

  • nz (int, default 200, 150) – Grid resolution. Chosen independently of the source mesh’s own resolution – there is no natural rectilinear resolution to inherit from an unstructured mesh – the same kind of pragmatic, documented default the rest of this format already makes (cf. PCSM’s row-width cap, the per-station curtain’s n_z default) rather than leaving it unbounded.

Returns:

A new grid2d model. Grid points outside the source mesh’s triangulation are nan. source_backend, created_by, and crs are carried over from model; description and metadata record that this is a synthesized regrid, not a native inversion output.

Return type:

PCSFModel

Raises:
  • ValueError – If model is not mesh_unstructured, or its resistivity is not already per-cell.

  • NotImplementedError – If the mesh’s plane is not "xz" – the only plane any current adapter produces; a general 3-D mesh has no single rectilinear plane to regrid onto.

Examples

>>> import numpy as np
>>> from pycsamt.format.schema import PCSFModel, UnstructuredMeshGeometry
>>> from pycsamt.format.regrid import mesh_to_grid2d
>>> geometry = UnstructuredMeshGeometry(
...     nodes=np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [1.0, 1.0]]),
...     connectivity=np.array([[0, 1, 2], [1, 3, 2]]),
...     region_ids=np.array([0, 1]),
... )
>>> model = PCSFModel(geometry=geometry, resistivity=np.array([10.0, 20.0]))
>>> regridded = mesh_to_grid2d(model, nx=5, nz=5)
>>> regridded.kind
'grid2d'
>>> regridded.resistivity.shape
(5, 5)