2.13. pycsamt.stratagem#

Post-acquisition tooling for AMT surveys collected with Geometrics/EMI Stratagem hardware: raw 19-column QC, WinGLink EDI-directory loading, GPS coordinate injection, static-shift/frequency/noise processing, and export/rename.

2.13.1. pycsamt.stratagem#

Tools for ingesting and pre-processing AMT surveys collected with the Geometrics/EMI Stratagem hardware.

2.13.1.1. Workflow#

Raw Stratagem files (.HXX / .MDX)
→ WinGLink EDI export (external tool, required once)
EDIBatch load the EDI directory
CoordinateInjector inject GPS coords (CSV / XLS / XLSX)

→ export to corrected EDIs ready for emtools processing

2.13.1.2. Classes#

StratagemRawReader

Parse raw 19-column Stratagem ASCII files for QC diagnostics and SNR masks. Does not produce EDI output.

EDIBatch

Load a WinGLink-exported EDI directory as a list of EDIFile objects with natural-sort ordering.

CoordinateInjector

Read a GPS coordinate table (CSV / XLS / XLSX), convert projected coordinates to WGS84, and inject them into EDI >HEAD sections.

StationLocator

Detect or specify the mapping between EDI acquisition order and GPS table row order (forward / reversed / custom index).

class pycsamt.stratagem.EDIBatch(edi_dir=None, *, pattern='*.edi', verbose=0)#

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)#

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()#

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

Returns:

Missing DATAIDs are replaced with the file stem.

Return type:

list of str

class pycsamt.stratagem.StratagemRawReader(station_dir=None, *, component='X', verbose=0)#

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)#

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()#

Return the number of usable frequencies per station.

Returns:

snr_mask_.sum(axis=1)

Return type:

ndarray of shape (n_stations,)

station_coverage()#

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

Return type:

float in [0, 1]

match_to_edis(edi_objects)#

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()#

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()#

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()#

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)#

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.CoordinateInjector(*, coordinate_system='utm', epsg=15921, utm_zone='49N', datum='WGS84', order='auto', verbose=0)#

Bases: PyCSAMTObject, MetadataMixin

Inject GPS coordinates into WinGLink EDI files.

Reads a coordinate table (CSV / XLS / XLSX), converts projected coordinates to WGS84 using project_point_utm2ll(), and writes the resulting latitude, longitude, and elevation into each EDI file’s >HEAD section. The injection is in-memory until export() is called.

Parameters:
  • coordinate_system (str, default 'utm') – Coordinate type of the input table (currently 'utm' is the only supported value; geographic tables can be loaded with easting_col / northing_col pointing to decimal-degree columns and epsg=4326).

  • epsg (int, default 15921) – EPSG code for the projected CRS. 15921 = Beijing 1954 / Gauss-Kruger Zone 49 (standard for Chinese AMT surveys in that belt). Change to match your survey area.

  • utm_zone (str, default '49N') – UTM zone string passed to project_point_utm2ll when epsg is not provided. Ignored when epsg is set.

  • datum (str, default 'WGS84')

  • order ({‘auto’, ‘forward’, ‘reversed’, ‘mapping’}, default 'auto') – Passed to StationLocator.

  • verbose (int, default 0)

Variables:
  • latitudes (ndarray, shape (n_stations,)) – WGS84 latitudes in decimal degrees, in GPS table order.

  • longitudes (ndarray, shape (n_stations,))

  • elevations (ndarray, shape (n_stations,))

  • station_ids (list) – Station labels from the station_col column of the GPS table.

  • edi_objects (list of EDIFile) – EDI objects with >HEAD coordinates updated in-memory. These are the same objects that were loaded into the supplied EDIBatch; pass copy=True to fit() to leave the source batch unchanged.

  • reversed (bool) – Whether StationLocator detected a reversed ordering.

Examples

Typical Stratagem workflow:

>>> from pycsamt.stratagem import EDIBatch, CoordinateInjector
>>> batch  = EDIBatch("2/2EDI").fit()
>>> injector = CoordinateInjector(epsg=15921, utm_zone="49N")
>>> injector.fit(batch, "2.csv")
CoordinateInjector(epsg=15921, ...)
>>> paths = injector.export("2/2EDI_coords")

