2.7.6.1. pycsamt.airborne.afmag#

AFMAG-family scientific adapter contracts.

The package separates historical comparator AFMAG from modern tensor AFMAG/AirMt instead of collapsing distinct response families into one schema. No proprietary native delivery parser is assumed.

exception pycsamt.airborne.afmag.AFMAGValidationError

Bases: ValueError

Raised when decoded AFMAG scientific arrays are inconsistent.

pycsamt.airborne.afmag.register_afmag_datatypes()

Register AFMAG derived response definitions idempotently.

The tensor response itself reuses the existing EMTF TI interstation magnetic transfer-function definition and therefore is not re-registered.

Returns:

(AFMAG_TILT_DEFINITION, AFMAG_AP_DEFINITION), each either newly registered or the already-registered definition sharing its tag; see ensure_emtf_datatype_registered().

Return type:

(DataTypeDefinition, DataTypeDefinition)

Raises:

ValueError – If either definition’s tag or code is already registered under a materially different definition.

class pycsamt.airborne.afmag.OriginalAFMAGSystemSpec(historical_frequency_band_hz=(1.0, 20000.0), typical_frequencies_hz=(150.0, 510.0), coil_count=2, coil_tilt_deg=45.0, coil_separation_deg=45.0, digital_recording=False, attrs=<factory>)

Bases: CoreObject

Descriptive characteristics of the historical comparator AFMAG.

These values describe the original airborne implementation and are not parser constraints. Historical systems reported a comparator deflection proportional to the polarization-plane tilt rather than a digital tensor; see AFMAGValidationError and build_original_afmag_emtf() for how that scalar response is built.

Parameters:
  • historical_frequency_band_hz ((float, float), optional) – Published historical operating band in Hz, (low, high) with 0 < low < high.

  • typical_frequencies_hz (tuple of float, optional) – Typical discrete operating frequencies in Hz historically used by comparator instruments (non-empty, finite, positive).

  • coil_count (int, default 2) – Fixed at 2: the original comparator design used two crossed coils.

  • coil_tilt_deg (float, optional) – Published nominal coil tilt angle in degrees.

  • coil_separation_deg (float, optional) – Published nominal angular separation between the two coils in degrees.

  • digital_recording (bool, default False) – Whether the archival record was digitized (True) or is a purely analogue comparator deflection (False).

  • attrs (dict, optional) – Free-form extension metadata.

Raises:

ValueError – If historical_frequency_band_hz is not finite and correctly ordered, if typical_frequencies_hz is empty or not all finite/positive, if coil_count is not 2, or if coil_tilt_deg/coil_separation_deg is not finite/positive.

historical_frequency_band_hz: tuple[float, float] = (1.0, 20000.0)
typical_frequencies_hz: tuple[float, ...] = (150.0, 510.0)
coil_count: int = 2
coil_tilt_deg: float = 45.0
coil_separation_deg: float = 45.0
digital_recording: bool = False
attrs: dict[str, Any]
validate()

Normalize and range-check every descriptive field in place.

Return type:

None

to_instrument_meta(*, serial=None, software_version='')

Return reusable instrument metadata for historical AFMAG.

Only a magnetic_sensor is populated – electric_sensor stays None, since original comparator AFMAG has no electric channel.

Parameters:
  • serial (str | None)

  • software_version (str)

Return type:

InstrumentMeta

class pycsamt.airborne.afmag.AirMtSystemSpec(practical_frequency_range_hz=(20.0, 800.0), typical_frequency_count=(5, 6), time_series_sampling_rate_hz=2000.0, input_channels=('Hx', 'Hy'), output_channels=('Hx', 'Hy', 'Hz'), reference_channels=('Hx', 'Hy', 'Hz'), attrs=<factory>)

Bases: CoreObject

Published characteristics of the tensor AFMAG/AirMt generation.

Parameters:
  • practical_frequency_range_hz ((float, float), optional) – Published practical frequency band in Hz, (low, high) with 0 < low < high. See practical_frequency_mask().

  • typical_frequency_count ((int, int), optional) – Typical minimum/maximum count of processed frequency windows, (low, high) with 0 < low <= high.

  • time_series_sampling_rate_hz (float, optional) – Published raw time-series sampling rate in Hz.

  • input_channels ((str, str), default ("Hx", "Hy")) – Fixed transfer-function input channels; must equal ("Hx", "Hy").

  • output_channels ((str, str, str), default ("Hx", "Hy", "Hz")) – Fixed airborne transfer-function output channels; must equal ("Hx", "Hy", "Hz").

  • reference_channels ((str, str, str), default ("Hx", "Hy", "Hz")) – Fixed channels measured at the fixed ground reference station; must equal ("Hx", "Hy", "Hz").

  • attrs (dict, optional) – Free-form extension metadata.

