2.14.2.2. pycsamt.emtools.ztem#
ZTEM-specific spatial-domain processing, diagnostics, and plotting.
ZTEM (Z-axis Tipper Electromagnetic; Lo and Zang 2008) is an airborne
AFMAG technique: a helicopter-towed vertical-field (\(H_z\)) coil
is referenced to fixed-ground horizontal-field (\(H_x\),
\(H_y\)) base-station coils, giving exactly the same
\(H_z = T_{zx}H_x + T_{zy}H_y\) tipper relationship that
Site already carries as
tipper – the equivalence
pycsamt.emtools.afmag documents and that
pycsamt.airborne.ztem encodes at the file-format/adapter layer.
This module is therefore built, like pycsamt.emtools.afmag and
pycsamt.emtools.tf, entirely on Site.tipper.
It does not repeat what those two modules already do:
pycsamt.emtools.afmaggives per-station, per-frequency tilt- angle diagnostics (afmag_tilt_angles()) and motion-coupling QC – purely local quantities, no derivative across stations.pycsamt.emtools.tfgives generic tipper visualization (induction arrows, polar plots, period sections) that applies equally to ground MT tipper and airborne ZTEM tipper alike.
What is missing from both, and what ZTEM survey practice specifically relies on for a first-pass, pre-inversion read of a flight line (Sattel and Witherly 2012), is along-profile spatial-derivative processing – comparing a station’s tipper to its neighbours’ rather than looking at one station in isolation:
total_divergence_table()– the horizontal derivative of the in-line tipper component along the flight line. Lo and Zang (2008) define the (map-grid) “Total Divergence” as \(DT = \partial T_{zx}/\partial x + \partial T_{zy}/\partial y\) (the literal equation is reproduced, e.g., as eq. 6 of wang2025). Sattel and Witherly (2012) note that “for the 2D case, the horizontal derivative is equivalent to the Peaker (Pedersen et al., 1994) and the total divergence” – i.e. along one flight line the two published image products, DT and the VLF-style “Peaker”, coincide with a single along-line derivative \(\partial T/\partial x\). Reproducing the full map-grid DT (needing a true 2-D grid across multiple flight lines, not a singleSitesprofile) is out of scope here; this function computes exactly the along-profile quantity the source papers show is equivalent for the 2D/profile case, and says so in its own docstring rather than silently overclaiming the 3-D grid product.phase_rotate_table()– the “phase-rotated response” image product Sattel and Witherly (2012, their Fig. 2) show converts a tipper crossover anomaly (over a lateral contact) into a peak anomaly, “obtained by reduction-to-pole (RTP) filtering and Hilbert transformation”, noting “little difference between the RTP-filtered and the Hilbert-transformed profiles”. This function implements the Hilbert-transform half of that pair directly (scipy.signal.hilbert()), a standard, unambiguous spatial analytic-signal transform.mask_outside_ztem_band()– aSites-in/Sites-out QC gate (mirroringflag_motion_susceptible_band()’s mask/drop contract) that reuses the survey’s own published usable bandwidth,pycsamt.airborne.ztem.ZTEMSystemSpec .practical_frequency_range_hz, rather than inventing a new band definition – the one function in this module meant to sit inside a processing pipeline rather than only produce a diagnostic table.
Karous-Hjelt (1983) pseudo-depth current-density sections and the
Becken and Pedersen (2003) tipper-gradient apparent-resistivity/phase
transform are both mentioned by Sattel and Witherly (2012) as further
image products, but neither closed-form is reproduced in the papers
available locally (data/ZTEM/), so neither is implemented here –
consistent with not silently converting an unverified formula into a
“working” function.
References
Lo, B., and Zang, M. (2008). Numerical modeling of Z-TEM (airborne AFMAG) responses to guide exploration strategies. SEG Expanded Abstracts, 27, 1098-1101.
Legault, J. M., Zhao, S., and Fitch, R. (2012). ZTEM airborne AFMAG survey results over low sulphidation epithermal gold-silver vein systems at Gold Springs, south eastern Nevada. 22nd International Geophysical Conference and Exhibition (ASEG), Brisbane.
Sattel, D., and Witherly, K. (2012). An overview of ZTEM data interpretation tools. 2012 NFEM Forum.
Pedersen, L. B., Qian, W., Dynesius, L., and Zhang, P. (1994). An airborne tensor VLF system. From concept to realization. Geophysical Prospecting, 42, 863-883.
Wang, Y., Qu, J., Chen, T., Zhou, S., and Li, Y. (2025). Studies of three dimensional staggered-grid finite difference for Z-axis tipper electromagnetic numerical simulation. Frontiers in Earth Science, 13:1496312.
Functions
|
Mask/drop tipper frequencies outside the usable ZTEM band. |
|
Hilbert-transform "phase-rotated" ZTEM profile at one frequency. |
|
Plot before/after \(|T|\) pseudosections around the ZTEM usable band. |
|
Plot the ZTEM total-divergence / Peaker flight-line profile. |
|
Plot a ZTEM total-divergence pseudosection (station x log-period). |
|
Compare several flight lines' divergence pseudosections at once. |
|
Plot a Sattel and Witherly (2012, Fig. |
|
Legault et al. (2012, Fig. |
|
Plot raw vs. Hilbert-phase-rotated ZTEM response at one frequency. |
|
Legault et al. (2012, Fig. |
|
Along-profile ZTEM total-divergence / Peaker table. |
|
Legault et al. (2012, Fig. |
- pycsamt.emtools.ztem.ztem_crossover_diagnostics(sites, *, frequency_hz=None, period_s=None, component='tzx', spacing_m=200.0, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Legault et al. (2012, Fig. 6)-style raw in-phase/quadrature crossover.
Their own synthetic forward-model example over a mushroom-shaped epithermal target reads a negative-to-positive in-phase crossover directly above the target, generally accompanied by a (noisier) negative-to-positive quadrature crossover at every frequency – the qualitative, single-frequency, pre-processing read of a flight line before any derivative or transform is applied (contrast
total_divergence_table()/phase_rotate_table(), both of which operate on this same raw tipper but convert the crossover into a peak). This function finds those two crossovers and reports the peak-to-peak swing of each, the same crossover/amplitude measurementsoriginal_afmag_conductor_diagnostics()reports for the AFMAG comparator, applied here to the real/ imaginary parts of one tipper component instead of two hardware frequencies.Warning
Like
total_divergence_table(), sites is assumed to be one flight line; pre-filter a multi-line survey to one line first (see that function’s own warning for why).- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites().frequency_hz (float, optional) – Reference frequency/period; nearest available value is used. At most one may be given; the median frequency across the profile is used when neither is given.
period_s (float, optional) – Reference frequency/period; nearest available value is used. At most one may be given; the median frequency across the profile is used when neither is given.
component ({"tzx", "tzy"}, default "tzx") –
"tzx"is the classical in-line choice (Legault et al. 2012);"tzy"highlights cross-line structure (Sattel and Witherly 2012).spacing_m (float, default 200.0) – Forwarded to
_station_positions().recursive (bool) – Forwarded to
ensure_any_sites().on_dup (str) – Forwarded to
ensure_any_sites().strict (bool) – Forwarded to
ensure_any_sites().verbose (int) – Forwarded to
ensure_any_sites().
- Returns:
Keys:
freq_hz,crossover_real_m,crossover_imag_m(along-profile position,nanif that part never changes sign between its own max and min),peak_to_peak_real,peak_to_peak_imag, andprofile– apandas.DataFramewith columnsstation,position_m,real,imag(the raw, dimensionless tipper values; multiply by 100 for the percent convention Legault et al. 2012 and Sattel and Witherly 2012 both plot).- Return type:
- Raises:
ValueError – If component is not
"tzx"/"tzy", or fewer than 2 stations have a usable value at the resolved frequency.
- pycsamt.emtools.ztem.total_divergence_table(sites, spacing_m=200.0, *, component='tzx', recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Along-profile ZTEM total-divergence / Peaker table.
Computes the along-line horizontal derivative of the selected tipper component by first-order central-in-space finite differences between adjacent stations, at every frequency:
\[DT(j,\,f) \approx \frac{T(j+1,\,f) - T(j,\,f)}{x(j+1) - x(j)}\]where stations are ordered by chainage along the profile (see
_station_positions()). Per Sattel and Witherly (2012), this single along-line derivative is both the “Total Divergence” (Lo and Zang 2008) and the VLF-style “Peaker” (Pedersen et al. 1994) in the 2D/profile case – the full 3-D map-grid divergence (\(\partial T_{zx}/\partial x + \partial T_{zy}/\partial y\)) would additionally require a genuine cross-line (y) sampling that a singleSitesprofile does not carry, and is not attempted here.Warning
sites is assumed to be one flight line. Chainage comes from
_station_positions(), which projects every station onto a single bearing; passing a multi-line survey directly differentiates across line boundaries too, producing a physically meaningless value at every line-to-line join. Pre-filter to one line first (e.g.select()on a per-line predicate) before calling this function on a multi-line dataset – seeplot_ztem_map()’s ownquantity="divergence"branch for a worked example that does this per-line grouping automatically.- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(): groundSiteswhen the data carries an impedance channel too, orAirborneSitesfor genuine tipper-only ZTEM/AFMAG data (a path/directory of EMTF-XML is routed automatically based on what it contains).spacing_m (float, default 200.0) – Fall-back inter-station spacing [m] used only when no station coordinates are available; see
_station_positions().component ({"tzx", "tzy"}, default "tzx") – Tipper component to differentiate.
"tzx"is the classical in-line (flight-direction) choice (Legault et al. 2012);"tzy"highlights structures striking across the line (Sattel and Witherly 2012).recursive (bool) – Forwarded to
ensure_any_sites().on_dup (str) – Forwarded to
ensure_any_sites().strict (bool) – Forwarded to
ensure_any_sites().verbose (int) – Forwarded to
ensure_any_sites().
- Returns:
One row per (adjacent-station pair, frequency). Columns:
station_a,station_b(left/right station of the pair),x_m(pair midpoint chainage),dx_m(station spacing),freq_hz,period_s,divergence_real,divergence_imag[each in units of tipper per metre],divergence_abs. Pairs/frequencies with a missing tipper value on either side are omitted, not filled with zero.- Return type:
- Raises:
ValueError – If component is not
"tzx"or"tzy".
- pycsamt.emtools.ztem.phase_rotate_table(sites, *, frequency_hz=None, period_s=None, component='tzx', part='real', spacing_m=200.0, n_resample=None, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Hilbert-transform “phase-rotated” ZTEM profile at one frequency.
Reproduces the Hilbert-transform half of the phase-rotation image product described by Sattel and Witherly (2012, Fig. 2): the tipper component’s along-profile crossover anomaly (odd about the causative contact) is converted into a peak anomaly (even about it) by taking the imaginary part of its spatial analytic signal (
scipy.signal.hilbert()). Because the Hilbert transform assumes uniform sampling, the selected component is first linearly interpolated onto a uniform grid along chainage; the returned table is indexed by that uniform grid (with the nearest real station attached for reference), not by the original, generally unevenly spaced, station positions.Warning
Like
total_divergence_table(), sites is assumed to be one flight line: chainage is a single-bearing projection of every station, so a multi-line survey passed directly gets interpolated across line boundaries too. Pre-filter to one line first for a multi-line dataset.- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(): groundSiteswhen the data carries an impedance channel too, orAirborneSitesfor genuine tipper-only ZTEM/AFMAG data (a path/directory of EMTF-XML is routed automatically based on what it contains).frequency_hz (float, optional) – Target frequency/period; the nearest available frequency is used. At most one may be given; the median frequency across the profile is used when neither is given.
period_s (float, optional) – Target frequency/period; the nearest available frequency is used. At most one may be given; the median frequency across the profile is used when neither is given.
component ({"tzx", "tzy"}, default "tzx")
part ({"real", "imag"}, default "real") – Which part of the complex tipper to phase-rotate.
"real"(in-phase) matches the classical VLF/ZTEM crossover-to-peak image product.spacing_m (float, default 200.0) – Fall-back inter-station spacing [m]; see
_station_positions().n_resample (int, optional) – Number of points on the uniform resampling grid. Defaults to the number of stations with a valid value (minimum 64).
recursive (bool) – Forwarded to
ensure_any_sites().on_dup (str) – Forwarded to
ensure_any_sites().strict (bool) – Forwarded to
ensure_any_sites().verbose (int) – Forwarded to
ensure_any_sites().
- Returns:
Columns:
x_m(uniform-grid chainage),nearest_station,freq_hz,period_s,raw(the interpolated, un- rotated component),rotated(its Hilbert transform),envelope(the analytic-signal magnitude \(\sqrt{raw^2 + rotated^2}\)).- Return type:
- Raises:
ValueError – If component is not
"tzx"/"tzy", if part is not"real"/"imag", or if both frequency_hz and period_s are given.
- pycsamt.emtools.ztem.mask_outside_ztem_band(sites, *, band_hz=None, system_spec=None, action='mask', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Mask/drop tipper frequencies outside the usable ZTEM band.
Reuses the published usable bandwidth already carried by
pycsamt.airborne.ztem.ZTEMSystemSpec(defaultpractical_frequency_range_hzof 22-720 Hz) rather than inventing a new band definition. For groundSitesinput, this mirrors the sameensure_sites->_apply_eachmutation contract used byflag_motion_susceptible_band()andnotch_powerline(): this is the one function in this module meant to sit inside a processing pipeline (container in, container out) rather than only produce a diagnostic table. ForAirborneSitesinput,action="drop"is refused (see Raises) because it would leave theEMTFdocument’s shared period axis inconsistent with the tipper transfer function’s own periods; onlyaction="mask"is offered there, matchingmask_outside_mobilemt_band()’s identical restriction for the identical reason.- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(): groundSiteswhen the data carries an impedance channel too, orAirborneSitesfor genuine tipper-only ZTEM/AFMAG data (a path/directory of EMTF-XML is routed automatically based on what it contains).band_hz ((float, float), optional) – Explicit
(low, high)band in Hz. Mutually exclusive with system_spec; when neither is given, a defaultZTEMSystemSpec’spractical_frequency_range_hzis used.system_spec (pycsamt.airborne.ztem.ZTEMSystemSpec, optional) – Survey-specific system metadata to read the band from.
action ({"mask", "drop"}, default "mask") –
"mask"sets out-of-band tipper values tonanin place;"drop"removes the corresponding frequency rows entirely.inplace (bool) – Standard
emtoolsprocessing-function tail; seeflag_motion_susceptible_band()for the established convention this mirrors.recursive (bool) – Standard
emtoolsprocessing-function tail; seeflag_motion_susceptible_band()for the established convention this mirrors.on_dup (str) – Standard
emtoolsprocessing-function tail; seeflag_motion_susceptible_band()for the established convention this mirrors.strict (bool) – Standard
emtoolsprocessing-function tail; seeflag_motion_susceptible_band()for the established convention this mirrors.verbose (int) – Standard
emtoolsprocessing-function tail; seeflag_motion_susceptible_band()for the established convention this mirrors.
- Returns:
The (optionally new) sites collection with out-of-band tipper frequencies masked or dropped.
- Return type:
- Raises:
ValueError – If action is not
"mask"or"drop"; if both band_hz and system_spec are given; or if action is"drop"and sites resolves toAirborneSites.TypeError – If system_spec is given and is not a
ZTEMSystemSpec.
- pycsamt.emtools.ztem.plot_ztem_tipper_profile(sites, *, frequency_hz=None, period_s=None, component='tzx', as_percent=True, figsize=(9.5, 4.2), recursive=True, on_dup='replace', strict=False, verbose=0, ax=None)[source]
Legault et al. (2012, Fig. 6)-style raw in-phase/quadrature profile.
The classic ZTEM field-presentation figure: real (in-phase) and imaginary (quadrature) tipper plotted together at one frequency, in percent, along real flight-line chainage – Fig. 6’s own “METERS” x-axis, not a discrete station index – with each part’s crossover marked; see
ztem_crossover_diagnostics().- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites().frequency_hz (float | None) – Forwarded to
ztem_crossover_diagnostics().period_s (float | None) – Forwarded to
ztem_crossover_diagnostics().component (str) – Forwarded to
ztem_crossover_diagnostics().as_percent (bool, default True) – Multiply the plotted tipper values by 100, matching the percent convention both cited papers use. Set
Falseto plot the raw dimensionless tipper instead.figsize ((float, float), default (9.5, 4.2)) – Used only when ax is not supplied.
recursive (bool) – Forwarded to
ztem_crossover_diagnostics().on_dup (str) – Forwarded to
ztem_crossover_diagnostics().strict (bool) – Forwarded to
ztem_crossover_diagnostics().verbose (int) – Forwarded to
ztem_crossover_diagnostics().ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.
- Return type:
- pycsamt.emtools.ztem.plot_ztem_divergence_profile(sites, *, component='tzx', part='real', frequency_hz=None, period_s=None, spacing_m=200.0, figsize=(9.5, 4.0), station_label_step=1, station_preset='pseudosection', station_style=None, ax=None)[source]
Plot the ZTEM total-divergence / Peaker flight-line profile.
One value per adjacent-station pair at a single reference frequency/period – the along-line, pre-gridding form of the “Total Divergence” / “Peaker” image product (see
total_divergence_table()).- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(): groundSiteswhen the data carries an impedance channel too, orAirborneSitesfor genuine tipper-only ZTEM/AFMAG data (a path/directory of EMTF-XML is routed automatically based on what it contains).component ({"tzx", "tzy"}, default "tzx")
part ({"real", "imag"}, default "real")
frequency_hz (float, optional) – Reference frequency/period; nearest available value is used per station pair. At most one may be given; the median frequency across all pairs is used when neither is given.
period_s (float, optional) – Reference frequency/period; nearest available value is used per station pair. At most one may be given; the median frequency across all pairs is used when neither is given.
spacing_m (float, default 200.0) – Forwarded to
total_divergence_table().figsize ((float, float), default (9.5, 4.0)) – Used only when ax is not supplied.
station_label_step (int | None) – Forwarded to
style_for()via the shared top-of-section station convention.station_preset (str) – Forwarded to
style_for()via the shared top-of-section station convention.station_style (Any | None) – Forwarded to
style_for()via the shared top-of-section station convention.ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.
- Return type:
- pycsamt.emtools.ztem.plot_ztem_divergence_psection(sites, *, component='tzx', part='real', spacing_m=200.0, cmap='RdBu_r', clim=None, clim_pct=95.0, show_grid=True, show_contour=True, n_contour_levels=3, figsize=(9.0, 5.0), station_label_step=1, station_preset='pseudosection', station_style=None, ax=None)[source]
Plot a ZTEM total-divergence pseudosection (station x log-period).
A diverging, zero-centred colour scale is used, matching the physical sign convention of a spatial derivative (positive on one side of an anomaly, negative on the other – see
total_divergence_table()). Optional cell-boundary gridlines and a contour overlay (defaultn_contour_levels=3, one interior level – here the physically meaningful zero-divergence line itself) match the sameimshow/contourconvention used byplot_airmt_tilt_psection()andpycsamt.emtools.fieldzone’s own pseudosections. For several flight lines compared side by side on one shared colour scale, seeplot_ztem_divergence_psection_grid().- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(): groundSiteswhen the data carries an impedance channel too, orAirborneSitesfor genuine tipper-only ZTEM/AFMAG data (a path/directory of EMTF-XML is routed automatically based on what it contains).component ({"tzx", "tzy"}, default "tzx")
part ({"real", "imag"}, default "real")
spacing_m (float, default 200.0) – Forwarded to
total_divergence_table().cmap (str, default "RdBu_r") – Diverging colormap name.
clim ((float, float), optional) – Explicit, zero-centred color limits; overrides clim_pct.
clim_pct (float, default 95.0) – Percentile of
|divergence|used to size a symmetric colour range when clim is not given.show_grid (bool, default True) – Draw thin gridlines at every station-pair/period cell boundary.
show_contour (bool, default True) – Overlay n_contour_levels - 2 evenly-spaced contour lines with inline labels; with the default zero-centred colour scale and 3 levels, the single interior level drawn is the zero-divergence contour itself, i.e. the crossover/conductor axis at every period simultaneously.
n_contour_levels (int, default 3) – Number of evenly-spaced levels spanning clim before dropping the two outermost; must be at least 3 for any line to be drawn. Kept low deliberately – a coarse station/period grid does not support many contour levels without the lines tangling into visual noise (see
plot_airmt_tilt_psection()’s docstring for the same reasoning).figsize ((float, float), default (9.0, 5.0)) – Used only when ax is not supplied.
station_label_step (int | None) – See
plot_ztem_divergence_profile().station_preset (str) – See
plot_ztem_divergence_profile().station_style (Any | None) – See
plot_ztem_divergence_profile().ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.
- Return type:
- pycsamt.emtools.ztem.plot_ztem_divergence_psection_grid(sites, *, component='tzx', part='real', spacing_m=200.0, max_lines=6, n_cols=3, cmap='seismic', clim=None, clim_pct=95.0, show_grid=True, show_contour=True, n_contour_levels=3, panel_size=(4.3, 3.4), station_label_step=2, station_preset='pseudosection', station_style=None, axes=None, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Compare several flight lines’ divergence pseudosections at once.
Every panel shares one colour scale (unlike calling
plot_ztem_divergence_psection()once per line, where each panel would size its own), so colour differences between lines are directly comparable – the multi-line counterpart of a singleplot_ztem_divergence_psection()call, laid out on a grid with n_cols columns. Flight lines are detected from station geometry (see_detect_line_groups()); when more than max_lines are found, a spatially even subset is kept rather than just the first max_lines encountered.- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(), spanning several flight lines.component (str) – Forwarded to
total_divergence_table()for every line.part (str) – Forwarded to
total_divergence_table()for every line.spacing_m (float) – Forwarded to
total_divergence_table()for every line.max_lines (int, default 6) – Maximum number of lines to draw.
n_cols (int, default 3) – Number of grid columns; rows are added as needed.
cmap (str, default "seismic") – Diverging colormap name.
clim ((float, float), optional) – Explicit, zero-centred color limits shared by every panel; overrides clim_pct.
clim_pct (float, default 95.0) – Percentile of
|divergence|, pooled across every drawn line, used to size the shared symmetric colour range when clim is not given.show_grid (bool) – See
plot_ztem_divergence_psection().show_contour (bool) – See
plot_ztem_divergence_psection().n_contour_levels (int) – See
plot_ztem_divergence_psection().panel_size ((float, float), default (4.3, 3.4)) – Per-panel figure size in inches; the full figure scales with the number of rows/columns actually used. Ignored when axes is supplied.
station_label_step (int | None) – See
plot_ztem_divergence_profile().station_preset (str) – See
plot_ztem_divergence_profile().station_style (Any | None) – See
plot_ztem_divergence_profile().axes (sequence of Axes, optional) – Existing axes to draw the (up to max_lines) panels on, flattened in the same row-major order the auto-created grid would use; must provide at least as many axes as lines are actually drawn. When not given, a new figure and grid of axes is created.
recursive (bool) – Forwarded to
ensure_any_sites().on_dup (str) – Forwarded to
ensure_any_sites().strict (bool) – Forwarded to
ensure_any_sites().verbose (int) – Forwarded to
ensure_any_sites().
- Return type:
matplotlib.Figure
- pycsamt.emtools.ztem.plot_ztem_phase_rotation_profile(sites, *, component='tzx', part='real', frequency_hz=None, period_s=None, spacing_m=200.0, n_resample=None, figsize=(9.5, 4.2), recursive=True, on_dup='replace', strict=False, verbose=0, ax=None)[source]
Plot raw vs. Hilbert-phase-rotated ZTEM response at one frequency.
Direct reproduction of the crossover-to-peak comparison in Sattel and Witherly (2012, Fig. 2); see
phase_rotate_table().- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(): groundSiteswhen the data carries an impedance channel too, orAirborneSitesfor genuine tipper-only ZTEM/AFMAG data (a path/directory of EMTF-XML is routed automatically based on what it contains).component (str) – Forwarded to
phase_rotate_table().part (str) – Forwarded to
phase_rotate_table().frequency_hz (float | None) – Forwarded to
phase_rotate_table().period_s (float | None) – Forwarded to
phase_rotate_table().spacing_m (float) – Forwarded to
phase_rotate_table().n_resample (int | None) – Forwarded to
phase_rotate_table().figsize ((float, float), default (9.5, 4.2)) – Used only when ax is not supplied.
recursive (bool) – Forwarded to
phase_rotate_table().on_dup (str) – Forwarded to
phase_rotate_table().strict (bool) – Forwarded to
phase_rotate_table().verbose (int) – Forwarded to
phase_rotate_table().ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.
- Return type:
- pycsamt.emtools.ztem.plot_ztem_band_mask_psection(sites, *, band_hz=None, system_spec=None, component='abs', cmap='RdBu_r', figsize=(9.5, 8.0), axes=None, recursive=True, on_dup='replace', strict=False, verbose=0)[source]
Plot before/after \(|T|\) pseudosections around the ZTEM usable band.
Reuses
plot_induction_section()for both panels rather than re-implementing pseudosection gridding, andmask_outside_ztem_band()to compute the “after” sites.- Parameters:
sites (Sites-like) – Anything accepted by
ensure_any_sites(): groundSitesor tipper-onlyAirborneSitestransparently, sinceplot_induction_section()now accepts both.band_hz (tuple[float, float] | None) – Forwarded to
mask_outside_ztem_band().system_spec (Any | None) – Forwarded to
mask_outside_ztem_band().component ({"real", "imag", "abs"}, default "abs") – Forwarded to
plot_induction_section().cmap (str, default "RdBu_r")
figsize ((float, float), default (9.5, 8.0)) – Used only when axes is not supplied.
axes (sequence of 2 Axes, optional) – Existing axes (before, after) to draw on.
recursive (bool) – Forwarded to
ensure_any_sites()andmask_outside_ztem_band().on_dup (str) – Forwarded to
ensure_any_sites()andmask_outside_ztem_band().strict (bool) – Forwarded to
ensure_any_sites()andmask_outside_ztem_band().verbose (int) – Forwarded to
ensure_any_sites()andmask_outside_ztem_band().
- Return type:
matplotlib.Figure
- pycsamt.emtools.ztem.plot_ztem_flight_lines(sites, *, figsize=(7.0, 6.0), recursive=True, on_dup='replace', strict=False, verbose=0, ax=None)[source]
Plot a Sattel and Witherly (2012, Fig. 7)-style flight-line map.
Every detected flight line (see
_detect_line_groups()) is drawn as its own connected navigation trace, coloured distinctly (aviridissample per line) and labelled near its first station – with the real flight-line identifier when a technology note carries one (e.g. ZTEM’s ownmetadata["notes"]["ZTEM"]["LineId"]), or else a genericL1,L2, … in detected-group order, which need not match any real line numbering – with station markers. The plan-view counterpart of every other function in this module, which reads a single profile at a time. Longitude tick labels are rotated 45 degrees to avoid overlapping.- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites().figsize ((float, float), default (7.0, 6.0)) – Used only when ax is not supplied.
recursive (bool) – Forwarded to
ensure_any_sites().on_dup (str) – Forwarded to
ensure_any_sites().strict (bool) – Forwarded to
ensure_any_sites().verbose (int) – Forwarded to
ensure_any_sites().ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.
- Return type:
- pycsamt.emtools.ztem.plot_ztem_map(sites, *, quantity='tipper', part='real', component='tzx', frequency_hz=None, period_s=None, n_grid=120, cmap='RdBu_r', clim=None, clim_pct=95.0, show_stations=True, figsize=(8.0, 6.5), recursive=True, on_dup='replace', strict=False, verbose=0, ax=None)[source]
Legault et al. (2012, Fig. 7) and Sattel and Witherly (2012, Fig. 8-11)-style map-view grid.
Interpolates one scalar field at one frequency across every flight line in sites onto a regular map grid (
scipy.interpolate.griddata(), linear inside the convex hull of the stations, unfilled – leftnan– outside it rather than extrapolated) and images it with a diverging, zero-centred colour scale – the genuine multi-line map product both papers show (their “DT map”/”XIP grid”/”phase-rotated grid”), as opposed to every other function in this module, which reads one flight line as a profile or pseudosection.- Parameters:
sites (Sites-like or AirborneSites-like) – Anything accepted by
ensure_any_sites(). A genuine map needs several roughly-parallel flight lines; a single line still renders, as a thin interpolated strip along it.quantity ({"tipper", "divergence"}, default "tipper") –
"tipper"images the raw, un-processed tipper component (Legault et al. 2012, Fig. 7’s own “In-Phase” map);"divergence"images the along-line total-divergence / Peaker value (total_divergence_table()) at each station’s own flight line, matching Sattel and Witherly (2012)’s “DT” grid.part ({"real", "imag"}, default "real")
component ({"tzx", "tzy"}, default "tzx")
frequency_hz (float, optional) – Reference frequency/period; nearest available value is used per station. At most one may be given; the median frequency is used when neither is given.
period_s (float, optional) – Reference frequency/period; nearest available value is used per station. At most one may be given; the median frequency is used when neither is given.
n_grid (int, default 120) – Number of grid points along the longer map axis; the shorter axis is scaled to preserve the survey’s aspect ratio.
cmap (str, default "RdBu_r")
clim ((float, float), optional) – Explicit, zero-centred color limits; overrides clim_pct.
clim_pct (float, default 95.0) – Percentile of
|value|used to size a symmetric colour range when clim is not given.show_stations (bool, default True) – Overlay the actual station positions as small markers.
figsize ((float, float), default (8.0, 6.5)) – Used only when ax is not supplied.
recursive (bool) – Forwarded to
ensure_any_sites().on_dup (str) – Forwarded to
ensure_any_sites().strict (bool) – Forwarded to
ensure_any_sites().verbose (int) – Forwarded to
ensure_any_sites().ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.
- Return type:
- Raises:
ValueError – If quantity is not
"tipper"/"divergence", or part/component is invalid.