Version 2.2.2#
pyCSAMT 2.2.2 Fix Docs Enhancement#
Released 2026-08-07.
A patch release. Its two real code fixes both came out of verification work: compiling and running Occam2D for real against pyCSAMT-generated input files exposed two solver-integration bugs, and building faithful, doctest-verified examples for the API view layer exposed a third. The bulk of the release is a new end-to-end tutorial and a corrected API Views page.
Verifying the whole pipeline against a real compiled solver Fix#
Stratagem Field Data To Occam2D Inversion walks a real
Dafang line-5 Stratagem field survey from raw hardware import through a
compiled Occam2D inversion: EDIBatch/
StratagemRawReader import, coordinate injection via
CoordinateInjector (against an empirically confirmed EPSG, cross-
checked with an independent tool’s own coordinates rather than assumed),
static-shift correction, frequency filtering, noise removal,
cross-validation against both that independent tool and
smooth_logfreq(), QC export, and a
real Occam2D inversion run against a genuinely compiled binary.
Bundled as data/stratagem/Dafang/ alongside its own README.md,
following the same pattern as the K2 dataset in
Process Zonge AVG Lines K1 and K2. The reported inversion result
is an honest, non-converged RMS of 11.20 rather than a cleaned-up figure
– consistent with this project’s practice of reporting real solver
behaviour, convergence problems included.
Running that real solver for the first time against real Occam2D mesh files surfaced two previously-latent bugs:
OccamRunner.compile()looked for a binary literally namedOccam2D, not the module’s own.exe-suffixed constant, so a genuinely successful Windowsmakewas reported as a failed compile.OccamMeshread and wrote the mesh header’s fourth control field as an air-layer count. The vendored Fortran solver (MT2D.f90) actually uses that field for the fixed-resistivity count (nrfix, always0for pyCSAMT-generated meshes) and manages air layers internally via its ownaddair()routine – confirmed by reading the solver’s own parser and cross-checking two independent, bundled reference mesh files, not by guessing at the format. Every mesh pyCSAMT wrote or read was desynchronized from that field onward. Fixed in parsing, writing, and the module docstring.
Correcting the API view documentation, and a real wrapper bug Fix Docs#
API Views previously claimed that pyCSAMT’s dataframe-
returning functions return a plain pandas.DataFrame by default.
Verifying that claim against real code proved the opposite: the api
keyword most of these functions accept defaults to api=None, which
resolves through the package-wide PYCSAMT_API_VIEW
switch – and that switch’s own default backend is already "pycsamt",
not "pandas". A bare call is therefore already wrapped into an
APIFrame or APIResult. The
page has been rewritten with real, doctest-verified examples throughout
to state this plainly instead of leaving a reader to discover it by
checking a type.
Building the page’s custom-wrapper example surfaced a second, independent
bug: maybe_wrap_frame(..., api=True) ignored any wrapper configured
via configure_api_view(wrapper=...) and always produced an
APIFrame regardless, contradicting the documented “swap the wrapper
out” contract. Fixed so an explicit api=True still respects a
configured custom wrapper; only an explicit api=False bypasses it.
Fixed#
Fix Occam2D binary discovery on Windows –
OccamRunner.compile()now looks for the module’s own.exe-suffixed binary name instead of a hardcodedOccam2D.Fix Occam2D mesh header field mislabeling –
OccamMeshno longer reads or writes an air-layer count into the mesh header’s fixed-resistivity (nrfix) field; air layers are inferred from the cell-type rows instead, matching the real vendored solver.Fix Custom API view wrapper bypassed by
api=True–maybe_wrap_framenow respects a wrapper configured viaconfigure_api_view(wrapper=...)on both a bare call and an explicitapi=Truecall.Fix Stray root-level artefacts – removed leftover example outputs (
figures/, generated.npz/.pngfiles,all_blocks.pycon) and gitignoredall_blocks.pyconso it stops reappearing.
Added#
New Stratagem Field Data To Occam2D Inversion and its bundled
data/stratagem/Dafang/dataset.Docs Rewrote API Views; added matching Frequently asked questions entries on the API view default behaviour and the new tutorial.
Changed#
Enhancement
TEM1DForwardnow delegates its Hankel/Fourier transform toempymod’s validated digital linear filters instead of a hand-rolled quadrature;empymodmoved from an optional extra to a core dependency.
Compatibility#
Default behaviour is unchanged for existing users. Anything that relied
on maybe_wrap_frame(..., api=True) silently ignoring a configured
custom wrapper – unlikely, since that contradicted the documented
contract – will now see the wrapper applied. Occam2D meshes written by
the previous, buggy OccamMesh are not compatible with a real Occam2D
binary and should be regenerated rather than reused.