Raises:

ValueError – If practical_frequency_range_hz is not finite and correctly ordered, if typical_frequency_count is not a valid 0 < low <= high pair, if time_series_sampling_rate_hz is not finite/positive, or if input_channels/output_channels/ reference_channels differs from its fixed value.

practical_frequency_range_hz: tuple[float, float] = (20.0, 800.0)
typical_frequency_count: tuple[int, int] = (5, 6)
time_series_sampling_rate_hz: float = 2000.0
input_channels: tuple[str, ...] = ('Hx', 'Hy')
output_channels: tuple[str, ...] = ('Hx', 'Hy', 'Hz')
reference_channels: tuple[str, ...] = ('Hx', 'Hy', 'Hz')
attrs: dict[str, Any]
validate()

Normalize and range-check every descriptive field in place.

Return type:

None

practical_frequency_mask(frequency)

Return a diagnostic mask for the descriptive frequency band.

Parameters:

frequency (Any)

Return type:

ndarray

to_instrument_meta(*, serial=None, software_version='')

Return reusable instrument metadata for tensor AFMAG/AirMt.

Only a magnetic_sensor is populated – electric_sensor stays None, since AirMt’s interstation transfer function has no electric channel.

Parameters:
  • serial (str | None)

  • software_version (str)

Return type:

InstrumentMeta

class pycsamt.airborne.afmag.AFMAGReferenceStation(station_id=None, site=None, measured_channels=('Hx', 'Hy', 'Hz'), transfer_input_channels=('Hx', 'Hy'), attrs=<factory>)

Bases: CoreObject

Fixed magnetic reference station for tensor AFMAG/AirMt processing.

Passed to build_airmt_emtf() to populate processing’s remote-reference metadata; see _processing_for_reference().

Parameters:
  • station_id (str, optional) – Explicit reference-station identifier. Falls back to site.preferred_name through preferred_id when omitted; see normalize_optional_identifier().

  • site (SiteMeta, optional) – Reference-station location/identity metadata.

  • measured_channels ((str, str, str), default ("Hx", "Hy", "Hz")) – Fixed channels physically measured at the reference station; must equal ("Hx", "Hy", "Hz").

  • transfer_input_channels ((str, str), default ("Hx", "Hy")) – Fixed subset of measured_channels used as the AirMt transfer function’s input; must equal ("Hx", "Hy").

  • attrs (dict, optional) – Free-form extension metadata.

Raises:
  • TypeError – If site is supplied and is not a SiteMeta.

  • ValueError – If measured_channels differs from ("Hx", "Hy", "Hz") or transfer_input_channels differs from ("Hx", "Hy").

station_id: str | None = None
site: SiteMeta | None = None
measured_channels: tuple[str, ...] = ('Hx', 'Hy', 'Hz')
transfer_input_channels: tuple[str, ...] = ('Hx', 'Hy')
attrs: dict[str, Any]
validate()

Normalize the identifier/channels and type-check site.

Return type:

None

property preferred_id: str | None

Return explicit station ID, then the SiteMeta preferred name.

pycsamt.airborne.afmag.compute_airmt_amplification_parameter(tensor, *, zero_policy='nan')

Compute the AirMt rotation-invariant complex amplification parameter.

For the two column vectors T1 and T2 of a 3 x 2 magnetic transfer function, the implemented patent formulation is:

Kvec = T1 x T2
AP = Kvec . Re(Kvec) / |Re(Kvec)|
Parameters:
  • tensor (array-like) – One (3, 2) or (3, 3) matrix, or a family with those trailing dimensions. The patent parameter uses the first two column vectors in either case.

  • zero_policy ({"nan", "raise"}) – Behavior when |Re(Kvec)| is zero. Such a sample has no defined projection direction for this parameter.

Returns:

Complex AP with shape equal to the leading tensor dimensions.

Return type:

numpy.ndarray

pycsamt.airborne.afmag.validate_airmt_transfer_function(tf)

Validate and return an AirMt 3 x 2 interstation magnetic TF.

Parameters:

