2.17.3.3. pycsamt.interp.export#

export — write EM interpretation results to industry formats.

Supported formats#

  • Oasis Montaj XYZ — point-data profile readable by Geosoft Oasis Montaj and any XYZ-aware GIS tool.

  • LAS 2.0 — CWLS well-log ASCII standard; compatible with petrophyscial software (Petrel, Kingdom, IHS Markit).

  • CSV — flat table; station, depth, log10-rho, lithology.

  • VTK — ASCII rectilinear-grid format readable by Paraview, QGIS, and other 3-D viewers.

  • Golden Software Surferto_surfer_grid (DSAA regular grid, opens directly as a finished map/section) and to_surfer_xyz (scattered X Y Z points at the model’s real, possibly non-uniform cell centres, gridded by Surfer itself). Both accept any 2-D inversion result — Occam2D, ModEM, the backend-neutral InversionResult, an AI agent result, or a raw array — via from_any(). to_surfer_bln writes the matching topography polygon (Surfer blanking file) so the air above real station elevation can be blanked out of the grid/map in Surfer directly.

Example

>>> from pycsamt.interp import export
>>> export.to_oasis_montaj_xyz(logs, "profile_K1.xyz")
>>> export.to_las(logs[0], "S17.las")
>>> export.to_csv(logs, "all_stations.csv")
>>> export.to_surfer_grid(model, "section.grd")

Functions

to_csv(logs, path, *[, log_rho])

Write all station logs to a flat CSV file.

to_las(log, path, *[, well_name, company, ...])

Write a single station log to LAS 2.0 format.

to_oasis_montaj_xyz(logs, path, *[, y, ...])

Write pseudo-stratigraphic logs to Oasis Montaj XYZ format.

to_surfer_bln(elevation, chainage, path, *)

Write a Golden Software Surfer blanking (.bln) polygon for topography.

to_surfer_dsaa(x, y, values, path, *[, ...])

Write a regular scalar grid as a Golden Software Surfer DSAA file.

to_surfer_grid(model, path, *[, log_rho, ...])

Write a 2-D resistivity model as a Golden Software Surfer DSAA grid.

to_surfer_xyz(model, path, *[, log_rho, ...])

Write a 2-D resistivity model as scattered Surfer X Y Z points.

to_vtk(model, path, *[, log_rho, field_name])

Write a 2-D resistivity model as a VTK rectilinear grid.

pycsamt.interp.export.to_oasis_montaj_xyz(logs, path, *, y=0.0, elevation=None, log_rho=True, channels=None)[source]

Write pseudo-stratigraphic logs to Oasis Montaj XYZ format.

Each station is written as a separate / Line block. The depth axis is encoded as a negative Z value (depth below surface).

Parameters:
  • logs (list of StratigraphicLog)

  • path (path-like) – Output file path (extension .xyz recommended).

  • y (float) – Northing to assign to all points (single-profile surveys).

  • elevation (ndarray (n_stations,), optional) – Surface elevation for each station in metres a.s.l. If provided, Z = elevation − depth. Otherwise Z = −depth.

  • log_rho (bool) – Write \(\log_{10}(\rho)\) (default) or linear ρ (Ω·m).

  • channels (list of str, optional) – Override column headers. Defaults to ['X', 'Y', 'Z', 'RESD', 'LITH'].

Returns:

Written file path.

Return type:

Path

pycsamt.interp.export.to_las(log, path, *, well_name='', company='pycsamt', null_value=-9999.25, log_rho=True)[source]

Write a single station log to LAS 2.0 format.

Parameters:
  • log (StratigraphicLog)

  • path (path-like) – Output .las file.

  • well_name (str) – Well / station identifier; defaults to log.station_name.

  • company (str)

  • null_value (float) – LAS null sentinel for missing values.

  • log_rho (bool) – Write \(\log_{10}(\rho)\) (default) or linear ρ.

Return type:

Path

pycsamt.interp.export.to_csv(logs, path, *, log_rho=True)[source]

Write all station logs to a flat CSV file.

Columns: station, x_m, depth_m, rho_log10, rho_ohm_m, lithology

Parameters:
  • logs (list of StratigraphicLog)

  • path (path-like)

  • log_rho (bool) – Include the rho_log10 column (always written); if False only rho_ohm_m is added.

Return type:

Path

pycsamt.interp.export.to_vtk(model, path, *, log_rho=True, field_name='log10_rho')[source]

