2.7. pycsamt.airborne#
Format-neutral airborne electromagnetic survey containers: flight
lines and datasets built from EMTF documents, a technology/format
registry, native-I/O extension points, structural QC, and the
AirborneSite/AirborneSites Sites-shaped read path. AFMAG,
ZTEM, and MobileMT map decoded scientific arrays onto this common
model rather than each inventing its own containers.
See also
Airborne EM Guide for narrative, runnable examples built page by page (data model, site view, technology/ format registry, and structural QC).
Format-neutral airborne electromagnetic survey containers.
The package provides common survey/navigation objects, a technology registry, native-I/O extension points, and structural QC. Technology subpackages map decoded scientific arrays into this model; native vendor readers remain real-data driven and are not guessed from literature descriptions.
Bases:
CoreObjectSample-aligned navigation and attitude information for one line.
The class intentionally contains only concepts that are broadly common across airborne EM systems. Technology-specific fields should be kept in
attrsuntil genuine delivery data justify a stable public field.- Parameters:
sample_ids (sequence of str-like) – Ordered identifiers defining the common sample axis.
latitude (array-like, optional) – Geographic coordinates in decimal degrees. They must be supplied together when used. NaN values are allowed for individual missing samples, while finite values are range-checked.
longitude (array-like, optional) – Geographic coordinates in decimal degrees. They must be supplied together when used. NaN values are allowed for individual missing samples, while finite values are range-checked.
easting (array-like, optional) – Projected coordinates. They must be supplied together when used.
northing (array-like, optional) – Projected coordinates. They must be supplied together when used.
terrain_elevation (array-like, optional) – Elevations on a common vertical datum, normally metres.
platform_elevation (array-like, optional) – Elevations on a common vertical datum, normally metres.
clearance (array-like, optional) – Explicit receiver/platform clearance above ground. If absent,
clearance_valuesderives it from platform minus terrain where both elevations are available.heading (array-like, optional) – Attitude channels in source-system angular convention. They are retained without imposing a proprietary sign convention.
pitch (array-like, optional) – Attitude channels in source-system angular convention. They are retained without imposing a proprietary sign convention.
roll (array-like, optional) – Attitude channels in source-system angular convention. They are retained without imposing a proprietary sign convention.
timestamps (sequence, optional) – Sample-aligned acquisition times. Values are preserved as supplied.
crs (str, optional) – Coordinate reference system label for projected coordinates.
datum (str, default
"WGS84") – Geographic datum label.attrs (dict) – Extension point for system-specific navigation metadata.
Validate object state.
Subclasses can override this hook. The base implementation intentionally accepts all states.
- Return type:
None
Number of navigation samples.
Whether latitude/longitude arrays are present.
Whether easting/northing arrays are present.
Return explicit or safely derived clearance values.
Explicit clearance always takes precedence. When it is unavailable, the difference
platform_elevation - terrain_elevationis returned without changing the stored metadata.
Tight geographic bounding box over finite coordinates.
- class pycsamt.airborne.AirborneEMRecord(sample_id, emtf=None, fields=<factory>, quality=<factory>, attrs=<factory>)#
Bases:
CoreObjectOne sample-aligned airborne EM scientific record.
- Parameters:
sample_id (str) – Identifier matching one entry of the owning line’s
navigation.sample_ids. Stripped and required to be non-empty.emtf (EMTF, optional) – Transfer-function payload for this sample.
EMTFis reused directly rather than introduced as a parallel matrix class, so MobileMT, ZTEM, AFMAG, and future passive systems share one scientific representation instead of duplicating it.fields (dict, optional) – Auxiliary decoded scalar/array fields with no stronger scientific type yet, for example a processed apparent conductivity vector. Content is technology-defined.
quality (dict, optional) – Sample-level quality flags or scores. Content is technology-defined.
attrs (dict, optional) – Free-form extension metadata.
- Raises:
ValueError – If
sample_idis empty after stripping.TypeError – If
emtfis supplied and is not anEMTFinstance.
Examples
>>> from pycsamt.airborne import AirborneEMRecord >>> record = AirborneEMRecord(sample_id=" S001 ") >>> record.sample_id 'S001' >>> record.transfer_function_names ()
- validate()#
Normalize identifier/dict fields and check the EMTF type.
- Return type:
None
- class pycsamt.airborne.AirborneEMLine(line_id, navigation, records=<factory>, attrs=<factory>)#
Bases:
CoreObjectOne airborne flight line with navigation and sparse EM records.
- Parameters:
line_id (str) – Flight-line identifier. Stripped and required to be non-empty.
navigation (NavigationTrack) – Sample-aligned navigation/attitude track defining the line’s common sample axis. Every record’s
sample_idmust appear innavigation.sample_ids.records (dict of str to AirborneEMRecord, optional) – Records keyed by
sample_id. The mapping key must equalrecord.sample_idfor every entry.attrs (dict, optional) – Free-form extension metadata.
- Raises:
ValueError – If
line_idis empty, a record key does not matchrecord.sample_id, or a record’ssample_idis not a known navigation sample.TypeError – If
navigationis not aNavigationTrack, orrecordscontains a non-AirborneEMRecordvalue.
Notes
Records are keyed by navigation
sample_idand may be sparse. This is deliberate: a missing or rejected EM sample should not require deleting the corresponding navigation point, nor fabricating a transfer function to fill the gap.Examples
>>> from pycsamt.airborne import AirborneEMLine, NavigationTrack >>> nav = NavigationTrack(sample_ids=("S1", "S2")) >>> line = AirborneEMLine(line_id="L001", navigation=nav) >>> line.n_samples, line.n_records (2, 0) >>> line.missing_sample_ids ('S1', 'S2')
- records: dict[str, AirborneEMRecord]#
- validate()#
Normalize the identifier and re-attach incoming records.
- Return type:
None
- property transfer_function_names: tuple[str, ...]#
Sorted union of transfer-function names present on this line.
- add_record(record, *, replace=False)#
Attach one record after verifying navigation alignment.
- Parameters:
record (AirborneEMRecord) – Record whose
sample_idmust already exist onnavigation.replace (bool, default False) – Whether to overwrite an existing record for the same sample instead of raising.
- Returns:
self, to support call chaining.- Return type:
- Raises:
TypeError – If
recordis not anAirborneEMRecord.KeyError – If
record.sample_idis not a known navigation sample.ValueError – If a record already exists for that sample and
replaceisFalse.
- add_emtf(sample_id, emtf, *, fields=None, quality=None, attrs=None, replace=False)#
Build and attach one
AirborneEMRecordfrom an EMTF.Convenience wrapper around
add_record()for the common case of attaching a decoded EMTF response without constructing the record explicitly.- Parameters:
sample_id (str) – Navigation sample identifier for the new record.
emtf (EMTF) – Transfer-function payload for the sample.
fields (dict, optional) – Forwarded to
AirborneEMRecord.quality (dict, optional) – Forwarded to
AirborneEMRecord.attrs (dict, optional) – Forwarded to
AirborneEMRecord.replace (bool, default False) – Forwarded to
add_record().
- Returns:
The record that was attached.
- Return type:
- get_record(sample_id)#
Return a record by sample identifier, or
Nonewhen absent.- Raises:
KeyError – If
sample_idis not a known navigation sample.- Parameters:
sample_id (str)
- Return type:
AirborneEMRecord | None
- record_at(index)#
Return the record aligned with navigation index index.
- Parameters:
index (int)
- Return type:
AirborneEMRecord | None
- iter_records()#
Iterate records in navigation order, skipping missing samples.
- Return type:
- class pycsamt.airborne.AirborneEMDataset(name, lines=<factory>, survey=None, instrument=None, method='AEM', attrs=<factory>)#
Bases:
CoreObjectFormat-neutral collection of airborne EM flight lines.
- Parameters:
name (str) – Survey/dataset name. Stripped and required to be non-empty.
lines (dict of str to AirborneEMLine, optional) – Flight lines keyed by
line_id. The mapping key must equalline.line_idfor every entry.survey (SurveyMeta, optional) – Survey-level metadata.
instrument (InstrumentMeta, optional) – System/instrument metadata.
method (str, default "AEM") – Survey method label, upper-cased on construction (for example
"AEM").attrs (dict, optional) – Free-form extension metadata.
- Raises:
ValueError – If
nameormethodis empty, or a line mapping key does not matchline.line_id.TypeError – If
survey,instrument, or an entry oflineshas the wrong type.
Notes
The dataset is intentionally an organisational layer above
EMTF. It does not define a MobileMT, ZTEM, or AFMAG file schema, and it inheritsCoreObjectrather thanMTBase: aggregating flight lines is not itself electromagnetic arithmetic, so this class should not carryMTBase’s numeric EM utilities (those belong to theEMTF/TransferFunctionobjects it holds). Technology adapters populate this object rather than introducing separate transfer-function mathematics.Examples
>>> from pycsamt.airborne import AirborneEMDataset >>> dataset = AirborneEMDataset(name="survey-001") >>> dataset.method, dataset.n_lines ('AEM', 0)
- lines: dict[str, AirborneEMLine]#
- survey: SurveyMeta | None = None#
- instrument: InstrumentMeta | None = None#
- validate()#
Normalize identifier/method fields and re-attach lines.
- Return type:
None
- property transfer_function_names: tuple[str, ...]#
Sorted union of transfer-function types in the dataset.
- add_line(line, *, replace=False)#
Attach one flight line.
- Parameters:
line (AirborneEMLine) – Flight line to attach.
replace (bool, default False) – Whether to overwrite an existing line with the same
line_idinstead of raising.
- Returns:
self, to support call chaining.- Return type:
- Raises:
TypeError – If
lineis not anAirborneEMLine.ValueError – If a line already exists for that
line_idandreplaceisFalse.
- get_line(line_id)#
Return a line by identifier, or
Nonewhen absent.- Parameters:
line_id (str)
- Return type:
AirborneEMLine | None
- iter_lines()#
Iterate flight lines in insertion order.
- Return type:
- iter_records()#
Iterate
(line_id, record)pairs in navigation order.- Return type:
- emtf_records()#
Return all non-empty EMTF records keyed by line/sample ID.
- inspect()#
Return the common airborne inspection summary lazily.
- Returns:
Compact scientific inventory; see
pycsamt.airborne.qc.inspect_airborne().- Return type:
Notes
The import is deferred to avoid a hard import-time dependency between
pycsamt.airborne.baseandpycsamt.airborne.qc, which itself imports this module.
- qc()#
Return the common structural airborne QC report lazily.
- Returns:
Structural/metadata completeness report; see
pycsamt.airborne.qc.assess_airborne_qc().- Return type:
- class pycsamt.airborne.AirborneSite(record, *, line_id=None, technology=None, coords=None)#
Bases:
CoreObjectOne airborne flight-line sample, read directly from its EMTF.
Unlike
Site, every numeric accessor here reads straight from the wrappedAirborneEMRecord’sEMTFdocument – there is no EDI bridge to materialize and no impedance requirement to satisfy.- Parameters:
record (AirborneEMRecord) – The sample this site wraps.
line_id (str, optional) – Owning flight-line identifier, for provenance/grouping.
Nonewhen unknown (e.g. a bare, line-less record).technology (str, optional) – Technology label (
"ztem","mobilemt","afmag", …), the explicit differentiator against ground MT. Falls back to the record’sEMTF.subtypewhen not given explicitly; seetechnology.coords ((float, float, float), optional) – Explicit
(lat, lon, elev)override, normally supplied by the constructing classmethod (AirborneSites.from_line()/from_dataset) from the parent line’sNavigationTrack. When omitted,coordsfalls back to the record’s ownEMTF.site.location, then to(nan, nan, nan).
- Raises:
TypeError – If record is not an
AirborneEMRecord.
See also
AirborneSitesOrdered collection of these.
pycsamt.site.base.SiteThe ground-MT, EDI-shaped counterpart.
- classmethod from_xml(source, *, line_id=None, technology=None)#
Build one site directly from an EMTF-XML file or document.
- Parameters:
source (pycsamt.emtf.document.EMTF or str or pathlib.Path) – Parsed document, or a path read via
from_xml().line_id (str, optional) – Forwarded to the constructor.
technology (str, optional) – Forwarded to the constructor.
- Return type:
Notes
The sample identifier is resolved from
document.site.site_id, thendocument.station, then the source file’s stem, in that order.
- property record: AirborneEMRecord#
The wrapped
AirborneEMRecord.
- property sample_id: str#
Navigation sample identifier (stable; independent of any richer
nameresolved from metadata).
- property technology: str | None#
Technology label (
"ztem","mobilemt", …).Explicit at construction, else the record’s
EMTF.subtype, elseNone.
- property name: str#
Station identifier resolved from metadata, else
sample_id.Resolution order:
EMTF.site.site_id,EMTF.station,sample_id.
- property coords: tuple[float, float, float]#
(lat, lon, elev)in decimal degrees and metres.Explicit constructor override first, then the record’s own
EMTF.site.location, then(nan, nan, nan)– never a fabricated position.
- property z: ndarray | None#
Impedance array, shape
(nf, 2, 2), orNoneif absent (the normal case for ZTEM/AFMAG/MobileMT).
- property admittance: ndarray | None#
MobileMT admittance array, shape
(nf, 3, 2).Nonefor any record without an attachedmobilemt_admittancetransfer function – there is no analogue of this accessor onSite, since a 3x2 admittance cannot be represented bySite.z’s 2x2 shape.
- property interstation_tensor: ndarray | None#
Tensor AFMAG/AirMt interstation magnetic TF, shape
(nf, 3, 2).Nonefor any record without an attachedinterstation_transfer_functionstransfer function. Deliberately a separate accessor fromadmittance(also(nf, 3, 2)-shaped): AirMt’s tensor relates ground-reference magnetic fields to airborne magnetic fields (Hx,Hy -> Hx,Hy,Hz), while MobileMT’s admittance relates ground electric fields to airborne magnetic fields (Ex,Ey -> Hx,Hy,Hz) – physically different responses that happen to share a matrix shape, so this module keeps them under different names rather than one generic “3x2 tensor” accessor that would blur which is which. Seepycsamt.airborne.afmag’s module docstring for why the original-comparator generation (afmag_tilt_deg) is kept separate again from this one.
- property afmag_tilt_deg: ndarray | None#
Original comparator AFMAG scalar tilt/deflection, shape
(nf,).Nonefor any record without an attachedafmag_tilttransfer function. Unlikeinterstation_tensoror a ground tipper, this is a single real number per frequency – the historical comparator has no polarization-ellipse decomposition available at all, only a line-direction deflection (seepycsamt.airborne.afmag’s module docstring).
- property afmag_amplification_parameter: ndarray | None#
AirMt rotation-invariant amplification parameter, shape
(nf,).Nonefor any record without an attachedairmt_amplification_parametertransfer function; seepycsamt.airborne.afmag.compute_airmt_amplification_parameter()for the formula that derives it frominterstation_tensor.
- property fields: dict[str, Any]#
Auxiliary decoded fields (technology-defined).
For MobileMT, this is where a vendor-delivered native
apparent_conductivityvector lives when present; seepycsamt.airborne.mobilemt.MOBILEMT_APPARENT_CONDUCTIVITY_FIELD.
- has_component(comp)#
Whether comp exists and has at least one finite value.
- Parameters:
comp (str) –
"tip"/"tx"/"ty"/"tipper"for the tipper;"admittance"/"y"for the MobileMT admittance;"interstation_tensor"/"ti"for the AirMt tensor;"afmag_tilt"/"tilt"for the original-comparator AFMAG scalar;"amplification_parameter"/"ap"for the AirMt derived parameter; anything else is looked up againstz.- Return type:
- to_dataframe(kind='tipper')#
Export this site’s data to a tidy
pandas.DataFrame.- Parameters:
kind ({"tipper", "admittance", "z"}, default "tipper")
- Returns:
Indexed by frequency (name
"f"). Columns depend on kind:Tx, Ty;Yxx, Yxy, Yyx, Yyy, Yhzx, Yhzy; orZxx, Zxy, Zyx, Zyy.- Return type:
- Raises:
ValueError – If kind is not recognized.
- summary()#
Summarize identity, geometry, and data coverage.
- Returns:
Keys:
name,line_id,sample_id,technology,nfreq,lat,lon,elev,tipper,admittance(booleans).- Return type:
- to_xml(target=None, **kwargs)#
Serialize this site’s document to EMTF XML.
- Parameters:
target (str or pathlib.Path, optional) – Destination path. If
None, the XML is returned as a string.**kwargs – Forwarded to
write_xml()/to_xml.
- Return type:
str or Any
- Raises:
ValueError – If this site has no attached
EMTFdocument.
- class pycsamt.airborne.AirborneSites(items)#
Bases:
CoreObjectOrdered collection of
AirborneSiteobjects.The airborne counterpart of
Sites. See the module docstring for why order here is simply preserved navigation order rather than something to infer.- Parameters:
items (AirborneSite, AirborneEMRecord, EMTF, str, Path, or iterable) – A single item, or an iterable of them. Raw
AirborneEMRecord/EMTF/path items are coerced viaAirborneSite.from_xml()-style construction with no line context; preferfrom_line()/from_dataset()when that context is available.- Raises:
TypeError – If an item cannot be coerced to
AirborneSite.
See also
ensure_asitesFlexible entry-point coercion, including directories of EMTF-XML files and duplicate-name policy.
pycsamt.site.base.SitesThe ground-MT counterpart.
- classmethod from_xml_dir(path, *, recursive=True, pattern='*.xml', line_id=None, strict=False)#
Read every EMTF-XML file under path into one container.
- Parameters:
path (str or pathlib.Path) – A single EMTF-XML file, or a directory to search.
recursive (bool, default True) – Search subdirectories too (
Path.rglob) instead of only the top level (Path.glob).pattern (str, default "*.xml") – Glob pattern used when path is a directory.
line_id (str, optional) – Forwarded to every
AirborneSite.from_xml()call.strict (bool, default False) – If
True, a file that fails to parse raises instead of being skipped, and an empty result raises too.
- Returns:
Sites in sorted-filename order.
- Return type:
- Raises:
ValueError – If strict and nothing could be read.
- classmethod from_line(line, *, technology=None)#
Build a container from one already-constructed flight line.
- Parameters:
line (AirborneEMLine) – Records are visited via
iter_records(), i.e. in navigation order, skipping samples with no attached record.technology (str, optional) – Forwarded to every
AirborneSite; falls back toline.attrs["technology"]when not given.
- Return type:
- Raises:
TypeError – If line is not an
AirborneEMLine.
- classmethod from_dataset(dataset, *, technology=None)#
Flatten every line of a dataset into one container.
- Parameters:
dataset (AirborneEMDataset) – Lines are visited via
iter_lines()in insertion order; seefrom_line()for the per-line ordering.technology (str, optional) – Forwarded to
from_line()for every line; falls back todataset.attrs["technology"]when not given.
- Return type:
- Raises:
TypeError – If dataset is not an
AirborneEMDataset.
- get(name)#
Safe lookup by case-insensitive name;
Noneif absent.- Parameters:
name (str)
- Return type:
AirborneSite | None
- as_list()#
The underlying list of
AirborneSiteobjects.- Return type:
- property technologies: tuple[str, ...]#
Sorted, deduplicated
AirborneSite.technologyvalues present in this container.
- property line_ids: tuple[str, ...]#
Sorted, deduplicated
AirborneSite.line_idvalues present in this container.
- select(names=None, predicate=None)#
Filter by explicit names or by a boolean predicate.
- Parameters:
names (sequence of str, optional) – Case-insensitive names to retain; takes precedence over predicate.
predicate (callable, optional) –
predicate(site) -> bool.
- Returns:
A new container; a shallow copy when neither argument is given.
- Return type:
- map(fn)#
Apply
fn(site) -> Anyto every site; collect results.
- closest(lat, lon, tol=None)#
Nearest site to a target coordinate (great-circle distance).
- Parameters:
- Returns:
Noneif every site lacks finite coordinates, or the nearest is farther than tol.- Return type:
AirborneSite or None
- write_xml(outdir, **kwargs)#
Write one EMTF-XML file per site into a directory.
- Parameters:
outdir (str or pathlib.Path) – Destination directory; created if missing.
**kwargs – Forwarded to
AirborneSite.to_xml()for each site.
- Returns:
Paths written, named
"{name}.xml".- Return type:
list of pathlib.Path
- pycsamt.airborne.ensure_asites(obj, *, recursive=True, on_dup='replace', strict=False, verbose=0)#
Normalize arbitrary airborne input to an
AirborneSites.The single entry-point coercion for airborne-aware
emtoolsfunctions, mirroring the roleensure_sites()plays for the rest ofemtools.- Parameters:
obj (Any) – Accepts: an existing
AirborneSites; anAirborneEMDataset(AirborneSites.from_dataset()); anAirborneEMLine(AirborneSites.from_line()); a path to a single EMTF-XML file or a directory of them (AirborneSites.from_xml_dir()); or an iterable mixing any of the above with bareAirborneEMRecord/EMTF/path items (each coerced with no line context).recursive (bool, default True) – Forwarded to
AirborneSites.from_xml_dir()for any directory encountered.on_dup ({"replace", "keep_first", "keep_last", "raise"}, default "replace") – Duplicate-name policy; see
pycsamt.site.base.to_sites()for the identical semantics on the ground side.strict (bool, default False) – If
True, raise when nothing can be resolved (or, for a directory, when no file parses).verbose (int, default 0) –
>0warns when the result is empty and strict isFalse.
- Return type:
- Raises:
ValueError – If obj is
None; if on_dup is invalid; or, in strict mode, if nothing could be resolved.
- class pycsamt.airborne.AirborneTechnologyDefinition(name, label, family, aliases=<factory>, primary_tf_names=<factory>, reference_required=False, infer_from_tf=False, description='')#
Bases:
PyCSAMTObjectDescribe one scientific airborne-EM technology contract.
A technology definition is intentionally free of file-format knowledge: it only records how to recognize the technology from an already-built
AirborneEMDataset/EMTFobject. A concrete native delivery is described separately byAirborneFormatDefinition.- Parameters:
name (str) – Canonical technology key, for example
"mobilemt". Passed throughnormalize_key().label (str) – Human-readable display name, for example
"MobileMT".family (str) – Broad measurement family shared by related technologies, for example
"natural_field_airborne_em". Also normalized.aliases (tuple of str, optional) – Alternate keys accepted for lookup, for example
("mobile_mt",).primary_tf_names (tuple of str, optional) – Transfer-function names that are unique enough to this technology to justify inference; see
infer_from_tf.reference_required (bool, default False) – Whether a fixed ground reference station is scientifically required for this technology’s response. Used by
assess_airborne_qc()to decide whether a missing reference-station is a QC issue.infer_from_tf (bool, default False) – Whether
identify_airborne_technologies()may infer this technology purely from a matching entry ofprimary_tf_names, when nothing else identifies it. DeliberatelyFalsefor tipper-only technologies (ZTEM), because standard tipperTis not unique to one technology.description (str, default "") – Short human-readable description.
- Raises:
ValueError – If
name,label, orfamilyis empty after normalization/stripping.
- class pycsamt.airborne.AirborneFormatDefinition(name, technology, reader=None, writer=None, detector=None, extensions=<factory>, aliases=<factory>, description='')#
Bases:
PyCSAMTObjectDescribe one concrete native airborne delivery format.
A format definition binds one technology to a concrete on-disk (or stream) representation. It stays empty of
reader/writeruntil a genuine sample or authoritative specification exists to validate against; see the module-level docstring andregister_airborne_format().- Parameters:
name (str) – Canonical format key, unique across all technologies.
technology (str) – Owning technology key; must already be registered via
register_airborne_technology()before this format is registered.reader (callable, optional) –
reader(source, **kwargs) -> AirborneEMDataset.Nonemeans the format is not yet readable.writer (callable, optional) –
writer(dataset, target, **kwargs) -> Any.Nonemeans the format is not yet writable.detector (callable, optional) –
detector(source) -> boolused for content-aware format detection, ahead of extension-based matching.extensions (tuple of str, optional) – File extensions used as a detection hint when no detector matches; normalized to a leading dot and lowercased.
aliases (tuple of str, optional) – Alternate keys accepted for lookup.
description (str, default "") – Short human-readable description.
- Raises:
ValueError – If
nameortechnologyis empty after normalization.
- exception pycsamt.airborne.AirborneRegistryError#
Bases:
ValueErrorBase exception for airborne technology/format registry errors.
- exception pycsamt.airborne.AirborneTechnologyAmbiguityError#
Bases:
AirborneRegistryErrorRaised when an object contains more than one airborne technology.
- exception pycsamt.airborne.AirborneFormatDetectionError#
Bases:
AirborneRegistryErrorRaised when native airborne format detection is ambiguous.
- pycsamt.airborne.register_airborne_technology(definition, *, replace=False)#
Register one scientific technology definition.
- Parameters:
definition (AirborneTechnologyDefinition) – Technology contract to register.
replace (bool, default False) – Whether to overwrite an existing registration under the same canonical name, forwarded to
register().
- Returns:
The same definition instance, for convenient chaining.
- Return type:
- Raises:
TypeError – If definition is not an
AirborneTechnologyDefinition.AirborneRegistryError – If the canonical name or an alias is already registered and
replaceisFalse.
- pycsamt.airborne.get_airborne_technology(name)#
Return a technology definition by canonical name or alias.
Returns
Nonerather than raising when name is unregistered, since callers such as_technology_from_text()use this for best-effort inference over untrustedattrs/subtypevalues.- Parameters:
name (str)
- Return type:
AirborneTechnologyDefinition | None
- pycsamt.airborne.list_airborne_technologies()#
Return registered technologies in registration order.
- Return type:
- pycsamt.airborne.identify_airborne_technologies(obj)#
Return canonical technologies explicitly or safely identified.
- Parameters:
obj (AirborneEMDataset, AirborneEMLine, AirborneEMRecord, or EMTF) – Object to inspect; see
_collect_object_technologies()for exactly what is walked and in what priority.- Returns:
Zero or more canonical technology names, in registration order. Zero means obj carries no explicit or safely inferable technology tag; more than one means obj genuinely mixes technologies (see
detect_airborne_technology()to turn that into an error instead).- Return type:
Notes
Only response types that are unique to one technology are inferred from transfer-function names. Standard tipper
Tand interstationTIare intentionally not enough by themselves to identify ZTEM or AirMt.
- pycsamt.airborne.detect_airborne_technology(obj, *, strict=True)#
Return one canonical technology, or report/ignore mixed content.
- Parameters:
obj (AirborneEMDataset, AirborneEMLine, AirborneEMRecord, or EMTF) – Object to inspect; forwarded to
identify_airborne_technologies().strict (bool, default True) – Whether more than one identified technology is an error (
True) or is reported asNone(False).
- Returns:
The single identified technology;
Noneif none was identified, or if more than one was identified andstrictisFalse.- Return type:
str or None
- Raises:
AirborneTechnologyAmbiguityError – If more than one technology is identified and
strictisTrue.
- pycsamt.airborne.register_airborne_format(definition, *, replace=False)#
Register a concrete native airborne file/delivery format.
- Parameters:
definition (AirborneFormatDefinition) – Format to register. Its
technologymust already be registered viaregister_airborne_technology().replace (bool, default False) – Whether to overwrite an existing registration under the same canonical name instead of raising.
- Returns:
The registered definition. This may be a new instance with technology rewritten to the owning definition’s canonical name when definition was constructed with an alias.
- Return type:
- Raises:
TypeError – If definition is not an
AirborneFormatDefinition.AirborneRegistryError – If
definition.technologyis not a registered technology, or if the canonical name/an alias collides andreplaceisFalse.
- pycsamt.airborne.get_airborne_format(name)#
Return a native format definition by name or alias, or
None.- Parameters:
name (str)
- Return type:
AirborneFormatDefinition | None
- pycsamt.airborne.list_airborne_formats(*, technology=None)#
Return registered native formats, optionally for one technology.
- Parameters:
technology (str, optional) – Canonical name or alias to filter by.
Nonereturns every registered format across all technologies.- Returns:
Matching formats in registration order.
- Return type:
- Raises:
AirborneRegistryError – If technology is supplied and is not registered.
- pycsamt.airborne.detect_airborne_format(source)#
Detect a registered native format using detectors, then extensions.
- Parameters:
source (Any) – Candidate to identify, typically a path or an open stream. Passed to each registered detector, and to
_extension_of()when no detector matches.- Returns:
The canonical format name, or
Noneif nothing matched.- Return type:
str or None
- Raises:
AirborneFormatDetectionError – If more than one registered format matches source, whether by detector or by extension.
Notes
Detectors have priority. Extensions are only hints and are used when they map to exactly one registered format. No built-in vendor formats are registered merely from published system descriptions.
- exception pycsamt.airborne.AirborneIOError#
Bases:
RuntimeErrorRaised when no defensible native airborne I/O path is available.
See the module docstring for why this is a
RuntimeErrorrather than aValueError.
- pycsamt.airborne.read_airborne(source, *, format=None, technology=None, **kwargs)#
Read one verified native airborne delivery into the common dataset.
- Parameters:
source (Any) – Delivery to read: typically a path, though the concrete type accepted depends on the registered reader. Passing an existing
AirborneEMDatasetis an intentional no-op when format is not explicitly requested, so pipeline code can call this uniformly whether it already has a dataset or a raw delivery.format (str, optional) – Explicit registered format name or alias. When omitted, content/extension-based detection selects the format.
technology (str, optional) – Restrict resolution to one technology’s formats; see
_resolved_format().**kwargs – Forwarded to the selected format’s registered reader.
- Returns:
The dataset produced by the resolved reader, or source itself when it already was one and format was omitted.
- Return type:
- Raises:
AirborneIOError – If no reader can be resolved for source (see
_resolved_format()), or if the resolved format has no registered reader, or if that reader does not return anAirborneEMDataset.
- pycsamt.airborne.write_airborne(dataset, target, *, format=None, technology=None, **kwargs)#
Write a dataset through a verified native airborne writer.
- Parameters:
dataset (AirborneEMDataset) – Dataset to serialize.
target (Any) – Output destination. When format is omitted, target must be a path/string with an extension that resolves unambiguously via
detect_airborne_format().format (str, optional) – Explicit registered format name or alias.
technology (str, optional) – Restrict resolution to one technology’s formats; see
_resolved_format().**kwargs – Forwarded to the selected format’s registered writer.
- Returns:
Whatever the resolved writer returns; not constrained by this dispatcher.
- Return type:
Any
- Raises:
TypeError – If dataset is not an
AirborneEMDataset.AirborneIOError – If format is omitted and cannot be inferred from target, if no writer can otherwise be resolved (see
_resolved_format()), or if the resolved format has no registered writer.
- pycsamt.airborne.available_airborne_readers(*, technology=None)#
Return native formats with a registered reader.
- Parameters:
technology (str, optional) – Restrict to one technology’s formats;
Nonelists across all registered technologies.- Returns:
Canonical format names currently readable. Empty until a native reader has been registered for at least one format; see the module docstring.
- Return type:
- Raises:
AirborneIOError – If technology is given but not registered.
- pycsamt.airborne.available_airborne_writers(*, technology=None)#
Return native formats with a registered writer.
- Parameters:
technology (str, optional) – Restrict to one technology’s formats;
Nonelists across all registered technologies.- Returns:
Canonical format names currently writable. Empty until a native writer has been registered for at least one format; see the module docstring.
- Return type:
- Raises:
AirborneIOError – If technology is given but not registered.
- class pycsamt.airborne.AirborneQCIssue(code, severity, message, line_id=None, sample_id=None)#
Bases:
PyCSAMTObjectOne structural/metadata QC finding.
- Parameters:
code (str) – Short machine-readable finding code, for example
"missing_reference_station". Lower-cased on construction.severity ({"info", "warning", "error"}) – Finding severity.
"error"reflects an internally inconsistent scientific state (for example a non-positive frequency axis), not merely incomplete or sparse data; seeassess_airborne_qc().message (str) – Human-readable description. Stripped on construction.
line_id (str, optional) – Flight line the finding applies to, when scoped to one line.
sample_id (str, optional) – Sample the finding applies to, when scoped to one record.
- Raises:
ValueError – If
codeis empty, orseverityis not one of"info","warning","error".
- class pycsamt.airborne.AirborneInspection(object_type, technologies=<factory>, n_lines=0, n_samples=0, n_records=0, transfer_function_names=<factory>, bbox=None, attrs=<factory>)#
Bases:
CoreObjectCompact scientific inventory of an airborne object.
Returned by
inspect_airborne()for a dataset, line, record, or bareEMTF; the fields below are filled in as far as they are meaningful for thatobject_type(for example a single record leavesn_lines/bboxat their defaults).- Parameters:
object_type ({"dataset", "line", "record", "emtf"}) – Kind of object the inventory describes.
technologies (tuple of str, optional) – Canonical technologies identified on the object; see
identify_airborne_technologies().n_lines (int, default 0) – Counts meaningful at and above the object’s own level.
n_samples (int, default 0) – Counts meaningful at and above the object’s own level.
n_records (int, default 0) – Counts meaningful at and above the object’s own level.
transfer_function_names (tuple of str, optional) – Sorted union of transfer-function names present.
bbox (BBox, optional) – Geographic bounding box, when applicable and available.
attrs (dict, optional) – Object-type-specific extra fields (for example
sample_idfor a record, orname/methodfor a dataset).
- class pycsamt.airborne.AirborneQCReport(technologies, metrics, line_metrics, issues=<factory>)#
Bases:
CoreObjectCommon structural QC report for an airborne dataset.
Returned by
assess_airborne_qc().- Parameters:
technologies (tuple of str) – Canonical technologies identified across the dataset.
metrics (dict) – Dataset-level scalar metrics (coverage fractions, counts); see
assess_airborne_qc()for the exact keys.line_metrics (dict of str to dict) – Per-line metrics keyed by
line_id; see_line_metrics()for the exact keys.issues (tuple of AirborneQCIssue, optional) – Individual findings, most to least specific in scope (per-sample, then per-line, then dataset-wide) in the order they were raised.
- issues: tuple[AirborneQCIssue, ...]#
- property status: str#
Return
"error","warning", or"pass".The worst severity present in
issues, or"pass"when there are none.
- property errors: tuple[AirborneQCIssue, ...]#
Return only the
"error"-severity issues.
- property warnings: tuple[AirborneQCIssue, ...]#
Return only the
"warning"-severity issues.
- pycsamt.airborne.inspect_airborne(obj)#
Return a compact inventory for dataset, line, record, or EMTF object.
- Parameters:
obj (AirborneEMDataset, AirborneEMLine, AirborneEMRecord, or EMTF) – Object to summarize.
- Returns:
Inventory populated as far as meaningful for obj’s type.
- Return type:
- Raises:
TypeError – If obj is none of the supported types.
- pycsamt.airborne.assess_airborne_qc(dataset)#
Assess common structural completeness and metadata consistency.
- Parameters:
dataset (AirborneEMDataset) – Dataset to assess.
- Returns:
Dataset-level and per-line metrics plus individual findings. See
AirborneQCReport.metricsfor the exact dataset-level keys this function populates (record/EMTF coverage fractions, valid-frequency and finite-response fractions, primary/derived transfer-function counts, variance/covariance coverage fractions, and reference-metadata coverage).- Return type:
- Raises:
TypeError – If dataset is not an
AirborneEMDataset.
Notes
The report is intentionally descriptive. A missing record, missing covariance, or absent coordinates can be important without being a universal processing failure, so only internally inconsistent scientific states – currently just a non-positive or non-finite frequency axis on an attached EMTF – are classified as
"error". Everything else that is merely incomplete or sparse is reported at"info"/"warning"severity; seeAirborneQCIssue.
2.7.1. Core Containers#
|
Format-neutral scientific containers for airborne EM surveys. |
|
Navigation and attitude containers for airborne EM surveys. |
2.7.2. Site View#
|
Airborne station containers: the non-EDI counterpart of |
2.7.3. Technology and Format Registry#
|
Technology and native-format registries for airborne EM data. |
|
Common native-I/O dispatcher for airborne EM deliveries. |
2.7.4. Quality Control#
|
Shared structural QC and inspection for airborne EM datasets. |
2.7.6. AFMAG Adapter#
|
AFMAG-family scientific adapter contracts. |
|
Scientific adapter contracts for historical and tensor AFMAG products. |
|
AFMAG-family metadata built on the common airborne model. |
|
AFMAG-family derived EMTF datatype registration. |
|
Stable scientific constants for AFMAG-family adapter contracts. |
2.7.7. ZTEM Adapter#
|
ZTEM scientific adapter contract. |
|
Array-to-scientific-object adapter contract for ZTEM products. |
|
ZTEM-specific metadata that reuses the common airborne/EMTF model. |
|
Stable scientific constants for the ZTEM adapter layer. |
2.7.8. MobileMT Adapter#
|
MobileMT scientific adapter contract. |
|
Array-to-scientific-object adapter contract for MobileMT products. |
|
MobileMT-specific metadata that does not duplicate EMTF mathematics. |
|
MobileMT transfer-function datatype registration. |
|
Stable scientific constants for the MobileMT adapter layer. |