tf (TransferFunction) – Transfer function to validate in place.

Returns:

tf, unchanged, for convenient chaining after add_transfer_function().

Return type:

TransferFunction

Raises:
  • TypeError – If tf is not a TransferFunction.

  • AFMAGValidationError – If tf does not use the standard EMTF interstation TI/interstation_transfer_functions datatype with Hx/Hy inputs, Hx/Hy/Hz outputs, and matrix shape (3, 2).

pycsamt.airborne.afmag.validate_original_afmag_tilt(tf)

Validate and return an original AFMAG scalar tilt response.

Parameters:

tf (TransferFunction) – Transfer function to validate in place.

Returns:

tf, unchanged, for convenient chaining after add_transfer_function().

Return type:

TransferFunction

Raises:
  • TypeError – If tf is not a TransferFunction.

  • AFMAGValidationError – If tf does not use the afmag_tilt datatype, is not scalar (no input/output channels, matrix shape (1, 1)), or carries a non-zero imaginary component.

pycsamt.airborne.afmag.build_airmt_emtf(tensor, *, frequency=None, periods=None, units='[]', variance=None, inverse_signal_covariance=None, residual_covariance=None, include_amplification_parameter=True, amplification_zero_policy='nan', product_id=None, description=None, reference_station=None, system_spec=None, site=None, orientation=None, processing=None, attrs=None)

Build one sample-level tensor AFMAG/AirMt EMTF response.

Parameters:
  • tensor (array-like) – Complex interstation magnetic transfer function with shape (nf, 3, 2), or one (3, 2) matrix for a single frequency.

  • frequency (array-like, optional) – Exactly one positive frequency or period vector must be supplied.

  • periods (array-like, optional) – Exactly one positive frequency or period vector must be supplied.

  • variance (array-like, optional) – Component variance with shape (nf, 3, 2).

  • inverse_signal_covariance (array-like, optional) – Input covariance factor S with shape (nf, 2, 2).

  • residual_covariance (array-like, optional) – Output residual covariance N with shape (nf, 3, 3).

  • include_amplification_parameter (bool, default True) – Whether to also attach the derived airmt_amplification_parameter transfer function; see compute_airmt_amplification_parameter().

  • amplification_zero_policy ({"nan", "raise"}, default "nan") – Forwarded to compute_airmt_amplification_parameter().

  • reference_station (AFMAGReferenceStation, optional) – Fixed ground reference metadata; folded into EMTF.processing and EMTF.attrs["afmag"] (see _processing_for_reference()).

  • system_spec (AirMtSystemSpec, optional) – System-description metadata; defaults to published nominal values.

  • units (str | None)

  • product_id (str | None)

  • description (str | None)

  • site (SiteMeta | None)

  • orientation (OrientationMeta | None)

  • processing (ProcessingMeta | None)

  • attrs (Mapping[str, Any] | None)

Returns:

Document carrying the interstation_transfer_functions (TI) transfer function and, unless disabled, the derived amplification parameter.

Return type:

EMTF

Raises:
  • AFMAGValidationError – If tensor, frequency/periods, or any statistical estimate does not match its expected shape.

  • TypeError – If system_spec, reference_station, site, or orientation has the wrong type.

pycsamt.airborne.afmag.build_airmt_record(sample_id, tensor, *, frequency=None, periods=None, fields=None, quality=None, record_attrs=None, **emtf_kwargs)

Build one airborne record from decoded tensor AFMAG/AirMt data.

Parameters:
  • sample_id (str) – Navigation sample identifier for the new record.

  • tensor (array-like) – Forwarded to build_airmt_emtf().

  • frequency (array-like, optional) – Exactly one must be supplied; forwarded to build_airmt_emtf().

  • periods (array-like, optional) – Exactly one must be supplied; forwarded to build_airmt_emtf().

  • fields (dict, optional) – Forwarded to AirborneEMRecord.

  • quality (dict, optional) – Forwarded to AirborneEMRecord.

  • record_attrs (dict, optional) – Forwarded to AirborneEMRecord.

  • **emtf_kwargs – Forwarded to build_airmt_emtf().

Returns:

The record, with its EMTF product_id defaulted to str(sample_id) unless overridden in emtf_kwargs.

Return type:

AirborneEMRecord

pycsamt.airborne.afmag.build_airmt_line(line_id, navigation, tensor, *, frequency, record_mask=None, variance=None, inverse_signal_covariance=None, residual_covariance=None, units='[]', include_amplification_parameter=True, reference_station=None, system_spec=None, orientation=None, attrs=None)

