pycsamt.interp.calibrate#

ModelCalibrator — constrain a 2-D EM model with borehole ground truth.

Implements the pseudo-stratigraphic New Model (NM) construction introduced in Kouadio et al. (2022) and generalized here to work with any EM inversion output (Occam2D, ModEM, AI-based 1-D/2-D).

Algorithm#

For each station column of the Calculated Resistivity Model (CRM):

  1. Soft replace — for every depth cell whose CRM resistivity is within ptol (default 10 %) of a borehole TRES value, replace the calculated value with the true value:

    \[\xi_{\mathrm{se}} = \frac{|\rho_{\mathrm{crm}} - \rho_k|}{\rho_k} \leq p_{\mathrm{tol}}\]
  2. Autolayer — for cells not matched in Step 1, assign the nearest rock from the geological database \(\Gamma\) in log-space.

The misfit G (%) between the CRM and the NM is:

\[G(\%) = 100 \times \sqrt{\frac{\sum_i (\mathrm{NM}_i - \mathrm{CRM}_i)^2} {\sum_i \mathrm{CRM}_i^2}}\]

References

Example

>>> from pycsamt.interp import ResistivityModel, Borehole, ModelCalibrator
>>> model = ResistivityModel.from_occam2d(result)
>>> bh = Borehole.from_csv("boreholes/Bo.csv", name="Bo", x=1050.0)
>>> cal = ModelCalibrator(ptol=0.10).fit(model, [bh])
>>> nm = cal.calibrated_model()
>>> logs = cal.stratigraphic_logs()

Classes

ModelCalibrator([ptol, ...])

Constrain a 2-D EM resistivity model with borehole TRES values.

class pycsamt.interp.calibrate.ModelCalibrator(ptol=0.1, *, max_borehole_distance=500.0, db=None, verbose=True)[source]#

Bases: object

Constrain a 2-D EM resistivity model with borehole TRES values.

Parameters:
  • ptol (float, default 0.10) – Soft-error threshold — fractional tolerance between a CRM resistivity value and a TRES value for accepting a replace. The paper uses 10 % (ptol = 0.10).

  • max_borehole_distance (float, default 500.0) – Maximum profile-distance (metres) from a station to the nearest borehole. Stations farther than this threshold are calibrated using the rock database only (no TRES constraint).

  • db (RockDatabase, optional) – Rock physics database for autolayer assignment. Defaults to default().

  • verbose (bool, default True)

fit(model, boreholes=None)[source]#

Calibrate model against boreholes.

Parameters:
  • model (ResistivityModel) – The Calculated Resistivity Model (CRM) from any EM inversion.

  • boreholes (list of Borehole, optional) – Ground-truth borehole logs. If None or empty, the calibration falls back to rock-database autolayer assignment for every cell.

Return type:

self

calibrated_model()[source]#

Return a ResistivityModel containing the NM.

Raises:

RuntimeError – If fit() has not been called.

Return type:

ResistivityModel

misfit_map()[source]#

Return the per-column misfit G (%), shape (n_z, n_x).

Values range 0 – 100 %. Low values indicate good CRM–TRES agreement; high values flag where the inversion needed the most correction.

Return type:

ndarray

stratigraphic_logs(*, db=None, model='nm', merge_tolerance=0.2)[source]#

Build a StratigraphicLog for every station.

Parameters:
  • db (RockDatabase, optional) – Override the classifier database.

  • model ({'nm', 'crm'}) – Which model to classify: the calibrated NM or the original CRM.

  • merge_tolerance (float) – Log-space merging tolerance passed to from_column().

Return type:

list of StratigraphicLog