robust_bayes_location / REPRODUCE.md
gcw_3Ac7ljDv
Sync audited synthetic QC, CENC aggregates and training provenance
6c31829
|
Raw
History Blame Contribute Delete
12.3 kB

Reproduce the final controlled comparison

The latest additive four-method synthetic QC postprocessing is documented in RELEASE_SYNC_20260911.md; its portable command does not rerun inference.

Commands run from the repository root unless stated otherwise. They describe the already completed experiments; downloading the archive does not launch training or location. Retain run-specific outputs instead of overwriting frozen evidence. Paths below are relative and contain no private host details.

1. Environment and integrity

git xet install
git clone https://huggingface.co/cangyeone/robust_bayes_location
cd robust_bayes_location
shasum -a 256 -c MANIFEST.sha256
python tools/privacy_audit.py --repository . --check-history
./setup_public.sh
python -m venv .venv-locator
source .venv-locator/bin/activate
python -m pip install -r environment/locator-requirements.txt

Use environment/eikonet-requirements.txt in a separate environment for EikoNet/HypoSVI. Recorded proposed science runs used MPS; final run-46 HypoSVI synthetic and both real runs used CUDA. Location supports the documented backends, but identical seeds across CPU/MPS/CUDA do not guarantee identical floating-point trajectories. Source-only checks:

cd revision_experiments
python -m unittest -v test_sampler_integrity test_hyposvi_baseline \
  test_eikonet_phase_adapter test_hyposvi_eikonet_initializer test_qc_rank_stability
cd ..

Do not count skipped optional upstream-equation tests as passes.

2. Supervised travel-time network

The retained checkpoint is models/proposed/time.v1.0.pt. This is supervised regression on labeled source–receiver P/S travel times, not a PINN. Velocity arrays generate labels offline; the training algorithm does not read velocity values or impose an eikonal equation.

python source/original_workflow/travel_time_train.py \
  --real_txt data/synthetic/train.synth_arrivals_skfmm_noise.new.txt \
  --meta_json data/velocity/xyz_vp_vs_meta.json \
  --device auto --seed 20260831 \
  --hidden_dim 256 --batch_size 128 --epochs 10 --lr 1e-4 \
  --save_ckpt work/time.retrained.pt

The legacy --real_txt argument names a synthetic training file here. The released checkpoint is the frozen experiment model; a fresh retraining is not asserted to reproduce its weights bit for bit.

3. Common synthetic input and proposed locator

All primary methods use data/synthetic/loc.synth_arrivals_skfmm_noise.new.txt: 3,206 event groups and 86,827 observations, including round(0.15*n_phase) 8 s Gaussian gross-error perturbations per event. The common numerical set is 2,998 events / 86,411 rows; 208 single-station P+S inputs count as failures.

cd revision_experiments
python synthetic15_corrected.py \
  --out_dir ../work/proposed_synthetic \
  --min_stations 4 --initialization multistart \
  --init_candidate_strategy hybrid --init_pool_size 32 \
  --init_refine_top_k 4 --init_steps 100 --chain_init_policy best \
  --chain_seeds 95001,95002,95003 \
  --n_samples 6000 --burn 3000 --thin 2
cd ..

The existing joint-model/indicator-ablation outputs and saved diagnostic draws are under revision_experiments/run_24_synthetic15_best_basin/. The writers use one event ordering for sample axes and catalog rows. The main result tables use frozen full-sample catalog estimates. Old exploratory held-out threshold/maximum-coordinate-width diagnostics are not controlling evidence for the paper's QC claim.

4. Fresh NLLoc EDT

Compile the pinned 7.1.04 source:

mkdir -p external/NonLinLoc/src/bin
cmake -S external/NonLinLoc/src -B work/nonlinloc-build
cmake --build work/nonlinloc-build --parallel

If necessary copy the built NLLoc and Grid2Time executables to external/NonLinLoc/src/bin/. The same 3-D slowness arrays, input stations, arrivals, and P/S reported uncertainties 0.3/0.4 s are used. Ordinary synthetic noise of 0.2/0.3 s is a different quantity.

cd revision_experiments
python nlloc_multicore_rerun.py grid2time \
  --dataset synthetic --out-dir ../work/nlloc_synthetic --workers 16
