"""Single entry point for the `silurian` study: regenerates every number and figure. python3 run_all.py # download anything missing (cached), then run every step python3 run_all.py --no-fetch # use the raw cache only (fails if a raw file is missing) python3 run_all.py s04 s07 s08 # run selected steps only Raw downloads go to $SILURIAN_RAW (default fermi_raw/silurian); small derived tables go to ../data, figures to ../figures. A cold start downloads about 210 MB and needs roughly 20-40 minutes, almost all of it the 4,000 Macrostrat map-point queries and the PBDB collection lists; with a warm cache the whole pipeline takes about three to five minutes on one core. Steps s00_fetch Macrostrat columns/units/sections + 4,000 random map points, PBDB collections, CENOGRID (PANGAEA 917660), DM-SED (Zenodo 14771859), Natural Earth land mask s01_macrostrat preserved sediment vs age, hiatuses, yr/cm (time-weighted and plain medians), Sadler slopes s02_mapsample global bedrock-map point sample: outcrop by age, North America -> globe scaling s03_pbdb fossil-collection density; space-time probe P(sampled | footprint, window) s04_cenogrid injection-recovery of industrial carbon pulses with two detectors (matched filter and a plain step statistic); sample-spacing coverage of the record itself s05_dmsed density and spacing of geochemical sampling in one deep-time compilation (exact interval union; lower bounds) s06_signals signal magnitudes: carbon, radionuclide windows, conditional 244Pu bound with the modern-layer test, lunar erasure s07_synthesis p(known today) by scenario, age and window, split into an assumed surface part and a data-based deep-time part; marginalised exclusion counts; modelling variants s08_figures fig1-fig5 Revision history: the first pass was reviewed by a referee (../referee_report.md); the changes made in response are listed in the module docstrings of s01, s04, s05, s06 and s07 and in the report. Random seeds are fixed (common.SEED), so a rerun on the same raw files reproduces the tables exactly. PBDB and Macrostrat are living databases: a fresh download at a later date will shift counts by a small amount. """ import os, sys, time, subprocess HERE = os.path.dirname(os.path.abspath(__file__)) STEPS = ["s00_fetch", "s01_macrostrat", "s02_mapsample", "s03_pbdb", "s04_cenogrid", "s05_dmsed", "s06_signals", "s07_synthesis", "s08_figures"] def main(argv): args = [a for a in argv if not a.startswith("--")] steps = [s for s in STEPS if not args or any(s.startswith(a) for a in args)] if "--no-fetch" in argv: steps = [s for s in steps if s != "s00_fetch"] logdir = os.path.join(os.path.dirname(HERE), "data") os.makedirs(logdir, exist_ok=True) t00 = time.time() with open(os.path.join(logdir, "run_all.log"), "w") as log: for s in steps: t0 = time.time() print(f"[run_all] {s} ...", flush=True) p = subprocess.run([sys.executable, os.path.join(HERE, s + ".py")], cwd=HERE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) log.write(f"===== {s} (exit {p.returncode}, {time.time() - t0:.0f} s) =====\n{p.stdout}\n") log.flush() if p.returncode != 0: print(p.stdout[-4000:]) raise SystemExit(f"[run_all] {s} failed (exit {p.returncode})") print(f"[run_all] {s} done in {time.time() - t0:.0f} s", flush=True) print(f"[run_all] all steps finished in {time.time() - t00:.0f} s; log: {os.path.join(logdir, 'run_all.log')}") if __name__ == "__main__": main(sys.argv[1:])