2.14.2.3. pycsamt.emtools.mobilemt#

MobileMT-specific processing, diagnostics, and plotting.

MobileMT (Prikhodko et al. 2022) is a natural-source airborne EM technology built on a fundamentally different scientific object than ZTEM/AFMAG: three orthogonal airborne magnetic coils (\(H_x, H_y, H_z\)) referenced to a fixed-ground horizontal electric dipole pair (\(E_x, E_y\)), giving a complex admittance tensor

\[\begin{split}\begin{pmatrix} H_x \\ H_y \\ H_z \end{pmatrix} = \begin{pmatrix} Y_{xx} & Y_{xy} \\ Y_{yx} & Y_{yy} \\ Y_{hzx} & Y_{hzy} \end{pmatrix} \begin{pmatrix} E_x \\ E_y \end{pmatrix}\end{split}\]

– the reciprocal relation of the classical MT impedance tensor \(Z\) (which gives \(E\) from \(H\)), not a tipper. This is why pycsamt.airborne.mobilemt maps it onto a dedicated mobilemt_admittance TransferFunction of shape (nf, 3, 2) rather than onto z or tipper, and why converting it to an EDI/Site is refused outright (EMTF.to_edi raises EMTFEDIConversionError for this transfer-function type – see pycsamt.airborne.mobilemt.tests.test_mobilemt_interop). Every emtools module before this one accepts and returns Sites; this module cannot honestly do that, so it works instead on the container hierarchy that already carries MobileMT’s real scientific content: AirborneEMDataset -> AirborneEMLine -> AirborneEMRecord. The public functions below accept a dataset (or one line, normalized through ensure_mobilemt_dataset(), this module’s ensure_sites counterpart) and return either a tidy table or a AirborneEMDataset – the closest honest analogue of the rest of emtools’s “sites in, sites/table out” contract.

ensure_mobilemt_dataset() also accepts anything ensure_asites() does – an AirborneSites/ AirborneSite, or a bare path/directory of EMTF-XML files – regrouping it into an AirborneEMDataset by each site’s line_id (a fresh, single-line grouping when that is unset) so a AirborneSites produced elsewhere in emtools – or a directory of raw MobileMT EMTF-XML – can flow straight into this module without an intermediate AirborneEMDataset construction step. This is deliberately one-directional, unlike ZTEM/AFMAG’s ensure_any_sites: the module still only ever returns a dataset (never AirborneSites), since its functions are organized around flight lines (plot_mobilemt_admittance_profile() and friends plot one line’s along-line chainage), not a flat station list.

Two kinds of quantity are computed here, and the distinction is kept visible in every column name:

  • Scale-invariant tensor diagnosticsadmittance_skew_table() (a Swift 1967-style skew ratio, \(|Y_{xx}+Y_{yy}| /|Y_{xy}-Y_{yx}|\), applied to the horizontal 2x2 admittance submatrix by direct algebraic analogy to the same ratio already used for the impedance tensor). Being a ratio of magnitudes, it needs no absolute physical constant and is safe to compute directly from any admittance tensor.

  • Theoretical apparent conductivity/phaseadmittance_determinant_table()’s theoretical_* columns. In the co-located-sensor limit, the MobileMT admittance tensor equals the classical MT admittance \(Z^{-1}\) (stated explicitly by Zhdanov et al. 2024 and Sattel et al. 2019). Applying that identity to pyCSAMT’s own, already-shipped and tested Berdichevsky-determinant convention for \(Z\) (pycsamt.z.resphase.ResPhase’s res_det/phase_det, \(\rho_a = 0.2\,|\det Z|/f\), \(\varphi = \arg\sqrt{\det Z}\)) gives, by direct algebraic substitution (\(\det Y = 1/\det Z\)):

    \[\sigma_a = 5\,f\,|\det Y|, \qquad \varphi_a = -\arg\sqrt{\det Y}\]

    This is a derived theoretical quantity, not a reproduction of MobileMT’s proprietary processed apparent-conductivity product – build_mobilemt_record()’s own docstring explicitly declines to derive that vendor quantity (“a verified delivery schema is required before pyCSAMT should codify its exact exported representation”), and this module respects that same restraint by never presenting the derived theoretical_* columns as the vendor product. When a record already carries the vendor-delivered fields["apparent_conductivity"], every table here reports it alongside as apparent_conductivity_native_Sm for direct comparison, and plot_mobilemt_conductivity_psection() can plot either one explicitly via its source argument.

References

[Prikhodko2022]

Prikhodko, A., Bagrianski, A., Kuzmin, P., and Sirohey, A. (2022). Natural field airborne electromagnetics – history of development and current exploration capabilities. Minerals, 12(5), 583.

[Sattel2019]

Sattel, D., Witherly, K., and Kaminski, V. (2019). A brief analysis of MobileMT data. SEG International Exposition and Annual Meeting, D043S102R007.

[Zhdanov2024]

