pycsamt.z.tipper#

Tipper

Classes

Tipper([tipper_array, tipper_err_array, ...])

Induction tipper container with derived quantities.

class pycsamt.z.tipper.Tipper(tipper_array=None, tipper_err_array=None, freq=None, *, name=None, **kw)[source]#

Bases: EMBase

Induction tipper container with derived quantities.

The class stores complex tipper components \((T_x, T_y)\) per frequency and provides convenience computations:

  • amplitude / phase of each component

  • Parkinson induction arrows (magnitude and direction) for real and imaginary parts

  • rotation of the tipper with optional error propagation

Internally, data are kept with shape (n_freq, 1, 2) where the last axis is ordered as [T_x, T_y]. Several common input shapes are accepted and normalized on assignment.

Parameters:
  • tipper_array (array-like, optional) –

    Complex tipper values. Accepted shapes:

    • (n_freq, 1, 2) (preferred)

    • (n_freq, 2) (promoted)

    • (2,) or (1, 2) (single row)

    The last axis is ordered as [T_x, T_y].

  • tipper_err_array (array-like, optional) – Absolute errors with the same normalized shape as tipper_array. If None, uncertainties are not propagated.

  • freq (array-like of float, optional) – Frequency vector in Hz. Length must be n_freq and values strictly positive.

  • name (str | None)

  • kw (Any)

Variables:
  • tipper (ndarray or None) – Complex tipper, shape (n_freq, 1, 2).

  • tipper_err (ndarray or None) – Absolute errors on :pyattr:`tipper`.

  • freq (ndarray or None) – Frequency vector (Hz).

  • rotation_angle (float or ndarray) – Cumulative rotation (deg, clockwise positive). Stored as a scalar or length n_freq vector.

  • phase (amplitude,) – \(|T|\) and phase (deg) for each component. Shape (n_freq, 1, 2).

  • phase_err (amplitude_err,) – Propagated absolute amplitude error and absolute phase error (deg), or None.

  • mag_imag (mag_real,) – Parkinson arrow magnitudes built from the real and imaginary parts, shape (n_freq,).

  • angle_imag (angle_real,) – Parkinson arrow directions (deg), real and imag, shape (n_freq,).

  • angle_err (mag_err,) – Heuristic uncertainty proxies for arrow metrics, or None.

Notes

  • Shape normalization. Inputs with shape (n_freq, 2) or (2,) are promoted to (n_freq, 1, 2). Errors follow the same rules.

  • Parkinson convention. Arrow directions use a minus sign so arrows point towards conductors:

    \[\theta = \operatorname{atan2}(-Y,\,-X)\]

    where \((X, Y)\) are the component pairs taken from either the real or the imaginary part.

  • Rotation. Angles are clockwise-positive and referenced to geographic North (X→North, Y→East).

Examples

Minimal construction and amplitude / phase:

>>> import numpy as np
>>> from pycsamt.z.tipper import Tipper
>>> T = np.array([[1+1j, 0+1j]])
>>> tip = Tipper(tipper_array=T)          # (1, 2)
>>> tip.amplitude.shape, tip.phase.shape
((1, 1, 2), (1, 1, 2))

Parkinson arrows for a known direction:

>>> th = np.deg2rad(30.0)
>>> Tarr = np.zeros((1, 1, 2), complex)
>>> Tarr[0, 0, 0] = -np.cos(th) + 0j
>>> Tarr[0, 0, 1] = -np.sin(th) + 0j
>>> tip = Tipper(tipper_array=Tarr)
>>> float(tip.mag_real[0])
1.0
>>> float(tip.angle_real[0])
30.0

See also

pycsamt.utils.zmath.rotatevector_incl_errors

Rotation with error propagation.

pycsamt.z.base.BaseEM

Shared container utilities.

References

property tipper: ndarray | None[source]#
property tipper_err: ndarray | None[source]#
property freq: ndarray | None[source]#
compute_amp_phase()[source]#

Compute \(|T|\) and phase (deg) for each component.

For every frequency and for both components \((T_x, T_y)\), the amplitude is \(|T| = \sqrt{(\Re T)^2 + (\Im T)^2}\) and the phase is the argument of the complex number in degrees.

When :pyattr:`tipper_err` is present, uncertainties are propagated component-wise using pycsamt.utils.zmath.propagate_error_rect2polar().

Returns:

Results are stored in the attributes :pyattr:`amplitude`, :pyattr:`phase`, and, when applicable, :pyattr:`amplitude_err`, :pyattr:`phase_err`.

Return type:

None

Notes

If :pyattr:`tipper` is None, the method exits silently and leaves derived fields unchanged.

Examples

>>> import numpy as np
>>> from pycsamt.z.tipper import Tipper
>>> T = np.array([[[1+1j, 0+1j]]])
>>> tip = Tipper(tipper_array=T)
>>> tip.compute_amp_phase()
>>> tip.amplitude.shape, tip.phase.shape
((1, 1, 2), (1, 1, 2))
compute_mag_direction()[source]#

Compute Parkinson arrow magnitudes and directions.

Real-part arrow:

\[M_{\Re} = \sqrt{(\Re T_x)^2 + (\Re T_y)^2}\]
\[\theta_{\Re} = \operatorname{atan2}(-\Re T_y,\,-\Re T_x)\]

