2.14.4.4. pycsamt.emtools.csumt#
Controlled-source ultra-audio MT depth and survey-planning tools.
The module converts apparent resistivity and transmitter frequency into Bostick depth estimates, evaluates vertical resolution and depth coverage, designs CSUMT frequency schedules, and plots depth sections for survey sites.
Module Attributes
|
Bostick depth constant in metres: |
|
9.6 kHz (zhang2025). |
|
614.4 kHz (zhang2025). |
Functions
|
Bostick depth estimate per station per frequency from measured data. |
|
Bostick depth estimate D(f) from apparent resistivity. |
|
Summary depth-coverage statistics per station. |
|
Invert the Bostick formula: return the frequency (Hz) that maps to a given depth for a background resistivity rho. |
|
Design a CSUMT frequency schedule that samples a set of target depths. |
|
Horizontal ranking of the deepest Bostick depth reached per station. |
|
Pseudosection of Bostick depth across stations and periods/frequencies. |
|
Visualize which requested target depths survive the CSUMT band filter applied by |
|
Vertical resolution ΔD between adjacent frequencies per station. |
|
Vertical resolution ΔD between two adjacent frequencies. |
- pycsamt.emtools.csumt.bostick_depth_from_rho(rho, freq)[source]
Bostick depth estimate D(f) from apparent resistivity.
D(f) = 356 × √(ρ_a / f) [metres]
- Parameters:
- Returns:
Depth in metres, same shape as broadcast of rho and freq.
- Return type:
References
Zhang et al. (2025), Eq. (1), Measurement.
- pycsamt.emtools.csumt.vertical_resolution_pair(rho, f_lo, f_hi)[source]
Vertical resolution ΔD between two adjacent frequencies.
ΔD = 356 × √ρ_c × (1/√f_lo − 1/√f_hi) [metres; f_lo < f_hi]
- Parameters:
- Returns:
Vertical resolution in metres. Positive when f_lo < f_hi.
- Return type:
References
Zhang et al. (2025), Eq. (2), Measurement.
- pycsamt.emtools.csumt.frequency_for_depth(depth_m, rho)[source]
Invert the Bostick formula: return the frequency (Hz) that maps to a given depth for a background resistivity rho.
f = ρ × (356 / D)² [Hz]
- Parameters:
- Returns:
Frequency in Hz, same shape as depth_m.
- Return type:
- pycsamt.emtools.csumt.frequency_schedule(target_depths, rho_estimate, *, f_min=9600.0, f_max=614400.0, min_resolution_m=None, fill_decades=False, per_decade=3, as_khz=False)[source]
Design a CSUMT frequency schedule that samples a set of target depths.
Each target depth is converted to a frequency via
frequency_for_depth(), then clipped to [f_min, f_max]. Optionally, intermediate frequencies can be inserted to guarantee a minimum vertical resolution between consecutive depth levels.- Parameters:
target_depths (float or array) – Target depths in metres (deepest first or any order — sorted internally).
rho_estimate (float) – Background apparent resistivity ρ (Ω·m) used for the conversion.
f_min (float, default=9.6e3) – Minimum transmitter frequency in Hz (lower bound of CSUMT range).
f_max (float, default=614.4e3) – Maximum transmitter frequency in Hz (upper bound of CSUMT range).
min_resolution_m (float or None) – If given, insert additional frequencies between adjacent target depths whenever their vertical resolution would exceed this value.
fill_decades (bool, default=False) – If True, add per_decade log-spaced frequencies within each decade of the schedule to smooth coverage.
per_decade (int, default=3) – Number of extra frequencies to insert per decade when fill_decades is True.
as_khz (bool, default=False) – If True, return frequencies in kHz instead of Hz.
- Returns:
Sorted frequencies in Hz (or kHz if as_khz is True).
- Return type:
References
Zhang et al. (2025), “Controlled source ultra-audio frequency magnetotellurics (CSUMT) transmitter”, Measurement.
- pycsamt.emtools.csumt.plot_frequency_schedule(target_depths, rho_estimate, *, f_min=9600.0, f_max=614400.0, ax=None, figsize=(7.0, 5.0), title='Frequency schedule from target depths')[source]
Visualize which requested target depths survive the CSUMT band filter applied by
frequency_schedule().Each target depth is converted to its raw frequency with
frequency_for_depth()and drawn as an open circle. Targets whose raw frequency falls inside [f_min, f_max] are additionally marked with a cross – exactly the filterfrequency_schedule()applies before anymin_resolution_mpadding. This makes the schedule’s silent clipping of unreachable targets visible instead of only reporting a row count.- Parameters:
target_depths (float or array) – Target depths in metres, as passed to
frequency_schedule().rho_estimate (float) – Background apparent resistivity ρ (Ω·m).
f_min (float) – CSUMT transmitter band, default
F_MIN_CSUMT/F_MAX_CSUMT.f_max (float) – CSUMT transmitter band, default
F_MIN_CSUMT/F_MAX_CSUMT.ax (matplotlib.axes.Axes, optional)
title (str)
- Return type:
Examples
>>> from pycsamt.emtools.csumt import plot_frequency_schedule >>> ax = plot_frequency_schedule([10.0, 20.0, 35.0, 50.0, 65.0], 300.0)
- pycsamt.emtools.csumt.bostick_depth(sites, *, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Bostick depth estimate per station per frequency from measured data.
Uses the apparent resistivity derived from the off-diagonal impedance tensor components (geometric mean):
D(f) = 356 × √(ρ_a(f) / f) [metres]
- Parameters:
- Returns:
One row per (station, frequency) with columns:
station,freq_hz,period_s,rho_a_ohmm,depth_m.- Return type:
References
Zhang et al. (2025), Eq. (1).
- pycsamt.emtools.csumt.vertical_resolution(sites, *, rho_override=None, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Vertical resolution ΔD between adjacent frequencies per station.
For each consecutive pair (f_lo, f_hi) in the station’s frequency list (sorted ascending), computes:
ΔD = D(f_lo) − D(f_hi) [metres]
using the Bostick depths derived from the measured ρ_a. Alternatively, supply rho_override to use a fixed background resistivity with the analytical formula
356 × √ρ × (1/√f_lo − 1/√f_hi).- Parameters:
rho_override (float or None) – If given, use this constant resistivity for all ΔD calculations (analytical formula) instead of the per-frequency ρ_a.
recursive (bool) – Forwarded to
ensure_sites().on_dup (str) – Forwarded to
ensure_sites().strict (bool) – Forwarded to
ensure_sites().verbose (int) – Forwarded to
ensure_sites().
- Returns:
Columns:
station,freq_lo_hz,freq_hi_hz,depth_lo_m,depth_hi_m,delta_depth_m,rho_a_ohmm.- Return type:
- pycsamt.emtools.csumt.depth_coverage_table(sites, *, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Summary depth-coverage statistics per station.
- Parameters:
- Returns:
One row per station with columns:
station,n_freq,freq_min_hz,freq_max_hz,depth_min_m,depth_max_m,mean_resolution_m,median_resolution_m.- Return type:
- pycsamt.emtools.csumt.plot_depth_section(sites, *, log_color=True, sort_by=None, cmap='viridis_r', figsize=(10.0, 5.0), period_axis=True, recursive=True, on_dup='replace', strict=False, verbose=0, ax=None)[source]
Pseudosection of Bostick depth across stations and periods/frequencies.
Each cell (station × period) is coloured by the Bostick depth D(f) = 356 √(ρ_a / f).
- Parameters:
log_color (bool, default=True) – Color by log10(depth) instead of depth.
sort_by ({"auto", "chainage", "input", "name", "lon", "lat"}, optional) – Station ordering along the x-axis.
Noneinheritspycsamt.api.PYCSAMT_ORDERING.cmap (str, default="viridis_r") – Matplotlib colormap name.
period_axis (bool, default=True) – If True y-axis is period (s); otherwise frequency (Hz).
recursive (bool) – Forwarded to
ensure_sites().on_dup (str) – Forwarded to
ensure_sites().strict (bool) – Forwarded to
ensure_sites().verbose (int) – Forwarded to
ensure_sites().ax (matplotlib.axes.Axes, optional)
- Return type:
- pycsamt.emtools.csumt.plot_depth_coverage_ranking(sites, *, depth_unit='km', flag_coarse_resolution=True, color_fine='#2e6f9e', color_coarse='#c0392b', title='Per-station Bostick depth coverage', ax=None, figsize=None, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Horizontal ranking of the deepest Bostick depth reached per station.
Reduces
depth_coverage_table()to one horizontal bar per station, sorted bydepth_max_mdescending – the fastest way to see which stations drive a line’s overall depth coverage. When flag_coarse_resolution is True, stations whosemedian_resolution_mis coarser than the survey-wide median are drawn in color_coarse rather than color_fine, so a station that only reaches deep with coarse vertical resolution is visually distinguished from one that reaches comparable depth with fine resolution.- Parameters:
sites (path, EDI-like, Sites, or iterable) – Any input accepted by
ensure_sites().depth_unit ({"km", "m"}, default="km") – Unit for the plotted depth axis.
flag_coarse_resolution (bool, default=True) – Colour bars by whether the station’s median vertical resolution exceeds the survey-wide median.
color_fine (str) – Bar colours for resolution at-or-finer than, and coarser than, the survey median.
color_coarse (str) – Bar colours for resolution at-or-finer than, and coarser than, the survey median.
title (str)
ax (matplotlib.axes.Axes, optional)
figsize ((float, float), optional) – Defaults to a height that grows with the station count.
recursive (bool) – Forwarded to
ensure_sites().on_dup (str) – Forwarded to
ensure_sites().strict (bool) – Forwarded to
ensure_sites().verbose (int) – Forwarded to
ensure_sites().
- Return type:
Examples
>>> from pycsamt.emtools.csumt import plot_depth_coverage_ranking >>> ax = plot_depth_coverage_ranking("data/AMT/WILLY_DATA/L18PLT")