6 Reproducible workflow — bedload seismology, Puyallup / Mt. Rainier
Run from the repo root inside the pixi env (pixi shell or prefix with pixi run).
| Step | Script | Output |
|---|---|---|
| 0 | python workflows/00_discover_stations.py |
config/_transect_discovery.json — stations + river-km along the corridor |
| 0b | python workflows/01_fetch_discharge.py |
USGS-NWIS discharge for every corridor gage (authoritative; the GAIA mirror was incomplete for Dec-2025) + config/discharge_manifest.json |
| 1 | python scripts/run_river_rumble_batch.py --focus-seis-key CC.PR03 --use-rss --exclude-earthquakes --clip-impulses --despike-proxy |
notebooks/data/results/*_timeseries.csv, fit_parameters.csv (single-pass multiband proxy; NWIS gages) |
| 2 | python workflows/02_make_figures.py |
fig1..5 (scaling, scatter, hysteresis, event ts) + scaling_table.csv |
| 3 | python workflows/03_make_map.py |
fig1_transect_map.png (PyGMT DEM + gages + SNOTEL + OPERA + station status) |
| 4 | python workflows/04_traffic_noise.py |
figS_traffic_noise.png (contamination control) |
| 5,7,8 | python workflows/05_bedload_time.py / 07_fetch_aux_data.py / 08_b_of_time.py |
fig6 bedload time, fig7 per-AR, fig8 b(t); config/aux_timeseries.json |
| 6,13 | python workflows/06_bedload_gif.py / 13_virtual_q_gif.py |
bedload_animation.gif, virtual_q_animation.gif |
| 9 | python workflows/09_attenuation.py |
fig9_attenuation.png (PNW Q, e-folding distance) |
| 10 | python workflows/10_early_warning.py |
fig10_early_warning.png (~36 h upstream lead) |
| 11,14 | python workflows/11_spectra.py / 14_bedload_ch.py |
fig11 flood-vs-quiet PSD, fig13 30–50 Hz edge |
| 12 | python workflows/12_virtual_q.py |
fig12_virtual_q.png + config/virtual_q*.json (ratings) |
| 15 | python workflows/15_threshold.py |
fig14_threshold.png + config/threshold_qc.json (Qc) |
| 16 | python workflows/16_classify_stations.py |
config/station_status.json (drives hollow no-signal markers) |
| 17 | python workflows/17_rating.py |
fig15_rating.png + config/rating_fits.json (stage–discharge) |
| 18 | python workflows/18_braided_hysteresis.py |
fig16_braided_hysteresis.png + config/braided_hysteresis.json |
| 19 | python workflows/19_braid_optical_change.py |
fig19_braid_change.png, fig20_braid_timeseries.png + config/braid_optical_change.json — Sentinel-2/-1 braid change, geometric drift, + SAR December series |
| 20 | python workflows/20_warm_ar_snotel.py |
fig21_warm_ar_snow.png + config/warm_ar_snotel.json — high-elevation SNOTEL temperature/SWE: warm rain-on-snow ARs vs cold late-Dec snow accumulation |
| 21 | python workflows/21_braided_reorg_timing.py --basin puyallup\|nisqually |
fig22_braided_reorg_timing[_nisqually].png + config/braided_reorg_timing_<basin>.json — event-scale TIMING of braided-channel reorganization (matched-Q baseline, logistic step, flood-wave lag correction, rain→snow supply-shutoff guard) |
| 22 | python workflows/22_domain_panel.py |
fig23_domain.png — domain of applicability (gage distance × channel width × elevation → clean/confounded); reads the two reorg JSONs from step 21 |
| 23 | python workflows/23_braid_two_region.py |
fig24_braid_two_region.png — Puyallup (compact incised) vs Nisqually (wide braidplain) change maps side-by-side, offline from the satellite cache |
| 42 | python workflows/42_pr01_braid_zoom.py --naip |
fig33_pr01_braid_zoom.png (Figure 5.5): PR01 braidplain zoom — 1 m NAIP basemap (committed braid_cache/naip_pr01.tif, public domain) resolving the braided threads/banks, with the Sentinel-2 10 m pre→post active-channel change overlaid. Offline from cache. No-arg run = 10 m Sentinel-2 placeholder; --pre-raster/--post-raster = ≈3 m PlanetScope (event-timed upgrade, pending Planet E&R approval) |
| 24 | python workflows/24_hazard_timing_clogging.py |
fig25_hazard_clogging.png + config/hazard_timing_clogging.json — bedload-initiation lead over peak Q/stage (M5, hazard) + slow AR3-recession braid clogging (M7, the avulsion mechanism) |
| 25 | python workflows/25_rating_geometry.py |
fig26_rating_geometry.png + config/rating_geometry.json — stage–discharge rating exponent β(Q): upstream confinement (β→2, seismic Qc in the steepening band) vs downstream overbank (β flat) (M2) |
| 26 | python workflows/26_channel_pattern.py |
fig27_channel_pattern.png — channel-pattern map: braided source reaches (PR compact, UW.LON wide) vs single-thread meandering lower Puyallup past CC.TRON, from OPERA flood water + cached Sentinel rasters + NHD (M1) |
| 29 | python workflows/29_rating_hysteresis.py |
fig29_rating_hysteresis_linear.png + config/rating_hysteresis.json — linear stage–discharge ratings coloured by time: within-event hysteresis (looped-rating) vs net cross-event drift; confined source gages single-valued, alluvial mid/lowland gages drift up → consistent with aggradation (SI) |
| 39 | python workflows/39_spectrogram_seismic.py |
fig30_spectrogram_seismic.png + cached notebooks/data/results/spectrogram_UW_LON.npz — UW.LON flood seismic spectrogram with discharge overlay; the seismic-only half of the bed-vs-air–water discriminant (Schmandt 2013; SI). Reads cached mseed, rebuilds offline from the committed npz |
| 40 | python workflows/40_infrasound_psd.py |
fig31_infrasound_psd.png + cached notebooks/data/results/infrasound_specgram_CC.npz — colocated CC microbarometer (BDF) infrasound spectrograms at CC.PR03/PR04/STYX through AR2; documents the (wind-contaminated) acoustic field. Queries FDSN (downloads BDF), rebuilds offline from the committed npz |
| 41 | python workflows/41_seis_infrasound_coherence.py |
fig32_seis_infrasound_coherence.png + cached notebooks/data/results/coherence_CC_PR03.npz — colocated seismic–infrasound coherence γ²(f,t) at CC.PR03/PR04: river band is at the noise floor (not air-coupled) vs a coherent array control. Queries FDSN (BHZ + BDF), rebuilds offline from the committed npz |
Scripts are standalone and idempotent; most read notebooks/data/results/ (step 1) plus committed config/*.json and write into paper/figures/. Steps 3–22 can run in any order after step 1 (22 needs 21’s two JSONs). Steps 19, 40 and 41 query the network — step 19 hits the Microsoft Planetary Computer STAC (Sentinel-2/-1, no credentials); steps 40/41 download CC BDF/BHZ infrasound+seismic from FDSN (IRIS), and step 39 reads cached UW.LON mseed. Step 19 runs fully offline with --from-cache (replaying notebooks/data/braid_cache/*.npz); pixi run make figures-from-cache rebuilds the core figures (fig19/20/22/23 etc.) with no network. The infrasound trio (39/40/41 → fig30/31/32) lives on the repro path: each writes a compact npz under notebooks/data/results/, and if a run finds no waveforms it rebuilds the figure from that npz instead — so committing those npz (force-added, as for spectra_psd.npz) makes the figures reproducible offline. See paper/ROADMAP.md for which figure supports which research thread.
Batch over the whole upper transect (all CC stations with gages):
pixi run python scripts/run_river_rumble_batch.py \
--start 2025-12-01T00:00:00 --end 2025-12-24T00:00:00 \
--network-filter CC --use-rss --exclude-earthquakes \
--clip-impulses --despike-proxy \
--flow-bands 0.5-2,1-5,2-8 --bedload-bands 5-15,10-30,30-606.1 Repository layout (paper-grade)
config/
transect_puyallup.yaml mountain-to-sea station↔gage transect (+ feasibility caveats)
analysis.yaml proxy/cleaning/lag/fit parameters (single source of truth)
_transect_discovery.json generated station list (step 0)
src/riverseis/
analysis.py load, robust log-log fit (bootstrap CI), Lawler hysteresis index
scripts/
run_river_rumble_batch.py proxy + alignment + per-station fit (uses notebooks/utils.py)
notebooks/
utils.py pipeline engine (Tier-1 fixes applied — see REVIEW_2026.md)
workflows/
00_discover_stations.py FDSN + USGS discovery
02_make_figures.py publication figures from results/
paper/
manuscript.md draft scaffold (findings + reviewer defenses)
LITERATURE.md annotated bibliography + novelty matrix
references.bib BibTeX
figures/ generated figures + scaling_table.csv
REVIEW_2026.md physics + code review, Tier-1 fixes, recomputed diagnostics
6.2 Key parameters (config/analysis.yaml)
- Strict response removal (no raw-counts fallback), RSS Z/N/E, Welch band power.
- Lag scan high-pass detrended (6 h) + sign-constrained.
- Impulse clipping restricted to triggered windows.
- Robust log–log fit with bootstrap 95% CI; turbulence baseline b≈0.9–1.4.
6.3 Pre-commit hook (render check)
A versioned hook in .githooks/pre-commit renders the book before a commit, but only when book inputs are staged (index.qmd, _quarto.yml, REVIEW_2026.md, paper/**, workflows/README.md) — other commits stay fast. It blocks the commit if the render fails. Quarto is a pixi dependency, so the hook is self-contained.
One-time install per clone:
git config core.hooksPath .githooksBypass for a single commit: git commit --no-verify. (_book/ is git-ignored; the hook is a render check — GitHub Pages publishes from source via CI.)
6.4 Provenance
Seismic: IRIS FDSN (CC, UW, GS, PB). Discharge: USGS NWIS IV (cfs). Event: Dec-2025 PNW atmospheric-river floods. All inputs public; large waveform caches are git-ignored.