2.13.2.2. pycsamt.stratagem.io#

stratagem.io#

Low-level I/O for Stratagem hardware surveys:

  • StratagemRawReader — parse raw 19-column ASCII spectral files (.HXX / .MDX) for quality diagnostics (SNR mask, stack counts, sensor metadata). Does not produce EDI output; use WinGLink for that.

  • EDIBatch — load a directory of WinGLink-exported EDI files as a list of EDIFile objects with natural-sort ordering that respects Stratagem’s three-digit station numbering (001 … 087).

Raw file format#

Each component file (X*.NNN, Y*.NNN, Z*.NNN) is a whitespace-separated ASCII table whose columns are:

col 0   frequency bin (Hz)
col 1   instrument constant (~2.93 for Stratagem)
col 2   stack count (0 = measurement absent / below threshold)
col 3-18  16 cross-spectral values (Re/Im of impedance components)

Rows where col 2 == 0 carry no useful signal and are marked False in the snr_mask_ array.

Classes

EDIBatch([edi_dir, pattern, verbose])

Load a directory of WinGLink-exported EDI files as EDIFile objects.

StratagemRawReader([station_dir, component, ...])

Parse raw Stratagem hardware files (19-column ASCII) for QC diagnostics.

class pycsamt.stratagem.io.StratagemRawReader(station_dir=None, *, component='X', verbose=0)[source]

Bases: PyCSAMTObject

Parse raw Stratagem hardware files (19-column ASCII) for QC diagnostics.

The Stratagem AMT system records frequency-band cross-spectral data for each station in separate component files named X*.NNN, Y*.NNN, and Z*.NNN (where NNN is the zero-padded station number). This reader extracts the frequency grid, stack counts, and SNR masks from those files.

Important

This class does not compute impedance tensors or produce EDI output. Use WinGLink 1.0.x for raw → EDI conversion. The masks produced here can later be consumed by FrequencyFilter to apply hardware-level quality information to the WinGLink EDIs.

Parameters:
  • station_dir (path-like, optional) – Directory containing the raw Stratagem component files. May also be supplied to fit().

  • component ({'X', 'Y', 'Z', 'ALL'}, default 'X') – Which component family to read for QC masks. 'ALL' reads X, Y, and Z and stores per-component masks under component_masks_.

  • verbose (int, default 0) – Verbosity level. 0 = silent; ≥1 = progress messages.

Variables:
  • stations (list of str) – Station file names in acquisition order (e.g. ['X2HX.001', …]).

  • station_numbers (ndarray of int, shape (n_stations,)) – Hardware station numbers extracted from the extension (e.g. [1, 2, …, 87]).

  • freqs (ndarray of shape (n_freqs,)) – Frequency grid in Hz, read from the X-component of the first station.

  • snr_mask (ndarray of shape (n_stations, n_freqs), dtype bool) – True where the stack count is non-zero (measurement present).

  • stack_counts (ndarray of shape (n_stations, n_freqs), dtype int) – Raw stack counts as recorded by the hardware.

  • n_stations (int)

  • n_freqs (int)

  • sensors (dict) – Contents of SENSORS.TBL as {lower_name: original_name}.

  • component_masks (dict, optional) – Present only when component='ALL'. Maps 'X', 'Y', 'Z' to their respective (snr_mask, stack_counts) tuples.

Examples

>>> rdr = StratagemRawReader("原始数据/2HX").fit()
>>> rdr.snr_mask_.shape  # (n_stations, n_freqs)
(87, 292)
>>> good = rdr.snr_mask_.sum(axis=1)  # usable freqs per station
fit(station_dir=None)[source]

Read raw Stratagem files and build QC arrays.

Parameters:

station_dir (path-like, optional) – Override the directory set in __init__.

Return type:

self

usable_freq_counts()[source]

Return the number of usable frequencies per station.

Returns:

snr_mask_.sum(axis=1)

Return type:

ndarray of shape (n_stations,)

station_coverage()[source]