python nlloc_multicore_rerun.py locate \
  --dataset synthetic --out-dir ../work/nlloc_synthetic --workers 32
python nlloc_multicore_rerun.py summarize --out-dir ../work/nlloc_synthetic
cd ..

data/nlloc/synthetic/ contains the fresh controls, synthetic real.obs (legacy filename), synthetic sc.stations, catalog, covariance, phase export, and run accounting. No real observations are stored in that directory. The reported point estimate is the EDT maximum-likelihood location.

5. Independent EikoNet and HypoSVI run 46

Official EikoNet model/source is pinned under external/EikoNet/. Training/checkpoint-selection code is eikonet_chuandian.py and eikonet_checkpoint_selection.py, with recorded training histories and candidate checkpoints in revision_experiments/run_34_eikonet_chuandian_formal/. The frozen selected models are P/eikonet_p_epoch0040.pt and S/eikonet_s_epoch0050.pt. Both use the common 3-D velocity arrays.

The final validation input and output are under revision_experiments/run_46_hyposvi_eikonet_independent_3206/. The validation_input directory contains 60 base events with no overlap with any of the 3,206 formal input IDs. Rebuild observations without loading the proposed surrogate or creating its refined centers:

python revision_experiments/build_hyposvi_validation_dataset.py \
  --clean-arrivals data/synthetic/synth_arrivals_skfmm.txt \
  --formal-event-table data/nlloc/synthetic/all.locfiles.posterior.csv \
  --data-only --out-dir work/hyposvi46/validation_input

Create independent EikoNet validation and test starting centers:

python revision_experiments/hyposvi_eikonet_initializer.py \
  --dataset-role validation --project-root . --device cuda \
  --checkpoint-p revision_experiments/run_34_eikonet_chuandian_formal/P/eikonet_p_epoch0040.pt \
  --checkpoint-s revision_experiments/run_34_eikonet_chuandian_formal/S/eikonet_s_epoch0050.pt \
  --validation-dir work/hyposvi46/validation_input \
  --out-dir work/hyposvi46/initializers/validation

python revision_experiments/hyposvi_eikonet_initializer.py \
  --dataset-role synthetic-test --project-root . --device cuda \
  --checkpoint-p revision_experiments/run_34_eikonet_chuandian_formal/P/eikonet_p_epoch0040.pt \
  --checkpoint-s revision_experiments/run_34_eikonet_chuandian_formal/S/eikonet_s_epoch0050.pt \
  --synthetic-input data/synthetic/loc.synth_arrivals_skfmm_noise.new.txt \
  --out-dir work/hyposvi46/initializers/test

Candidate generation is blind and uses the same raw opportunity as the proposed locator, but ranking/refinement uses EikoNet independently. Initializer seeds default to 94017 (validation) and 93017 (synthetic test). For cross-platform bitwise raw-candidate reproducibility, the initializer also supports --write-raw-candidate-npz and --raw-candidate-npz; the saved synthetic initializer bundles retain their attestations.

python revision_experiments/hyposvi_eikonet_comparison.py validate \
  --project-root . --device cuda \
  --checkpoint-p revision_experiments/run_34_eikonet_chuandian_formal/P/eikonet_p_epoch0040.pt \
  --checkpoint-s revision_experiments/run_34_eikonet_chuandian_formal/S/eikonet_s_epoch0050.pt \
  --out-dir work/hyposvi46 \
  --validation-dir work/hyposvi46/validation_input \
  --validation-initializer-dir work/hyposvi46/initializers/validation \
  --particles 150,300 --epochs 175,350 --step-sizes 0.5,1.0 \
  --validation-seeds 83001,83002 --batch-events 32 \
  --max-padded-pairs-per-batch 6720 --sigma-p 0.3 --sigma-s 0.4

