pycsamt.z.z#
Impedance tensor (Z) built on top of ResPhase.
This module defines the high-level Z class, which
inherits from ResPhase. It adds
conveniences around construction, input validation, storage of
the rotation history, and property setters for the impedance
tensor and the frequency vector.
Classes
|
High-level impedance tensor container built on |
- class pycsamt.z.z.Z(z_array=None, z_err_array=None, freq=None, *, name=None, meta=None, verbose=0)[source]#
Bases:
ResPhaseHigh-level impedance tensor container built on
ResPhase.Zstores complex impedances with shape(n, 2, 2)and manages absolute uncertainties of the same shape. A single(2, 2)matrix is promoted to a one-row stack.Frequency is held as a 1-D vector
(n,)in Hz. When either :pyattr:`z` or :pyattr:`freq` is set, apparent resistivity \(\rho\) and phase \(\phi\) are recomputed via the parent class.- Parameters:
z_array (ndarray, shape
(n, 2, 2)or(2, 2), optional) – Complex impedance tensor(s). Real arrays are cast to complex.z_err_array (ndarray, optional) – Absolute per-component errors on :pyattr:`z`. Shapes as for
z_arrayafter any promotion.freq (array-like of float, optional) – Frequency vector in Hz. Must be 1-D and strictly positive. Length must equal the number of rows in :pyattr:`z`.
meta (dict, optional) – Arbitrary metadata forwarded to
BaseEM.verbose (int, default 0) – Verbosity forwarded to
BaseEM.
- Variables:
z (ndarray or None) – Complex impedance stack, shape
(n, 2, 2).z_err (ndarray or None) – Absolute errors on :pyattr:`z`.
freq (ndarray or None) – Frequency vector in Hz.
rotation_angle (float or ndarray) – Accumulated rotation(s) in degrees (CW positive). A scalar before data are set; a length-
nvector once data exist.
Notes
The index convention is
Zxx→[:, 0, 0]Zxy→[:, 0, 1]Zyx→[:, 1, 0]Zyy→[:, 1, 1]
Uncertainties are absolute (not relative) and are propagated to \(\rho\) and \(\phi\) when available.
Examples
Create from a single tensor and frequency:
>>> import numpy as np >>> from pycsamt.z.z import Z >>> z = np.array([[0+0j, 1+1j], ... [-1-1j, 0+0j]]) >>> obj = Z(z_array=z, freq=[1.0]) >>> obj.resistivity.shape (1, 2, 2)
See also
pycsamt.z.resphase.ResPhaseImplements the \(\rho\) / \(\phi\) mapping and error propagation.
pycsamt.z.base.BaseEMMinimal mixin used for naming, metadata, and summary.
References
- classmethod from_res_phase(rho, phi, freq, *, rho_err=None, phi_err=None, name=None, meta=None, verbose=0)[source]#
Build a
Zinstance from \((\rho, \phi, f)\) (with errors).This convenience constructor reconstructs complex impedances from apparent resistivity \(\rho\), phase \(\phi\) (deg), and frequency, and attaches optional uncertainties. Internally it calls
set_res_phase().- Parameters:
rho (ndarray, shape
(n, 2, 2)) – Apparent resistivity (Ω·m).phi (ndarray, shape
(n, 2, 2)) – Phase (degrees).freq (ndarray, shape
(n,)) – Frequency in Hz. Must be strictly positive.rho_err (ndarray, optional) – Absolute error on \(\rho\) (same shape).
phi_err (ndarray, optional) – Absolute error on \(\phi\) (deg, same shape).
name (str | None) – Forwarded to the constructor.
meta (dict | None) – Forwarded to the constructor.
verbose (int) – Forwarded to the constructor.
- Returns:
A fully initialized impedance container.
- Return type:
Notes
The magnitude is recovered via
\[|Z| = \sqrt{5 \, f \, \rho} \, ,\]followed by Euler reconstruction using \(\phi\).
Examples
>>> import numpy as np >>> rho = np.ones((2, 2, 2)) >>> phi = np.zeros_like(rho) >>> f = np.array([10.0, 1.0]) >>> Z.from_res_phase(rho, phi, f).z.shape (2, 2, 2)
See also
pycsamt.z.resphase.ResPhase.set_res_phaseUnderlying implementation used here.
- property inverse: ndarray[source]#
Inverse tensor \(Z^{-1}\) for each frequency.
If
z_erris present, errors are propagated internally, but only the inverted tensor is returned (legacy API).
- rotate(alpha)[source]#
Rotate :pyattr:`z` by angle(s)
alpha(degrees, CW positive).The rotation is referenced to geographic axes (X→North, Y→East). A single angle is applied to all frequencies; a length-
nsequence applies element-wise angles. Errors are rotated consistently when present.- Parameters:
alpha (float or sequence of float) – Rotation angle(s) in degrees. If a sequence is given, its length must be 1 or equal to
n.- Raises:
pycsamt.exceptions.ZError – If :pyattr:`z` is missing or the number of angles is invalid.
- Return type:
None
Notes
The following are updated:
:pyattr:`z_err` (if present)
Derived \(\rho\) and \(\phi\)
Rotation uses
rotatematrix_incl_errors()per frequency.Examples
>>> import numpy as np >>> from pycsamt.z.z import Z >>> z = np.zeros((2, 2, 2), complex) >>> f = np.array([10.0, 1.0]) >>> obj = Z(z_array=z, freq=f) >>> obj.rotate(30.0) # single angle for all rows >>> obj.rotation_angle.shape (2,)
- remove_static_shift(reduce_res_factor_x=1.0, reduce_res_factor_y=1.0)[source]#
Remove static shift using resistivity-scale correction factors.
Assumes the observed tensor is \(Z = S \cdot Z_0\), with:
\[\begin{split}S = \begin{bmatrix} \sqrt{f_x} & 0 \\ 0 & \sqrt{f_y} \end{bmatrix}\end{split}\]where
f_xandf_yare resistivity-scale factors. The corrected tensor is then:\[Z_0 = S^{-1} \cdot Z\]- Parameters:
- Returns:
static_shift (ndarray, shape (n_freq, 2, 2)) – Static-shift matrices applied at each frequency.
z_corrected (ndarray, shape (n_freq, 2, 2)) – Corrected impedance tensor \(Z_0\).
- Raises:
ZError – If Z is missing or factor lengths are invalid.
- Return type:
Notes
Factors are in ρ scale; the matrix entries use their square roots. No uncertainty propagation is applied here.
- remove_distortion(distortion_tensor, distortion_err_tensor=None)[source]#
Remove galvanic distortion
Dfrom the observed impedance tensor \(Z\) to obtain the undistorted tensor \(Z_0 = D^{-1} Z\).Uncertainty propagation is included (first-order, 1-norm). If either
z_errordistortion_err_tensoris missing, zeros are assumed for the corresponding errors.- Parameters:
distortion_tensor (ndarray, shape (2, 2) or (n, 2, 2)) – Real 2×2 galvanic distortion matrix
D. If a stack is provided, only the first slice is used (distortion is assumed time-invariant).distortion_err_tensor (ndarray, shape (2, 2) or (n, 2, 2), ) – optional Absolute errors on
D. If omitted, zeros are assumed. If a stack is provided, only the first slice is used.
- Returns:
D (ndarray, shape (2, 2)) – The (real) distortion tensor used.
Z0 (ndarray, shape (n_freq, 2, 2)) – Corrected impedance tensor \(Z_0 = D^{-1} Z\).
Z0_err (ndarray or None, shape (n_freq, 2, 2)) – Propagated absolute errors on \(Z_0\).
Noneif both input errors wereNone.
- Raises:
ZError – If
Zis missing, distortion shapes are invalid, or the distortion matrix is singular.- Return type:
Notes
Error propagation for a component \((Z_0)_{ij} = \sum_k (D^{-1})_{ik} Z_{kj}\) uses the simple 1-norm bound:
\[\begin{split}\Delta (Z_0)_{ij} \approx \sum_k \\big( |\Delta (D^{-1})_{ik}| \cdot |Z_{kj}| + |(D^{-1})_{ik}| \\cdot |\Delta Z_{kj}| \big).\end{split}\]Examples
>>> D = np.array([[1.2, 0.5], [0.35, 2.1]]) >>> D_used, Z0, Z0_err = zobj.remove_distortion(D)
- property only_1d: ndarray[source]#
Return a 1-D-like version of \(Z\).
The diagonal entries are set to zero. The off-diagonal entries retain their complex signs, but their magnitudes are set to the mean of the original off-diagonal magnitudes at each frequency:
|Z01|, |Z10| → m = 0.5 (|Z01| + |Z10|) Z01 := sign(Z01) * m Z10 := sign(Z10) * m
- Returns:
New tensor with shape
(n_freq, 2, 2).- Return type:
ndarray
- property only_2d: ndarray[source]#
Return a 2-D-like version of \(Z\).
The diagonal entries are set to zero; off-diagonal terms are kept unchanged.
- Returns:
New tensor with shape
(n_freq, 2, 2).- Return type:
ndarray
- property trace: ndarray[source]#
Trace of \(Z\) at each frequency.
- Returns:
Array of shape
(n_freq,)with \(\operatorname{tr}(Z)\).- Return type:
ndarray
- property trace_err: ndarray | None[source]#
Approximate error on \(\operatorname{tr}(Z)\).
- Returns:
If
z_erris available, returns an array with shape(n_freq,)computed by summing the diagonal errors \(\Delta Z_{00} + \Delta Z_{11}\). OtherwiseNone.- Return type:
ndarray or None
- property skew: ndarray[source]#
Linear-algebra skew \(Z_{01} - Z_{10}\).
Note
This is not the MT skew used in dimensionality analysis; it is the simple matrix skew.
- Returns:
Array of shape
(n_freq,)with \(Z_{01} - Z_{10}\).- Return type:
ndarray
- property skew_err: ndarray | None[source]#
Approximate error on the linear-algebra skew.
- Returns:
If
z_erris available, returns an array with shape(n_freq,)computed as \(\Delta Z_{01} + \Delta Z_{10}\) (1-norm bound). OtherwiseNone.- Return type:
ndarray or None
- property det: ndarray[source]#
Determinant of \(Z\) at each frequency.
- Returns:
Array of shape
(n_freq,)with \(\det(Z)\).- Return type:
ndarray
- property det_err: ndarray | None[source]#
Approximate error on \(\det(Z)\).
Uses a central-difference style perturbation:
\[\begin{split}\Delta \det(Z) \approx \tfrac{1}{2}\\,\big|\det(Z+\Delta Z) - \det(Z-\Delta Z)\big|.\end{split}\]- Returns:
Array of shape
(n_freq,)with an error proxy, orNoneifz_erris not available.- Return type:
ndarray or None
- property norm: ndarray[source]#
Frobenius norm \(\lVert Z \rVert_F\) at each frequency.
- Returns:
Array of shape
(n_freq,)with Frobenius norms.- Return type:
ndarray
- property norm_err: ndarray | None[source]#
Approximate error on the Frobenius norm.
Uses a first-order bound combining real and imaginary parts.
- Returns:
Array of shape
(n_freq,)orNoneifz_erris not available.- Return type:
ndarray or None
- property invariants: dict[str, ndarray][source]#
Compute several algebraic invariants of \(Z\).
- Returns:
Dictionary with keys:
'z1'\(= (Z_{01} - Z_{10}) / 2\)'det'determinant of \(Z\)'det_real'determinant of \(\Re(Z)\)'det_imag'determinant of \(\Im(Z)\)'trace'trace of \(Z\)'skew'linear-algebra skew'norm'Frobenius norm'lambda_plus','lambda_minus': \(z_1 \pm \sqrt{z_1^2 / \det(Z)}\)'sigma_plus','sigma_minus': scalar combinations of norm and determinant magnitudes.
- Return type:
Notes
lambda_±are simple combinations frequently used in analytic manipulations of 2×2 matrices.sigma_±follow the historical form found in legacy code; they reduce to simple combinations of \(\lVert Z \rVert_F\) and \(|\det|\).
- remove_ss(reduce_res_factor_x=1.0, reduce_res_factor_y=1.0)#
Remove static shift using resistivity-scale correction factors.
Assumes the observed tensor is \(Z = S \cdot Z_0\), with:
\[\begin{split}S = \begin{bmatrix} \sqrt{f_x} & 0 \\ 0 & \sqrt{f_y} \end{bmatrix}\end{split}\]where
f_xandf_yare resistivity-scale factors. The corrected tensor is then:\[Z_0 = S^{-1} \cdot Z\]- Parameters:
- Returns:
static_shift (ndarray, shape (n_freq, 2, 2)) – Static-shift matrices applied at each frequency.
z_corrected (ndarray, shape (n_freq, 2, 2)) – Corrected impedance tensor \(Z_0\).
- Raises:
ZError – If Z is missing or factor lengths are invalid.
- Return type:
Notes
Factors are in ρ scale; the matrix entries use their square roots. No uncertainty propagation is applied here.