Custom column names and reversed order:

>>> injector = CoordinateInjector(epsg=15921, order="reversed")
>>> injector.fit(
...     batch, "coords.xlsx",
...     easting_col="E", northing_col="N", elev_col="elevation",
... )
fit(edi_batch, coord_file, *, easting_col=None, northing_col=None, elev_col='elev', station_col='stations', read_kwargs=None, copy=False)#

Load coordinates and inject them into EDI HEAD sections.

Parameters:
  • edi_batch (EDIBatch or list of EDIFile) – Source EDI objects. When copy=True each EDIFile is shallow-copied before modification so the originals are not mutated.

  • coord_file (path-like) – GPS coordinate table. Supported: .csv, .xls, .xlsx (and any format registered in Config).

  • easting_col (str, optional) – Column name for the E-W coordinate. Auto-detected by value magnitude when omitted (see module docstring).

  • northing_col (str, optional) – Column name for the N-S coordinate. Auto-detected when omitted.

  • elev_col (str, default 'elev') – Column name for elevation. If absent from the table, elevations default to zero.

  • station_col (str, default 'stations') – Column with station labels (used to populate station_ids_).

  • read_kwargs (dict, optional) – Extra keyword arguments forwarded to the table reader (e.g. {'sheet_name': 1} for multi-sheet Excel files).

  • copy (bool, default False) – When True, shallow-copy each EDIFile before injecting coordinates so the source batch is not mutated.

Return type:

self

export(savepath, *, basename=None, overwrite=False)#

Write coordinate-injected EDI files to savepath.

Parameters:
  • savepath (path-like) – Output directory. Created automatically when absent.

  • basename (str, optional) – When given, output files are named {basename}{i+1:03d}.edi (e.g. basename='Z2HX' produces Z2HX001.edi, Z2HX002.edi, …). When omitted the original file name is preserved.

  • overwrite (bool, default False) – Skip files that already exist when False.

Returns:

Paths of the written EDI files.

Return type:

list of Path

coordinate_frame()#

Return a DataFrame with station IDs and WGS84 coordinates.

Returns:

Columns: station, latitude, longitude, elevation.

Return type:

pandas.DataFrame

Raises:

NotFittedError – If fit() has not been called.

class pycsamt.stratagem.StationLocator(*, order='auto', mapping=None, verbose=0)#

Bases: PyCSAMTObject

Resolve the mapping between EDI acquisition order and GPS table rows.

Stratagem numbers station files from the first measurement point (001, 002, …, 087). The GPS table is ordered along the physical profile direction, which may run from the opposite end. This class detects or specifies the correct correspondence.

Parameters:
  • order ({'auto', 'forward', 'reversed', 'mapping'}, default 'auto') –

    How to align EDI indices with GPS rows:

    'auto'

    Heuristic: compares the median northing of the first half of GPS records against the direction of increasing station numbers. Falls back to 'forward' when the signal is ambiguous.

    'forward'

    EDI index i maps to GPS row i.

    'reversed'

    EDI index i maps to GPS row n - 1 - i.

    'mapping'

    Use the explicit mapping list supplied to the constructor.

  • mapping (list of int, optional) – Required when order='mapping'. mapping[i] is the GPS row index for EDI station i.

  • verbose (int, default 0)

Variables:
  • index_map (list of int) – After fit(), index_map_[i] is the GPS row for EDI i.

  • reversed (bool) – True when the final mapping is the reverse of natural order.

Examples

>>> loc = StationLocator(order="auto")
>>> loc.fit(batch.edi_objects_, lats, lons)
>>> loc.index_map_[:3]
[0, 1, 2]   # or [86, 85, 84] if reversed
fit(edi_objects, latitudes, longitudes)#

Compute the index map.

Parameters:
  • edi_objects (list of EDIFile)

  • latitudes (ndarray of shape (n_stations,)) – WGS84 coordinates of the GPS table rows in their original order.

  • longitudes (ndarray of shape (n_stations,)) – WGS84 coordinates of the GPS table rows in their original order.

Return type:

self

class pycsamt.stratagem.FrequencyFilter(*, fmin=None, fmax=None, snr_thresh=2.5, min_frac=0.4, use_hardware_mask=True, verbose=0)#