Zhdanov, M. S., Gribenko, A., Prikhodko, A., Sabra, H. E., Jorgensen, M., and Cox, L. H. (2024). Three-dimensional MobileMT and TMI data inversions for mineral exploration. 1st ASEG DISCOVER Symposium.

[Swift1967]

Swift, C. M. (1967). A magnetotelluric investigation of an electrical conductivity anomaly in the southwestern United States. PhD thesis, MIT.

Functions

admittance_determinant_table(dataset)

Return the theoretical Berdichevsky-determinant admittance table.

admittance_skew_table(dataset)

Return a Swift (1967)-style skew table for the admittance tensor.

admittance_table(dataset)

Return a tidy per-(line, sample, frequency) admittance table.

ensure_mobilemt_dataset(obj)

Normalize a dataset or single line to an AirborneEMDataset.

mask_outside_mobilemt_band(dataset, *[, ...])

Mask admittance/conductivity outside the usable MobileMT band.

plot_mobilemt_admittance_profile(dataset, *)

Plot one admittance component along one flight line.

plot_mobilemt_conductivity_psection(dataset, *)

Plot an apparent-conductivity pseudosection for one flight line.

plot_mobilemt_skew_profile(dataset, *[, ...])

Plot the admittance skew profile along one flight line.

pycsamt.emtools.mobilemt.ensure_mobilemt_dataset(obj)[source]

Normalize a dataset or single line to an AirborneEMDataset.

The single entry-point validator for every public function in this module, mirroring the role ensure_sites() plays for the rest of emtools.

Parameters:

obj (AirborneEMDataset or AirborneEMLine or AirborneSites or AirborneSite or str or pathlib.Path) – Accepted as-is when already a dataset; a single line is wrapped in a new one-line dataset. An AirborneSites/ AirborneSite, or a path to a single EMTF-XML file or a directory of them, is first coerced via ensure_asites() and then regrouped into flight lines by line_id (see _dataset_from_asites()).

Return type:

AirborneEMDataset

Raises:

TypeError – If obj is none of the accepted types.

pycsamt.emtools.mobilemt.admittance_table(dataset)[source]

Return a tidy per-(line, sample, frequency) admittance table.

Parameters:

dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

Returns:

Columns: line_id, sample_id, x_m (chainage along the flight line, see _station_positions()’s along-profile convention), freq_hz, period_s, the real/imaginary parts of every entry of the horizontal 2x2 admittance (Yxx, Yxy, Yyx, Yyy) and of the vertical-field row (Yhzx, Yhzy), and apparent_conductivity_native_Sm – the vendor-delivered processed field (MOBILEMT_APPARENT_CONDUCTIVITY_FIELD) when present, NaN otherwise.

Return type:

pandas.DataFrame

pycsamt.emtools.mobilemt.admittance_determinant_table(dataset)[source]

Return the theoretical Berdichevsky-determinant admittance table.

See the module docstring for the full derivation. In brief, using the horizontal 2x2 admittance submatrix \(Y = \begin{pmatrix}Y_{xx}&Y_{xy}\\Y_{yx}&Y_{yy}\end{pmatrix}\) and the co-located-sensor identity \(Y=Z^{-1}\) (Zhdanov et al. 2024; Sattel et al. 2019), applying pyCSAMT’s own \(Z\)-determinant convention (pycsamt.z.resphase.ResPhase) by substitution gives:

\[Y_{\mathrm{eff}} = \sqrt{\det Y}, \qquad \sigma_a = 5\,f\,|Y_{\mathrm{eff}}|^2, \qquad \varphi_a = -\arg(Y_{\mathrm{eff}})\]
Parameters:

dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

Returns:

Columns: line_id, sample_id, x_m, freq_hz, period_s, det_abs (\(|\det Y|\)), theoretical_sigma_a_Sm, theoretical_rho_a_ohm_m (\(1/\sigma_a\)), theoretical_phase_deg, and apparent_conductivity_native_Sm (the vendor-delivered field, for direct comparison, NaN when absent). Samples with a non-finite determinant are omitted.

Return type:

pandas.DataFrame

Notes

The theoretical_* columns are a derived quantity assuming ideal co-located sensors; they are not a reproduction of MobileMT’s proprietary processed apparent-conductivity output. Prefer apparent_conductivity_native_Sm whenever it is present.

pycsamt.emtools.mobilemt.admittance_skew_table(dataset)[source]

Return a Swift (1967)-style skew table for the admittance tensor.

\[\mathrm{skew} = \frac{|Y_{xx} + Y_{yy}|}{|Y_{xy} - Y_{yx}|}\]

applied to the horizontal 2x2 admittance submatrix by direct algebraic analogy to the identical ratio already used for the impedance tensor elsewhere in pyCSAMT. Being a ratio of magnitudes, it needs no absolute physical constant and is safe to compute directly, unlike admittance_determinant_table()’s theoretical_* columns. Large values flag departures from an ideal 1D/2D-consistent admittance tensor (instrument coupling, cultural noise, genuinely 3-D structure).

