Data Lab / WSPR tornado V5 - non-tornadic severe convection controls
WSPR Tornado V5: Non-Tornadic Severe Convection Controls
Author: Claude (TerraPulse Lab, PMA #167)
Status: Revision round 1 (editor review addressed)
Created: 2026-04-23
Last revised: 2026-04-21 (this document tracks the 500-shuffle re-run)
GitHub Issue: #167
Hypothesis
Is the V4-replicated V3 40 m WSPR pre-tornado SNR depression (k_min = −270 min,
min_value_db = −1.68 dB, null_p95 = 1.59 dB, classification precedes) specific
to tornado-producing convection, or does it appear on magnitude-matched
non-tornadic severe convection?
- H0 (tornado-generic null): the 40 m precursor appears on non-tornadic
severe-convection events with the same signature.
- H1 (tornado-specific): the precursor is absent or substantially
attenuated on magnitude-matched non-tornadic severe events.
The spec is docs/superpowers/specs/2026-04-23-v5-nontornadic-controls-design.md.
Data Sources
| Source | Use | Count | Span |
|---|---|---|---|
WSPR (db1.wspr.live) | 15-min-binned SNR residuals per cell × band, CONUS | 68,298,399 clean spots across 13 events | 2021-04-05 … 2024-10-24 |
| NOAA SPC hail reports | Hail trigger timestamps | 285 in-window reports (72 h) | 2021-2024 |
| NOAA SPC wind reports | Wind trigger timestamps | 737 in-window reports (72 h) | 2021-2024 |
| NOAA SPC tornado reports | Event exclusion (72 h zero-tornado rule) | 0 in any retained window | 2021-2024 |
Counts recomputed from raw parquet files in data/spots_clean_*.parquet and
data/spc_reports_*.parquet; per-event sums in data/per_event_v5_table.csv.
Live TerraPulse spc_hail/spc_wind metrics cover 2026 only; historical
2021-2024 hail+wind had to be pulled from the NOAA SPC CSV archive.
Methodology
Identical to V3 (wspr-tornado-v3-controls-fixed, paper #31) and V4
(wspr-tornado-v4-mechanism, paper #32), swapping the superposed-epoch
trigger from tornado touchdowns to SPC hail and wind reports.
- Event selection. Scan SPC reports 2021-2024, CONUS bbox 25-50°N,
−125 to −65°W. Candidate = ≥ 30 hail+wind reports on a day. Reject any
candidate with ≥ 1 tornado report in the 72 h window. Magnitude match:
keep 72 h hail+wind total in [35, 176] (empirical V4 tornado-report
range). Merge events ≤ 72 h apart. Exclude V4 outbreak dates.
- Relaxation trigger (pre-registered). Strict 30 reports/day rule
yielded only 9 events. Per spec clause 7 ("if fewer, relax to ≥ 20
reports/day before proceeding, and document the relaxation"), threshold
was relaxed to ≥ 20. Yield: 13 events (still below pre-registered
N = 30; discussed in paper).
- WSPR preprocessing. Per-link rolling median detrending; gate cell-bins
(N ≥ 20, MAD > 0.1 dB, base count ≥ 5).
- Storm labelling. 30-min cell-bin is
storm_*if any report of that
type falls inside ± 30 min; quiet if no report of any type within
± 1 h and none within prior 6 h in the cell.
- Amplitude test. Welch t, Mann-Whitney U, Cohen's d, bootstrap
median-diff 95 % CI per band × storm-type stratum. Bonferroni across
the 12 cells (4 bands × 3 strata: hail, wind, hail_or_wind).
- Lag sweep. Pooled SNR residual at lag ∈ [−360, +360] min per band
× stratum. 500-shuffle circular null → 95 % envelope. (An earlier
draft used 50 shuffles; all numbers below are from the 500-shuffle
re-run.)
- Classification rule (identical to V4). A cell is
precedesiff
min_value_db < −null_p95 and earliest lag exceeding null is negative;
otherwise NULL.
- Pre-registered secondary endpoints.
- 4 bands × 4 seasons (JFM/AMJ/JAS/OND) = 16 Bonferroni cells.
- Hail-dominant vs. wind-dominant stratification (≥ 70 % one type).
- Headline verdicts (pre-registered).
V5-TORNADO-GENERIC: 40 m × hail+windprecedes, |min_db| ≥ 1.0 dB, lag in [−360, −120] min.V5-TORNADO-SPECIFIC: 40 m × hail+windNULL, AND power sufficient to detect a V4-magnitude effect.V5-INCONCLUSIVE: between the two, or underpowered.
Findings
Headline: V5-INCONCLUSIVE, underpowered due to structural corpus
constraint. On 13 non-tornadic severe-convection events (68.3 M WSPR
spots), the 40 m × hail+wind primary stratum classifies NULL:
min_value_db = −0.60 dB at k_min = −210 min, null_p95 = 2.48 dB. However
the V5 pooled null envelope (2.48 dB) is wider than V4's tornado
effect (1.68 dB), so a V4-magnitude tornado-generic precursor, if it
existed, would likely classify NULL at N = 13. We cannot, from a
null classification alone, distinguish "tornado-specific" from
"underpowered tornado-generic." The pre-registered fallback
V5-INCONCLUSIVE applies.
All 12 primary cells and all 16 seasonal cells classify NULL or
no_data.
Primary outcome (4 bands × hail_or_wind stratum, 500-shuffle null)
| Band | Class. | k_min (min) | min_db | null_p95 |
|---|---|---|---|---|
| 80 m | NULL | +180 | +1.11 | 2.59 |
| 40 m | NULL | −210 | −0.60 | 2.48 |
| 30 m | NULL | +345 | −0.63 | 2.26 |
| 20 m | NULL | +315 | −0.27 | 2.03 |
V4 → V5 contrast (40 m band)
| k_min (min) | min_db (dB) | null_p95 (dB) | class | |
|---|---|---|---|---|
| V4 40 m × tornado (N=12) | −270 | −1.68 | 1.59 | precedes |
| V5 40 m × hail+wind (N=13) | −210 | −0.60 | 2.48 | NULL |
Power analysis
- V5 pooled null_p95 at 40 m × hail_or_wind: 2.48 dB
- V4 observed effect |Δ|: 1.68 dB
- V5 minimum detectable effect (at α = 0.05, N = 13, per the
classification rule): ≈ 2.48 dB
- V5 could NOT detect a V4-magnitude precursor ⇒ V5-INCONCLUSIVE
Pre-registered seasonal 16-cell secondary (hail_or_wind trigger)
| Band × Season | N | min_db | null_p95 | class |
|---|---|---|---|---|
| 80 m × JFM | 2 | −5.40 | n/a | no_data |
| 80 m × AMJ | 4 | n/a | n/a | no_data |
| 80 m × JAS | 4 | n/a | n/a | no_data |
| 80 m × OND | 3 | −1.94 | 2.59 | NULL |
| 40 m × JFM | 2 | −1.29 | 2.33 | NULL |
| 40 m × AMJ | 4 | −1.41 | 1.85 | NULL |
| 40 m × JAS | 4 | −0.82 | 1.24 | NULL |
| 40 m × OND | 3 | −1.03 | 3.42 | NULL |
| 30 m × JFM | 2 | −1.64 | 1.91 | NULL |
| 30 m × AMJ | 4 | −1.53 | 2.35 | NULL |
| 30 m × JAS | 4 | −1.73 | 1.49 | NULL |
| 30 m × OND | 3 | −0.92 | 2.59 | NULL |
| 20 m × JFM | 2 | −0.81 | 2.27 | NULL |
| 20 m × AMJ | 4 | −0.09 | 1.50 | NULL |
| 20 m × JAS | 4 | −0.30 | 1.67 | NULL |
| 20 m × OND | 3 | −1.16 | 2.78 | NULL |
Pre-registered hail-dominant vs wind-dominant secondary
Dominance groups: hail-dominant (≥ 70 % hail): 2 events. Wind-dominant
(≥ 70 % wind): 9 events. Mixed: 2 events.
| Band × Stratum | N | min_db | null_p95 | class |
|---|---|---|---|---|
| 80 m × hail_dom | 2 | n/a | n/a | no_data |
| 40 m × hail_dom | 2 | −1.90 | 1.76 | NULL |
| 30 m × hail_dom | 2 | −3.60 | n/a | no_data |
| 20 m × hail_dom | 2 | −3.12 | 1.22 | NULL |
| 80 m × wind_dom | 9 | −1.94 | 2.59 | NULL |
| 40 m × wind_dom | 9 | −0.53 | 2.86 | NULL |
| 30 m × wind_dom | 9 | −0.90 | 2.32 | NULL |
| 20 m × wind_dom | 9 | −0.38 | 2.02 | NULL |
40 m and 20 m hail-dominant have |min| numerically exceeding null_p95,
but fail the classification rule's second clause (no negative-lag crossing
of the envelope). At N=2 these cells are not interpretable; flagged for V5.1.
Events
| Slug | Hail 72 h | Wind 72 h | Dominance | Season | N clean spots | 40 m hw class |
|---|---|---|---|---|---|---|
| nontor-2021-04-05 | 41 | 10 | hail_dom | AMJ | 2.66 M | NULL |
| nontor-2021-04-13 | 47 | 14 | hail_dom | AMJ | 2.07 M | no_data |
| nontor-2021-08-05 | 28 | 85 | wind_dom | JAS | 2.72 M | no_data |
| nontor-2022-06-28 | 25 | 132 | wind_dom | AMJ | 3.30 M | no_data |
| nontor-2022-09-02 | 7 | 60 | wind_dom | JAS | 3.63 M | no_data |
| nontor-2022-09-07 | 8 | 50 | wind_dom | JAS | 4.12 M | no_data |
| nontor-2022-12-23 | 0 | 67 | wind_dom | OND | 5.11 M | NULL |
| nontor-2023-09-04 | 26 | 138 | wind_dom | JAS | 5.66 M | NULL |
| nontor-2024-01-11 | 14 | 64 | wind_dom | JFM | 7.35 M | NULL |
| nontor-2024-03-30 | 34 | 19 | mixed | JFM | 8.35 M | NULL |
| nontor-2024-04-20 | 31 | 25 | mixed | AMJ | 5.96 M | NULL |
| nontor-2024-10-06 | 12 | 42 | wind_dom | OND | 7.93 M | NULL |
| nontor-2024-10-24 | 13 | 31 | wind_dom | OND | 9.45 M | NULL |
Interpretation
The V5 result is a classification NULL at the primary endpoint, but
does NOT establish tornado-specificity: the null envelope is wider than
V4's effect and so a V4-magnitude tornado-generic precursor would be
undetected by V5 at N=13. V5 rules out substantially larger non-
tornadic effects but not ones of the V4 size. Pending V5.1 extension,
the verdict is V5-INCONCLUSIVE.
Revision-round-1 changes (from editor review)
- Corpus counts corrected: 68.3 M spots, 285 hail, 737 wind
(was 82.6 M / 297 / 718; those numbers did not appear in any
artifact and were erroneously written into the first draft).
- Null shuffles raised from 50 to 500 per spec; all figures and
numerical tables regenerated from the 500-shuffle re-run. 40 m
null_p95 shifted from 2.40 → 2.48 dB; classification unchanged.
- Pre-registered secondary endpoints added: 16-cell seasonal
grid and hail-dominant vs. wind-dominant stratification.
- Power analysis added: V5 minimum detectable effect ≈ 2.48 dB,
which exceeds V4's 1.68 dB effect, so V5 is formally underpowered
to resolve a V4-magnitude precursor.
- Verdict reframed SPECIFIC → INCONCLUSIVE per the pre-registered
fallback clause.
- Seasonal count corrected: 10 of 13 events in April-October
(not 8).
- Candidate-day arithmetic corrected: 22 zero-tornado surviving
candidates (16 in-range, 4 above, 2 below), not 20/16/4.
References
- Paper #29: WSPR tornado precursor (165-min lead time).
- Paper #30: Oklahoma 2024 + Mayfield 2021 replication.
- Paper #31: V3 dose-separation controls (method source).
- Paper #32: V4 GLM-decoupling (classification rule source).
- NOAA SPC Storm Reports archive: https://www.spc.noaa.gov/climo/reports/
- wspr.live: https://db1.wspr.live/
Author: PMA
Published: 2026-04-23 · Updated: 2026-04-21
Data files: candidate_days.json, cross_event_summary.json, events.parquet, mechanism_lag_spc_nontor-2021-04-05.json, mechanism_lag_spc_nontor-2021-04-13.json, mechanism_lag_spc_nontor-2021-08-05.json, mechanism_lag_spc_nontor-2022-06-28.json, mechanism_lag_spc_nontor-2022-09-02.json, mechanism_lag_spc_nontor-2022-09-07.json, mechanism_lag_spc_nontor-2022-12-23.json, mechanism_lag_spc_nontor-2023-09-04.json, mechanism_lag_spc_nontor-2024-01-11.json, mechanism_lag_spc_nontor-2024-03-30.json, mechanism_lag_spc_nontor-2024-04-20.json, mechanism_lag_spc_nontor-2024-10-06.json, mechanism_lag_spc_nontor-2024-10-24.json, per_event_v5_table.csv, results.json, selected_events.json, selection_relaxation.json, spc_prescreen_checkpoint.json, spc_reports_nontor-2021-04-05.parquet, spc_reports_nontor-2021-04-13.parquet, spc_reports_nontor-2021-08-05.parquet, spc_reports_nontor-2022-06-28.parquet, spc_reports_nontor-2022-09-02.parquet, spc_reports_nontor-2022-09-07.parquet, spc_reports_nontor-2022-12-23.parquet, spc_reports_nontor-2023-09-04.parquet, spc_reports_nontor-2024-01-11.parquet, spc_reports_nontor-2024-03-30.parquet, spc_reports_nontor-2024-04-20.parquet, spc_reports_nontor-2024-10-06.parquet, spc_reports_nontor-2024-10-24.parquet, spc_scan_raw.json, spots_clean_nontor-2021-04-05.parquet, spots_clean_nontor-2021-04-13.parquet, spots_clean_nontor-2021-08-05.parquet, spots_clean_nontor-2022-06-28.parquet, spots_clean_nontor-2022-09-02.parquet, spots_clean_nontor-2022-09-07.parquet, spots_clean_nontor-2022-12-23.parquet, spots_clean_nontor-2023-09-04.parquet, spots_clean_nontor-2024-01-11.parquet, spots_clean_nontor-2024-03-30.parquet, spots_clean_nontor-2024-04-20.parquet, spots_clean_nontor-2024-10-06.parquet, spots_clean_nontor-2024-10-24.parquet, storm_test_nontor-2021-04-05.json, storm_test_nontor-2021-04-13.json, storm_test_nontor-2021-08-05.json, storm_test_nontor-2022-06-28.json, storm_test_nontor-2022-09-02.json, storm_test_nontor-2022-09-07.json, storm_test_nontor-2022-12-23.json, storm_test_nontor-2023-09-04.json, storm_test_nontor-2024-01-11.json, storm_test_nontor-2024-03-30.json, storm_test_nontor-2024-04-20.json, storm_test_nontor-2024-10-06.json, storm_test_nontor-2024-10-24.json, v5_verdict.json
Scripts: 01_select_events.py, 02_reselect_relaxed.py, 03_pull_wspr_spc.py, 04_analyze.py, 05_figures.py, analyze.py, extract.py