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 Surfer —
to_surfer_grid(DSAA regular grid, opens directly as a finished map/section) andto_surfer_xyz(scatteredX Y Zpoints 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-neutralInversionResult, an AI agent result, or a raw array — viafrom_any().to_surfer_blnwrites 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
|
Write all station logs to a flat CSV file. |
|
Write a single station log to LAS 2.0 format. |
|
Write pseudo-stratigraphic logs to Oasis Montaj XYZ format. |
|
Write a Golden Software Surfer blanking ( |
|
Write a regular scalar grid as a Golden Software Surfer DSAA file. |
|
Write a 2-D resistivity model as a Golden Software Surfer DSAA grid. |
|
Write a 2-D resistivity model as scattered Surfer |
|
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
/ Lineblock. 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
.xyzrecommended).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
.lasfile.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_log10column (always written); ifFalseonlyrho_ohm_mis 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
.vtkfile.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-neutralInversionResult, an AI agent result, a raw(x_centers, z_centers, rho_2d)triple, or an existingResistivityModel) — 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
nxxnyregular grid first. The resample is exact and separable when elevation is omitted (a straightforward 1-D linear interpolation along each axis, since aResistivityModel’srho_2dalready sits on a truex_centersxz_centerstensor 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 — passmodel.clip_to_stations()(afterResistivityModel.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
.grdfile.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, matchingto_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.xandyare increasing one-dimensional grid axes andvalueshas shape(len(y), len(x)). Non-finite cells are written with Surfer’s blanking sentinel.
- 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 Zpoints.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 asto_surfer_grid()viafrom_any().- Parameters:
model (object) – Anything
ResistivityModel.from_any()accepts.path (path-like) – Output text file (
.xyz/.datrecommended).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>Zheader 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 > Blankin Surfer, using this file). Loaded together with a terrain-draped grid fromto_surfer_grid()(pass the same elevation/chainage), this removes the flat rectangular “no data” band above real terrain thatto_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
.blnfile.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.0m).
- Return type:
Path
Notes
The Surfer
.blnformat’s first line isn_points,blank_flag, whereblank_flag=1blanks the polygon’s interior (used here) and0would blank everything outside it. Each following line is onex,yvertex; 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_gridWrite the matching terrain-draped resistivity grid.