Parameters:

dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

Returns:

Columns: line_id, sample_id, x_m, freq_hz, period_s, skew. Non-finite values are omitted.

Return type:

pandas.DataFrame

pycsamt.emtools.mobilemt.mask_outside_mobilemt_band(dataset, *, band_hz=None, system_spec=None, inplace=False)[source]

Mask admittance/conductivity outside the usable MobileMT band.

Reuses the published usable bandwidth already carried by MobileMTSystemSpec (default nominal_frequency_range_hz of 19-26,000 Hz) rather than inventing a new band definition. This is the one function in this module meant to sit inside a processing pipeline (dataset in, dataset out) rather than only produce a diagnostic table – the closest analogue here to flag_motion_susceptible_band() and mask_outside_ztem_band().

Unlike those two functions, only masking is offered (no action="drop"): each AirborneEMRecord packages its admittance transfer function and any auxiliary per-frequency fields (variance, covariances, native apparent conductivity) around one shared period axis, and safely dropping frequencies would require rebuilding all of them consistently. Masking with nan needs no such reconstruction and never confuses “known bad” with a physical zero.

Parameters:
  • dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

  • band_hz ((float, float), optional) – Explicit (low, high) band in Hz. Mutually exclusive with system_spec; when neither is given, a default MobileMTSystemSpec’s nominal_frequency_range_hz is used.

  • system_spec (MobileMTSystemSpec, optional) – Survey-specific system metadata to read the band from.

  • inplace (bool, default False) – When False (default), a deep copy of dataset is masked and returned, leaving the input untouched.

Returns:

The (optionally new) dataset with out-of-band admittance values and native apparent-conductivity samples set to nan.

Return type:

AirborneEMDataset

Raises:
  • ValueError – If both band_hz and system_spec are given.

  • TypeError – If system_spec is given and is not a MobileMTSystemSpec.

pycsamt.emtools.mobilemt.plot_mobilemt_admittance_profile(dataset, *, line_id=None, component='det', part='abs', frequency_hz=None, period_s=None, figsize=(9.5, 4.0), ax=None)[source]

Plot one admittance component along one flight line.

Parameters:
  • dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

  • line_id (str, optional) – Flight line to plot; defaults to the first line in dataset.

  • component ({"xx", "xy", "yx", "yy", "hzx", "hzy", "det"}, default "det") – Admittance entry to plot, or "det" for the horizontal 2x2 determinant (see admittance_determinant_table()).

  • part ({"real", "imag", "abs"}, default "abs")

  • frequency_hz (float, optional) – Reference frequency/period; nearest available value is used per sample. 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 sample. At most one may be given; the median frequency is used when neither is given.

  • figsize ((float, float), default (9.5, 4.0)) – Used only when ax is not supplied.

  • ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.

Return type:

matplotlib.axes.Axes

pycsamt.emtools.mobilemt.plot_mobilemt_conductivity_psection(dataset, *, line_id=None, source='theoretical', cmap='viridis', clim=None, clim_pct=(2.0, 98.0), figsize=(9.0, 5.0), ax=None)[source]

Plot an apparent-conductivity pseudosection for one flight line.

Parameters:
  • dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

  • line_id (str, optional) – Flight line to plot; defaults to the first line in dataset.

  • source ({"theoretical", "native"}, default "theoretical") – "theoretical" plots admittance_determinant_table()’s derived theoretical_sigma_a_Sm (see the module docstring for the caveat); "native" plots the vendor-delivered apparent_conductivity_native_Sm field, when present.

  • cmap (str, default "viridis")

  • clim ((float, float), optional) – Explicit color limits; overrides clim_pct.

  • clim_pct ((float, float), default (2.0, 98.0)) – Percentile color limits when clim is not given.

  • figsize ((float, float), default (9.0, 5.0)) – Used only when ax is not supplied.

  • ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.

Return type:

matplotlib.axes.Axes

Raises:

ValueError – If source is not "theoretical" or "native".

pycsamt.emtools.mobilemt.plot_mobilemt_skew_profile(dataset, *, line_id=None, frequency_hz=None, period_s=None, figsize=(9.5, 4.0), ax=None)[source]

Plot the admittance skew profile along one flight line.

See admittance_skew_table() for the underlying formula.

Parameters:
  • dataset (AirborneEMDataset or AirborneEMLine) – Anything accepted by ensure_mobilemt_dataset().

  • line_id (str, optional) – Flight line to plot; defaults to the first line in dataset.

  • frequency_hz (float, optional) – Reference frequency/period; nearest available value is used per sample. 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 sample. At most one may be given; the median frequency is used when neither is given.

  • figsize ((float, float), default (9.5, 4.0)) – Used only when ax is not supplied.

  • ax (matplotlib.axes.Axes, optional) – Existing axes to draw on.

Return type:

matplotlib.axes.Axes