Data Lab / WSPR tornado season — CONUS 10-day SNR/density map with severe weather overlay
Fig. 1: cohens d by band
Fig. 2: diag anomaly zscore hist
Fig. 3: diag band mix
Fig. 4: diag diurnal snr
Fig. 5: diag geography
Fig. 6: diag snr histogram
Fig. 7: diag storm overlay static
Fig. 8: mechanism lag ci spc
Fig. 9: mechanism lag ci
Fig. 10: mechanism lag curves spc
Fig. 11: mechanism lag curves
WSPR tornado season: CONUS 10-day SNR/density map with severe weather overlay
Author: TerraPulse Paper Machine (M. Isenbek, E. Isenbek, B. Isenbek)
Status: V1 Complete; paper drafted
Created: 2026-04-19
GitHub Issue: #141 (parent); #133, #134, #135, #136, #137, #138 (workspace + diagnostics); #139 (NWS lag); #140 (SPC lag)
Hypothesis
Does HF propagation measured by the WSPR network show a detectable and physics-consistent depression in SNR during severe convective weather, and, critically, does that depression precede storm reports on enough bands and storm types to constitute an operationally useful precursor?
We test two things separately:
- Amplitude. During active severe weather, is the per-cell residual SNR statistically depressed relative to quiet cell–hours, across 4 bands × 2 storm classes?
- Timing. If so, does the depression lead, align with, or lag the storm report clock?
Data Sources
CONUS only (lat 24–50°N, lon 125–66°W), 10-day window 10–19 April 2026, 1° × 1° cell grid.
| Source | N | Role |
|---|---|---|
| WSPR residual grid (per cell, hour, band) | 909,504 | Primary SNR residual pool |
| SPC storm reports (tornado/hail/wind) | 3,798 | Lag-test event source (main) |
| NWS severe-weather CAP alerts | 1,500 | Lag-test control / forecaster-lag comparison |
| Qualified cell–hours (n_min=20) | 357,829 | Amplitude denominator |
| Epoch-stack rows (SPC) | 130,550 | Superposed-epoch pool |
Residuals are per-cell, per-hour WSPR SNR minus the cell × hour-of-day baseline (computed within the 10-day window), with n_min=20 spots/cell–hour and mad_min=0.1 dB.
Methodology
Amplitude (issue #138 → data/storm_test.json)
- Welch t-test + Mann–Whitney U on storm vs quiet per-cell residuals across an 8-stratum primary grid: {80m, 40m, 30m, 20m} × {tornado, severe}.
- Cohen's d with pooled SD; bootstrap 95% CI on median difference (5,000 resamples).
- Bonferroni correction across the 8 strata: α_corr = 6.25 × 10⁻³.
- Paired-matched within-cell control (n=5,325 pairs).
- Sensitivity grid: n_min ∈ {10, 20, 50} × kernel ∈ {0, 1} × storm_window ∈ {0, 30, 60} min.
- Null calibration: 100-trial time-shuffle; track per-trial max |d|.
Lag / precursor (issues #139, #140 → data/mechanism_lag*.json)
- Superposed-epoch analysis aligned to event report time, 49 lag bins spanning ±360 min at 15-min resolution.
- Bootstrap SE of per-lag mean residual (5,000 iterations) → 95% CI on each bin.
- k_min = lag at which stack mean residual is most negative.
- earliest_lag_exceeds_null = earliest (most negative) lag at which the stack exceeds the stratum-specific null p95 (100-trial storm-time shuffle).
- Classification by earliest excursion:
precedes/aligns/lags. - Identical pipeline run against NWS warnings (8 strata) and SPC reports (12 strata). Difference between the two k_min values bounds the human forecaster lag.
Findings
Amplitude: all 8 strata Bonferroni-significant
- Primary 40m severe stratum: Cohen's d = −0.51 (medium), Welch p = 2.6×10⁻⁷², N_storm = 1,343, N_quiet = 122,633, median depression 1.27 dB (95% CI [−1.42, −1.11]).
- Maximum effect: 80m tornado, |d| = 1.36 at N_storm = 15 (V2-flagged).
- Null shuffle: mean max|d| = 0.14, p95 = 0.23, max = 0.41. Observed max |d| is 5.8× p95 null.
- Paired-matched test (n=5,325 in-cell pairs): Δ̄ = −1.19 dB, paired t = −32.1, p = 7.5×10⁻²⁰⁷.
- Band gradient (|d|): 80m (1.05–1.36) > 40m (0.51–0.92) ≳ 30m (0.27–0.64) > 20m (0.19–0.31). Consistent with lower-ionospheric absorption.
Precursor: 40m tornado leads by 165 min
- 40m tornado (SPC, N_events = 106): k_min = −165 min, min = −3.43 dB (95% CI [−4.79, −2.12]), earliest excursion above null p95 at −240 min. Classification:
precedes. - 40m hail (N=981): k_min = −60 min,
precedes. - 30m hail (N=676): k_min = −120 min,
precedes. - 30m wind (N=786): k_min = −135 min,
precedes. - 80m wind (N=308): k_min = 0 min, but earliest excursion at −30 min →
precedes. - Verdict (SPC): 5 precedes / 0 aligns / 0 lags across 5/12 significant strata.
Null (V2-flagged) strata
- All four 20m strata lag or fall below the stratum-specific null p95 in the SPC analysis. 20m contributes no precursor signal. (Amplitude effect is the smallest here too.)
- 80m tornado (N_events = 20, N_storm = 15), 80m hail at precursor (|min|
30m tornado at precursor (N=79, |min|
Forecaster lag (NWS vs SPC)
- NWS 40m tornado: k_min = −195 min (N=197).
- SPC 40m tornado: k_min = −165 min (N=106).
- Difference: ~30 min. The NWS warning timestamp leads SPC by ~30 min → bounds human forecaster decision lag from below; the 165 min SPC lead is our best estimate of the raw ionospheric precursor.
- NWS overall verdict:
mixed(2 precedes / 0 aligns / 3 lags of 5/8).
Caveats (non-negotiable)
- 10 days of data only; many stratum Ns are modest.
- CONUS only; no claim of generalization.
- 1° cells vs warning polygons: cell-scale neighborhood average, not point estimate.
- Tornado precursor rests on N = 106 after SPC gating; CI on the min residual is wide.
- 20m is a null result in every configuration tested, reported prominently and not buried.
References
- Issue #141 (this paper / PMA parent).
- Issues #133–137 (workspace setup, ingestion, cleaning, diagnostics).
- Issue #138 (amplitude test: storm_test.json).
- Issue #139 (NWS-warning lag: mechanism_lag.json).
- Issue #140 (SPC-report lag: mechanism_lag_spc.json).
- Prior TerraPulse workspace:
wspr-storm-corridor-response(path-dependent geomagnetic WSPR response). - Prior TerraPulse workspace:
wspr-ionospheric-baseline(residual methodology). - WSPRnet / wspr.live ClickHouse archive.
- NOAA SPC storm reports, NOAA NWS CAP alert feed.
Artifacts
- Paper:
paper/paper.tex,paper/paper.pdf(4 pages). - Figures:
paper/figure1.png(12-strata superposed-epoch curves),paper/figure2.png(CONUS overlay map),paper/figure3.png(Cohen's d by band). - Data:
data/storm_test.json,data/mechanism_lag.json,data/mechanism_lag_spc.json, plus parquet intermediates (anomaly_grid.parquet,spots_clean.parquet,spc_reports.parquet,nws_alerts.parquet). - Scripts:
scripts/extract.py,scripts/clean.py,scripts/anomaly.py,scripts/storm_test.py,scripts/mechanism_lag.py,scripts/mechanism_lag_spc.py,scripts/plots_static.py,scripts/render_animation.py.
Author: bisenbek
Published: 2026-04-19 · Updated: 2026-04-19
Data files: anomaly.log, anomaly_grid.parquet, anomaly_summary.json, baseline_by_cell_hour.parquet, clean.log, extract.log, mechanism_lag.json, mechanism_lag.log, mechanism_lag_spc.json, mechanism_lag_spc.log, nws_alerts.parquet, render.log, sanity.log, spc_reports.parquet, spots_clean.parquet, spots_raw.parquet, storm_test.json, storm_test.log
Scripts: anomaly.py, clean.py, compare_139_140.py, extract.py, eyeball.py, fetch_states.py, mechanism_lag.py, mechanism_lag_spc.py, peek.py, plots_static.py, prep_dirs.py, probe_mp4.py, render_animation.py, sanity.py, storm_test.py, summarize_sensitivity.py