Imag-part arrow is computed identically, using \(\Im T_x\) and \(\Im T_y\).

The minus sign makes arrows point towards conductors (Parkinson convention).

Returns:

Results are stored in :pyattr:`mag_real`, :pyattr:`mag_imag`, :pyattr:`angle_real`, :pyattr:`angle_imag`. If :pyattr:`tipper_err` is present, heuristic proxies :pyattr:`mag_err` and :pyattr:`angle_err` are also set.

Return type:

None

Notes

Angle uncertainties are estimated via a bounded small-angle proxy and wrapped within a legacy 45° cap.

Examples

>>> import numpy as np
>>> from pycsamt.z.tipper import Tipper
>>> th = np.deg2rad(60.0)
>>> Tarr = np.zeros((1, 1, 2), complex)
>>> Tarr[0, 0, 0] = 0.0 + 1j*(-np.cos(th))
>>> Tarr[0, 0, 1] = 0.0 + 1j*(-np.sin(th))
>>> tip = Tipper(tipper_array=Tarr)
>>> float(tip.angle_imag[0])
60.0
property amplitude: ndarray | None[source]#
property phase: ndarray | None[source]#
property amplitude_err: ndarray | None[source]#
property phase_err: ndarray | None[source]#
property mag_real: ndarray | None[source]#
property mag_imag: ndarray | None[source]#
property angle_real: ndarray | None[source]#
property angle_imag: ndarray | None[source]#
property mag_err: ndarray | None[source]#
property angle_err: ndarray | None[source]#
set_amp_phase(r_array, phi_array)[source]#

Set tipper from amplitude \(r\) and phase \(\phi\).

Converts the provided real arrays to complex tipper values via

\[T = r \, e^{j \, \phi},\]

where \(\phi\) is given in degrees. Shapes are normalized to (n_freq, 1, 2) following the same rules as :pyattr:`tipper`.

Parameters:
  • r_array (array-like) – Real amplitudes. Accepted shapes are the same as for :pyattr:`tipper`. Must be real-valued.

  • phi_array (array-like) – Real phases in degrees. Same shape rules as r_array.

Raises:

ZError – If shapes are incompatible or inputs are not real after normalization.

Returns:

The method updates :pyattr:`tipper` and then recomputes amplitude / phase and arrow metrics.

Return type:

None

Notes

If :pyattr:`tipper` already exists, both arrays must match its normalized shape.

Examples

>>> import numpy as np
>>> from pycsamt.z.tipper import Tipper
>>> r = np.ones((2, 1, 2))
>>> phi = np.zeros_like(r)
>>> phi[:, 0, 1] = 90.0
>>> tip = Tipper()
>>> tip.set_amp_phase(r, phi)
>>> tip.tipper.shape
(2, 1, 2)
set_mag_direction(mag_real, ang_real, mag_imag, ang_imag)[source]#

Set tipper from Parkinson magnitudes and directions.

For each frequency, reconstruct components per the Parkinson convention:

\[T_x = -M \cos\theta,\quad T_y = -M \sin\theta,\]

applied separately to the real and the imaginary parts. Angles are provided in degrees.

Parameters:
  • mag_real (array-like) – Arrow magnitudes for the real and imaginary parts. Scalar or length n_freq.

  • mag_imag (array-like) – Arrow magnitudes for the real and imaginary parts. Scalar or length n_freq.

  • ang_real (array-like) – Arrow directions (deg) for real and imaginary parts. Scalar or length n_freq.

  • ang_imag (array-like) – Arrow directions (deg) for real and imaginary parts. Scalar or length n_freq.

Raises:

ZError – If :pyattr:`tipper` is not initialized or if the supplied vectors are not scalar or length n_freq.

Returns:

The method updates :pyattr:`tipper` and then recomputes arrow metrics and amplitude / phase.

Return type:

None

Examples

>>> import numpy as np
>>> from pycsamt.z.tipper import Tipper
>>> tip = Tipper(tipper_array=np.zeros((1, 1, 2), complex))
>>> tip.set_mag_direction(1.0, 0.0, 2.0, 90.0)
>>> tuple(np.round(tip.tipper[0, 0].real, 6))
(-1.0, -0.0)
rotate(alpha)[source]#

Rotate tipper(s) clockwise by the given angle(s).

Angles are referenced to geographic North (X→North, Y→East). Positive angles are clockwise.

Parameters:

alpha (float or sequence of float) – Single angle applied to all frequencies, or a length n_freq sequence of angles (deg).

Raises:

ZError – If :pyattr:`tipper` is missing, or if the number of angles is not 1 or n_freq.

Returns:

The method updates :pyattr:`tipper`, :pyattr:`tipper_err` (if present), and :pyattr:`rotation_angle`, then recomputes amplitude / phase and arrow metrics.

Return type:

None

Notes

Error propagation uses pycsamt.utils.zmath.rotatevector_incl_errors(). Angles are reduced modulo 360° in the rotation history.

Examples

>>> import numpy as np
>>> from pycsamt.z.tipper import Tipper
>>> T = np.array([[[1.0+0.0j, 0.0+0.0j]]])
>>> tip = Tipper(tipper_array=T)
>>> tip.rotate(90.0)
>>> np.allclose(tip.rotation_angle, 90.0)
True