pycsamt.emtools.remove_noise#

Functions

apply_emap_filter(sites, *[, method, ...])

Apply one EMAP-style spatial filter to MT/AMT sites.

confidence_gated_emap_filter(sites, *[, ...])

Apply EMAP filtering only as strongly as confidence requires.

correct_static_shift(sites, *[, window_m, ...])

Remove static shift via Hanning adaptive moving-average (AMA) spatial filter.

drop_freqs_manual(sites, *[, drop_freqs, ...])

Drop Z (and tipper) rows at user-specified frequencies.

emap_filter_report(before_sites, after_sites, *)

Summarize station-level changes after an EMAP-style filter.

emi_mitigation_report(sites, *[, ...])

Summarise remote-reference status and EMI mitigation per station.

enforce_offdiag_consistency(sites, *[, ...])

fixed_length_moving_average(sites, *[, ...])

Apply a fixed-length EMAP moving average along a profile.

hampel_filter_freq(sites, *[, win, nsig, ...])

Remove frequency-domain outliers with a sliding Hampel filter.

mask_incoherent_freqs(sites, *[, ...])

Mask frequencies that fail the requested cross-station SNR vote.

notch_powerline(sites, *[, mains_hz, ...])

Suppress mains-frequency harmonics in impedance and tipper data.

nr_qc_delta_offdiag_psection(sites, *[, ...])

Plot denoising changes in off-diagonal impedance as a pseudosection.

nr_qc_harmonic_waterfall(sites, *[, method, ...])

Plot harmonic-noise reduction by station and mains harmonic.

nr_qc_snr_gain_profile(sites, *[, method, ...])

Plot the station-by-station SNR gain produced by denoising.

nr_qc_station_offdiag_curves(sites, *[, ...])

Compare raw and denoised off-diagonal curves for one station.

plot_emap_filter_profile(before_sites[, ...])

Plot a before/after EMAP filter station profile.

plot_emap_filter_psection(before_sites[, ...])

Plot before/after/delta pseudo-sections for an EMAP filter.

remove_noise_pipeline(sites, *[, mains_hz, ...])

rpca_offdiag_denoise(sites, *[, rank, ...])

shrink_to_group_trend(sites, *[, groups, ...])

smooth_logfreq(sites, *[, win, kind, also, ...])

smooth_rho_phase(sites, *[, components, ...])

Smooth apparent resistivity and phase trends, then rebuild Z.

snr_table(sites, *[, recursive, on_dup, ...])

spatial_median_filter(sites, *[, ...])

trimmed_moving_average(sites, *[, window, ...])

Apply a trimmed EMAP moving average along a profile.

Classes

EMAPFilterResult(sites, report, decisions, ...)

Container returned by confidence-gated EMAP filtering.

class pycsamt.emtools.remove_noise.EMAPFilterResult(sites, report, decisions, method, confidence_method, ci_hi, ci_lo)[source]#

Bases: object

Container returned by confidence-gated EMAP filtering.

Parameters:
sites: Any#
report: DataFrame#
decisions: DataFrame#
method: str#
confidence_method: str#
ci_hi: float#
ci_lo: float#
property n_preserved: int[source]#

Number of station-frequency rows left unchanged.

property n_blended: int[source]#

Number of station-frequency rows partially blended.

property n_filtered: int[source]#

Number of station-frequency rows fully filtered.

summary()[source]#

Return a compact text summary.

Return type:

str