Bases: PyCSAMTObject

Remove bad frequency bins from Stratagem AMT data.

Combines three filtering strategies that are applied in order:

  1. Hardware mask (optional) — zero-stack rows from raw Stratagem files are masked before any statistical analysis. Requires a fitted StratagemRawReader.

  2. Band selection — frequencies outside [fmin, fmax] are dropped.

  3. Incoherent-frequency mask — frequencies that fail the SNR threshold across more than (1 - min_frac) of stations are masked.

All masking is performed in-place on the EDIFile.Z.z arrays of the supplied objects. Use copy=True in fit() to avoid mutating the originals.

Parameters:
  • fmin (float, optional) – Lower frequency bound (Hz). Default: no lower bound.

  • fmax (float, optional) – Upper frequency bound (Hz). Default: no upper bound.

  • snr_thresh (float, default 2.5) – Per-station SNR threshold for incoherent-frequency masking.

  • min_frac (float, default 0.4) – Minimum fraction of stations that must pass snr_thresh for a frequency to be retained.

  • use_hardware_mask (bool, default True) – When a raw_reader is given to fit(), apply the hardware SNR mask.

  • verbose (int, default 0)

Variables:
  • edi_objects (list of EDIFile) – Filtered EDI objects (in-place modified unless copy=True).

  • n_masked_hw (int) – Number of (station, frequency) pairs masked by hardware SNR.

  • n_masked_stat (int) – Number masked by the statistical incoherence criterion.

  • n_dropped_band (int) – Number of frequency rows removed by band selection.

Examples

>>> filt = FrequencyFilter(fmin=10.0, fmax=10000.0)
>>> filt.fit(inj.edi_objects_, raw_reader=rdr)
FrequencyFilter(fmin=10.0, fmax=10000.0, ...)
>>> paths = filt.out("2/2EDIF")
fit(edi_objects, raw_reader=None, *, copy=False)#

Apply frequency filters.

Parameters:
  • edi_objects (list of EDIFile)

  • raw_reader (StratagemRawReader, optional) – Provides hardware SNR masks aligned to station order.

  • copy (bool, default False) – When True, deep-copies the Z data of each EDIFile before masking so the originals are not mutated.

Return type:

self

out(savepath=None, *, overwrite=False)#

Write filtered EDI files to disk or return objects.

Parameters:
  • savepath (path-like, optional) – Output directory. When None, returns the list of filtered EDIFile objects instead of writing to disk.

  • overwrite (bool, default False)

Return type:

list of EDIFile (when savepath is None) or list of Path

class pycsamt.stratagem.QualityController(*, min_frac_ok=0.6, min_snr_med=2.0, max_skew_med=6.0, include_skew=True, verbose=0)#

Bases: PyCSAMTObject, MetadataMixin

Station-level quality-control report for Stratagem AMT surveys.

Wraps build_qc_table() and qc_flags() with optional hardware-level enrichment from a StratagemRawReader.

Parameters:
  • min_frac_ok (float, default 0.6) – Minimum fraction of valid (non-NaN) impedance rows; stations below this are flagged low_coverage.

  • min_snr_med (float, default 2.0) – Minimum median SNR; stations below this are flagged low_snr.

  • max_skew_med (float, default 6.0) – Maximum median absolute phase-tensor skew angle (°); stations exceeding this are flagged high_skew.

  • include_skew (bool, default True) – Include phase-tensor skew in the report. Requires a valid impedance tensor.

  • verbose (int, default 0)

Variables:
  • report (pandas.DataFrame) – Per-station QC metrics. Columns: station, n_freq, n_ok, frac_ok, snr_med, pmin, pmax, and (when include_skew=True) skew_med, skew_iqr. When a StratagemRawReader is supplied to fit(), three additional columns are appended: hw_freqs, hw_usable_freqs, hw_coverage.

  • flags (pandas.DataFrame) – Per-station flag strings in the flags column.

Examples

>>> from pycsamt.stratagem import EDIBatch, CoordinateInjector
>>> from pycsamt.stratagem.qc import QualityController
>>> batch = EDIBatch("2/2EDI").fit()
>>> inj = CoordinateInjector(epsg=32649).fit(batch, "2.csv")
>>> qc = QualityController().fit(inj.edi_objects_)
>>> qc.report_.head()
>>> qc.summary()
fit(edi_objects, raw_reader=None)#