Write a 2-D resistivity model as a VTK rectilinear grid.

The output is plain ASCII VTK (RECTILINEAR_GRID) readable by Paraview, QGIS (via the SimpleVTK plugin), and most 3-D viewers.

Parameters:
  • model (ResistivityModel)

  • path (path-like) – Output .vtk file.

  • log_rho (bool) – Write \(\log_{10}(\rho)\) (default) or linear ρ.

  • field_name (str) – VTK scalar name.

Return type:

Path

pycsamt.interp.export.to_surfer_grid(model, path, *, log_rho=True, nx=None, ny=None, elevation=None, station_x=None, chainage=None, blank_value=1.70141e+38)[source]

Write a 2-D resistivity model as a Golden Software Surfer DSAA grid.

Accepts any 2-D inversion result via from_any() (Occam2D, ModEM, the backend-neutral InversionResult, an AI agent result, a raw (x_centers, z_centers, rho_2d) triple, or an existing ResistivityModel) — not just resistivity models already in hand. The written file opens directly in Surfer (File > Open) as a finished grid, no further gridding step needed.

DSAA is a regular grid format: X and Y must each be evenly spaced. The source model’s cell centres generally are not (Occam2D depth cells expand geometrically, mesh padding is uneven, …), so this resamples onto a new nx x ny regular grid first. The resample is exact and separable when elevation is omitted (a straightforward 1-D linear interpolation along each axis, since a ResistivityModel’s rho_2d already sits on a true x_centers x z_centers tensor grid). With elevation given, each x-column’s local depth-to-elevation mapping differs (real terrain), so the grid becomes column-sheared before resampling; this handles that with one linear interpolation per column rather than a full 2-D scattered regrid, still exact along each axis and scipy-free. Grid cells outside a column’s real elevation coverage (above local terrain, or below the deepest column-local sample) are written as blank_value, Surfer’s own missing-data sentinel.

Parameters:
  • model (object) – Anything ResistivityModel.from_any() accepts. Native MARE2DEM results (an unstructured triangular mesh, not a regular grid) are not supported — regrid onto a (x_centers, z_centers, rho_2d) triple first. A native Occam2D/ModEM result is not auto-cropped to the station-carrying core — pass model.clip_to_stations() (after ResistivityModel.from_any) instead of the raw result if Occam2D’s own wide boundary-padding columns should not appear in the output.

  • path (path-like) – Output .grd file.

  • log_rho (bool) – Write \(\log_{10}(\rho)\) (default) or linear ρ (Ω·m).

  • nx (int, optional) – Output grid resolution. Default to the source model’s own n_x/n_z (a reasonable resolution match; raise for a finer resample).

  • ny (int, optional) – Output grid resolution. Default to the source model’s own n_x/n_z (a reasonable resolution match; raise for a finer resample).

  • elevation (ndarray, optional) – Real terrain elevation (m a.s.l.) — pairs with chainage (or station_x when chainage is omitted). When given, Y becomes real elevation (elevation depth); otherwise Y is −depth (flat datum at 0, matching to_oasis_montaj_xyz()’s convention).

  • station_x (ndarray, optional) – Overrides the station positions used to resolve model via ResistivityModel.from_any() (only meaningful for input forms that need it, e.g. a raw array triple).

  • chainage (ndarray, optional) – Along-profile positions matching elevation, metres. Defaults to the resolved model’s own station_x.

  • blank_value (float) – Surfer’s missing-data sentinel. Default matches Surfer’s own default (1.70141e38); change only if a project’s Surfer installation uses a different one.

Return type:

Path

Examples

>>> import numpy as np
>>> from pycsamt.interp import export
>>> x = np.linspace(0.0, 900.0, 10)
>>> z = np.array([10.0, 50.0, 120.0])
>>> rho_log10 = np.tile(np.array([[2.0], [2.5], [3.0]]), (1, 10))
>>> path = export.to_surfer_grid(
...     (x, z, rho_log10),
...     "surfer_grid_doctest.grd",
...     nx=5,
...     ny=3,
... )
>>> lines = path.read_text().splitlines()
>>> lines[0]
'DSAA'
>>> lines[1]
'5 3'
>>> path.unlink()
pycsamt.interp.export.to_surfer_dsaa(x, y, values, path, *, blank_value=1.70141e+38)[source]