Build one tensor-AFMAG/AirMt flight line from decoded arrays.

Parameters:
  • line_id (str) – Flight-line identifier.

  • navigation (NavigationTrack) – Sample-aligned navigation defining the line’s sample axis.

  • tensor (array-like) – Line-batched interstation tensor. For n_samples == 1, a single (3, 2) matrix or one (nf, 3, 2) stack is also accepted (n_frequency is not known in advance, unlike normalize_sample_axis_array()’s contract); for n_samples > 1, the canonical (samples, nf, 3, 2) shape is required directly.

  • frequency (array-like) – Either one shared (nf,) vector or a per-sample (n_samples, nf) grid; see _line_frequency_rows().

  • record_mask (array-like of bool, optional) – Marks which navigation samples get an attached record; None means every sample does.

  • variance (Any | None)

  • inverse_signal_covariance (Any | None)

  • residual_covariance (Any | None)

  • array-like – Per-sample statistical estimates, each shaped (n_samples, nf, *tail); forwarded per sample to build_airmt_record().

  • optional – Per-sample statistical estimates, each shaped (n_samples, nf, *tail); forwarded per sample to build_airmt_record().

  • include_amplification_parameter (bool, default True) – Forwarded to build_airmt_emtf() for every sample.

  • units (optional) – Forwarded to build_airmt_emtf() for every sample.

  • reference_station (optional) – Forwarded to build_airmt_emtf() for every sample.

  • system_spec (optional) – Forwarded to build_airmt_emtf() for every sample.

  • orientation (optional) – Forwarded to build_airmt_emtf() for every sample.

  • attrs (dict, optional) – Line-level extension metadata; "technology" is set to "AirMt" here.

Returns:

The line, with one record per sample where record_mask (or its default) is True.

Return type:

AirborneEMLine

Raises:
  • TypeError – If navigation is not a NavigationTrack.

  • AFMAGValidationError – If tensor, frequency, record_mask, or any statistical estimate does not match its expected shape.

pycsamt.airborne.afmag.build_airmt_dataset(name, lines, *, survey=None, system_spec=None, instrument_serial=None, attrs=None)

Build a common airborne dataset for tensor AFMAG/AirMt lines.

Parameters:
  • name (str) – Dataset/survey name.

  • lines (iterable of AirborneEMLine) – Lines to attach, typically previously built by build_airmt_line().

  • survey (SurveyMeta, optional) – Survey-level metadata; defaults to SurveyMeta(name=name, method="AEM").

  • system_spec (AirMtSystemSpec, optional) – Used to build the dataset’s instrument metadata; defaults to published nominal values.

  • instrument_serial (str, optional) – Forwarded to AirMtSystemSpec.to_instrument_meta().

  • attrs (dict, optional) – Dataset-level extension metadata; "technology" is set to "AirMt" here.

Returns:

The dataset, with every line attached.

Return type:

AirborneEMDataset

Raises:

TypeError – If system_spec has the wrong type, or an entry of lines is not an AirborneEMLine (this is enforced by AirborneEMDataset construction, unlike build_ztem_dataset(), which checks explicitly beforehand and additionally rejects a line tagged with a conflicting technology; this function does not perform that second, stricter check).

pycsamt.airborne.afmag.build_original_afmag_emtf(tilt, *, frequency=None, periods=None, response_kind='tilt_angle', units=None, variance=None, product_id=None, description=None, system_spec=None, site=None, orientation=None, attrs=None)

Build one historical comparator-AFMAG scalar tilt response.

response_kind='tilt_angle' represents a calibrated tilt angle and defaults to degrees. 'comparator_deflection' preserves an archival instrument deflection without pretending it is an angle; units should then be supplied when known.

Parameters:
  • tilt (array-like) – Real-valued tilt/deflection response, scalar or shape (nf,).

  • frequency (array-like, optional) – Exactly one positive frequency or period vector must be supplied.

  • periods (array-like, optional) – Exactly one positive frequency or period vector must be supplied.

  • response_kind (str, default "tilt_angle") – Either "tilt_angle" (a calibrated angle, defaulting to degrees) or "comparator_deflection" (a raw archival instrument deflection with no implied angular unit).

  • variance (array-like, optional) – Real-valued response variance, scalar or shape (nf,) / (nf, 1, 1).

  • system_spec (OriginalAFMAGSystemSpec, optional) – System-description metadata; defaults to published nominal values.

  • units (str | None)

  • product_id (str | None)

  • description (str | None)

  • site (SiteMeta | None)

  • orientation (OrientationMeta | None)

  • attrs (Mapping[str, Any] | None)