Fraction of (station, frequency) cells with valid data.

Return type:

float in [0, 1]

match_to_edis(edi_objects)[source]

Map EDI batch indices to raw station indices by hardware number.

Stratagem raw files are numbered X*.001X*.087 (extension = hardware station number). WinGLink EDI files are named Z*002.ediZ*087.edi (stem suffix = same number). Index-based alignment is wrong when WinGLink skipped stations or the two sequences start at different offsets.

This method extracts the numeric suffix from each EDI file’s stem and from each raw file’s name, then cross-references by value.

Parameters:

edi_objects (list of EDIFile)

Returns:

{edi_batch_index: raw_station_index} for every EDI that has a matching raw file. EDIs with no matching raw file are absent from the dict.

Return type:

dict[int, int]

Examples

>>> mapping = rdr.match_to_edis(batch.edi_objects_)
>>> mapping[0]  # raw index for the first EDI station
1
station_frame()[source]

Per-station coverage summary as a DataFrame.

Returns:

One row per station. Columns: station, station_number, total_freqs, usable_freqs, coverage, max_stacks, med_stacks.

Return type:

pandas.DataFrame

Examples

>>> rdr.station_frame().sort_values("coverage").head()
freq_frame()[source]

Per-frequency coverage summary as a DataFrame.

Returns:

One row per frequency bin. Columns: freq_hz, stations_ok, frac_ok, med_stacks.

Return type:

pandas.DataFrame

Examples

>>> rdr.freq_frame().query("frac_ok > 0.8")
stack_audit()[source]

Full stack-count audit as a (stations × frequencies) DataFrame.

Returns:

Index = station file names, columns = frequency values (Hz), values = integer stack counts (0 = no measurement).

Return type:

pandas.DataFrame

Examples

>>> audit = rdr.stack_audit()
>>> audit.loc["X2HX.005"]  # one station across all freqs
>>> (audit > 0).sum(axis=1).plot()  # usable freqs per station
plot_coverage(*, kind='snr', cmap='RdYlGn', figsize=None, log_freq=True, title=None)[source]

Plot hardware data coverage as a station × frequency heatmap.

Parameters:
  • kind ({‘snr’, ‘stacks’}, default 'snr') – 'snr' plots the boolean presence/absence mask; 'stacks' shows the raw stack count values.

  • cmap (str, default 'RdYlGn') – Matplotlib colormap.

  • figsize (tuple, optional)

  • log_freq (bool, default True) – Use a log-frequency x-axis.

  • title (str, optional)

Return type:

matplotlib.figure.Figure

class pycsamt.stratagem.io.EDIBatch(edi_dir=None, *, pattern='*.edi', verbose=0)[source]

Bases: PyCSAMTObject

Load a directory of WinGLink-exported EDI files as EDIFile objects.

Files are sorted with a natural-sort key so that Stratagem’s three-digit station numbering (001, 002, …, 087) is preserved regardless of how the OS returns directory entries.

Parameters:
  • edi_dir (path-like, optional) – Directory containing .edi files. May also be given to fit().

  • pattern (str, default '*.edi') – Glob pattern used to discover EDI files.

  • verbose (int, default 0)

Variables:
  • edi_paths (list of Path) – Sorted list of discovered EDI file paths.

  • edi_objects (list of EDIFile) – Successfully parsed EDIFile objects.

  • n_stations (int) – Number of successfully loaded EDI files.

Examples

>>> batch = EDIBatch("2/2EDI").fit()
>>> len(batch)
87
>>> batch[0].station  # DATAID from >HEAD
'S00'
>>> for edi in batch:
...     print(edi.station)
fit(edi_dir=None)[source]

Discover and load EDI files from edi_dir.

Parameters:

edi_dir (path-like, optional) – Override the directory set in __init__.

Return type:

self

station_names()[source]

Return DATAID strings from each loaded EDI’s >HEAD section.

Returns:

Missing DATAIDs are replaced with the file stem.

Return type:

list of str