Build the QC report.

Parameters:
  • edi_objects (list of EDIFile) – Stations to assess. Typically from edi_objects_ or edi_objects_.

  • raw_reader (StratagemRawReader, optional) – When supplied, hardware stack counts and SNR masks are joined into report_ as extra columns hw_freqs, hw_usable_freqs, and hw_coverage.

Return type:

self

summary()#

Return a compact text summary of the QC results.

Return type:

str

flagged_stations()#

Return station names with at least one QC flag.

Return type:

list of str

class pycsamt.stratagem.NoiseRemover(*, mains_hz=50.0, n_harm=30, tol_hz=0.08, notch_mode='interp', hampel_win=3, hampel_nsig=3.0, smooth=False, smooth_win=3, verbose=0)#

Bases: PyCSAMTObject

Multi-stage noise-removal pipeline for Stratagem AMT data.

Applies three sequential filters to the impedance tensor:

  1. Powerline notch — masks (interpolates) the mains frequency and its harmonics. Controlled by mains_hz and n_harm.

  2. Hampel outlier filter — identifies and replaces frequency-domain spike outliers using a median-absolute-deviation test.

  3. Log-frequency smoothing (optional) — applies a triangular or Gaussian kernel along the log-frequency axis.

All corrections are applied in-place on EDIFile.Z.z.

Parameters:
  • mains_hz (float, default 50.0) – Mains frequency (Hz). Use 60.0 for North American data.

  • n_harm (int, default 30) – Number of powerline harmonics to notch.

  • tol_hz (float, default 0.08) – Frequency tolerance (Hz) around each harmonic for the notch filter.

  • notch_mode ({‘interp’, ‘zero’, ‘nan’}, default 'interp') – How to handle notched bins: 'interp' interpolates across them (recommended), 'nan' flags them as missing.

  • hampel_win (int, default 3) – Half-window size for the Hampel outlier filter (in frequency bins).

  • hampel_nsig (float, default 3.0) – Outlier threshold in units of median absolute deviation.

  • smooth (bool, default False) – Enable log-frequency smoothing (stage 3).

  • smooth_win (int, default 3) – Smoothing half-window. Values above 4 may trigger a known shape issue in smooth_logfreq() for short frequency vectors; keep ≤ 3 unless you have verified your data.

  • verbose (int, default 0)

Variables:

edi_objects (list of EDIFile) – Denoised EDI objects (in-place modified unless copy=True).

Examples

>>> from pycsamt.stratagem.process import NoiseRemover
>>> nr = NoiseRemover(mains_hz=50.0, smooth=True, smooth_win=3)
>>> nr.fit(edis)
>>> paths = nr.out("2/2EDID")
fit(edi_objects, *, copy=False)#

Apply the noise-removal pipeline.

Parameters:
  • edi_objects (list of EDIFile)

  • copy (bool, default False) – Deep-copy Z data before processing.

Return type:

self

out(savepath=None, *, overwrite=False)#

Return denoised EDI objects or write them to savepath.

Parameters:
  • savepath (path-like, optional)

  • overwrite (bool, default False)

Return type:

list of EDIFile or list of Path

class pycsamt.stratagem.StaticShiftCorrector(*, sort_by='lon', half_window=3, weights='tri', pband=None, max_skew=6.0, verbose=0)#

Bases: PyCSAMTObject, MetadataMixin

Estimate and remove static-shift from Stratagem AMT impedance data.

Implements the AMA (Adaptive Moving-Average) spatial filter to estimate per-station static-shift factors and correct the impedance tensor amplitudes accordingly.

The correction is applied in-place on EDIFile.Z.z. Use copy=True in fit() to preserve originals.