python revision_experiments/hyposvi_eikonet_comparison.py test \
  --project-root . --device cuda \
  --checkpoint-p revision_experiments/run_34_eikonet_chuandian_formal/P/eikonet_p_epoch0040.pt \
  --checkpoint-s revision_experiments/run_34_eikonet_chuandian_formal/S/eikonet_s_epoch0050.pt \
  --out-dir work/hyposvi46 \
  --selected-configuration work/hyposvi46/selected_configuration.json \
  --synthetic-input data/synthetic/loc.synth_arrivals_skfmm_noise.new.txt \
  --initializer-csv work/hyposvi46/initializers/test/multistart_initialization.csv \
  --initializer-info work/hyposvi46/initializers/test/shared_initializer_info.json \
  --test-seeds 82001 --workers 1 --batch-events 32 \
  --max-padded-pairs-per-batch 6720 --sigma-p 0.3 --sigma-s 0.4

The archived grid selects 300/350/0.5. The frozen completed formal run has 2,998 finite solutions and mean H/Z/T errors 5.884 km / 5.406 km / 0.419 s. Its audit summary passes 503/503 checks. Earlier run-35 shared-initializer or pilot-overlap outputs cannot be relabeled as this independent result.

6. Frozen-result plots and diagnostic checks

Regenerate the unfiltered synthetic map without inference:

python revision_experiments/plot_synthetic15_locations.py \
  --input-data repro_outputs/synthetic/synthetic15_location_comparison.csv \
  --output-stem work/fig_synthetic15_locations_grayscale

Recompute residual fits and coverage from saved arrays:

python revision_experiments/synthetic_residual_coverage.py \
  --synthetic-input data/synthetic/loc.synth_arrivals_skfmm_noise.new.txt \
  --checkpoint models/proposed/time.v1.0.pt \
  --proposed-npz \
    revision_experiments/run_24_synthetic15_best_basin/diagnostic_seed95001_student_t_z.npz \
    revision_experiments/run_24_synthetic15_best_basin/diagnostic_seed95002_student_t_z.npz \
    revision_experiments/run_24_synthetic15_best_basin/diagnostic_seed95003_student_t_z.npz \
  --hyposvi-npz revision_experiments/run_46_hyposvi_eikonet_independent_3206/test/particles_test_p300_e350_s0p5_seed82001.npz \
  --nlloc data/nlloc/synthetic/all.locfiles.posterior.csv \
  --out-dir work/residual_coverage --device cpu

python revision_experiments/qc_rank_stability.py \
  --synthetic revision_experiments/run_24_synthetic15_best_basin \
  --output-dir work/qc_stability \
  --private-manifest work/private/qc_source_manifest.json

QC stability uses the exact horizontal/depth percentile score. Diagnostic draws are additionally thinned (150 per synthetic chain, 75 per real chain); frozen operational catalog widths use all 1,500 retained draws per chain. Residual-fit means and full coverage curves use the saved diagnostic draws. The new check neither replaces catalog point estimates nor calibrates intervals. The public synthetic-only invocation produces 10 comparisons. Authorized users may add --direct and --associated directories for the 30-comparison analysis reported in SI; raw real inputs and chain arrays are not released.

7. Restricted real-data reproduction and SI timing

Real inputs exist but are intentionally excluded, including every .pha file. Obtain and cite the permitted Luding comparison data through Liu et al. (2023), https://doi.org/10.6038/cjg2023Q0841. CENC inputs have separate restrictions. Keep all permitted inputs and event-level outputs in work/private_real_data/. Do not attempt to reconstruct restricted locations from aggregate tables.

hyposvi_eikonet_initializer.py supports real-direct and real-associated roles; supply --observations and --stations privately and use its independent EikoNet outputs with hyposvi_eikonet_real.py. Use published defaults: 150 particles, 175 epochs, step size 1.0, seed 84001; no catalog-based tuning. Three methods share the same 10,487/224,644 direct and 10,950/176,243 associated event/phase counts. NLLoc's one associated solver failure stays a failed output and is not deleted from another method's input.

Real three-method recall curves (180 aggregate points), paired intervals, conditional-difference summaries, GAU/EDT checks and timing are in repro_outputs/real_aggregate/. Real maps, particles, matched-event tuples, station tables and restricted source fingerprints are not part of this release. Forward validation at actual receivers is therefore reproducible only by authorized users with those receiver definitions; public tables provide aggregate evidence, not substitute inputs.

The native real-catalog timing comparison is SI-only (Table S7). It excludes training/table construction, initialization, checkpoint compression and downstream analysis, and is not a common-latency or equal-posterior-quality benchmark. NLLoc is fastest in the recorded native configuration.