2.25.3.19. pycsamt.ai.processing.plot#
Visualisation helpers for pycsamt.ai.processing output.
- QC (
EMQCScorer) plot_qc_scores()— per-station bar chartplot_qc_heatmap()— station × freq. heat-mapplot_qc_feature_heatmap()— one panel per QC featureplot_qc_score_distribution()— score histogram + KDEplot_qc_score_spread()— violin / box / stripplot_qc_summary()— 3-panel summary figure
- Denoising (
EMDenoiser) plot_denoise_spectra()— before/after spectra, per siteplot_denoise_noise_reduction()— per-station roughness reductionplot_denoise_summary()— combined summary figure
- Anomaly detection (
AnomalyDetector) plot_anomaly_scores()— per-station bar chartplot_anomaly_score_distribution()— score histogram + KDEplot_anomaly_summary()— 2-panel summary figure
- Dimensionality (
DimensionalityClassifier) plot_dimensionality_map()— station × freq. class mapplot_predicted_strike_rose()— 2-D strike rose diagramplot_dimensionality_summary()— 3-panel summary figure
- Gap filling (
EMImputer) plot_imputer_gaps()— station × freq. missing-data mapplot_imputer_validation()— held-out true-vs-reconstructed scatter, faceted by componentplot_imputer_reconstruction()— per-site spectra, reconstructed cells highlightedplot_imputer_summary()— 3-panel summary figure
- Uncertainty calibration (
UncertaintyCalibrator) plot_uncertainty_map()— station × freq. fractional-error heat-map (log colour scale)plot_uncertainty_validation()— held-out true-vs-calibrated scatterplot_uncertainty_summary()— 4-panel summary figure
- Distortion triage (
DistortionTypeClassifier) plot_distortion_map()— per-station regime bar chartplot_distortion_feature_space()— feature scatter coloured by regime, with rule thresholdsplot_distortion_summary()— 4-panel summary figure
- Time-series denoising (
TimeSeriesDenoiser) plot_ts_denoise_mmf_split()— raw + low-frequency envelope, high-frequency residualplot_ts_denoise_segments()— residual with SVM-flagged noisy windows shadedplot_ts_denoise_summary()— 3-panel before/after summary
- Shared
plot_training_history()— train/val loss curve for any of the three network-based estimators above.
Functions
|
Anomaly-score histogram and optional KDE, mirroring |
|
Per-station anomaly-score bar chart, mirroring |
|
Two-panel anomaly-detection summary: per-station bar chart and score distribution, sharing one resolved threshold. |
|
Per-station roughness reduction achieved by |
|
Before/after spectra for |
|
Combined denoiser figure: before/after spectra, per-station roughness reduction, and (when available) the training curve. |
|
Station × frequency dimensionality-class heat-map. |
|
Three-panel dimensionality-classification summary. |
|
Two-feature scatter coloured by predicted distortion regime, for |
|
Per-station distortion-regime bar chart, for |
|
Combined |
|
Station x frequency map of genuinely missing cells for |
|
Per-station, per-channel spectra with reconstructed cells highlighted, for |
|
Combined |
|
Predicted-vs-true scatter for a synthetic held-out-cell validation of |
|
Rose diagram of predicted geoelectric strike directions. |
|
One panel per QC feature — station × frequency heat-maps. |
|
Station × frequency QC-score heat-map. |
|
Score histogram and optional KDE per profile. |
|
Per-profile score spread: violin, box, or jitter-strip plot. |
|
Per-station QC-score bar chart, optionally grouped by profile. |
|
Three-panel QC summary figure. |
|
Train/validation loss curve for a pycsamt.ai.processing estimator. |
|
Mathematical-morphological-filter (MMF) low/high split. |
|
High-frequency residual with SVM window classification overlaid. |
|
Combined before/after summary for |
|
Station x frequency heat-map of a fractional-error column, for |
|
Combined |
|
Predicted-vs-true scatter for |
- pycsamt.ai.processing.plot.plot_qc_scores(scores, *, station_labels=None, profile_colors=None, score_threshold=0.5, threshold_color='#c0392b', threshold_lw=1.4, threshold_ls='--', bad_zone_color='#fde8e8', bad_zone_alpha=0.3, bar_width=0.8, bar_alpha=0.88, show_scatter=True, show_profile_labels=True, profile_label_fontsize=8, separator_color='gray', separator_lw=0.7, separator_ls='--', show_zone_labels=True, zone_label_fontsize=8, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, xlabel='Station', ylabel='QC score', title='', ylim=None, show_grid=True, figsize=(10.0, 4.2), ax=None)[source]
Per-station QC-score bar chart, optionally grouped by profile.
Handles label overlap automatically:
tick_every="auto"(the default) picks the smallest nice step (1 → 2 → 5 → 10 → 25 → …) so that station labels never overlap, regardless of how many stations are shown. Pass aStationTickConfigvia station_tick_config for fine-grained reusable control.- Parameters:
scores (ndarray, dict, or DataFrame) –
Quality scores. Accepted forms:
ndarrayshape(n_st,)— single profile.dict[str, ndarray]— one 1-D array per profile name.pandas.DataFramefromEMQCScorer.score_table()— requires ascorecolumn; optionalstation,freq,profilecolumns are used when present.
station_labels (list of str or None) – X-axis tick labels. Inferred from the
stationcolumn when scores is a DataFrame. Defaults to integer index strings.profile_colors (dict, list, or None) –
{profile_name: color}mapping, ordered list, orNonefor the built-in colour cycle.score_threshold (float, default
0.5) – Threshold line and rejection-zone boundary.bar_width (float, default
0.80)bar_alpha (float, default
0.88)show_scatter (bool, default
True) – When scores is a DataFrame with afreqcolumn, draw semi-transparent per-frequency score dots behind each bar.show_profile_labels (bool, default
True)profile_label_fontsize (int, default
8)show_zone_labels (bool, default
True) – Add “Good ▶” / “◀ Review” margin annotations.zone_label_fontsize (int, default
8)tick_every (int or
"auto", default"auto") – Station tick step."auto"computes the step from the figure width and label length so labels never overlap. Pass an integer to force a fixed step, e.g.tick_every=5shows every 5th label.tick_label_rotation (float, default
45.0)tick_fontsize (int, default
7)station_tick_config (
StationTickConfigor None) – If provided, overrides tick_every, tick_label_rotation, and tick_fontsize entirely.xlabel (str)
ylabel (str)
title (str)
ylim ((ymin, ymax) or None)
show_grid (bool, default
True)figsize ((w, h), default
(10.0, 4.2))ax (Axes or None)
- Returns:
ax
- Return type:
Examples
>>> from pycsamt.ai.processing.plot import plot_qc_scores >>> plot_qc_scores({"L18": sc_18, "L22": sc_22}, tick_every=5)
>>> from pycsamt.ai.plot import StationTickConfig >>> cfg = StationTickConfig(every=10, rotation=30, fontsize=8) >>> plot_qc_scores(scores_dict, station_tick_config=cfg)
- pycsamt.ai.processing.plot.plot_qc_heatmap(scores, *, station_labels=None, score_threshold=0.5, cmap='RdYlGn', vmin=0.0, vmax=1.0, period_up=True, show_threshold_contour=True, contour_color='white', contour_lw=0.8, n_yticks=7, colorbar_label='QC score', xlabel='Station', ylabel='Period (s)', title='', station_markers=True, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, figsize=(10.0, 5.2), ax=None)[source]
Station × frequency QC-score heat-map.
- Parameters:
scores (DataFrame) – Must contain
station,freq, andscorecolumns (output ofscore_table()).score_threshold (float, default
0.5)cmap (str, default
"RdYlGn")vmin (float)
vmax (float)
period_up (bool, default
True)show_threshold_contour (bool, default
True)n_yticks (int, default
7)colorbar_label (str)
xlabel (str)
ylabel (str)
title (str)
station_markers (bool, default
True) – Draw the station axis at the top with pyCSAMT’s shared downward-triangle convention (PYCSAMT_STATION_RENDERING), the same rendering used throughout the rest of the package for period/station sections. Set toFalseto fall back to a plain bottom axis controlled by tick_every / tick_label_rotation / tick_fontsize / station_tick_config instead.tick_every (int or
"auto") – Only used whenstation_markers=False.tick_label_rotation (float, default
45.0) – Only used whenstation_markers=False.tick_fontsize (int, default
7) – Only used whenstation_markers=False.station_tick_config (
StationTickConfigor None) – Only used whenstation_markers=False.figsize ((w, h))
ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_qc_feature_heatmap(df, *, features=None, station_labels=None, cmaps=None, period_up=True, n_yticks=5, station_markers=True, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=6, station_tick_config=None, clim_pct=(2.0, 98.0), title='', figsize=None)[source]
One panel per QC feature — station × frequency heat-maps.
- Parameters:
df (DataFrame) – Output of
EMQCScorer.score_table(). Must containstation,freq, and the feature columns.features (list of str or None) – Feature columns to plot. Defaults to all five QC features.
cmaps (dict or None) –
{feature: cmap_name}overrides.period_up (bool, default
True)n_yticks (int, default
5)station_markers (bool, default
True) – Draw the station axis once, above the top panel, using pyCSAMT’s shared downward-triangle convention (seeplot_qc_heatmap()). Set toFalsefor a plain bottom axis on the last panel, controlled by tick_every / tick_label_rotation / tick_fontsize / station_tick_config.tick_every (tick control) – Only used when
station_markers=False.tick_label_rotation (tick control) – Only used when
station_markers=False.tick_fontsize (tick control) – Only used when
station_markers=False.station_tick_config (
StationTickConfigor None) – Only used whenstation_markers=False.clim_pct ((lo, hi), default
(2.0, 98.0))title (str)
figsize ((w, h) or None)
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_qc_score_distribution(scores, *, station_labels=None, profile_colors=None, score_threshold=0.5, n_bins=20, show_kde=True, kde_bw=None, fill_alpha=0.35, line_lw=1.8, threshold_color='#c0392b', threshold_lw=1.3, threshold_ls='--', xlabel='QC score', ylabel='Density', title='', show_legend=True, figsize=(6.0, 4.0), ax=None)[source]
Score histogram and optional KDE per profile.
Each profile’s scores are shown as a semi-transparent histogram with an overlaid KDE curve. The review threshold is marked as a vertical line. Suitable as a standalone figure or embedded in a summary panel.
- Parameters:
scores (ndarray, dict, or DataFrame) – Same flexible input as
plot_qc_scores().score_threshold (float, default
0.5)n_bins (int, default
20)show_kde (bool, default
True) – Overlay a KDE curve on top of each histogram.kde_bw (float, str, or None) – KDE bandwidth passed to
scipy.stats.gaussian_kde.None→ Scott’s rule.fill_alpha (float, default
0.35)line_lw (float, default
1.8)xlabel (str)
ylabel (str)
title (str)
show_legend (bool, default
True)figsize ((w, h), default
(6.0, 4.0))ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_qc_score_spread(scores, *, station_labels=None, profile_colors=None, score_threshold=0.5, kind='violin', show_scatter=True, scatter_alpha=0.25, scatter_size=5.0, jitter=0.08, violin_alpha=0.7, threshold_color='#c0392b', threshold_lw=1.3, threshold_ls='--', ylabel='QC score', title='', show_legend=False, figsize=(6.0, 4.0), ax=None)[source]
Per-profile score spread: violin, box, or jitter-strip plot.
- Parameters:
scores (ndarray, dict, or DataFrame) – Same flexible input as
plot_qc_scores().score_threshold (float, default
0.5)kind (
"violin"|"box"|"strip", default"violin") – Plot style."strip"shows only jittered scatter dots.show_scatter (bool, default
True) – Overlay jittered scatter dots (ignored when kind is"strip").scatter_alpha (float, default
0.25)scatter_size (float, default
5.0)jitter (float, default
0.08) – Maximum horizontal jitter width.violin_alpha (float, default
0.70)ylabel (str)
title (str)
show_legend (bool, default
False)figsize ((w, h), default
(6.0, 4.0))ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_qc_summary(scores, *, station_labels=None, profile_colors=None, score_threshold=0.5, show_scatter=True, n_bins=20, show_kde=True, kde_bw=None, spread_kind='violin', tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, suptitle='', figsize=(13.0, 9.5))[source]
Three-panel QC summary figure.
Layout:
┌────────────────────────────────┐ │ (a) Per-station bar chart │ full width ├──────────────────┬─────────────┤ │ (b) Score dist │ (c) Spread │ │ histogram + KDE │ per profile│ └──────────────────┴─────────────┘
Panels (b) and (c) are produced by
plot_qc_score_distribution()andplot_qc_score_spread()respectively, so they can also be used as standalone figures.- Parameters:
scores (ndarray, dict, or DataFrame) – Same flexible input as
plot_qc_scores().score_threshold (float, default
0.5)show_scatter (bool, default
True)n_bins (int, default
20)show_kde (bool, default
True)spread_kind (
"violin"|"box"|"strip")tick_every (int or
"auto")tick_label_rotation (float, default
45.0)tick_fontsize (int, default
7)station_tick_config (
StationTickConfigor None)suptitle (str)
figsize ((w, h), default
(13.0, 9.5))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_denoise_spectra(freq, X_raw, X_denoised, *, station_labels=None, component_labels=None, sites=None, n_show=4, raw_color='#7f7f7f', denoised_color='#d62728', raw_alpha=0.75, log_freq=True, sharey='row', suptitle='', figsize=None)[source]
Before/after spectra for
EMDenoiser.One column per selected site, one row per feature component, following the
(n_sites, n_components, n_freqs)array convention used byprepare_z_features().- Parameters:
freq (ndarray, shape (n_freqs,)) – Frequency grid in Hz shared by all sites (the
freq_refgrid fromprepare_z_features()).X_raw (ndarray, shape (n_sites, n_components, n_freqs)) – Input and
transform()output.X_denoised (ndarray, shape (n_sites, n_components, n_freqs)) – Input and
transform()output.station_labels (list of str or None) – One label per site. Defaults to
site0, site1, ....component_labels (list of str or None) – One label per row. Defaults to the standard
[log|Zxy|, phi_xy, log|Zyx|, phi_yx]ordering (or its 8-component variant) used byprepare_z_features().sites (list of int or None) – Explicit site indices to display. Overrides n_show when given.
n_show (int, default
4) – Number of sites to display when sites isNone— the first n_show sites are used.raw_color (str)
denoised_color (str)
raw_alpha (float, default
0.75)log_freq (bool, default
True)sharey (
"row"|"none", default"row") – Share the y-axis across sites within each component row so amplitudes are directly comparable.suptitle (str)
figsize ((w, h) or None)
- Returns:
fig
- Return type:
Examples
>>> from pycsamt.ai.processing.plot import plot_denoise_spectra >>> plot_denoise_spectra( ... freq, X_noisy, X_denoised, n_show=3, ... )
- pycsamt.ai.processing.plot.plot_denoise_noise_reduction(X_raw, X_denoised, *, station_labels=None, aggregate='mean', bar_color='#2166ac', negative_color='#c0392b', tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, xlabel='Station', ylabel='Roughness reduction (%)', title='', show_grid=True, figsize=(10.0, 4.0), ax=None)[source]
Per-station roughness reduction achieved by
EMDenoiser.“Roughness” is the mean absolute second difference along the frequency axis — large for jagged, noisy spectra and small for smooth ones. The plotted quantity is the percentage reduction in roughness from X_raw to X_denoised, aggregated over feature components with aggregate. Positive values mean the denoiser removed high-frequency scatter; values near zero or negative flag stations where denoising had little effect or over-smoothed genuine structure.
- Parameters:
X_raw (ndarray, shape (n_sites, n_components, n_freqs))
X_denoised (ndarray, shape (n_sites, n_components, n_freqs))
aggregate (
"mean"|"median", default"mean") – Reduction statistic across components.bar_color (str) – Colour for stations with a positive (improved) reduction.
negative_color (str) – Colour for stations with zero or negative reduction.
tick_every (tick control)
tick_label_rotation (tick control)
tick_fontsize (tick control)
station_tick_config (
StationTickConfigor None)xlabel (str)
ylabel (str)
title (str)
show_grid (bool, default
True)figsize ((w, h), default
(10.0, 4.0))ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_denoise_summary(freq, X_raw, X_denoised, *, history=None, station_labels=None, component_labels=None, n_show=3, suptitle='', figsize=(13.0, 10.0))[source]
Combined denoiser figure: before/after spectra, per-station roughness reduction, and (when available) the training curve.
Layout:
┌──────────────────────────────────────────┐ │ Before / after spectra, n_show sites │ ├───────────────────────┬──────────────────┤ │ Roughness reduction │ Training history │ │ per station │ (if available) │ └───────────────────────┴──────────────────┘
- Parameters:
X_raw (ndarray, shape (n_sites, n_components, n_freqs))
X_denoised (ndarray, shape (n_sites, n_components, n_freqs))
history (estimator, dict, or None) – Passed to
plot_training_history()when not empty; the bottom-right panel is left blank otherwise.n_show (int, default
3)suptitle (str)
figsize ((w, h), default
(13.0, 10.0))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_anomaly_scores(scores, *, station_labels=None, profile_colors=None, threshold=None, threshold_percentile=95.0, threshold_color='#c0392b', threshold_lw=1.4, threshold_ls='--', bad_zone_color='#fde8e8', bad_zone_alpha=0.3, bar_width=0.8, bar_alpha=0.88, show_profile_labels=True, profile_label_fontsize=8, separator_color='gray', separator_lw=0.7, separator_ls='--', show_zone_labels=True, zone_label_fontsize=8, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, xlabel='Station', ylabel='Anomaly score (reconstruction error)', title='', ylim=None, show_grid=True, figsize=(10.0, 4.2), ax=None)[source]
Per-station anomaly-score bar chart, mirroring
plot_qc_scores().Unlike QC scores, higher values are worse: the shaded rejection band and the “Anomalous” label sit above the threshold line rather than below it.
- Parameters:
scores (ndarray, dict, or DataFrame) – Reconstruction-error scores from
transform(). Same flexible input asplot_qc_scores(): a single 1-D array,{profile: array}, or a DataFrame with ascorecolumn.threshold (float or None) – Explicit anomaly threshold. When
None, computed as the threshold_percentile-th percentile of the pooled scores. PassAnomalyDetector.threshold_directly to plot the fitted value.threshold_percentile (float, default
95.0)bar_width (float)
bar_alpha (float)
show_profile_labels (bool, default
True)profile_label_fontsize (int, default
8)show_zone_labels (bool, default
True)zone_label_fontsize (int, default
8)tick_every (tick control)
tick_label_rotation (tick control)
tick_fontsize (tick control)
station_tick_config (
StationTickConfigor None)xlabel (str)
ylabel (str)
title (str)
ylim ((ymin, ymax) or None) – Defaults to
(0, 1.15 * max(scores, threshold)).show_grid (bool, default
True)figsize ((w, h), default
(10.0, 4.2))ax (Axes or None)
- Returns:
ax
- Return type:
Examples
>>> from pycsamt.ai.processing.plot import plot_anomaly_scores >>> plot_anomaly_scores( ... scores, threshold=det.threshold_, ... )
- pycsamt.ai.processing.plot.plot_anomaly_score_distribution(scores, *, station_labels=None, profile_colors=None, threshold=None, threshold_percentile=95.0, n_bins=20, show_kde=True, kde_bw=None, fill_alpha=0.35, line_lw=1.8, threshold_color='#c0392b', threshold_lw=1.3, threshold_ls='--', xlabel='Anomaly score', ylabel='Density', title='', show_legend=True, figsize=(6.0, 4.0), ax=None)[source]
Anomaly-score histogram and optional KDE, mirroring
plot_qc_score_distribution().The shaded rejection band and threshold line sit to the right of the threshold value (high score = anomalous) — the opposite convention from the QC-score version.
- Parameters:
scores (ndarray, dict, or DataFrame)
threshold (float or None) – See
plot_anomaly_scores().threshold_percentile (float, default
95.0)n_bins (int, default
20)show_kde (bool, default
True)fill_alpha (float, default
0.35)line_lw (float, default
1.8)xlabel (str)
ylabel (str)
title (str)
show_legend (bool, default
True)figsize ((w, h), default
(6.0, 4.0))ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_anomaly_summary(scores, *, station_labels=None, profile_colors=None, threshold=None, threshold_percentile=95.0, n_bins=20, show_kde=True, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, suptitle='', figsize=(13.0, 4.6))[source]
Two-panel anomaly-detection summary: per-station bar chart and score distribution, sharing one resolved threshold.
- Parameters:
scores (ndarray, dict, or DataFrame)
threshold (float or None)
threshold_percentile (float, default
95.0)n_bins (int, default
20)show_kde (bool, default
True)tick_every (tick control)
tick_label_rotation (tick control)
tick_fontsize (tick control)
station_tick_config (
StationTickConfigor None)suptitle (str)
figsize ((w, h), default
(13.0, 4.6))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_dimensionality_map(df, *, dim_col='dim', station_labels=None, class_colors=('#2ca02c', '#1f77b4', '#d62728'), class_labels=('1-D', '2-D', '3-D'), period_up=True, n_yticks=7, station_markers=True, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, xlabel='Station', ylabel='Period (s)', title='', figsize=(10.0, 5.2), ax=None)[source]
Station × frequency dimensionality-class heat-map.
Renders the categorical 1-D / 2-D / 3-D output of
DimensionalityClassifier.predict_tablethe same wayplot_qc_heatmap()renders continuous QC scores, with a discrete three-colour legend in place of a colourbar.- Parameters:
df (DataFrame) – Output of
DimensionalityClassifier.predict_table(). Must containstation,freq, and dim_col.dim_col (str, default
"dim") – Column with integer class labels (0=1-D, 1=2-D, 2=3-D).period_up (bool, default
True)n_yticks (int, default
7)station_markers (bool, default
True) – Draw the station axis at the top with pyCSAMT’s shared downward-triangle convention (seeplot_qc_heatmap()). Set toFalsefor a plain bottom axis controlled by tick_every / tick_label_rotation / tick_fontsize / station_tick_config.tick_every (tick control) – Only used when
station_markers=False.tick_label_rotation (tick control) – Only used when
station_markers=False.tick_fontsize (tick control) – Only used when
station_markers=False.station_tick_config (
StationTickConfigor None) – Only used whenstation_markers=False.xlabel (str)
ylabel (str)
title (str)
figsize ((w, h), default
(10.0, 5.2))ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_predicted_strike_rose(strike_deg, *, bins=18, fold_180=True, color='#1f77b4', edgecolor='white', alpha=0.85, show_mean=True, mean_color='#d62728', title='', figsize=(5.0, 5.0), ax=None)[source]
Rose diagram of predicted geoelectric strike directions.
- Parameters:
strike_deg (array-like or DataFrame) – Strike angles in degrees, typically the
strikecolumn returned byDimensionalityClassifier.predict_table()(NaNfor non-2-D observations). A DataFrame is expected to carry astrikecolumn.bins (int, default
18) – Number of angular bins spanning 0-360 degrees (10-degree bins by default).fold_180 (bool, default
True) – Strike has a 180-degree ambiguity (a line has no direction of travel). WhenTrue, every angle is plotted together with its 180-degree-rotated counterpart so the rose is symmetric — the standard convention for strike roses.show_mean (bool, default
True) – Draw a radial line at the circular mean strike.mean_color (str)
title (str)
figsize ((w, h), default
(5.0, 5.0))ax (polar Axes or None) – When given, must have been created with
subplot_kw={"projection": "polar"}.
- Returns:
ax
- Return type:
matplotlib.axes.Axes(polar)
Examples
>>> from pycsamt.ai.processing.plot import plot_predicted_strike_rose >>> plot_predicted_strike_rose( ... table["strike"], title="L18 strike rose", ... )
- pycsamt.ai.processing.plot.plot_dimensionality_summary(df, *, dim_col='dim', strike_col='strike', station_labels=None, class_colors=('#2ca02c', '#1f77b4', '#d62728'), class_labels=('1-D', '2-D', '3-D'), tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, rose_bins=18, suptitle='', figsize=(13.0, 9.0))[source]
Three-panel dimensionality-classification summary.
Layout:
┌────────────────────────────────────┐ │ Station × frequency dim map │ full width ├───────────────────┬────────────────┤ │ Class proportions │ Strike rose │ │ │ (2-D sites) │ └───────────────────┴────────────────┘
- Parameters:
df (DataFrame) – Output of
DimensionalityClassifier.predict_table().dim_col (str)
strike_col (str)
tick_every (tick control)
tick_label_rotation (tick control)
tick_fontsize (tick control)
station_tick_config (
StationTickConfigor None)rose_bins (int, default
18)suptitle (str)
figsize ((w, h), default
(13.0, 9.0))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_imputer_gaps(gap_table, *, status_col='missing', station_labels=None, observed_color='#2166ac', missing_color='#d62728', period_up=True, colorbar_label='Status', xlabel='Station', ylabel='Period (s)', title='', station_markers=True, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, n_yticks=7, figsize=(10.0, 5.2), ax=None)[source]
Station x frequency map of genuinely missing cells for
EMImputer.- Parameters:
gap_table (DataFrame) – Must contain
station,freq, and status_col columns. status_col is1where the (station, frequency) cell is genuinely missing (any tensor componentNaN) and0where every component is observed – build it from a site collection withnumpy.isnan(z).any(axis=(1, 2))per station, one row per frequency (see theimputeruser_guide page for a worked example).observed_color (str)
missing_color (str)
period_up (bool, default
True)colorbar_label (str)
xlabel (str)
ylabel (str)
title (str)
station_markers (bool, default
True) – Draw the station axis at the top with pyCSAMT’s shared downward-triangle convention (PYCSAMT_STATION_RENDERING). Set toFalseto fall back to a plain bottom axis controlled by tick_every / tick_label_rotation / tick_fontsize / station_tick_config instead.tick_every (int | str) – Only used when
station_markers=False.tick_label_rotation (float) – Only used when
station_markers=False.tick_fontsize (int) – Only used when
station_markers=False.station_tick_config (StationTickConfig | None) – Only used when
station_markers=False.n_yticks (int, default
7)figsize ((w, h))
ax (Axes or None)
status_col (str)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_imputer_validation(y_true, y_pred, *, component_ids=None, component_labels=None, colors=None, n_cols=2, point_size=10.0, alpha=0.5, show_metrics=True, xlabel='True value', ylabel='Reconstructed value', suptitle='', figsize=None)[source]
Predicted-vs-true scatter for a synthetic held-out-cell validation of
EMImputer.Genuinely missing cells have no known ground truth to compare against, so the standard masked-reconstruction validation protocol instead hides a known fraction of already observed cells, reconstructs them, and compares the reconstruction against the real, held-back values – exactly what this scatter plots.
- Parameters:
y_true (ndarray, shape (n_points,)) – Flattened true / reconstructed values at synthetically hidden cells only.
y_pred (ndarray, shape (n_points,)) – Flattened true / reconstructed values at synthetically hidden cells only.
component_ids (ndarray of int, shape (n_points,), or None) – Per-point feature-component index. When given, one panel is drawn per component rather than one shared-axis scatter – log-amplitude and phase channels live on very different scales, and a single pooled RMSE / \(R^2\) (or a single shared axis range) would be dominated by whichever channel has the largest numeric range, the same pooled-metric pitfall documented for
EMDenoiserin Learned Spectral Denoising.component_labels (list of str or None) – Panel title for each
component_idsvalue.n_cols (int, default
2) – Panel-grid columns when faceting by component.point_size (float, default
10.0)alpha (float, default
0.5)show_metrics (bool, default
True) – Annotate RMSE and \(R^2\) on each panel.xlabel (str)
ylabel (str)
suptitle (str)
figsize ((w, h) or None)
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_imputer_reconstruction(freq, X_raw, X_filled, *, missing_mask=None, station_labels=None, component_labels=None, sites=None, n_show=4, line_color='#2166ac', fill_marker_color='#d62728', fill_marker_size=22.0, log_freq=True, sharey='row', suptitle='', figsize=None)[source]
Per-station, per-channel spectra with reconstructed cells highlighted, for
EMImputer.One column per selected site, one row per feature component, following the
(n_sites, n_components, n_freqs)array convention used byprepare_z_features(). The continuous curve is X_filled – observed and reconstructed values alike – with a marker overlaid at every genuinely missing cell, so the reconstructed segment is visually distinct from the real, measured backbone around it.- Parameters:
freq (ndarray, shape (n_freqs,)) – Frequency grid in Hz shared by all sites.
X_raw (ndarray, shape (n_sites, n_components, n_freqs)) – Data before imputation – only used to infer missing_mask when not given explicitly (
~numpy.isfinite(X_raw)).X_filled (ndarray, shape (n_sites, n_components, n_freqs)) –
transform()output – the curve actually plotted.missing_mask (ndarray of bool, same shape, or None)
sites (list of int or None) – Explicit site indices to display. Overrides n_show when given.
n_show (int, default
4) – Number of sites to display when sites isNone– sites with at least one missing cell are preferred, first n_show such sites are used (falling back to the first n_show sites overall when fewer than n_show have any gap).line_color (str)
fill_marker_color (str)
fill_marker_size (float, default
22.0)log_freq (bool, default
True)sharey (
"row"|"none", default"row")suptitle (str)
figsize ((w, h) or None)
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_imputer_summary(gap_table, freq, X_raw, X_filled, *, missing_mask=None, history=None, station_labels=None, component_labels=None, n_show=2, suptitle='', figsize=(12.0, 11.0))[source]
Combined
EMImputerfigure: the missing-data map, reconstruction detail for a handful of sites, and (when available) the training curve.Layout:
┌──────────────────────────────────────────────┐ │ (a) Station x frequency missing-data map │ ├──────────────────────────────────────────────┤ │ (b) Reconstruction detail, n_show sites │ ├──────────────────────────────────────────────┤ │ (c) Training history │ └──────────────────────────────────────────────┘
The held-out-cell validation scatter is deliberately not one of these panels – see
plot_imputer_validation()and pass it the samey_true/y_predseparately, faceted one panel per feature component, the same reasonplot_denoise_spectra()never pools log-amplitude and phase into one shared-axis view.- Parameters:
gap_table (DataFrame) – Passed to
plot_imputer_gaps().freq (ndarray) – Passed to
plot_imputer_reconstruction().X_raw (ndarray) – Passed to
plot_imputer_reconstruction().X_filled (ndarray) – Passed to
plot_imputer_reconstruction().missing_mask (ndarray | None) – Passed to
plot_imputer_reconstruction().station_labels (list[str] | None) – Passed to
plot_imputer_reconstruction().component_labels (list[str] | None) – Passed to
plot_imputer_reconstruction().history (estimator, dict, or None) – Passed to
plot_training_history()when not empty; panel (c) is left blank otherwise.n_show (int, default
2)suptitle (str)
figsize ((w, h), default
(12.0, 11.0))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_uncertainty_map(table, *, value_col='z_err_frac_calibrated', station_labels=None, cmap='viridis', vmin=None, vmax=None, period_up=True, n_yticks=7, colorbar_label='Fractional error', xlabel='Station', ylabel='Period (s)', title='', station_markers=True, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, figsize=(10.0, 5.2), ax=None)[source]
Station x frequency heat-map of a fractional-error column, for
UncertaintyCalibrator.Colour is log-scaled: fractional error routinely spans more than a decade within one survey, and a linear scale would wash out the low end.
- Parameters:
table (DataFrame) – Output of
UncertaintyCalibrator.predict_table(orbuild_uncertainty_features_table()). Must containstation,freq, and value_col columns.value_col (str, default
"z_err_frac_calibrated") – Column to plot – pass"z_err_frac"instead for the original field-processing fractional error, e.g. to build a matching before/after pair of figures.cmap (str, default
"viridis")vmin (float or None) – Log-color-scale bounds;
Noneinfers both from the data.vmax (float or None) – Log-color-scale bounds;
Noneinfers both from the data.period_up (bool, default
True)n_yticks (int, default
7)colorbar_label (str)
xlabel (str)
ylabel (str)
title (str)
station_markers (bool, default
True) – Seeplot_qc_heatmap().tick_every (int | str) – Only used when
station_markers=False.tick_label_rotation (float) – Only used when
station_markers=False.tick_fontsize (int) – Only used when
station_markers=False.station_tick_config (StationTickConfig | None) – Only used when
station_markers=False.figsize ((w, h))
ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_uncertainty_validation(y_true, y_pred, *, point_size=10.0, alpha=0.5, show_metrics=True, xlabel='True fractional error', ylabel='Calibrated fractional error', title='', figsize=(5.0, 5.0), ax=None)[source]
Predicted-vs-true scatter for
UncertaintyCalibrator.Same held-out-cell validation idea as
plot_imputer_validation(), but for a single unit (fractional error) rather than several feature components, so one shared axis is appropriate here.- Parameters:
y_true (ndarray, shape (n_points,)) – Held-out field
z_err_fracand the calibrator’s reconstruction of it.y_pred (ndarray, shape (n_points,)) – Held-out field
z_err_fracand the calibrator’s reconstruction of it.point_size (float)
alpha (float)
show_metrics (bool, default
True)xlabel (str)
ylabel (str)
title (str)
figsize ((w, h))
ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_uncertainty_summary(table, y_true, y_pred, *, history=None, station_labels=None, suptitle='', figsize=(13.0, 10.0))[source]
Combined
UncertaintyCalibratorfigure: the calibrated-error map, a per-station original-vs.- calibrated comparison, the held-out validation scatter, and (when available) the training curve.Layout:
┌──────────────────────────────────────────────┐ │ (a) Station x frequency calibrated-error map │ ├───────────────────────┬────────────────────────┤ │ (b) Original vs. │ (c) Held-out │ │ calibrated, │ validation │ │ per station │ │ ├───────────────────────┴────────────────────────┤ │ (d) Training history │ └──────────────────────────────────────────────┘
- Parameters:
table (DataFrame) – Output of
predict_table(), with bothz_err_fracandz_err_frac_calibratedcolumns – passed toplot_uncertainty_map()for panel (a) and aggregated per station (median) for panel (b).y_true (ndarray) – Passed to
plot_uncertainty_validation()for panel (c).y_pred (ndarray) – Passed to
plot_uncertainty_validation()for panel (c).history (estimator, dict, or None) – Passed to
plot_training_history()when not empty; panel (d) is left blank otherwise.suptitle (str)
figsize ((w, h), default
(13.0, 10.0))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_distortion_map(table, *, station_labels=None, class_colors=('#2ca02c', '#ff7f0e', '#d62728'), class_labels=('Clean', 'Static-shift-only', 'Distorted'), bar_width=0.8, bar_alpha=0.88, tick_every='auto', tick_label_rotation=45.0, tick_fontsize=7, station_tick_config=None, xlabel='Station', ylabel='Confidence', title='', show_grid=True, figsize=(10.0, 4.0), ax=None)[source]
Per-station distortion-regime bar chart, for
DistortionTypeClassifier.Bar colour encodes the predicted regime (clean / static-shift-only / distorted); bar height is the model’s confidence for that station – both come straight out of
predict_table().- Parameters:
table (DataFrame) – Output of
predict_table(). Must containstation,regime, andconfidencecolumns.station_labels (list of str or None) – Station order; defaults to the table’s own row order.
class_colors ((str, str, str)) – Colour and legend label for regimes 0, 1, 2.
class_labels ((str, str, str)) – Colour and legend label for regimes 0, 1, 2.
bar_width (float)
bar_alpha (float)
tick_every (int | str) – Station-axis tick control (see
StationTickConfig).tick_label_rotation (float) – Station-axis tick control (see
StationTickConfig).tick_fontsize (int) – Station-axis tick control (see
StationTickConfig).station_tick_config (StationTickConfig | None) – Station-axis tick control (see
StationTickConfig).xlabel (str)
ylabel (str)
title (str)
show_grid (bool, default
True)figsize ((w, h))
ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_distortion_feature_space(table, *, x_col='delta_log10_rho', y_col='twist_deg', shift_th=0.1, twist_th=10.0, class_colors=('#2ca02c', '#ff7f0e', '#d62728'), class_labels=('Clean', 'Static-shift-only', 'Distorted'), point_size=45.0, alpha=0.85, xlabel=None, ylabel=None, title='', show_legend=True, figsize=(6.0, 5.5), ax=None)[source]
Two-feature scatter coloured by predicted distortion regime, for
DistortionTypeClassifier.Shows why a station lands in a given class: with the default axes,
delta_log10_rho(resistivity departure from the along- line spatial trend) drives clean/static-shift-only, andtwist_deg(Groom-Bailey rotation) drives the distorted class, with the rule-based self-training thresholds drawn as dashed guide lines.- Parameters:
table (DataFrame) – Output of
predict_table(). Must containregimeplus x_col and y_col.x_col (str, default
"delta_log10_rho","twist_deg")y_col (str, default
"delta_log10_rho","twist_deg")shift_th (float or None) – Rule-based threshold guide lines drawn on the x / y axis respectively (mirrored for negative values where relevant).
Noneskips that guide line – passNonefor both when x_col / y_col are not the threshold features.twist_th (float or None) – Rule-based threshold guide lines drawn on the x / y axis respectively (mirrored for negative values where relevant).
Noneskips that guide line – passNonefor both when x_col / y_col are not the threshold features.point_size (float)
alpha (float)
xlabel (str or None) – Default to x_col / y_col.
ylabel (str or None) – Default to x_col / y_col.
title (str)
show_legend (bool, default
True)figsize ((w, h))
ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_distortion_summary(table, *, history=None, station_labels=None, x_col='delta_log10_rho', y_col='twist_deg', shift_th=0.1, twist_th=10.0, suptitle='', figsize=(12.0, 10.5))[source]
Combined
DistortionTypeClassifierfigure: the per-station regime map, the feature-space scatter that explains it, class proportions, and (when available) the training curve.Layout:
┌──────────────────────────────────────────────┐ │ (a) Per-station regime map │ ├───────────────────────┬────────────────────────┤ │ (b) Feature space │ (c) Class proportions │ ├───────────────────────┴────────────────────────┤ │ (d) Training history │ └──────────────────────────────────────────────┘
- Parameters:
table (DataFrame) – Output of
predict_table().history (estimator, dict, or None) – Passed to
plot_training_history()when not empty; panel (d) is left blank otherwise.x_col (str) – Passed to
plot_distortion_feature_space().y_col (str) – Passed to
plot_distortion_feature_space().shift_th (float) – Passed to
plot_distortion_feature_space().twist_th (float) – Passed to
plot_distortion_feature_space().suptitle (str)
figsize ((w, h), default
(12.0, 10.5))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_ts_denoise_mmf_split(t, x, low, high, *, raw_color='#7f7f7f', low_color='#1f77b4', xlabel='Time (s)', suptitle='', figsize=(9.0, 4.6))[source]
Mathematical-morphological-filter (MMF) low/high split.
Mirrors Fig. 8(a)-(d) of Gui et al. (2024): the raw channel with its extracted low-frequency envelope overlaid, and the high-frequency residual carrying any strong interference plus genuine high-frequency signal.
- Parameters:
x (ndarray, shape (n,)) – Raw channel and
mmf_split()output (low + high == x).low (ndarray, shape (n,)) – Raw channel and
mmf_split()output (low + high == x).high (ndarray, shape (n,)) – Raw channel and
mmf_split()output (low + high == x).raw_color (str)
low_color (str)
xlabel (str)
suptitle (str)
figsize ((w, h))
- Returns:
fig
- Return type:
See also
pycsamt.ai.processing.tsdenoise.mmf_splitProducer of low / high.
- pycsamt.ai.processing.plot.plot_ts_denoise_segments(t, high, diagnostics, *, color='#7f7f7f', noisy_span_color='#f4c7c3', xlabel='Time (s)', ylabel='Amplitude', title='', figsize=(9.5, 3.2), ax=None)[source]
High-frequency residual with SVM window classification overlaid.
Shades every window
SignalQualityClassifierlabelled noisy – mirrors Fig. 8(e)-(f)’s SVM-Good / SVM-Noisy split, drawn as one trace with shaded spans rather than two separate panels.- Parameters:
high (ndarray, shape (n,)) – MMF high-frequency residual (see
mmf_split()).diagnostics (DataFrame) –
diagnostics_(or a subset filtered to one channel) – columnswin_start,win_stop(s),label.color (str)
noisy_span_color (str)
xlabel (str)
ylabel (str)
title (str)
figsize ((w, h))
ax (Axes or None)
- Returns:
ax
- Return type:
- pycsamt.ai.processing.plot.plot_ts_denoise_summary(t, x, denoised, diagnostics, *, low=None, high=None, raw_color='#7f7f7f', denoised_color='#d62728', noisy_span_color='#f4c7c3', xlabel='Time (s)', suptitle='', figsize=(10.0, 7.0))[source]
Combined before/after summary for
TimeSeriesDenoiser.Three panels: raw channel with SVM-flagged noisy windows shaded, the same windows on the MMF high-frequency residual, and a final raw-vs-denoised overlay – one figure spanning the paper’s Fig. 8(b), (e)-(f), and (g).
- Parameters:
x (ndarray, shape (n,)) – Channel before and after
apply()/transform().denoised (ndarray, shape (n,)) – Channel before and after
apply()/transform().diagnostics (DataFrame) – See
plot_ts_denoise_segments().low (ndarray or None) –
mmf_split()output for x; when given, the second panel plots high (the residual actually classified) instead of x.high (ndarray or None) –
mmf_split()output for x; when given, the second panel plots high (the residual actually classified) instead of x.raw_color (str)
denoised_color (str)
noisy_span_color (str)
xlabel (str)
suptitle (str)
figsize ((w, h))
- Returns:
fig
- Return type:
- pycsamt.ai.processing.plot.plot_training_history(history, *, train_key='train_loss', val_key='val_loss', train_label='Train', val_label='Validation', train_color='#1f77b4', val_color='#d62728', log_y=False, mark_best=True, best_color='#2ca02c', xlabel='Epoch', ylabel='Loss', title='', show_legend=True, figsize=(6.0, 4.0), ax=None)[source]
Train/validation loss curve for a pycsamt.ai.processing estimator.
Works with the
history_property exposed afterfit()byEMDenoiser,AnomalyDetector, andDimensionalityClassifier— pass either the fitted estimator itself or itshistory_dict.- Parameters:
history (estimator or dict) – A fitted estimator exposing
history_, or a dict with train_key / val_key entries (lists of per-epoch loss values). Estimators trained through a non-network fallback (scipy smoothing, PCA, random forest) have an empty history and raiseValueError.train_key (str) – Dictionary keys holding the per-epoch loss lists.
val_key (str) – Dictionary keys holding the per-epoch loss lists.
train_label (str)
val_label (str)
train_color (str)
val_color (str)
log_y (bool, default
False) – Use a log-scaled y-axis — useful when the loss spans more than one order of magnitude early in training.mark_best (bool, default
True) – Mark the lowest-validation-loss epoch with a vertical dashed line and an annotation.best_color (str)
xlabel (str)
ylabel (str)
title (str)
show_legend (bool, default
True)figsize ((w, h), default
(6.0, 4.0))ax (Axes or None)
- Returns:
ax
- Return type:
Examples
>>> from pycsamt.ai.processing import EMDenoiser >>> from pycsamt.ai.processing.plot import plot_training_history >>> den = EMDenoiser().fit(X_clean, epochs=60) >>> plot_training_history(den, title="Denoiser training")