Parameters:
  • sort_by ({‘lon’, ‘lat’, ‘name’}, default 'lon') – Spatial ordering of stations for the AMA spatial average. Use 'lon' for E-W profiles, 'lat' for N-S profiles.

  • half_window (int, default 3) – Number of neighbour stations on each side used in the AMA spatial average.

  • weights ({‘tri’, ‘gauss’, ‘uniform’}, default 'tri') – Distance-weighting scheme for AMA neighbours.

  • pband (tuple of (float, float), optional) – Period range (T_min, T_max) in seconds used when estimating the shift factor. Useful for restricting the estimation to a band free of near-surface distortion.

  • max_skew (float or None, default 6.0) – Phase-tensor skew threshold: stations with median |β| above this are excluded from the spatial average (strong 3-D distortion). Set to None to disable.

  • verbose (int, default 0)

Variables:
  • factors (pandas.DataFrame) – Per-station shift factors with columns station, delta_log10_rho, fac_rho, fac_z, n_used.

  • edi_objects (list of EDIFile) – Corrected EDI objects (in-place modified unless copy=True).

Examples

>>> from pycsamt.stratagem.process import StaticShiftCorrector
>>> sc = StaticShiftCorrector(sort_by="lon", half_window=3).fit(edis)
>>> sc.factors_.head()
>>> paths = sc.out("2/2EDISS")
fit(edi_objects, *, copy=False)#

Estimate and apply static-shift corrections.

Parameters:
  • edi_objects (list of EDIFile)

  • copy (bool, default False) – Deep-copy Z data before correcting.

Return type:

self

out(savepath=None, *, overwrite=False)#

Return corrected EDI objects or write them to savepath.

Parameters:
  • savepath (path-like, optional) – When None returns the list of EDIFile objects; otherwise writes files and returns a list of pathlib.Path.

  • overwrite (bool, default False)

Return type:

list of EDIFile or list of Path

class pycsamt.stratagem.EDIRenamer(*, basename='S', zero_pad=3, trailer='', update_dataid=True, overwrite=False, verbose=0)#

Bases: PyCSAMTObject

Rename Stratagem EDI files with a standardised naming convention.

Reads each source EDI, updates >HEAD.DATAID and the linked SECTID fields to match the new name, then writes the result to dst_path (keeping the source files untouched).

Parameters:
  • basename (str, default 'S') – Name prefix. E.g. 'T2.' produces T2.000.edi, T2.001.edi, …

  • zero_pad (int, default 3) – Width of the zero-padded integer part ('T2.000' has zero_pad=3).

  • trailer (str, default '') – Optional string appended after the index (before .edi).

  • update_dataid (bool, default True) – When True, >HEAD.DATAID and all linked SECTID fields are updated to match the new filename stem.

  • overwrite (bool, default False) – Overwrite existing files in dst_path.

  • verbose (int, default 0)

Variables:
  • renamed_pairs (list of (Path, Path)) – (src, dst) path pairs for every file that was processed.

  • skipped (list of Path) – Source files skipped because the destination already existed and overwrite=False.

Examples

Rename processed EDIs to T2.000.ediT2.082.edi:

>>> rn = EDIRenamer(basename="T2.", zero_pad=3)
>>> rn.fit("2/2EDIP", "2/renamedEDIs")

Or rename in-memory objects produced by the processing pipeline:

>>> rn.fit(nr.edi_objects_, "2/renamedEDIs")
fit(source, dst_path)#

Rename EDI files and write them to dst_path.

Parameters:
  • source (path-like, list of EDIFile, or list of Path) –

    Input EDI files. Accepts:

    • A directory path — all .edi files in it (natural-sort order).

    • A list of EDIFile objects (e.g. from NoiseRemover.edi_objects_).

    • A list of pathlib.Path EDI paths.

  • dst_path (path-like) – Output directory. Created if absent.

Return type:

self

dst_paths()#

Return the list of written destination paths.

Return type:

list[Path]

class pycsamt.stratagem.EDIWriter(*, dataid_prefix=None, zero_pad=3, overwrite=False, verbose=0)#

Bases: PyCSAMTObject, MetadataMixin

Write in-memory EDIFile objects to disk with optional HEAD overrides.

Provides a thin, consistent wrapper around write() that also allows batch update of >HEAD fields (DATAID, ACQBY, DATAID prefix, etc.) before writing.

Parameters:
  • dataid_prefix (str, optional) – When set, each station’s DATAID is overwritten with f"{dataid_prefix}{i:0{zero_pad}d}". Useful for standardising station identifiers across a profile.

  • zero_pad (int, default 3) – Zero-pad width used with dataid_prefix.

  • overwrite (bool, default False)

  • verbose (int, default 0)