Write a regular scalar grid as a Golden Software Surfer DSAA file.

Unlike to_surfer_grid(), this generic writer applies no resistivity, logarithm, depth, or elevation convention. x and y are increasing one-dimensional grid axes and values has shape (len(y), len(x)). Non-finite cells are written with Surfer’s blanking sentinel.

Parameters:
Return type:

Path

pycsamt.interp.export.to_surfer_xyz(model, path, *, log_rho=True, elevation=None, station_x=None, chainage=None, delimiter='\t', header=True)[source]

Write a 2-D resistivity model as scattered Surfer X Y Z points.

Unlike to_surfer_grid(), this writes the model’s actual cell centres exactly as they are — no resampling, no regularity requirement, nothing blanked — and lets Surfer’s own gridding (Grid > Data) turn it into a map with whatever method and blanking the user chooses. Accepts the same input forms as to_surfer_grid() via from_any().

Parameters:
  • model (object) – Anything ResistivityModel.from_any() accepts.

  • path (path-like) – Output text file (.xyz / .dat recommended).

  • log_rho (bool) – Write \(\log_{10}(\rho)\) (default) or linear ρ (Ω·m).

  • elevation (ndarray | None) – Same meaning as to_surfer_grid() — with elevation, Y is real elevation (elevation depth); without it, Y is −depth.

  • station_x (ndarray | None) – Same meaning as to_surfer_grid() — with elevation, Y is real elevation (elevation depth); without it, Y is −depth.

  • chainage (ndarray | None) – Same meaning as to_surfer_grid() — with elevation, Y is real elevation (elevation depth); without it, Y is −depth.

  • delimiter (str) – Column separator (default tab, Surfer’s own default import delimiter).

  • header (bool) – Write an X<delim>Y<delim>Z header row.

Return type:

Path

Examples

>>> import numpy as np
>>> from pycsamt.interp import export
>>> x = np.array([0.0, 100.0])
>>> z = np.array([10.0, 50.0])
>>> rho_log10 = np.array([[2.0, 2.1], [2.5, 2.6]])
>>> path = export.to_surfer_xyz(
...     (x, z, rho_log10), "surfer_xyz_doctest.dat"
... )
>>> path.read_text().splitlines()
['X\tY\tZ', '0.000\t-10.000\t2.00000', '0.000\t-50.000\t2.50000', '100.000\t-10.000\t2.10000', '100.000\t-50.000\t2.60000']
>>> path.unlink()
pycsamt.interp.export.to_surfer_bln(elevation, chainage, path, *, sky_margin=100.0)[source]

Write a Golden Software Surfer blanking (.bln) polygon for topography.

Traces the real, along-profile station elevation as one edge of a closed polygon covering everything above the terrain (the “sky”), with the blanking flag set so Surfer blanks that polygon’s interior (Map/Grid > Blank in Surfer, using this file). Loaded together with a terrain-draped grid from to_surfer_grid() (pass the same elevation/chainage), this removes the flat rectangular “no data” band above real terrain that to_surfer_grid() otherwise leaves filled with its blanking sentinel but does not clip out of the plot.

Parameters:
  • elevation (ndarray) – Real terrain elevation at each profile position, metres a.s.l. (e.g. real station elevation from EDI headers via pycsamt.topo.extract.extract_elevation()).

  • chainage (ndarray) – Along-profile position matching elevation, metres, in the same coordinate frame as the grid written by to_surfer_grid() (its chainage/station_x argument).

  • path (path-like) – Output .bln file.

  • sky_margin (float) – Extra height, in metres, added above the highest station so the polygon’s top edge clears the grid’s own upper bound with room to spare (default 100.0 m).

Return type:

Path

Notes

The Surfer .bln format’s first line is n_points,blank_flag, where blank_flag=1 blanks the polygon’s interior (used here) and 0 would blank everything outside it. Each following line is one x,y vertex; Surfer closes the polygon back to the first vertex automatically.

Examples

>>> import numpy as np
>>> from pycsamt.interp import export
>>> elev = np.array([100.0, 120.0, 90.0])
>>> chain = np.array([0.0, 50.0, 100.0])
>>> path = export.to_surfer_bln(elev, chain, "topo_doctest.bln")
>>> path.read_text().splitlines()[0]
'5,1'
>>> path.unlink()

See also

to_surfer_grid

Write the matching terrain-draped resistivity grid.