Returns:

Document carrying the afmag_tilt transfer function.

Return type:

EMTF

Raises:
  • AFMAGValidationError – If tilt, frequency/periods, or variance does not match its expected shape.

  • ValueError – If response_kind is not a recognized value.

  • TypeError – If system_spec, site, or orientation has the wrong type.

pycsamt.airborne.afmag.build_original_afmag_record(sample_id, tilt, *, frequency=None, periods=None, fields=None, quality=None, record_attrs=None, **emtf_kwargs)

Build one record from a historical AFMAG tilt response.

Parameters:
  • sample_id (str) – Navigation sample identifier for the new record.

  • tilt (array-like) – Forwarded to build_original_afmag_emtf().

  • frequency (array-like, optional) – Exactly one must be supplied; forwarded to build_original_afmag_emtf().

  • periods (array-like, optional) – Exactly one must be supplied; forwarded to build_original_afmag_emtf().

  • fields (dict, optional) – Forwarded to AirborneEMRecord.

  • quality (dict, optional) – Forwarded to AirborneEMRecord.

  • record_attrs (dict, optional) – Forwarded to AirborneEMRecord.

  • **emtf_kwargs – Forwarded to build_original_afmag_emtf().

Returns:

The record, with its EMTF product_id defaulted to str(sample_id) unless overridden in emtf_kwargs.

Return type:

AirborneEMRecord

pycsamt.airborne.afmag.build_original_afmag_line(line_id, navigation, tilt, *, frequency, record_mask=None, response_kind='tilt_angle', units=None, variance=None, system_spec=None, orientation=None, attrs=None)

Build one historical comparator-AFMAG flight line.

Parameters:
  • line_id (str) – Flight-line identifier.

  • navigation (NavigationTrack) – Sample-aligned navigation defining the line’s sample axis.

  • tilt (array-like) – Line-batched real tilt/deflection response, shape (n_samples, nf) (or unbatched when n_samples == 1).

  • frequency (array-like) – Either one shared (nf,) vector or a per-sample (n_samples, nf) grid; see _line_frequency_rows().

  • record_mask (array-like of bool, optional) – Marks which navigation samples get an attached record; None means every sample does.

  • response_kind (optional) – Forwarded to build_original_afmag_emtf() for every sample.

  • units (optional) – Forwarded to build_original_afmag_emtf() for every sample.

  • variance (array-like, optional) – Per-sample response variance, shape (n_samples, nf).

  • system_spec (optional) – Forwarded to build_original_afmag_emtf() for every sample.

  • orientation (optional) – Forwarded to build_original_afmag_emtf() for every sample.

  • attrs (dict, optional) – Line-level extension metadata; "technology" is set to "AFMAG" here.

Returns:

The line, with one record per sample where record_mask (or its default) is True.

Return type:

AirborneEMLine

Raises:
  • TypeError – If navigation is not a NavigationTrack.

  • AFMAGValidationError – If tilt, frequency, record_mask, or variance does not match its expected shape.

pycsamt.airborne.afmag.build_original_afmag_dataset(name, lines, *, survey=None, system_spec=None, instrument_serial=None, attrs=None)

Build a common airborne dataset for original AFMAG lines.

Parameters:
  • name (str) – Dataset/survey name.

  • lines (iterable of AirborneEMLine) – Lines to attach, typically previously built by build_original_afmag_line().

  • survey (SurveyMeta, optional) – Survey-level metadata; defaults to SurveyMeta(name=name, method="AEM").

  • system_spec (OriginalAFMAGSystemSpec, optional) – Used to build the dataset’s instrument metadata; defaults to published nominal values.

  • instrument_serial (str, optional) – Forwarded to OriginalAFMAGSystemSpec.to_instrument_meta().

  • attrs (dict, optional) – Dataset-level extension metadata; "technology" is set to "AFMAG" here.

Returns:

The dataset, with every line attached.

Return type:

AirborneEMDataset

Raises:

TypeError – If system_spec has the wrong type, or an entry of lines is not an AirborneEMLine; see build_airmt_dataset() for how this differs from the ZTEM/MobileMT dataset builders.