pycsamt.emtools.remove_noise.snr_table(sites, *, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
Return type:

DataFrame

pycsamt.emtools.remove_noise.emi_mitigation_report(sites, *, remote_reference_attempted=False, remote_reference_reason=None, mains_hz=50.0, n_harm=30, tol_hz=0.08, notch_mode='interp', coherent_noise_subtraction=False, applied_measures=None, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Summarise remote-reference status and EMI mitigation per station.

This report is intentionally conservative: pyCSAMT’s emtools operates on estimated transfer functions and does not perform time-series remote-reference processing itself. If a project used externally remote-referenced EDIs, record that with remote_reference_attempted=True and station metadata; otherwise the table documents the post-estimation mitigation path, such as power-line notching, masking/interpolation, coherence masking, Hampel, spatial median, RPCA, or EMAP filtering.

Parameters:
  • sites (Any)

  • remote_reference_attempted (bool)

  • remote_reference_reason (str | None)

  • mains_hz (float)

  • n_harm (int)

  • tol_hz (float)

  • notch_mode (str)

  • coherent_noise_subtraction (bool)

  • applied_measures (Sequence[str] | None)

  • recursive (bool)

  • on_dup (str)

  • strict (bool)

  • verbose (int)

Return type:

DataFrame

pycsamt.emtools.remove_noise.notch_powerline(sites, *, mains_hz=50.0, n_harm=30, tol_hz=0.08, mode='interp', also='both', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Suppress mains-frequency harmonics in impedance and tipper data.

Parameters:
pycsamt.emtools.remove_noise.smooth_logfreq(sites, *, win=5, kind='tri', also='both', gate_snr=None, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
pycsamt.emtools.remove_noise.smooth_rho_phase(sites, *, components='offdiag', degree=3, min_points=None, smooth_rho=True, smooth_phase=True, robust=True, robust_iters=3, blend=1.0, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Smooth apparent resistivity and phase trends, then rebuild Z.

The function operates station-by-station along the frequency axis. It fits polynomial trends versus \(\log_{10}(f)\) to \(\log_{10}(\rho_a)\) and to unwrapped impedance phase, then writes the corresponding complex impedance back into each selected tensor component. This keeps apparent resistivity and phase physically coupled through the same complex Z tensor instead of only smoothing display arrays.

sitesobject

Any input accepted by ensure_sites().

components : {“offdiag”, “diagonal”, “all”, “xx”, “xy”, “yx”, “yy”}

or sequence, default “offdiag”

Tensor components to smooth. The default targets xy and yx because they are the usual MT/CSAMT apparent-resistivity and phase components used for interpretation and 2-D preparation.

degreeint, default 3

Polynomial degree for the log-frequency trend. It is automatically reduced when a station has too few valid frequencies.

min_pointsint or None, default None

Minimum number of finite points required per component. If None, uses degree + 2.

smooth_rho, smooth_phasebool, default True

Select whether the impedance amplitude, phase angle, or both are replaced by the fitted trend.

robustbool, default True

Use a Tukey-style iteratively reweighted polynomial fit to reduce the influence of isolated spikes.

robust_itersint, default 3

Maximum robust reweighting iterations.

blendfloat, default 1.0

Blend between original and smoothed curves. 1 fully applies the trend; 0.5 applies half of the correction.

inplacebool, default False

If True, mutate the normalized input sites. Otherwise work on a best-effort copy of the underlying EDI objects and return new Sites.

recursive, on_dup, strict, verbose

Forwarded to ensure_sites() / to_edis.

pycsamt.site.base.Sites

Sites containing the smoothed impedance tensors.

Apparent resistivity is smoothed in logarithmic space because \(\rho_a\) commonly spans orders of magnitude. Phase is unwrapped before fitting so that crossings near \(\pm 180^\circ\) do not create artificial jumps.

Parameters:
Return type:

Any

pycsamt.emtools.remove_noise.shrink_to_group_trend(sites, *, groups=None, group_key=None, lam=0.25, gate_harm=True, mains_hz=50.0, n_harm=30, tol_hz=0.08, also='both', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
pycsamt.emtools.remove_noise.remove_noise_pipeline(sites, *, mains_hz=50.0, n_harm=30, tol_hz=0.08, notch_mode='interp', smooth_win=5, smooth_kind='tri', gate_snr=2.5, group_shrink=False, shrink_lam=0.25, groups=None, also='both', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
pycsamt.emtools.remove_noise.hampel_filter_freq(sites, *, win=3, nsig=3.0, on='both', domain='reim', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Remove frequency-domain outliers with a sliding Hampel filter.

Parameters:
pycsamt.emtools.remove_noise.spatial_median_filter(sites, *, half_window=2, lam=0.25, on='z', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
pycsamt.emtools.remove_noise.rpca_offdiag_denoise(sites, *, rank=2, keep_phase=True, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
pycsamt.emtools.remove_noise.enforce_offdiag_consistency(sites, *, mode='anti', lam=0.5, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#
Parameters:
pycsamt.emtools.remove_noise.mask_incoherent_freqs(sites, *, snr_thresh=2.5, min_frac=0.4, also='both', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Mask frequencies that fail the requested cross-station SNR vote.

Parameters:
pycsamt.emtools.remove_noise.drop_freqs_manual(sites, *, drop_freqs=(), tol_rel=0.005, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Drop Z (and tipper) rows at user-specified frequencies.

Parameters:
  • sites (object) – Any input accepted by ensure_sites().

  • drop_freqs (sequence of float) – Frequencies (Hz) to remove. Each value is matched within tol_rel relative tolerance: |f - f_drop| / f_drop < tol_rel.

  • tol_rel (float, default 0.005) – Relative frequency tolerance for matching (≈0.5%).

  • inplace (bool, default False) – If True mutate; otherwise work on a copy.

  • recursive (bool)

  • on_dup (str)

  • strict (bool)

  • verbose (int)

Returns:

Sites with the specified frequency rows removed from Z, Z errors, apparent resistivity/phase, and tipper arrays where present.

Return type:

Sites

pycsamt.emtools.remove_noise.correct_static_shift(sites, *, window_m=1500.0, spacing_m=200.0, comp='det', inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Remove static shift via Hanning adaptive moving-average (AMA) spatial filter.

Implements the Torres-Verdín & Bostick (1992) approach used in Kouadio et al. (2024):

  1. For each frequency, build the spatial log(ρ_a) profile across stations.

  2. Apply a Hanning low-pass spatial filter with full-width window_m.

  3. The static-shift correction factor at station i is C_i = sqrt(ρ_smooth_i / ρ_obs_i) (in log space: log C = 0.5 (log ρ_smooth log ρ_obs)).

  4. Update every Z component: Z_corrected = Z × C.

Parameters:
  • sites (path, EDI-like, Sites, or iterable) – Input sites.

  • window_m (float) – Full Hanning window width [m] (Torres-Verdín W_H). Stations further than window_m/2 contribute zero weight.

  • spacing_m (float) – Fallback station spacing [m] used when EDI metadata carries no coordinate information.

  • comp ({"det", "xy", "yx"}) – Apparent-resistivity component used to estimate the static shift. "det" uses the arithmetic mean of |Z_xy|² and |Z_yx|².

  • inplace (bool) – If True, modify the input sites in place. If False (default), return a new Sites object with corrected Z tensors.

  • recursive (bool) – Passed to ensure_sites().

  • on_dup (str) – Passed to ensure_sites().

  • strict (bool) – Passed to ensure_sites().

  • verbose (int) – Passed to ensure_sites().

Returns:

Sites with static-shift-corrected Z tensors (when inplace=False).

Return type:

Sites

pycsamt.emtools.remove_noise.fixed_length_moving_average(sites, *, window=5, component='all', frequency_rtol=1e-06, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Apply a fixed-length EMAP moving average along a profile.

The filter replaces each selected impedance component by the local arithmetic mean of neighboring stations at the same frequency. It is a v2 functional equivalent of the classic FLMA idea and preserves the input frequency grids.

Parameters:
Return type:

Any

pycsamt.emtools.remove_noise.trimmed_moving_average(sites, *, window=5, component='all', frequency_rtol=1e-06, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Apply a trimmed EMAP moving average along a profile.

The filter is similar to fixed_length_moving_average(), but when a full enough window is available it removes the smallest and largest magnitudes before averaging. This makes the profile smoothing less sensitive to isolated bad stations.

Parameters:
Return type:

Any

pycsamt.emtools.remove_noise.apply_emap_filter(sites, *, method='ama', window=5, window_m=1500.0, spacing_m=200.0, component='all', comp='det', frequency_rtol=1e-06, inplace=False, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Apply one EMAP-style spatial filter to MT/AMT sites.

method='ama' delegates to correct_static_shift(), the existing Hanning adaptive moving-average correction. 'flma' and 'tma' apply count-based spatial smoothing along station order.

Parameters:
Return type:

Any

pycsamt.emtools.remove_noise.confidence_gated_emap_filter(sites, *, before_sites=None, method='flma', confidence_method='composite', component='xy', ci_hi=0.9, ci_lo=0.5, weights=None, blend_power=1.0, window=5, window_m=1500.0, spacing_m=200.0, comp='det', frequency_rtol=1e-06, recursive=True, on_dup='replace', strict=False, verbose=0)[source]#

Apply EMAP filtering only as strongly as confidence requires.

Rows with confidence greater than or equal to ci_hi are preserved. Rows below ci_lo are fully replaced by the EMAP-filtered estimate. Rows between the two limits are linearly blended, with optional blend_power shaping.

Parameters:
Return type:

EMAPFilterResult

pycsamt.emtools.remove_noise.emap_filter_report(before_sites, after_sites, *, component='xy', period_s=None, frequency_hz=None)[source]#

Summarize station-level changes after an EMAP-style filter.

The report compares the selected impedance component before and after a filter. When period_s or frequency_hz is provided, the table also includes a reference-row before/after profile value for each station.

Parameters:
  • before_sites (Any)

  • after_sites (Any)

  • component (str)

  • period_s (float | None)

  • frequency_hz (float | None)

Return type:

DataFrame

pycsamt.emtools.remove_noise.plot_emap_filter_profile(before_sites, after_sites=None, *, method='flma', component='xy', period_s=None, frequency_hz=None, window=5, window_m=1500.0, spacing_m=200.0, comp='det', figsize=(9.5, 4.0), station_label_step=1, station_preset='pseudosection', station_style=None, ax=None, **filter_kws)[source]#

Plot a before/after EMAP filter station profile.

Parameters:
Return type:

Axes

pycsamt.emtools.remove_noise.plot_emap_filter_psection(before_sites, after_sites=None, *, method='flma', component='xy', window=5, window_m=1500.0, spacing_m=200.0, comp='det', cmap='RdYlBu_r', delta_cmap='RdBu_r', clim=None, clim_pct=(2.0, 98.0), delta_vlim=None, delta_vlim_pct=95.0, axes=None, figsize=(11.0, 8.2), station_label_step=1, station_preset='pseudosection', station_style=None, **filter_kws)[source]#

Plot before/after/delta pseudo-sections for an EMAP filter.

Parameters:
Return type:

Figure

pycsamt.emtools.remove_noise.nr_qc_delta_offdiag_psection(sites, *, method='pipeline', vlim=None, figsize=(9.0, 4.8), ax=None, **denoise)[source]#

Plot denoising changes in off-diagonal impedance as a pseudosection.

Parameters:
Return type:

Axes

pycsamt.emtools.remove_noise.nr_qc_snr_gain_profile(sites, *, method='pipeline', pband=None, figsize=(8.6, 3.6), ax=None, **denoise)[source]#

Plot the station-by-station SNR gain produced by denoising.

Parameters:
Return type:

Axes

pycsamt.emtools.remove_noise.nr_qc_harmonic_waterfall(sites, *, method='notch', mains_hz=50.0, n_harm=30, tol_hz=0.08, figsize=(9.0, 4.6), ax=None, **denoise)[source]#

Plot harmonic-noise reduction by station and mains harmonic.

Parameters:
Return type:

Axes

pycsamt.emtools.remove_noise.nr_qc_station_offdiag_curves(sites, *, method='pipeline', station=None, mains_hz=50.0, n_harm=12, tol_hz=0.08, figsize=(8.0, 4.2), ax=None, **denoise)[source]#

Compare raw and denoised off-diagonal curves for one station.

Parameters:
Return type:

Axes