Variables:
  • written (list of Path) – Paths of successfully written files.

  • failed (list of tuple(str, Exception)) – (filename, exc) for any file that could not be written.

Examples

Write the noise-corrected EDIs, keeping original file names:

>>> wr = EDIWriter()
>>> wr.fit(nr.edi_objects_, "2/final")
>>> wr.written_

Write with standardised DATAID S000S082:

>>> wr = EDIWriter(dataid_prefix="S", zero_pad=3)
>>> wr.fit(nr.edi_objects_, "2/final")
fit(edi_objects, savepath, *, head_overrides=None)#

Write edi_objects to savepath.

Parameters:
  • edi_objects (list of EDIFile)

  • savepath (path-like) – Output directory.

  • head_overrides (dict, optional) – Key-value pairs applied to every EDI’s >HEAD object before writing. Keys must be valid HEAD attribute names (e.g. 'acqby', 'stdvers').

Return type:

self

class pycsamt.stratagem.StratagemSurvey(edi_dir, coord_file, *, raw_dir=None, epsg=32649, utm_zone='49N', coordinate_system='utm', order='auto', drop_stations=None, easting_col=None, northing_col=None, elev_col='elev', station_col='stations', read_kwargs=None, verbose=0)#

Bases: PyCSAMTObject, MetadataMixin

End-to-end Stratagem AMT survey processing pipeline.

Parameters:
  • edi_dir (path-like, Sites, or sequence of EDIFile) – Directory of WinGLink-exported EDI files (uses Stratagem’s own natural 3-digit sort via EDIBatch), or an already-loaded Sites / EDICollection / list of EDIFile — normalised through ensure_sites(), the same entry point the rest of pycsamt.emtools uses. In the latter case batch_ stays None (there’s no directory to report) and ordering is whatever the source already has.

  • coord_file (path-like) – GPS coordinate table (CSV / XLS / XLSX).

  • raw_dir (path-like, optional) – Directory of raw Stratagem hardware files (X*.NNN, …). When supplied, hardware SNR masks are used in QC and frequency filtering.

  • epsg (int, default 32649) – EPSG code of the projected CRS of coord_file. Use 32649 (UTM Zone 49N WGS84) for the standard south-China survey area.

  • utm_zone (str, default '49N') – UTM zone string for project_point_utm2ll when epsg is not sufficient.

  • coordinate_system (str, default 'utm')

  • order (str, default 'auto') – Station-to-GPS row ordering for StationLocator.

  • drop_stations (list of int, optional) – 0-based indices into the loaded EDIBatch to exclude before coordinate injection — e.g. a calibration/test shot that isn’t a real profile position and has no matching row in coord_file.

  • easting_col (str, optional) – Column names in coord_file for the projected E-W / N-S coordinates. Forwarded to fit(). Required whenever coord_file has more than two numeric columns besides elev_col — auto-detection raises rather than guessing in that case (see pycsamt.stratagem.gis_correct).

  • northing_col (str, optional) – Column names in coord_file for the projected E-W / N-S coordinates. Forwarded to fit(). Required whenever coord_file has more than two numeric columns besides elev_col — auto-detection raises rather than guessing in that case (see pycsamt.stratagem.gis_correct).

  • elev_col (str, default 'elev')

  • station_col (str, default 'stations')

  • read_kwargs (dict, optional) – Extra keyword arguments forwarded to the coord_file reader.

  • verbose (int, default 0)

Variables:
  • batch (EDIBatch or None) – Loaded EDI collection when edi_dir was a directory path; None when edi_dir was already a Sites/list of EDIFile.

  • raw_reader (StratagemRawReader or None) – Hardware file reader (None when raw_dir not supplied).

  • injector (CoordinateInjector) – Coordinate-injected EDI wrapper.

  • qc (QualityController or None) – QC report (populated after run_qc()).

  • edi_objects (list of EDIFile) – Current working set of EDI objects. Modified in-place by each processing step.

Examples

Full pipeline, one fluent expression:

