pycsamt.z.utils#
General utilities for working with impedance tensors (Z) and tippers.
This module provides small, composable helpers that complement
the object APIs in pycsamt.z.
Functions
|
Align a Z component/vector to a reference frequency grid. |
|
Correct an impedance tensor for sensor misorientation. |
|
Enforce the magnetotelluric property |
|
Normalize an impedance array to shape |
|
Boolean mask where all real and imaginary parts are finite. |
|
Convert period (s) to frequency (Hz). |
|
Invert Z (or each Z slice) with optional error propagation. |
|
Convert frequency (Hz) to period (s). |
|
Compute apparent resistivity and phase from Z. |
|
Rotate Z by |
|
Sigma-clip mask for outlier rejection. |
- pycsamt.z.utils.correct_for_sensor_orientation(z_prime, bx=0.0, by=90.0, ex=0.0, ey=90.0, z_prime_err=None)[source]#
Correct an impedance tensor for sensor misorientation.
Given measured fields in non-standard sensor frames,
\[\mathbf{E}' = \mathbf{Z}' \, \mathbf{B}',\]and change-of-basis matrices \(\mathbf{T}\) (for E) and \(\mathbf{U}\) (for B), the tensor in standard coordinates is
\[\mathbf{Z} = \mathbf{T} \, \mathbf{Z}' \, \mathbf{U}^{-1}.\]This function builds \(\mathbf{T}\) and \(\mathbf{U}\) from the sensor orientations and applies the transform.
- Parameters:
z_prime (ndarray) – Input impedance tensor(s). Shape
(2, 2)or(n_freq, 2, 2). Complex valued.bx (float, default 0, 90) – Orientations (deg) of Bx, By relative to geographic North (0°). Positive clockwise.
by (float, default 0, 90) – Orientations (deg) of Bx, By relative to geographic North (0°). Positive clockwise.
ex (float, default 0, 90) – Orientations (deg) of Ex, Ey relative to geographic North (0°). Positive clockwise.
ey (float, default 0, 90) – Orientations (deg) of Ex, Ey relative to geographic North (0°). Positive clockwise.
z_prime_err (ndarray, optional) – Standard deviations for \(\mathbf{Z}'\), same shape as
z_primeand real-valued. If provided, a conservative error propagation is applied (see Notes).
- Returns:
z (ndarray) – Orientation-corrected tensor(s), same shape as
z_prime.z_err (ndarray or None) – Propagated standard deviations in the default orientation.
Noneifz_prime_errwas not given.
- Return type:
Notes
Matrices \(\mathbf{T}\) and \(\mathbf{U}\) are real and built from unit vectors at angles
ex, eyandbx, byrespectively:T = [[cos(ex), cos(ey)], [sin(ex), sin(ey)]], U = [[cos(bx), cos(by)], [sin(bx), sin(by)]]Error propagation uses a simple 1-norm–like bound for \(Z = T Z' U^{-1}\):
\[\Delta Z \approx |T| \, \Delta Z' \, |U^{-1}|,\]applied element-wise by summation. This is conservative and ignores covariances.
Examples
>>> import numpy as np >>> from pycsamt.z.utils import correct_for_sensor_orientation >>> Zp = np.array([[0+0j, 1+1j], [-1-1j, 0+0j]]) >>> Z, Zerr = correct_for_sensor_orientation(Zp, bx=5, by=95)
- pycsamt.z.utils.periods_from_freq(freq, *, log10=False)[source]#
Convert frequency (Hz) to period (s).
- pycsamt.z.utils.freq_from_periods(period, *, log10=False)[source]#
Convert period (s) to frequency (Hz).
- pycsamt.z.utils.ensure_z3(z)[source]#
Normalize an impedance array to shape
(n_freq, 2, 2).- Parameters:
z (ndarray) – Array with shape
(2, 2)or(n_freq, 2, 2)(real or complex).- Returns:
Complex array of shape
(n_freq, 2, 2).- Return type:
ndarray
- Raises:
ZError – If the shape is not supported.
- pycsamt.z.utils.rho_phi_from_z(z, freq, z_err=None)[source]#
Compute apparent resistivity and phase from Z.
- Parameters:
z (ndarray) – Impedance tensor(s), shape
(2, 2)or(n, 2, 2).freq (array-like of float) – Frequency vector (Hz). Length must be
n.z_err (ndarray, optional) – Absolute errors for Z, same shape as
z. If given, uncertainties are propagated component-wise.
- Returns:
rho (ndarray) – Apparent resistivity (Ohm·m), shape
(n, 2, 2).phi (ndarray) – Phase (deg), shape
(n, 2, 2).rho_err (ndarray or None) – Error on resistivity (Ohm·m) or
Noneifz_errisNone.phi_err (ndarray or None) – Error on phase (deg) or
Noneifz_errisNone.
- Return type:
- pycsamt.z.utils.enforce_offdiag_antisymmetry(z, z_err=None)[source]#
Enforce the magnetotelluric property
Zxy = -Zyx.- Parameters:
z (ndarray) – Z tensor(s), shape
(2, 2)or(n, 2, 2).z_err (ndarray, optional) – Errors with same shape as
z. If provided, off-diagonal errors are combined via RMS.
- Returns:
z_new (ndarray) – Copy of Z with enforced antisymmetry on off-diagonals.
z_err_new (ndarray or None) – Propagated errors (off-diagonals via RMS), or
Noneifz_errwas not given.
- Return type:
Notes
We set
\[m = \tfrac{1}{2}(Z_{xy} - Z_{yx}),\; Z_{xy}=m,\; Z_{yx}=-m,\]which minimally enforces antisymmetry.
- pycsamt.z.utils.rotate_z(z, angle_deg, z_err=None)[source]#
Rotate Z by
angle_deg(CW positive), vectorized over freq.- Parameters:
- Returns:
z_rot (ndarray) – Rotated Z with same shape as
z.z_err_rot (ndarray or None) – Rotated error, if
z_errwas provided.
- Return type:
- pycsamt.z.utils.invert_z(z, z_err=None)[source]#
Invert Z (or each Z slice) with optional error propagation.
- Parameters:
z (ndarray) – Z tensor(s), shape
(2, 2)or(n, 2, 2).z_err (ndarray, optional) – Error tensor matching
zshape.
- Returns:
z_inv (ndarray) – Inverse of Z with same shape as
z.z_inv_err (ndarray or None) – Propagated error of Z inverse, or
Noneif no input error given.
- Raises:
ZError – If any slice is singular.
- Return type:
- pycsamt.z.utils.align_frequency_stack(ref_freq, freq, z, *, fill_value=nan)[source]#
Align a Z component/vector to a reference frequency grid.
This is a generalization of a “fit tensor” operation: values at
freqare placed at the matching indices ofref_freqand missing locations are filled withfill_value.- Parameters:
ref_freq (array-like of float) – Target frequency grid (Hz), length
N.freq (array-like of float) – Source frequency grid (Hz), length
Mwith values contained inref_freq(within exact match).z (ndarray) – Data to align. Shape must be compatible with the first dimension being
M(e.g.,(M,)or(M, 2, 2)).fill_value (scalar, default NaN) – Value used to fill missing entries.
- Returns:
Aligned array with shape
(N, ...).- Return type:
ndarray
- Raises:
ZError – If shapes are incompatible.
- pycsamt.z.utils.finite_mask(a)[source]#
Boolean mask where all real and imaginary parts are finite.
- Parameters:
a (ndarray) – Input array.
- Returns:
Mask with
Truefor finite entries.- Return type:
ndarray of bool