pycsamt.zonge.base#
pycsamt.zonge.base#
Foundational building blocks for the Zonge sub-package.
Goals#
Provide a single, flexible base every component can inherit from (e.g., Station, Frequency, Resistivity…).
Offer a robust AVGFrame holder for data + metadata.
- Define a clear component contract:
from_avg(...)→ build from an AVG file/tableread(...)→ parse & populate attributeswrite()→ reconstruct a textual AVG block
Be agnostic to legacy/modern files. Upstream loaders (e.g.,
utils.load_avg) normalize columns; components consume the tidy frame.
Design notes#
All public objects keep string widths short for readability.
Columns are lower-case canonical names (e.g.,
'freq','rho','phase','comp'…).Components target subsets of the frame and may expose additional, derived attributes internally.
Functions
|
Infers the AVG format kind from a DataFrame's columns. |
Classes
|
Abstract base class for a single AVG data component. |
|
A container for a tidy AVG table and its metadata. |
|
A structured, format-agnostic representation of a single row. |
Dynamically provides all known aliases for canonical names. |
- class pycsamt.zonge.base.FieldAliases[source]#
Bases:
objectDynamically provides all known aliases for canonical names.
This class serves as a convenient, centralized namespace for accessing all known variations of a given canonical column name. It is designed to be a single source of truth for developers who need to work with different possible column names.
Notes
The primary purpose of this class is to improve code readability and maintainability by avoiding the use of “magic strings” for column names. Instead of writing
df[("rho", "Resistivity")], a developer can use the more explicitdf[FieldAliases.rho].The class attributes are not hardcoded. They are generated dynamically by introspecting the
ALL_ALIASESdictionary from theschemamodule. This ensures that FieldAliases is always in sync with the master data schema and adheres to the DRY (Don’t Repeat Yourself) principle.Examples
You can access the tuple of aliases for any canonical name directly as a class attribute:
>>> from pycsamt.zonge.base import FieldAliases >>> # Get all known names for apparent resistivity >>> FieldAliases.rho ('ARes.mag', 'Resistivity')
>>> # Get all known names for H-field phase error >>> FieldAliases.s_hphz ('B.perr', 'H.perr', 'sHphz')
See also
pycsamt.zonge.schema.ALL_ALIASESThe source dictionary used to build this class.
- attr_name = 'z_pcterr'#
- aliases = ('Z.%err',)#
- amps = ('Amps', 'Tx.Amp')#
- canon = 'z.%err'#
- coh = ('Choer',)#
- e_wgt = ('E.wgt',)#
- emag = ('E.mag', 'Emag')#
- ephz = ('E.phz', 'Ephz')#
- gdp_blk = ('Gdp.Blk',)#
- gdp_chn = ('Gdp.Chn',)#
- gdp_time = ('Gdp.Time',)#
- h_wgt = ('B.wgt', 'H.wgt')#
- hmag = ('B.mag', 'H.mag', 'Hmag')#
- hphz = ('B.phz', 'Hphz')#
- pc_emag = ('%Emag', 'E.%err')#
- pc_hmag = ('%Hmag', 'B.%err', 'H.%err')#
- pc_rho = ('%Rho', 'ARes.%err')#
- rho_sc = ('SRes', 'TMARES', 'TMARES/SRES')#
- s_ephz = ('E.perr', 'sEphz')#
- s_hphz = ('B.perr', 'H.perr', 'sHphz')#
- s_phz = ('Z.perr', 'sPhz')#
- skp = ('skp',)#
- tx = ('tx',)#
- ty = ('ty',)#
- z_mwgt = ('Z.mwgt',)#
- z_pcterr = ('Z.%err',)#
- z_pwgt = ('Z.pwgt',)#
- zabs = ('|Z|',)#
- zmag = ('Z.mag',)#
- class pycsamt.zonge.base.AvgRow(station, freq, comp, amps=None, emag=None, ephz=None, hmag=None, hphz=None, rho=None, phase=None, e_err=None, e_perr=None, h_err=None, h_perr=None, rho_err=None, z_perr=None)[source]#
Bases:
objectA structured, format-agnostic representation of a single row.
This dataclass provides a type-safe container for the data from a single measurement record in an AVG file. It serves as a convenient Data Transfer Object (DTO) for operations that require iterating over individual data points, such as testing, serialization to JSON, or specific calculations.
- Variables:
station (int or float) – The station identifier for the measurement.
freq (float) – The frequency at which the measurement was taken (Hz).
comp (str) – The component label (e.g., ‘ExHy’). Defaults to ‘ExHy’ if not provided.
amps (float, optional) – The transmitter current amplitude (A).
ephz (emag,) – The magnitude and phase of the electric field.
hphz (hmag,) – The magnitude and phase of the magnetic field.
phase (rho,) – The calculated apparent resistivity (ohm-m) and impedance phase (mrad).
rho_err (e_err, h_err,) – The relative percent error for E-field, H-field, and resistivity magnitudes.
z_perr (e_perr, h_perr,) – The standard deviation (error) for E-field phase, H-field phase, and impedance phase.
- Parameters:
- class pycsamt.zonge.base.AVGFrame(data, meta=<factory>, source=None)[source]#
Bases:
objectA container for a tidy AVG table and its metadata.
This dataclass acts as a standardized wrapper for the data and metadata parsed from a Zonge AVG file. It ensures that data passed between different parts of the package is consistent and self-contained.
The __post_init__ hook automatically standardizes the column names of the incoming DataFrame, ensuring that any instance of AVGFrame always contains a clean, canonical dataset.
- Parameters:
data (pandas.DataFrame) – A DataFrame containing the tabular data from an AVG file. Column names are automatically normalized to the package’s internal canonical schema upon initialization.
meta (dict, optional) – A dictionary holding the header metadata (e.g., survey parameters, units) extracted from the
$keyword=valuelines in the AVG file.source (pathlib.Path, optional) – The filesystem path to the original
.avgfile, used for provenance and logging.
Examples
>>> import pandas as pd >>> from pycsamt.zonge.base import AVGFrame >>> df = pd.DataFrame({'Resistivity': [100], 'Freq': [1024]}) >>> frame = AVGFrame(data=df, meta={'Survey.Type': 'CSAMT'}) >>> print(frame.data.columns) Index(['rho', 'freq'], dtype='object') >>> print(frame.meta['Survey.Type']) CSAMT
See also
pycsamt.zonge.avg.AVGThe main user-facing data object.
pycsamt.zonge.info.DataInfoAggregator that uses AVGFrame.
- class pycsamt.zonge.base.AVGComponentBase(data=None, meta=None, *, name=None, verbose=0)[source]#
Bases:
ABCAbstract base class for a single AVG data component.
This class defines the fundamental “contract” that all data components (e.g., Station, Resistivity, Phase) must follow. It ensures that every component can be initialized from a standardized data source and can serialize itself back into a textual format.
Subclasses are expected to be specialized containers that manage a specific subset of columns from the main AVG DataFrame.
- Variables:
required (set[str]) – A class attribute specifying the set of canonical column names that must be present in the source DataFrame for the component to be initialized.
provides (set[str]) – A class attribute specifying the set of canonical column names that this component is responsible for managing or creating.
_frame (pandas.DataFrame) – A protected attribute holding the component’s data as a tidy DataFrame with canonical column names.
_meta (dict) – A protected attribute holding relevant metadata.
- Parameters:
data (pd.DataFrame | None)
meta (MutableMapping[str, Any] | None)
name (str | None)
- read(source, meta=None)[source]#
Abstract method to parse a source DataFrame and populate the component’s internal state.
- write()[source]#
Abstract method to serialize the component’s data into a sequence of text lines suitable for an AVG file.
- from_avg(avg, meta=None, \*\*kws)[source]#
A classmethod factory that provides a convenient way to build a component from various sources, including file paths or in-memory DataFrames.
Notes
The design of this base class ensures that all components operate on a consistent, tidy data structure. The from_avg factory method is particularly important, as it handles the automatic transformation of legacy AVG files into the modern, canonical format before passing the data to the component’s read method. This makes all components inherently agnostic to the original file format.
- classmethod from_avg(avg, *, meta=None, **kws)[source]#
Build a component from a path / AVGFrame / dataframe.
- The method accepts:
path → uses
utils.load_avg(modern or legacy)AVGFrame→ uses its data/meta directly(df, meta)tuplebare
df+ explicitmetakwarg
- abstractmethod read(source, meta=None)[source]#
Parse source and mutate component state.
- Implementations should:
validate required columns using
_require(...)copy/select needed columns into
self._frameset/merge metadata into
self._meta
- abstractmethod write()[source]#
Serialise the component to text lines. Implementations may delegate to
_write_csv_blockfor a consistent block format (header + CSV). The base does not write to disk.
- pycsamt.zonge.base.guess_kind_from_df(df_or_frame, meta=None, *, transform=False, mode='soft', error='raise', verbose=False)[source]#
Infers the AVG format kind from a DataFrame’s columns.
This helper inspects the column names of a DataFrame to make an educated guess about whether it represents a legacy (kind-1) or modern (kind-2) AVG file. It can optionally transform legacy data into the modern structure.
- Parameters:
df_or_frame (pd.DataFrame or AVGFrame) – The DataFrame or AVGFrame object to inspect.
meta (mapping, optional) – An optional metadata dictionary. Required if transform is
Trueand the source is a legacy DataFrame.transform (bool, default False) – If
Trueand a legacy (kind-1) format is detected, this function will use theLegacyAVGBasetransformer to convert the data into the modern structure.error ({'raise', 'warn', 'ignore'}, default 'raise') – Determines the behavior when a format cannot be reliably determined. - ‘raise’: Raises an AvgFileError. - ‘warn’: Issues a warning and defaults to kind-2. - ‘ignore’: Silently defaults to kind-2.
verbose (bool, default False) – Controls logging output during transformation.
mode (Literal['strict', 'soft'])
- Returns:
If transform is
False, returns an integer:1for legacy,2for modern.If transform is
True, returns a tuple:(df, meta, kind), where df and meta are the (potentially transformed) data and metadata.
- Return type:
- Raises:
TypeError – If the input is not a pandas DataFrame or AVGFrame.
AvgFileError – If error is ‘raise’ and the format cannot be determined.
Notes
The detection logic uses a multi-pass heuristic: 1. It first checks for columns with dot-notation (e.g.,
‘ARes.mag’), which are exclusive to modern files.
If none are found, it checks for legacy-specific QC column names (e.g., ‘%Emag’, ‘sPhz’).
If neither is found, it checks for the presence of internal canonical QC names (e.g., ‘pc_emag’, ‘s_phz’), treating them as modern.
Finally, it falls back to a default controlled by the error parameter.
- class pycsamt.zonge.base.LegacyAVGBase(mu0=1.2566370614359173e-06, prefer_emh_over_rho=True)#
Bases:
objectBase transformer to convert legacy Zonge
*.avgtables (AMTAVG/MTEdit style) into a modern xarray dataset.- The class:
normalizes legacy columns → canonical, lower-case names
guarantees minimalist coordinates (station, freq, comp)
injects modern fields that may be missing in legacy data
derives conservative quantities (e.g., |Z| in ohms)
composes survey attrs with safe placeholders
- Subclass this base to customize any hook:
_normalize_columns_ensure_coords_inject_placeholders_derive_safe_quantities_build_attrs
Notes on units#
Legacy files are not always explicit about units. This base assumes the modern CSAVGW conventions when deriving |Z|:
E.magin nV/(m·A) → converted to V/(m·A)B.magin pT/A → converted to T/A|Z| = E/Bin ohms
- If only
rhoandfreqexist, we use: |Z| = sqrt(μ0 * ω * ρa)(SI coherent)
We do not synthesize
zmag(historic “km/sec”) to avoid mixing conventions. IfZ.magexists, it is preserved.Resulting Dataset#
- The dataset is shaped as:
station × freq × comp
and contains all numeric legacy variables plus modern stubs (weights, errors, rho_sc, etc.), ready for downstream tools.
- from_path(path, *, utm_zone=None)#
Read a legacy
*.avgfile and return a dataset.
- from_dataframe(df, *, meta=None, coords=('station', 'freq', 'comp'), data_vars=None)#
Transform an already-parsed legacy table into a dataset.
- Parameters:
df (DataFrame) – Tidy legacy data as a
pandas.DataFrame.meta (dict[str, Any] | None) – Optional metadata dict (e.g., from
load_avg).coords (Sequence[str]) – Coordinate columns to use for gridding.
data_vars (Sequence[str] | None) – Optional explicit list of data variables to include. If
None, all numeric columns not used as coords are included.
- Returns:
Dataset with conservative placeholders in place.
- Return type:
xarray.Dataset
- to_xarray(obj, *, meta=None, coords=('station', 'freq', 'comp'), data_vars=None, utm_zone=None)#
Convert a legacy table (DataFrame) or a path to a legacy
*.avgfile into a modern xarray.Dataset.If
objis a path/str → reads the file viafrom_path.If
objis a DataFrame → forwards tofrom_dataframe.