# Scripts Run every script from the repository root with the project's environment, for example `.venv/bin/python scripts/phase1.py`. Each script's docstring gives its full usage and options. ## The phases of the study Each phase answers one question of the study and is written up in the [report](../REPORT.md). Phases 2–10 are ablation tables in [sgloc/ablations.py](../sgloc/ablations.py), run with `sweep.py ` and summarized with `summarize.py
`. | Phase | Question | How to run it | Results | |---|---|---|---| | 0 | Simulator, data pools and the rebuilt v1 | `make_pools.py`, `validate_sim.py`, `train_v1.py` | `results/validation.json`, `results/runs.jsonl` | | 1 | Physics checks and baselines | `phase1.py` | `results/phase1.json` | | 2 | Architecture (Q2) | `sweep.py phase2` | `results/phase2_tables.md` | | 3 | Inputs, sensor noise and when to watch (Q1) | `sweep.py phase3` | `results/phase3_tables.md` | | 3, addendum | Phase 3's noise-and-timing grid on the swing-averaged label | `sweep.py phase3_avg`, `noise_tradeoff.py` | `results/phase3_avg_tables.md`, `results/noise_tradeoff.json` | | 4 | Loss (Q3) | `sweep.py phase4` | `results/phase4_tables.md` | | 5 | Optimizer (Q4) | `lr_range_test.py`, then `sweep.py phase5` | `results/lr_range.json`, `results/phase5_tables.md` | | 6 | The final model, its leave-one-out ablations and robustness (Q5) | `sweep.py phase6` (and its parts `phase6_deploy`, `phase6_label`, `phase6_damping`), `make_robustness_pools.py`, `robustness.py`, `damping_physics.py` | `results/phase6_tables.md`, `results/robustness.jsonl`, `results/damping_physics.json` | | 7 | The key choices on the swing-averaged label | `sweep.py phase7` | `results/phase7_tables.md` | | 8 | Regularization with little data | `sweep.py phase8`, `regularization.py` | `results/phase8_tables.md`, `results/phase8_regularization.md` | | 9 | The hump-scale label and a second site | `add_labels.py hump`, `sweep.py phase9`, `top2.py` | `results/phase9_tables.md`, `results/top2.json` | | 10 | The key choices and sensing setups on the hump label | `add_labels.py hump_top`, `sweep.py phase10`, `hump_label.py` | `results/phase10_tables.md`, `results/hump_label.json` | | Camera start time | When a coarse camera should start watching, at full budget | `sweep.py deploy_start` | `results/deploy_start_tables.md` | ## Data and checks | Script | What it does | Writes | |---|---|---| | `make_pools.py` | Simulates the training, validation and test pools (100,000 / 20,000 / 20,000 runs of initial angles and labels) | `data/pool_*.npz` | | `add_labels.py` | Adds labels that are not computed by default (`hump`, `hump_top`) to existing pools, re-simulated from their stored initial angles | `data/pool_*.npz` | | `make_robustness_pools.py` | Test pools for Phase 6: shifted couplings, more initial noise, other ring lengths, impurities and damping | `data/robust_*.npz` | | `validate_sim.py` | Checks the simulator against the paper's own `odeint` pipeline, step-size convergence, the paper's box-car number and the Floquet threshold | `results/validation.json` | ## Training | Script | What it does | Writes | |---|---|---| | `sweep.py` | Runs one phase's ablation table on GPU and CPU slots, skipping configs already in `results/runs.jsonl`. It fills the trajectory cache in `data/cache/` first. | `runs//`, `results/runs.jsonl` | | `run_config.py` | Runs one config in its own process, so memory is returned when it finishes (called by `sweep.py`) | as above | | `run_one.py` | Runs a single config of a table, by phase, name and seed | as above | | `train_v1.py` | Trains the rebuilt v1, the paper's CNN-BiLSTM | `runs//`, `results/runs.jsonl` | | `summarize.py` | Mean ± standard deviation over seeds for one table | `results/
_tables.md` | ## Analyses | Script | What it does | Writes | |---|---|---| | `phase1.py` | Growth spectrum, best box-car width against amplitude, mode knockouts, sensitivity to the initial state, and the physics baselines | `results/phase1.json` | | `noise_tradeoff.py` | Fits the trade-off between sensor noise and waiting, on both labels | `results/noise_tradeoff.json` | | `lr_range_test.py` | Learning-rate range test for each optimizer of Phase 5 | `results/lr_range.json` | | `robustness.py` | Re-evaluates trained runs on shifted test conditions, without retraining | `results/robustness.jsonl` | | `damping_physics.py` | Which damped runs still localize, and when | `results/damping_physics.json`, `figures/fig20_damping.*` | | `eval_final.py` | The final models' time head and prediction sets | `results/time_head.json`, `results/prediction_sets.json` | | `hotspot_timing.py` | Is the localization time just an amplitude trend, and is the hotspot one pendulum? | `results/hotspot_timing.json` | | `diagnose_late_frames.py` | How readable the site is from a single later snapshot (a check on the v1 reproduction gap) | `results/late_frames.json` | | `regularization.py` | How each regularizer changes overfitting with little data | `results/phase8_regularization.md`, `results/phase8_curves.json`, `results/phase8_train.json` | | `top2.py` | A second site, for runs where a rival hump competes | `results/top2.json`, `results/top2_deploy.json` | | `hump_label.py` | Why the hump label is easier to predict than the swing-averaged label | `results/hump_label.json` | ## Tables and figures | Script | What it does | Writes | |---|---|---| | `headline.py` | The v1 against v2 headline tables | `results/headline.md` | | `make_figures.py` | Every report figure whose inputs exist | `figures/*.png`, `figures/*.pdf` |