>>> sv = (
...     StratagemSurvey(
...         edi_dir="2/2EDI",
...         coord_file="2.csv",
...         raw_dir="原始数据/2HX",
...         epsg=32649,
...     )
...     .fit()
...     .run_qc()
...     .remove_static_shift()
...     .drop_frequencies(fmin=10.0)
...     .remove_noises()
...     .export("2/2EDIP")
...     .rename(basename="T2.", dst_path="2/renamedEDIs")
... )
>>> print(sv.qc_.summary())
batch_: EDIBatch | None#
raw_reader_: StratagemRawReader | None#
injector_: CoordinateInjector | None#
qc_: QualityController | None#
edi_objects_: list | None#
fit()#

Load EDIs, optional raw files, and inject GPS coordinates.

This is the only mandatory step. All processing methods (remove_static_shift(), drop_frequencies(), etc.) must be called after fit().

Return type:

self

run_qc(*, min_frac_ok=0.6, min_snr_med=2.0, max_skew_med=6.0, include_skew=True)#

Run the station-level QC report.

Results stored in qc_. Does not modify Z data.

Return type:

self

Parameters:
remove_static_shift(*, sort_by='lon', half_window=3, weights='tri', pband=None, max_skew=6.0)#

Apply AMA static-shift correction.

Important

Call this before drop_frequencies() to ensure the full frequency range is available for spatial averaging.

Return type:

self

Parameters:
drop_frequencies(*, fmin=None, fmax=None, snr_thresh=2.5, min_frac=0.4, use_hardware_mask=True)#

Filter frequency bands and mask incoherent bins.

Parameters:
  • fmin (float, optional) – Frequency band limits in Hz.

  • fmax (float, optional) – Frequency band limits in Hz.

  • snr_thresh (float) – Per-station SNR threshold for incoherence masking.

  • min_frac (float) – Minimum fraction of stations that must pass snr_thresh.

  • use_hardware_mask (bool) – Apply hardware SNR mask when raw files were loaded.

Return type:

self

remove_noises(*, mains_hz=50.0, n_harm=30, tol_hz=0.08, notch_mode='interp', hampel_win=3, hampel_nsig=3.0, smooth=False, smooth_win=3)#

Apply powerline notch + Hampel outlier + optional smoothing.

Return type:

self

Parameters:
export(savepath, *, dataid_prefix=None, overwrite=False)#

Write the current edi_objects_ to savepath.

Parameters:
  • savepath (path-like) – Output directory (created if absent).

  • dataid_prefix (str, optional) – When given, >HEAD.DATAID is standardised to {dataid_prefix}{i:03d} before writing.

  • overwrite (bool, default False)

Return type:

self

rename(basename, dst_path, *, zero_pad=3, trailer='', overwrite=False, source=None)#

Rename EDI files with a standardised basename.

Parameters:
  • basename (str) – Filename prefix, e.g. 'T2.'T2.000.edi.

  • dst_path (path-like) – Output directory for renamed files.

  • zero_pad (int, default 3)

  • trailer (str, default '')

  • overwrite (bool, default False)

  • source (path-like, optional) – Source directory or list. Defaults to the directory written by the most recent export() call; falls back to the current edi_objects_.

Return type:

self

summary()#

Return a human-readable pipeline status summary.

Return type:

str

property coordinate_frame#

DataFrame of WGS84 coordinates (requires fit()).

property sites_: Sites#

Current edi_objects_ wrapped as a Sites.

A fresh view built on every access, so it always reflects the current pipeline state (post-QC, post-static-shift, etc.). This is the interop point with the conventional pycsamt.emtools / pycsamt.site stack — e.g. use sv.sites_.write(outdir) for the generic {station}.edi writer instead of Stratagem’s own export()/rename() (which additionally handle DATAID prefixing and Stratagem’s zero-padded naming convention).

Examples

>>> sv.sites_.write("out_dir", exist_ok=True)

2.13.2. Stratagem Modules#

pycsamt.stratagem.gis_correct

stratagem.gis_correct

pycsamt.stratagem.io

stratagem.io

pycsamt.stratagem.process

stratagem.process

pycsamt.stratagem.qc

stratagem.qc

pycsamt.stratagem.rename

stratagem.rename

pycsamt.stratagem.survey

stratagem.survey