2.16. pycsamt.geology#
General-purpose geological domain knowledge with no electromagnetic
dependency: resistivity-to-lithology classification, the literature-compiled
rock/fluid property table behind it, pluggable rock-property sources,
ground-truth borehole logs, and field structural measurements (strike/dip,
trend/plunge, fault traces). pycsamt.interp builds on this package (see
pycsamt.interp.ModelCalibrator) rather than the other way round.
pycsamt.geology — general-purpose geological domain knowledge.
This package holds earth-science concepts that are not themselves
electromagnetic: a resistivity-to-lithology classification engine, a
literature-compiled rock/fluid property table, ground-truth borehole logs,
and (as the package grows) structural-geology primitives. Nothing here
imports pycsamt.interp.ResistivityModel or any other EM concept;
pycsamt.interp depends on this package, not the other way round.
For the interpretation workflow that turns an EM resistivity model into a
calibrated, geologically classified section — the part that does know
about resistivity models, boreholes-as-constraints, and misfit review —
see pycsamt.interp (ModelCalibrator in
particular). pycsamt.interp.RockDatabase, pycsamt.interp.Borehole,
and the other classes below remain importable from pycsamt.interp
for backward compatibility; this package is their canonical home.
2.16.1. Quickstart#
>>> from pycsamt.geology import RockDatabase, Borehole, FaultTrace
>>>
>>> db = RockDatabase.default()
>>> db.classify(250.0).name
'Granite (weathered)'
>>>
>>> bh = Borehole.from_csv("boreholes/Bo.csv", x=1050.0)
>>>
>>> fault = FaultTrace(x=500.0, dip_deg=70.0, downthrown_side="right")
2.16.2. Package layout#
lithologyRockDatabase,RockEntry,StratigraphicLog,Layer— resistivity-to-lithology classification engine only; the built-in table itself lives inrock_library.rock_libraryBUILTIN_ROCKS— the literature-compiled rock/ fluid resistivity table behindRockDatabase.default(), kept separate so it can grow without touching classification logic.rock_providersRockPropertyProvider,LocalRockPropertyProvider,RemoteRockPropertyProvider— pluggable rock-property sources behindRockDatabase.from_url()andRockDatabase.from_provider(), with local caching and fallback-to-default on failure.boreholeBorehole,Interval— ground-truth depth-interval data; readers for CSV and LAS 2.0.structuralStructuralMeasurement(planar: strike/dip/dip-direction),LinearMeasurement(linear: trend/plunge), andFaultTrace(where a fault crosses the profile) — field structural evidence;StructuralModelcollects all three per profile with CSV I/O and nearest/within queries.
References
- class pycsamt.geology.RockDatabase(entries, *, metadata=None)#
Bases:
PyCSAMTObject,MetadataMixinExtensible rock physics database for EM resistivity interpretation.
- Parameters:
Example
>>> db = RockDatabase.default() >>> db.classify(180.0).name 'Granite (weathered)'
- property entries: tuple[RockEntry, ...]#
Read-only view of the database entries, in insertion order.
- classmethod default()#
Return a database pre-loaded with the built-in rock entries.
Entries come from
pycsamt.geology.rock_library.BUILTIN_ROCKS; see that module for the literature the ranges are drawn from.- Return type:
- classmethod from_csv(path)#
Load from a CSV file.
Required columns:
name, rho_min, rho_maxOptional columns:color, description, code, source- Parameters:
- Return type:
- classmethod from_provider(provider)#
Build a database from any
RockPropertyProvider.This is the generic entry point behind
from_url(); call it directly when provider is something other than a plain URL fetch, such as a provider pre-configured with authentication or a provider composing several sources.- Parameters:
provider (RockPropertyProvider)
- Return type:
- classmethod from_url(url, *, cache_dir=None, ttl_seconds=86400.0, timeout=10.0, force=False, fallback=True)#
Fetch a database from url, with local caching and fallback.
url must serve a JSON array of objects using the same fields as
RockEntry(name,rho_min,rho_max, and optionallycolor,description,code,source). No public rock-resistivity service is bundled or assumed by default – point this at a project- or organisation-controlled endpoint (an internal API, a shared JSON file on a file server, and so on).- Parameters:
url (str) – Location to fetch the JSON entry list from.
cache_dir (path-like, optional) – Override the local cache location. Defaults to
$PYCSAMT_ROCKDB_CACHEor~/.pycsamt/rock_db.ttl_seconds (float) – Reuse a cached response younger than this many seconds instead of re-fetching. Default one day.
timeout (float) – Network timeout in seconds for the fetch itself.
force (bool) – Re-fetch even if a fresh cache entry exists.
fallback (bool) – If the fetch fails (network, timeout, malformed response) and no usable cache entry exists, fall back to
default()instead of raising. Set toFalseto surface the failure instead.
- Return type:
See also
pycsamt.geology.rock_providers.RemoteRockPropertyProviderThe provider implementing the fetch/cache/fallback policy used here.
- classify(rho_ohm_m, method='nearest')#
Return the best-matching rock entry for rho_ohm_m.
- class pycsamt.geology.RockEntry(name, rho_min, rho_max, color='#AAAAAA', description='', code=0, source='')#
Bases:
PyCSAMTObjectA single entry in the rock physics database.
- Parameters:
name (str) – Geological unit / lithology name.
rho_min (float) – Resistivity range in Ω·m (linear scale).
rho_max (float) – Resistivity range in Ω·m (linear scale).
color (str) – Hex colour code for plotting (e.g.
'#28B463').description (str) – Optional free-text note.
code (int) – Integer code used in LAS exports.
source (str) – Optional literature citation for this range (e.g.
'Palacky (1988)'). Empty when unspecified, as for entries loaded from a CSV without asourcecolumn.
- class pycsamt.geology.Layer(top, bottom, rho_log10, lithology, color='#AAAAAA', confidence=1.0)#
Bases:
PyCSAMTObjectOne geological unit in a pseudo-stratigraphic log.
- Parameters:
top (float) – Depth in metres (positive downward).
bottom (float) – Depth in metres (positive downward).
rho_log10 (float) – Representative \(\log_{10}(\rho)\) of the layer.
lithology (str) – Rock name from
RockDatabase.color (str) – Hex colour for plotting.
confidence (float) – Fraction of depth cells whose DB classification matches the reported lithology (0 – 1).
- class pycsamt.geology.StratigraphicLog(station_name, station_x, z_centers, rho_log10, layers)#
Bases:
PyCSAMTObjectPer-station pseudo-stratigraphic depth profile.
Constructed from a 1-D log10-rho column and a
RockDatabase, it merges adjacent cells that share the same lithology into discreteLayerobjects.- Parameters:
- classmethod from_column(station_name, x, z_centers, rho_log10, db=None, *, merge_tolerance=0.2)#
Build a log from a 1-D resistivity column.
- Parameters:
station_name (str)
x (float) – Station position, metres.
z_centers (ndarray (n_z,))
rho_log10 (ndarray (n_z,))
db (RockDatabase, optional) – Defaults to
RockDatabase.default().merge_tolerance (float) – Log10-rho difference threshold for merging adjacent cells into one layer (default 0.2 decade).
- Return type:
- to_dataframe()#
Return layers as a
pandas.DataFrame.
- class pycsamt.geology.Borehole(name, x, intervals, *, collar_elevation=0.0)#
Bases:
PyCSAMTObjectBorehole / well log with depth-interval data.
- Parameters:
name (str) – Well / borehole identifier.
x (float) – Position along the survey profile, metres.
collar_elevation (float) – Surface elevation at the borehole collar, metres a.s.l. Used only when elevation-corrected exports are requested.
intervals (list of Interval) – Depth-interval log, sorted ascending by top.
- interval_at_depth(z)#
Return the interval that contains depth z, or
None.
- tres_at_depth(z)#
Return TRES (Ω·m) at depth z, or
Noneif unknown.
- lithology_at_depth(z)#
Return the lithology name at depth z, or
None.
- tres_column(z_centers)#
Return TRES values at z_centers as a float array.
Depths not covered by any interval are
nan.
- classmethod from_csv(path, *, name=None, x=0.0, collar_elevation=0.0, delimiter=',', top_col='top', bottom_col='bottom', lithology_col='lithology', resistivity_col='resistivity')#
Load from a CSV file.
Expected columns (case-insensitive header):
top, bottom, lithology[, resistivity]- Parameters:
path (path-like)
name (str, optional) – Defaults to the file stem.
x (float) – Profile position.
collar_elevation (float)
delimiter (str)
top_col (str) – Column header names.
bottom_col (str) – Column header names.
lithology_col (str) – Column header names.
resistivity_col (str) – Column header names.
- Return type:
- classmethod from_las(path, *, x=0.0, collar_elevation=0.0, depth_curve='DEPT', resistivity_curve='RESD', lithology_curve='LITH', null_value=-9999.25, step=None)#
Load from a LAS 2.0 well-log file.
Converts the continuous depth log into discrete intervals by grouping consecutive samples with the same lithology code.
- Parameters:
path (path-like)
x (float) – Profile position.
depth_curve (str) – Curve mnemonics. lithology_curve may be
Noneto assign a generic label.resistivity_curve (str) – Curve mnemonics. lithology_curve may be
Noneto assign a generic label.lithology_curve (str | None) – Curve mnemonics. lithology_curve may be
Noneto assign a generic label.null_value (float) – LAS null sentinel replaced with
nan.step (float, optional) – If provided, override the step value from the LAS header.
collar_elevation (float)
- Return type:
- to_dataframe()#
Return intervals as a
pandas.DataFrame.
- class pycsamt.geology.Interval(top, bottom, lithology, resistivity=None)#
Bases:
PyCSAMTObjectA single depth interval in a borehole log.
- Parameters:
top (float) – Depth to the top of the interval, metres.
bottom (float) – Depth to the bottom of the interval, metres.
lithology (str) – Geological formation / lithology name.
resistivity (float or None) – True resistivity (TRES) in Ω·m (linear, not log₁₀).
Nonewhen no electrical measurement is available.
- class pycsamt.geology.StructuralMeasurement(x, kind, strike_deg, dip_deg, dip_direction_deg, z=None, station=None, confidence=1.0, notes='', dip_direction_tolerance_deg=20.0)#
Bases:
PyCSAMTObjectA planar structural field measurement.
- Parameters:
x (float) – Position along the survey profile, metres.
kind (str) – Feature type, e.g.
'bedding','foliation','joint','cleavage','contact','fault_plane','unconformity'. Free text – not an enforced enumeration, matchinglithology.strike_deg (float) – Compass strike, degrees clockwise from north,
[0, 360)as measured. Normalised on construction; not reduced modulo 180, so the raw field reading is preserved.dip_deg (float) – Dip angle below horizontal, degrees,
[0, 90].dip_direction_deg (float) – Compass direction the surface dips toward,
[0, 360). Must be within dip_direction_tolerance_deg ofstrike_deg + 90orstrike_deg - 90(mod 360); raisesValueErrorotherwise, since a wider mismatch usually means one of the two readings was transposed in the field notebook.z (float, optional) – Depth (positive downward) or elevation of the measurement, metres.
Nonefor a surface outcrop reading with no associated depth.station (str, optional) – Field station or outcrop label.
confidence (float) – Subjective reading confidence,
[0, 1](default 1.0).notes (str) – Free-text field note.
dip_direction_tolerance_deg (float)
Examples
>>> m = StructuralMeasurement( ... x=500.0, kind="bedding", strike_deg=45.0, dip_deg=30.0, ... dip_direction_deg=135.0, ... ) >>> m.dip_azimuth_ok True
- validate()#
Re-check and re-normalise this measurement’s fields.
Called automatically by
__post_init__, and byupdate()/clone()after they set new attribute values – both go through this method rather than__post_init__(which only runs once, at construction), so aclone(dip_direction_deg=...)that breaks the strike/dip-direction consistency check is caught rather than silently accepted.- Return type:
None
- classmethod from_right_hand_rule(x, kind, dip_direction_deg, dip_deg, **kwargs)#
Build from a dip-direction/dip pair, deriving strike.
Strike is set to
dip_direction_deg - 90(mod 360), the right-hand-rule convention: facing along strike with the dip direction to your right.
- class pycsamt.geology.LinearMeasurement(x, kind, trend_deg, plunge_deg, z=None, station=None, confidence=1.0, notes='')#
Bases:
PyCSAMTObjectA linear structural field measurement.
- Parameters:
x (float) – Position along the survey profile, metres.
kind (str) – Feature type, e.g.
'fold_axis','lineation','slickenline','fold_hinge','intersection_lineation'. Free text, as withStructuralMeasurement.trend_deg (float) – Compass direction the line plunges toward, degrees clockwise from north,
[0, 360).plunge_deg (float) – Angle below horizontal, degrees,
[0, 90].z (float, optional)
station (str, optional)
confidence (float)
notes (str)
Examples
>>> LinearMeasurement(x=500.0, kind="fold_axis", trend_deg=210.0, plunge_deg=15.0) LinearMeasurement(x=500.0 m, 'fold_axis', 210/15)
- validate()#
Re-check and re-normalise this measurement’s fields.
Called by
__post_init__and byupdate/clone; seeStructuralMeasurement.validate().- Return type:
None
- class pycsamt.geology.FaultTrace(x, dip_deg, downthrown_side, sense='unknown', throw_m=None, strike_deg=None, z_top=None, confidence=1.0, evidence='', notes='')#
Bases:
PyCSAMTObjectWhere a fault crosses the 2-D profile.
- Parameters:
x (float) – Profile position where the fault is picked, metres.
dip_deg (float) – Apparent dip of the fault plane in the section, degrees,
[0, 90](0 = flat detachment, 90 = vertical). This is the angle a 2-D EM section can actually constrain; the true 3-D dip differs unless the profile happens to run perpendicular to strike. Pass strike_deg separately when the true attitude is independently known (surface mapping, borehole).downthrown_side ({'left', 'right'}) – Which side of
x– toward decreasing or increasing profile distance – is downthrown.sense ({'normal', 'reverse', 'strike_slip', 'unknown'}) – Kinematic sense, where known (default
'unknown').throw_m (float, optional) – Vertical displacement, metres (magnitude; direction is carried by downthrown_side).
Nonewhen unknown or unmeasured.strike_deg (float, optional) – True compass strike, when independently known.
z_top (float, optional) – Depth to the top of the picked trace, metres.
Nonefor a surface trace or when unconstrained.confidence (float)
evidence (str) – Free-text source, e.g.
'resistivity offset','borehole','surface mapping'.notes (str)
Examples
>>> FaultTrace(x=500.0, dip_deg=70.0, downthrown_side="right", throw_m=12.0) FaultTrace(x=500.0 m, dip=70 deg, down=right, throw=12.0 m)
- validate()#
Re-check and re-normalise this trace’s fields.
Called by
__post_init__and byupdate/clone; seeStructuralMeasurement.validate().- Return type:
None
- class pycsamt.geology.StructuralModel(*, planar=None, linear=None, faults=None, metadata=None)#
Bases:
PyCSAMTObject,MetadataMixinCollection of structural evidence along one survey profile.
- Parameters:
planar (list of StructuralMeasurement, optional)
linear (list of LinearMeasurement, optional)
faults (list of FaultTrace, optional)
metadata (dict, optional) – Free-form provenance, e.g. survey name or source file paths.
Examples
>>> model = StructuralModel( ... faults=[FaultTrace(x=500.0, dip_deg=70.0, downthrown_side="right")], ... ) >>> len(model.faults) 1
- planar: list[StructuralMeasurement]#
- linear: list[LinearMeasurement]#
- faults: list[FaultTrace]#
- add_planar(measurement)#
- Parameters:
measurement (StructuralMeasurement)
- Return type:
None
- add_linear(measurement)#
- Parameters:
measurement (LinearMeasurement)
- Return type:
None
- add_fault(fault)#
- Parameters:
fault (FaultTrace)
- Return type:
None
- within(x_min, x_max)#
Return a new model restricted to
x_min <= x <= x_max.- Parameters:
- Return type:
- nearest(x, *, kind='faults', max_distance=None)#
Return the item of kind nearest to profile position x.
- Parameters:
- Return type:
StructuralMeasurement | LinearMeasurement | FaultTrace | None
- classmethod from_csv(*, planar_path=None, linear_path=None, faults_path=None, delimiter=',')#
Load a model from up to three CSV files, one per evidence type.
Expected columns (case-insensitive header, optional columns may be omitted):
planar_path –
x, kind, strike_deg, dip_deg, dip_direction_deg[, z, station, confidence, notes]linear_path –
x, kind, trend_deg, plunge_deg[, z, station, confidence, notes]faults_path –
x, dip_deg, downthrown_side[, sense, throw_m, strike_deg, z_top, confidence, evidence, notes]
Any path left as
Noneyields an empty list for that evidence type.
2.16.3. Geology Modules#
|
Borehole — ground-truth data model for EM geological interpretation. |
|
Lithology — resistivity-to-geology classification for EM methods. |
|
Built-in rock/fluid resistivity table for |
|
Pluggable rock-property sources for |
|
Structural geology — field measurements and fault traces. |