An AVG instance loads a raw text file, normalizes
its content, and hydrates a full suite of data components,
including stations, frequencies, impedance, quality metrics,
and header blocks. This makes the entire survey accessible
through strongly-typed attributes [1]_.
Parameters:
verbose (bool, default False) – If True, log messages will be printed to the console
during file reading and writing operations.
Returns a JSON-serializable dictionary of all header
metadata.
Notes
Zonge Engineering produced two AVG file formats:
Kind-1 (Legacy): Fixed-width text tables with minimal
metadata.
Kind-2 (Modern): CSV-based format with rich
$key=value headers, used by modern AMTAVG and ASTATIC.
The loader automatically detects the format and transforms it
into a canonical, tidy DataFrame. All subsequent processing is
format-agnostic. Zonge placeholders (*) are converted to
NaN.
Examples
Load a file, access a component, and write back:
>>> frompycsamt.zongeimportAVG>>> avg=AVG.from_file('LCS01.avg',verbose=True)>>> # Access resistivity for a specific component>>> rho_xy=avg.resistivity.frame[... avg.resistivity.frame.comp=='ExHy'... ]>>> avg.write('LCS01_clean.avg')
This classmethod is the primary factory for creating a
fully populated AVG instance directly from a file
on disk. It handles the entire data loading pipeline.
Parameters:
path (str or pathlib.Path) – The filesystem path to the .avg file. Both legacy
(kind-1) and modern (kind-2) formats are supported.
verbose (bool, default False) – If True, log messages will be printed to the console
during the file loading and parsing process.
Returns:
A new, fully initialized instance of the AVG
class containing all the data and metadata from the
file.
This method is a convenient wrapper around the more general
read() method. It creates an instance of the class
and then immediately calls obj.read(path) to perform
the actual data loading and component population.
Examples
>>> frompycsamt.zongeimportAVG>>> # Load a modern AVG file>>> avg=AVG.from_file('data/avg/K2.avg',verbose=True)>>> print(avg.summary)
Export the complete dataset to a single xarray.Dataset.
This is the primary export method for creating a comprehensive,
multi-dimensional, and self-describing dataset. It aggregates
the primary data variables (resistivity, phase), the computed
impedance tensor (Z), and all available quality control (QC)
metrics into a single object.
Parameters:
include_qc (bool, default True) – If True, all available QC components (e.g., pc_emag,
s_phz) will be included as data variables in the
dataset.
include_z (bool, default True) – If True, the real and imaginary parts of the complex
impedance tensor (Z) and its propagated error will be
included as data variables.
Returns:
A dataset with coordinates (station,freq,comp) and
data variables for all included measurements and QC
metrics. The dataset’s attributes are populated from the
AVG file’s header.
Return type:
xarray.Dataset
Notes
This method provides a high-level, convenient way to get all
the processed data into a standard format for analysis and
plotting. It gracefully handles cases where optional
components (like certain QC metrics) are not available in the
source data by skipping them.
This is a convenience method that provides direct access to the
underlying tensor-shaping capabilities of the data components.
It delegates the call to the appropriate component (e.g., Z,
Resistivity) to reshape the selected variable into a NumPy
array.
Parameters:
var ({'z', 'z_real', 'z_imag', 'z_err', 'rho', 'phase'}, default 'z') – The specific data variable to export as a tensor.
station (int or float, optional) – If provided, the method returns a 3D tensor for only this
station. If None, it returns a 4D tensor containing
data for all stations.
agg (str or None, default 'mean') – The aggregation method to use if duplicate measurements
exist for the same station, frequency, and component.
fill_value (float, default np.nan) – The value to use for missing elements in the tensor grid.
sort_freq (bool, default True) – If True, the frequency axis of the tensor will be
sorted.
align ({'union', 'intersection'}, default 'union') – For multi-station tensors, determines how to handle
different frequency sets between stations.
Returns:
tensor (numpy.ndarray) – The data reshaped into a tensor. Shape is
(n_freq,2,2) for a single station or
(n_station,n_freq,2,2) for multiple stations.
freqs (numpy.ndarray) – The frequency axis for the tensor.
stations (numpy.ndarray) – The station axis for the tensor (empty for a single-
station request).
Read, parse, and populate components from a data source.
This is the primary data ingestion method for the class. It
is designed to be flexible, accepting various data sources
and orchestrating the entire process of parsing, transforming,
and populating the internal data components.
meta (mapping, optional) – An optional dictionary of metadata. This is primarily
used when source is a pd.DataFrame to provide
header-like information.
Returns:
self – The method returns the instance of the class, allowing
for convenient method chaining.
AvgFileError – If a file source cannot be reliably classified as either
legacy (kind-1) or modern (kind-2).
AvgDataError – If parsing fails due to malformed or missing data.
Notes
The read method encapsulates a complete data processing
pipeline:
File Handling: If a path is provided, it reads the
file and uses classify_avg_format() to
determine the file kind.
Transformation: If a legacy (kind-1) file is
detected, it automatically uses the
LegacyAVGBase transformer to
convert the data to a modern, structured format.
Standardization: If a raw pd.DataFrame is
provided, it is wrapped in an AVGFrame, which
triggers the automatic standardization of column names
to the internal canonical schema.
Component Population: The final, clean DataFrame and
metadata are passed to the DataInfo component, which
in turn populates all the individual data components
(e.g., Station, Z, Resistivity).
Examples
>>> frompycsamt.zongeimportAVG>>> # Read from a modern file>>> avg=AVG().read('data/avg/K2.avg')>>>>>> # Read from a legacy file (will be auto-transformed)>>> avg_legacy=AVG().read('data/avg/K1.avg')>>>>>> # Read from an in-memory DataFrame>>> importpandasaspd>>> df=pd.DataFrame({'Freq':[1024],'Resistivity':[100]})>>> avg_from_df=AVG().read(df)
Extends AVG with tensor components and analytical methods.
This class inherits from AVG and
provides a more specialized, analysis-focused interface. It is
designed for users who need to perform advanced geophysical
data processing and manipulation. It is designed for working
directly with specific tensor elements (e.g., z_xy, rho_yx).
The primary features of this class include:
Direct, property-based access to individual components of
the impedance, resistivity, and phase tensors as pandas
Series (e.g., z_xy, res_yx_err).
A suite of methods for advanced data processing, such as
tensor rotation, phase unwrapping, and statistical analysis.
In addition to providing direct access to tensor components,
this class includes methods for advanced data manipulation,
such as recalculating resistivity and phase from the impedance
tensor.
Variables:
z_yy (z_xx, z_xy, z_yx,) – The complex impedance for the respective tensor component.
z_yy_err (z_xx_err, z_xy_err, z_yx_err,) – The propagated error for the respective impedance component.
res_yy (res_xx, res_xy, res_yx,) – The apparent resistivity for the respective tensor component.
>>> frompycsamt.zongeimportAMTAVG>>> amt_avg=AMTAVG.from_file('data/avg/K2.avg')>>> # Rotate the data by 30 degrees clockwise>>> amt_avg.rotate(30)>>> # Access the newly rotated Z_xy component>>> z_xy_rotated=amt_avg.z_xy
This method calculates the apparent resistivity (\(\rho_a\))
and impedance phase (\(\phi\)) from the complex
impedance tensor (\(\mathbf{Z}\)). It also propagates
the errors from \(\mathbf{Z}\) to the new values.
Parameters:
todeg (bool, default False) – If True, the output impedance phase and its error
will be converted from milliradians to degrees.
Returns:
rho (pandas.Series) – The calculated apparent resistivity in ohm-meters.
phi (pandas.Series) – The calculated impedance phase in milliradians or
degrees.
rho_err (pandas.Series) – The propagated relative error in apparent resistivity
(in percent).
phi_err (pandas.Series) – The propagated error in impedance phase (in the same
units as phi).
This method updates the core DataFrame with new apparent
resistivity and impedance phase values. After updating, it
automatically re-initializes all data components, ensuring
that dependent values (like the impedance tensor Z) are
recalculated and the entire object state remains consistent.
Parameters:
rho (pandas.Series) – A Series containing the new apparent resistivity values.
The index must align with the internal DataFrame.
phi (pandas.Series) – A Series containing the new impedance phase values,
assumed to be in milliradians.
rho_err (pandas.Series, optional) – A Series containing the new relative error values for
resistivity (in percent).
phi_err (pandas.Series, optional) – A Series containing the new error values for phase (in
milliradians).
Notes
This is a powerful method for data manipulation, such as
applying static shifts or corrections. By calling
self.info.read at the end, it ensures that all changes
are propagated correctly throughout the entire data model.
Fetch a 3D tensor for a single station using xarray.
This method extracts the data for a single station from the
full multi-station dataset and returns it as a 3D tensor
in an xarray.DataArray.
Parameters:
station_id (int or float) – The unique identifier for the station to retrieve. This
must match one of the values in the ‘station’
coordinate of the dataset.
var ({'z', 'rho', 'phase'}, default 'z') – The specific data variable to retrieve.
- ‘z’: Complex impedance tensor.
- ‘rho’: Apparent resistivity tensor.
- ‘phase’: Impedance phase tensor.
Returns:
A 3D DataArray with dimensions (frequency,e,h)
containing the tensor data for the requested station.
Return type:
xarray.DataArray
Raises:
KeyError – If the specified station_id is not found in the
dataset’s station coordinates.
NotReadError – If this method is called before data has been loaded.
Notes
This method leverages the powerful label-based indexing of
xarray’s .sel() method. It first constructs the full
multi-station tensor in memory and then selects the slice
corresponding to the given station_id.
Examples
>>> frompycsamt.zongeimportAMTAVG>>> avg=AMTAVG.from_file('data/avg/K2.avg')>>> # Get the resistivity tensor for station 25.0>>> rho_tensor_25=avg.get_tensor_by_station(25.0,var='rho')>>> print(rho_tensor_25.shape)(28, 2, 2)
This method computes statistical metrics for repeated
measurements, mirroring the process of the original Zonge
AMTAVG program. It groups the data by station and frequency
and calculates the mean, standard deviation (σ), and
coefficient of variation (C-var) for key measurement
columns.
Parameters:
drop_on_failure (bool, default True) – If True, rows where statistical calculations
cannot be performed (e.g., only one measurement in a
group) will be excluded from the output DataFrame.
update_components (bool, default True) – If True, after calculating the statistics, this
method will automatically update the corresponding QC
components (e.g., self.pc_rho, self.s_phz) with the
newly computed values.
Returns:
A DataFrame containing the calculated statistical
metrics, including mean, standard deviation, and
coefficient of variation for rho, phase,
emag, and hmag.
The calculations are based on the formulas described in the
AMTAVG manual [1]_. The coefficient of variation (C-var),
which corresponds to the legacy % columns, is
calculated as:
\[C_{var} = 100 \cdot \frac{\sigma}{\bar{x}}\]
where \(\sigma\) is the standard deviation and
\(\bar{x}\) is the mean of the measurements.
Unwraps the impedance phase to correct for 2π jumps.
This method implements a phase referencing/unwrapping
algorithm, similar to the PHASEREF mode in the original
Zonge AMTAVG program. It corrects for phase wrapping by
ensuring that the absolute difference between consecutive
phase values (sorted by frequency) does not exceed π
radians (1000π milliradians).
Parameters:
todeg (bool, default False) – If True, the final unwrapped phase values in the
DataFrame will be converted from milliradians to
degrees.
update_components (bool, default True) – If True, the main DataFrame (self.info.df) is
updated in place with the unwrapped phase values, and
all data components are re-read to reflect this change.
Returns:
A new DataFrame with the unwrapped phase values. The
main self.info.df is also updated if
update_components is True.
The unwrapping is performed independently for each unique
station and component pair. The data is first sorted by
frequency to ensure the correct sequence for unwrapping.
The core of the algorithm uses numpy.unwrap(), which
operates in radians. The phase values, assumed to be in
milliradians, are converted to radians before unwrapping
and then converted back to the desired output unit.
Examples
>>> frompycsamt.zongeimportAMTAVG>>> avg=AMTAVG.from_file('data/avg/K2.avg')>>> # Unwrap phase and update the object in place>>> avg.unwrap_phase()>>> # Get the unwrapped phase for the xy component>>> unwrapped_phi_xy=avg.phase_xy
This method performs a 2D rotation of the impedance tensor
\(\mathbf{Z}\) for all measurements. The rotation is
applied in a clockwise-positive direction, which is standard
in many geophysical applications.
Parameters:
angle (float) – The rotation angle in degrees, where a positive angle
corresponds to a clockwise rotation of the coordinate
system.
update_components (bool, default True) – If True, the main DataFrame (self.info.df) is
updated in place with the new, rotated impedance values,
and all dependent components (like resistivity and
phase) are recalculated and updated.
Returns:
A new DataFrame containing the four rotated complex
impedance components (z_xx_rot, z_xy_rot,
z_yx_rot, z_yy_rot). The main self.info.df is
also updated if update_components is True.
where \(\mathbf{Z}\) is the original impedance tensor,
\(\mathbf{Z'}\) is the rotated tensor, \(\theta\)
is the rotation angle, and \(\mathbf{R}(\theta)\) is
the rotation matrix:
This operation updates the z_xx, z_xy, z_yx,
and z_yy components. If update_components is
True, the apparent resistivity and phase are then
recalculated from this new rotated impedance tensor.
This method computes the complex Tipper components (Tx, Ty)
by solving the linear relationship:
\(H_z = T_x H_x + T_y H_y\)
Parameters:
hz_data (pandas.Series) – A Series containing the complex vertical magnetic field
(\(H_z\)) data. The index of this Series must match
the index of the main DataFrame (self.info.df).
update_components (bool, default True) – If True, a new Tipper component will be created and
attached to the self.info object, populated with the
calculated Tx and Ty values.
Returns:
A new DataFrame containing the calculated complex Tipper
components, tx and ty.
The calculation is performed for each unique station and
frequency using a least-squares approach to solve for
\(T_x\) and \(T_y\). This requires at least two
linearly independent horizontal field measurements for a
stable solution.
This method requires the horizontal magnetic field data
(hmag, hphz) to be present in the dataset.
Base class for AVG data handling and file writing.
This class serves as the core engine for reading, parsing,
and writing Zonge AVG data files. It handles the logic for
identifying file types (legacy vs. modern), transforming
legacy data, and populating a structured data model.
Parameters:
verbose (bool, default False) – If True, log messages will be printed to the console
during file reading and writing operations, providing
insight into the process.
Variables:
info (DataInfo) – An aggregator object that holds all the individual data
components (e.g., Header, Station, Z, Resistivity).
verbose (bool) – Controls the verbosity of logging output.
_kind ({1, 2} or None) – Indicates the detected file format: 1 for legacy, 2 for
modern. None if no file has been read.
_source_path (pathlib.Path or None) – The path to the source file that was read.
Notes
This class is typically not instantiated directly by users.
Instead, the AVG class, which
inherits from BaseAVG, is the primary user-facing entry
point.
The read method is the main entry point for data ingestion
and is designed to be flexible, accepting file paths or
in-memory data structures.
Examples
While direct use is uncommon, one could use BaseAVG like so:
Read, parse, and populate components from a data source.
This is the primary data ingestion method for the class. It
is designed to be flexible, accepting various data sources
and orchestrating the entire process of parsing, transforming,
and populating the internal data components.
meta (mapping, optional) – An optional dictionary of metadata. This is primarily
used when source is a pd.DataFrame to provide
header-like information.
Returns:
self – The method returns the instance of the class, allowing
for convenient method chaining.
AvgFileError – If a file source cannot be reliably classified as either
legacy (kind-1) or modern (kind-2).
AvgDataError – If parsing fails due to malformed or missing data.
Notes
The read method encapsulates a complete data processing
pipeline:
File Handling: If a path is provided, it reads the
file and uses classify_avg_format() to
determine the file kind.
Transformation: If a legacy (kind-1) file is
detected, it automatically uses the
LegacyAVGBase transformer to
convert the data to a modern, structured format.
Standardization: If a raw pd.DataFrame is
provided, it is wrapped in an AVGFrame, which
triggers the automatic standardization of column names
to the internal canonical schema.
Component Population: The final, clean DataFrame and
metadata are passed to the DataInfo component, which
in turn populates all the individual data components
(e.g., Station, Z, Resistivity).
Examples
>>> frompycsamt.zongeimportAVG>>> # Read from a modern file>>> avg=AVG().read('data/avg/K2.avg')>>>>>> # Read from a legacy file (will be auto-transformed)>>> avg_legacy=AVG().read('data/avg/K1.avg')>>>>>> # Read from an in-memory DataFrame>>> importpandasaspd>>> df=pd.DataFrame({'Freq':[1024],'Resistivity':[100]})>>> avg_from_df=AVG().read(df)
This method serializes the object’s data into a modern,
CSAVGW-style .avg file. It delegates the core writing
and formatting logic to the write_avg()
function.
Parameters:
path (str or pathlib.Path, optional) – The output file path. If None, a default filename
(e.g., K2_modern.avg) is created in the current
working directory.
stamp (bool, default True) – If True, a $Written=<timestamp> line is added to
the header for provenance.
float_fmt (str, default "%.6g") – The format specifier for floating-point numbers.
na_rep (str, default "*") – The string representation for missing (NaN) values.
header_spaces (bool, default False) – If True, adds spaces around the equals sign in header
keywords (e.g., $Key=Value).
Notes
This method intelligently prepares the data for writing by:
1. Assembling a complete header by calling the
This method reconstructs the classic, fixed-width format of
older Zonge AVG files. It uses the populated data components
to generate the header and formatted data rows.
Parameters:
path (str or pathlib.Path, optional) – The output file path. If None, a default filename
(e.g., K2_legacy.avg) is created in the current
working directory.
precision (int, default 4) – The number of decimal places for scientific notation
fields (e.g., ‘Emag’, ‘Resistivity’).
na_rep (str, default "*") – The string representation for missing (NaN) values.
Notes
The conversion from a modern, comprehensive data structure to
the legacy format involves several key steps:
Header Synthesis: It creates a minimal legacy header
using $ASPACE and $XMTR keywords derived from the
header component.
Column Translation: It translates the internal canonical
column names (e.g., ‘pc_emag’) back to their legacy
equivalents (e.g., ‘%Emag’) for correct formatting.
Data Filtering: It first filters out any artificial
data rows (e.g., those with NaN in the ‘rho’ column) to
ensure the output is clean.
Be aware that some information from a modern dataset may be
lost in this conversion, as the legacy format does not
support all the fields of the modern format.
This method acts as a high-level dispatcher, calling either
the to_legacy() or to_modern() method based on the
fmt parameter. It provides a single, convenient entry point
for file serialization.
Parameters:
path (str or pathlib.Path, optional) – The output file path. If None, a default filename will
be generated based on the source file’s name.
fmt ({'legacy', 'kind1', 'modern', 'kind2', 'auto'}, default 'auto') – The desired output format.
- ‘legacy’ or ‘kind1’: Writes a fixed-width legacy file.
- ‘modern’ or ‘kind2’: Writes a CSV-based modern file.
- ‘auto’: Defaults to the modern format.
**kwargs – Additional keyword arguments to be passed to the specific
writing method (to_legacy or to_modern). For example,
precision for to_legacy or float_fmt for
to_modern.
Provide a Bunch object with a summary of key attributes.
This property aggregates the most important descriptive
metadata and statistics from the loaded dataset into a single,
easy-to-read object. It is useful for quickly inspecting the
contents and overall scope of the survey data.
Returns:
A Bunch object (which behaves like a dictionary with
attribute-style access) containing key information such
as the source filename, data format kind, project name,
number of stations and frequencies, and their respective
ranges.
The summary property is read-only and is generated on-demand
by introspecting the various data components (e.g., header,
station, frequency). If no data has been loaded, it will
return a Bunch with a ‘status’ key indicating this.
The Bunch object has a user-friendly string representation,
making it ideal for printing in interactive sessions.
Return a shallow, JSON-serializable representation.
This method aggregates the keyword dictionaries from all
header components into a single dictionary, providing a
complete, serializable view of the survey’s metadata.
This class provides common attributes and methods, such as
verbosity control, a standardized logger, and parameter
management, that can be inherited by other classes in the
Zonge subpackage.
Parameters:
verbose (bool, default False) – Controls the level of detail in logging output. If True,
informational and debugging messages will be displayed.
**kws (dict) – Additional keyword arguments for future compatibility.
A 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=value
lines in the AVG file.
source (pathlib.Path, optional) – The filesystem path to the original .avg file, used for
provenance and logging.
A 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.
Dynamically 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
explicit df[FieldAliases.rho].
The class attributes are not hardcoded. They are generated
dynamically by introspecting the ALL_ALIASES dictionary
from the schema module. 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:
>>> frompycsamt.zonge.baseimportFieldAliases>>> # 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')
Abstract 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.
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.
Serialise the component to text lines. Implementations
may delegate to _write_csv_block for a consistent block
format (header + CSV). The base does not write to disk.
High-level aggregator for a complete Zonge AVG dataset.
This class acts as the primary container and orchestrator for
all data and metadata parsed from a Zonge AVG file. It
composes all other data components (e.g., Header, Z,
Resistivity, Phase, and QC metrics) into a single,
convenient object.
Its main role is to provide a unified interface, holding all
the structured information in one place after the initial
parsing is complete.
Variables:
df (pandas.DataFrame or None) – The core tidy DataFrame containing all available data
columns after parsing and standardization.
meta (mapping or None) – The raw metadata dictionary extracted from the file’s
header section.
header (Header) – A component that aggregates all header-level metadata.
station (Station) – A component that manages survey line geometry.
z (Z) – The component for computing the complex impedance tensor.
phase (resistivity,) – Components for apparent resistivity and phase data.
comp (frequency, amps,) – Components for core measurement quantities.
pc_rho (pc_emag, pc_hmag,) – Components for percent-error quality control metrics.
s_phz (s_ephz, s_hphz,) – Components for phase standard deviation QC metrics.
The read method is the core of this class. It iterates
through all its component attributes and calls their
respective read methods. It includes a robust error-
handling mechanism that will issue a warning and skip any
component that fails to load (e.g., due to missing data in
the source file), making the loading process resilient.
Examples
While typically used internally by the AVG class, you could
use DataInfo directly:
>>> frompycsamt.zonge.infoimportDataInfo>>> frompycsamt.zonge.utilsimportload_avg>>> df,meta=load_avg('data/avg/K2.avg')>>> data_info=DataInfo()>>> data_info.read(df,meta)>>> print(data_info.station)Station(n=28, span=25.0–1375.0 m, inc=50.0)
Transmitter current amplitude container (unit: A).
The class normalises the amps column to numeric, tracks
a few useful stats, and can (optionally) export itself as a
small CSV block. Context columns are preserved.
Examples
>>> amps=Amps.from_avg((df,meta))>>> amps.stats.mean12.7>>> ds=amps.to_xarray()# optional grid for convenience
Enumeration/validator for classical CSAMT component labels.
The class guarantees a canonical comp column with allowed
values (case-sensitive): {'ExHy','ExHx','EyHy','EyHx'}.
A few common case variants are accepted and normalized.
Convert to an xarray.Dataset. We include freq as a data
variable as well, which is helpful in some consumers; the
coordinate is still the same freq axis created by coords.
A class for advanced processing of Zonge AVG data.
This class provides a suite of methods for data conditioning
and analysis that mirror the functionality of Zonge’s ASTATIC
software [1]_. It operates on a loaded
AMTAVG object, allowing for complex
operations like static shift correction, data filtering, and
interpolation.
Parameters:
avg_data (BaseAVG, optional) – An initialized and loaded AVG object. If provided, the
processor is immediately ready for use.
verbose (bool, default False) – If True, log messages will be printed to the console
during processing operations, providing insight into the
process.
Variables:
avg (AMTAVG or None) – The AVG data object that the processor is operating on.
It is populated by either passing it to the constructor or
by using the read() method.
The ASTATIC class is designed using a “composition over
inheritance” approach. It is not a type of AVG file;
rather, it is a tool that contains and operates on an
AVG object.
Most processing methods, such as correct_static_shift,
modify the underlying avg object’s DataFrame in place when
the update_components parameter is set to True. This
ensures that all data components are consistently updated
after a processing step.
Examples
The typical workflow involves loading data with an AMTAVG
object and then passing that object to the ASTATIC
processor.
>>> frompycsamt.zongeimportAMTAVG,ASTATIC>>> # 1. Load the data>>> avg=AMTAVG.from_file('data/avg/K2.avg')>>>>>> # 2. Create a processor and apply a correction>>> processor=ASTATIC().read(avg)>>> processor.correct_static_shift(... reference_freq=4096,filter_method='tma'... )>>>>>> # 3. The original avg object is now updated and can be saved>>> avg.to_modern('K2_corrected.avg')
This is the primary method for associating a dataset with
the ASTATIC processor. It is designed to be flexible,
accepting various input types and ensuring that the
processor is initialized with a valid, fully-loaded AVG
data object.
TypeError – If the source is of an unsupported type.
NotReadError – If an AVG-like object is passed as the source but
it has not been populated with data yet.
Notes
This method acts as a smart constructor for the processor.
If the provided source is not already a loaded AVG
object, the method takes on the responsibility of creating
one. This ensures that the self.avg attribute is always
a valid, ready-to-use data container.
Examples
>>> frompycsamt.zongeimportAMTAVG,ASTATIC>>> # --- Reading from a pre-loaded AVG object --->>> avg=AMTAVG.from_file('data/avg/K2.avg')>>> processor=ASTATIC().read(avg)>>>>>> # --- Reading directly from a file path --->>> processor_from_file=ASTATIC().read('data/avg/K1.avg')
Correct for capacitive coupling effects in E-field data.
This method remediates distortions in high-frequency data
caused by capacitive coupling between receiver wires and
the ground.
Parameters:
contact_resistance (float, pd.Series, or str) – The contact resistance at the electrodes, in Ohms. Can
be a single value for all measurements, a Series, or
the name of a column in the dataset.
setup_length (float, pd.Series, or str) – The length of the setup wire, in meters. This is often
the distance from the GDP to the dipole center.
wire_capacitance (float, pd.Series, or str, default 15.0) – The wire-to-ground capacitance in picofarads per meter
(pF/m). This is often an empirical tuning parameter.
update_components (bool, default True) – If True, the main DataFrame (self.avg.info.df) is
updated in place with the corrected E-field values, and
all dependent components (Z, rho, phase) are
recalculated.
Returns:
A new DataFrame containing the corrected emag and
ephz columns.
The correction is based on a simple circuit model where the
capacitive admittance (\(Y_c\)) shunts the true Earth
impedance. The measured voltage is corrected to estimate
the true voltage that would be measured without this effect.
The correction factor is given by:
\[E_{true} = \frac{E_{measured}}{1 + Z_c Y_c}\]
where \(Z_c\) is the contact impedance (resistance) and
\(Y_c = i \omega C\) is the capacitive admittance.
This method applies a spatial filter to the data at a
single reference frequency to estimate and correct for
static shift effects.
Parameters:
reference_freq (float) – The frequency (in Hz) at which to perform the spatial
filtering. This should typically be the highest
frequency with clean data.
filter_method ({'tma', 'flma', 'ama'}, default 'tma') – The filtering algorithm to use:
- ‘tma’: Trimmed Moving Average (works on resistivity).
- ‘flma’: Fixed-Length Moving Average (works on impedance).
- ‘ama’: Adaptive Moving Average (works on impedance).
update_components (bool, default True) – If True, the main DataFrame (self.avg.info.df) is
updated in place with the static-shifted resistivity
values, and all components are re-read.
**kwargs – Additional keyword arguments to be passed to the chosen
filtering function (e.g., window_size for tma,
filter_width_dipoles for flma).
Returns:
A DataFrame containing the station, the original data
profile, the smoothed profile, and the shift factor.
This is a scalar variable (one number per row), but the
class inherits the tensor-alignment logic so values land in
the appropriate \(2\times 2\) slot given by comp.
This class manages the impedance phase data, inheriting from
TensorBase to allow its scalar values to be
aligned into a \(2 \times 2\) tensor-like grid based on
the component label.
Notes
Values are typically reported in milliradians in modern
CSAVGW tables (Unit.Phase='mrad'). Use the
convert_unit() method to switch to degrees when
desired.
The internal canonical column name for phase data is phase.
Recognized source columns:
Z.phz (modern)
Phase (legacy)
phase, ZPHZ (common variants)
Variables:
VAR_NAME (str) – The canonical column name used in the internal frame
("phase").
UNIT_ATTR (str) – The dataset attribute key used for storing units
("Unit.Phase").
Parse source and produce a compact frame with
station,freq,comp,phase. Coordinates are injected
conservatively when absent (station=NaN,
comp='ExHy'). Unit.Phase defaults to 'mrad'.
This component reads the station coordinate from a tidy AVG frame
(usually column 'station'), validates and stores unique positions,
and (optionally) normalizes the origin to zero. It also derives a
stable set of header keys ($Stn.*) for round-tripping modern headers.
Accepts either a DataFrame (from AVG parsers) or raw arrays.
Handles ragged frequency coverage (no equal-count requirement).
Tracks units; internal helpers can work in metres when desired.
Derives $Stn.Beg / $Stn.Inc / $Stn.Left / $Stn.Right if grid-like.
Exposes dictionary mappings useful for downstream selection.
Notes
We do not modify the caller’s AVG frame; we keep our own view
in self._frame that at minimum contains a numeric 'station'
column and (if relevant) a 'station_m' column when the input
length unit is feet (‘ft’) and conversion to metres is helpful.
source (DataFrame | Sequence[float] | ndarray) – DataFrame with a 'station' column or a 1-D array of
station values (possibly repeated across frequencies).
meta (Mapping[str, Any] | None) – Optional file metadata. If provided and unit is None, we
try meta['Unit.Length'] for (‘m’|’ft’).
unit (str | None) – Length unit of source values. Defaults to ‘m’ or to
meta['Unit.Length'] when available.
names (Sequence[str] | None) – Optional labels for unique station positions. If omitted,
we auto-generate: ‘S00’, ‘S01’, …
normalize (bool | None) – When True, shift the origin so the first station is 0.0.
allow_ragged (bool | None) – When False, all stations must have identical row counts
(one per frequency). When True (default), ragged coverage
is allowed.
Emit a small, human-friendly header preamble plus a CSV of the
station coordinate. This is mainly useful for diagnostics and
tests; full file writing should be orchestrated at a higher
level.
Adds impedance-like tensor helpers to a component.
This class acts as a mixin, providing methods to transform
data between a tidy DataFrame format (one measurement per
row) and a dense, multi-dimensional tensor format suitable
for numerical computations.
It is agnostic to the actual physical quantity being
reshaped; the var parameter in its methods specifies which
column from the internal DataFrame to use for the tensor’s
values.
Notes
Subclasses must provide a tidy _frame attribute containing
at least the columns ['freq','comp'] and optionally
'station'.
The tensor axes are consistently ordered:
- 3D (single station): (frequency,E-field,H-field)
- 4D (multi-station): (station,frequency,E,H)
The E-field and H-field axes are of size 2, corresponding to
the x and y components.
Serialise the component to text lines. Implementations
may delegate to _write_csv_block for a consistent block
format (header + CSV). The base does not write to disk.
The Tipper, also known as the induction vector, is a transfer
function that relates the vertical component of the magnetic
field (\(H_z\)) to the horizontal components
(\(H_x\), \(H_y\)).
\[H_z = T_x H_x + T_y H_y\]
This class is designed to hold the complex Tipper components
\(T_x\) and \(T_y\) after they have been calculated.
Variables:
ty (tx,) – The complex Tipper components for the x and y directions.
This method expects a DataFrame that contains the
calculated Tipper components, named ‘tx’ and ‘ty’. If these
columns are missing, they will be created and filled with
NaNs for structural consistency.
Read a Zonge AVG file and return a tidy DataFrame and metadata.
This function serves as the primary parser for both legacy
(kind-1) and modern (kind-2) Zonge AVG files. It automatically
detects the file format, parses the data accordingly, and
standardizes all column names to a consistent, canonical
schema.
Parameters:
path (str or pathlib.Path) – The filesystem path to the .avg file.
ll_columns (tuple[str, str], default ('latitude', 'longitude')) – Column names in the source data that contain latitude and
longitude values in decimal degrees. This is not a standard
Zonge field but is supported for custom data formats.
utm_zone (int, optional) – The UTM zone number to use for coordinate conversion. If
None, the zone is auto-detected from the longitude.
inplace (bool, default False) – This parameter is deprecated and no longer has an effect,
as the function always returns a new DataFrame.
Returns:
df (pandas.DataFrame) – A tidy DataFrame where all column names have been
standardized to the internal canonical schema (e.g.,
‘Resistivity’ becomes ‘rho’).
meta (dict) – A dictionary containing all header metadata from the file.
For modern files, this includes a ‘blocks’ key with a
list of per-station metadata blocks.
The standardization of column names is a key feature of this
function. It ensures that all subsequent processing steps can
rely on a consistent and predictable data structure, regardless
of the input file’s original format. This is achieved by using
the _CANONICAL_MAP from the schema module.
Examples
>>> frompycsamt.zonge.utilsimportload_avg>>> # Load a modern AVG file>>> df,meta=load_avg('data/avg/K2.avg')>>> print(df.columns)Index(['z_mwgt', 'freq', ..., 'station', 'comp', 'use'], dtype='object')>>> print(meta['Survey.Type'])CSAMT
This function serves as the core writer for creating modern,
CSAVGW/ASTATIC-style .avg files. It takes a DataFrame
with canonical column names, aggregates metadata, and formats
the output into a structured text file with data blocks
grouped by station.
Parameters:
core (pandas.DataFrame) – The main DataFrame containing the core measurement data.
It is expected to have canonical column names (e.g.,
‘rho’, ‘phase’, ‘pc_emag’).
extra (pandas.DataFrame or None) – An optional DataFrame containing additional columns to be
merged with the core data before writing.
meta (dict, optional) – A dictionary of global metadata to be written as
$keyword=value pairs in the file header.
path (str or pathlib.Path, optional) – The output file path. If None, a default filename
like exported_kind2.avg is created in the current
working directory.
stamp (bool, default True) – If True, a $Written=<timestamp> line is added to
the header for provenance.
float_fmt (str, default "%.6g") – The format specifier for writing floating-point numbers
in the data blocks.
na_rep (str, default "*") – The string representation for missing (NaN) values in the
data blocks, conforming to the Zonge convention.
header_spaces (bool, default False) – If True, adds spaces around the equals sign in header
keywords (e.g., $Key=Value).
banner_lines (sequence of str, optional) – A sequence of comment lines (starting with ‘\’) to be
prepended to the file header, typically for hardware and
processing information.
This function is designed to produce clean, compliant, and
human-readable kind-2 AVG files. Its key behaviors include:
Column Renaming: It uses the CANON_TO_MODERN_MAP from
the schema module to automatically convert the
internal canonical column names back to the standard modern
format (e.g., ‘rho’ becomes ‘ARes.mag’).
Block Grouping: If a ‘station’ column is present, the
function intelligently groups the data by station and writes
a separate data block for each, preceded by its specific
$Rx.* metadata.
Smart Column Filtering: It automatically detects and
omits placeholder columns (like ‘Choer’, ‘Gdp.Blk’) if they
contain no valid data, preventing empty columns from
cluttering the output file. It also excludes internal helper
columns from the final output.
Aligned Formatting: The function uses a custom CSV
formatter to produce neatly aligned, fixed-width-like
columns within the data blocks, matching the appearance of
files generated by Zonge’s proprietary software.
This filter is designed to remove single-station static
offsets while preserving broader geological trends. It can
operate on a pandas Series, a NumPy array, or a column
within a pandas DataFrame.
The apparent resistivity data to be filtered. This can be:
- A pandas Series of resistivity values.
- A 1D NumPy array of resistivity values.
- The string name of the column to use if data is
provided.
data (pd.DataFrame, optional) – A DataFrame containing the resistivity data. Required if
rho_profile is provided as a string.
window_size (int, default 5) – The size of the moving window for the filter. Must be
an odd integer.
trim_proportion (float, default 0.2) – The proportion of observations to trim from each end of
the window before computing the mean. For a window of 5,
0.2 trims 1 value from each end (the min and max).
Returns:
The smoothed resistivity profile, returned in the same
format as the input (rho_profile). If a DataFrame was
passed to data, the function returns a new DataFrame
with an added column for the smoothed data.
Return type:
pd.Series, np.ndarray, or pd.DataFrame
Raises:
ValueError – If rho_profile is a string but data is not provided,
or if window_size is not an odd integer.
Apply a Fixed-Length Moving Average (FLMA) filter.
This filter smooths complex impedance data using a spatial
Hanning window whose width is a fixed multiple of the
receiver dipole length.
Parameters:
z_profile (pd.Series, np.ndarray, or str) – The complex impedance data (Z) to be filtered. Can be:
- A pandas Series of complex impedance values.
- A 1D NumPy array of complex impedance values.
- The string name of the column if data is provided.
stations (pd.Series, np.ndarray, or str) – The station locations (coordinates). Must correspond to
the z_profile data. Can be a Series, array, or column
name if data is provided.
dipole_length (float) – The length of the E-field receiver dipole in the same
units as the station locations.
data (pd.DataFrame, optional) – A DataFrame containing the impedance and station data.
Required if z_profile or stations are strings.
filter_width_dipoles (float, default 5.0) – The total width of the Hanning window, expressed in
multiples of the dipole_length.
Returns:
The smoothed complex impedance profile, returned in the
same format as the input. If a DataFrame was passed to
data, a new DataFrame with an added column for the
smoothed data is returned.
Interpolate AVG data onto a regular log-spaced grid.
This function resamples the apparent resistivity and phase
data for each station and component onto a new, logarithmically
spaced frequency axis. This is a common preprocessing step for
inversion and modeling.
Parameters:
df (pandas.DataFrame) – The input DataFrame containing the AVG data. Must include
‘station’, ‘freq’, ‘rho’, and ‘phase’ columns.
freq_min (float, optional) – The minimum frequency for the new grid. If None, it is
inferred from the minimum frequency in the data.
freq_max (float, optional) – The maximum frequency for the new grid. If None, it is
inferred from the maximum frequency in the data.
num_points (int, default 50) – The number of logarithmically spaced points to create
between freq_min and freq_max.
interp_kind (str, default 'cubic') – The kind of interpolation to perform, passed to
scipy.interpolate.interp1d. Common options are
‘slinear’, ‘quadratic’, and ‘cubic’.
Returns:
A new DataFrame with the data interpolated onto the
specified logarithmic frequency grid.
Smooth apparent resistivity using the Hilbert transform.
This function reconstructs a smoother apparent resistivity
curve from the impedance phase data, leveraging the causal
nature of magnetotelluric data.
Parameters:
df (pandas.DataFrame) – The input DataFrame. Must include ‘station’, ‘freq’,
‘rho’, and ‘phase’ columns.
smoothing_factor (float, default 0.1) – The smoothing factor for the UnivariateSpline applied
to the phase data before the Hilbert transform. A smaller
value results in less smoothing.
Returns:
A new DataFrame with a ‘rho_smoothed’ column containing
the reconstructed, smoother apparent resistivity values.
Determine a suitable reference frequency for static shift.
This utility automatically selects a reference frequency based
on the principle of using the “highest frequency with clean
data,” as recommended in the ASTATIC manual.
Parameters:
df (pandas.DataFrame) – The input DataFrame containing the AVG data. Must include
‘station’, ‘freq’, and a quality control column.
The method for determining the reference frequency.
- ‘auto’: Automatically select the frequency based on QC
metrics.
float: A specific frequency value to use, which will be
returned directly.
qc_column (str, default 'pc_rho') – The canonical name of the quality control column to use for
filtering “clean” data points.
qc_threshold (float, default 20.0) – The threshold for the qc_column. Data points where the
value in this column is below the threshold are
considered clean.
The ‘auto’ mode follows a robust, data-driven approach:
1. It filters the dataset to include only “clean” data points
(where qc_column < qc_threshold).
For each station, it finds the highest frequency that has
clean data.
It then returns the median of these highest frequencies.
The median is used to provide a stable estimate that is
robust against outlier stations.
If no data points meet the clean criteria, the function will
issue a warning and fall back to using the absolute maximum
frequency present in the entire dataset.
Skew is a dimensionless parameter that quantifies the
three-dimensionality of the subsurface conductivity structure.
It is a crucial diagnostic tool for determining whether a 1D
or 2D interpretation is appropriate for the data.
Parameters:
df (pandas.DataFrame) – A tidy DataFrame containing the impedance tensor components.
Must include ‘station’, ‘freq’, ‘comp’, and a complex ‘z’
column.
Returns:
A DataFrame with columns for ‘station’, ‘freq’, and the
calculated ‘skew’.
Generally, skew values are interpreted as follows:
- skew < 0.1: Data can be considered 1D.
- 0.1 <= skew <= 0.3: Data is likely 2D.
- skew > 0.3: Data is likely 3D or affected by significant
This function determines the principal axis direction of the
impedance tensor for each station and frequency. The strike is
the angle to which the coordinate system must be rotated to
minimize the diagonal components of the impedance tensor
(\(Z_{xx}\), \(Z_{yy}\)), which is a common assumption
for 2D geological structures.
Parameters:
df (pandas.DataFrame) – A tidy DataFrame containing the impedance tensor components.
Must include ‘station’, ‘freq’, ‘comp’, and a complex ‘z’
column from which the tensor elements can be pivoted.
Returns:
A DataFrame with columns for ‘station’, ‘freq’, and the
calculated ‘strike_angle’ in degrees clockwise from North.
The calculation is performed using a common tensor
decomposition method based on the real parts of the impedance
tensor components [1]_. The formula used is:
This angle represents the orientation of the primary 2D
geological structure.
Examples
>>> frompycsamt.zongeimportAMTAVG>>> frompycsamt.zonge.proc_utilsimportget_strike>>> avg=AMTAVG.from_file('data/avg/K2.avg')>>> # The Z component's frame already has the required columns>>> strike_df=get_strike(avg.z.frame)>>> print(strike_df.head())
Header facade that aggregates survey-level property containers (Hardware, Annotation, Configuration, Tx, Rx, Skip) and exposes a uniform read/write API based on $keyword=value lines.