Fast Lookup-based Acoustic-seismic Reconstruction of Entries for meteoroid/space debris trajectory reconstruction, from event time and
location to a sampled posterior, driven by one YAML file per event.
Three stages share one code base and can be run separately:
| stage | command | what it does | typical cost |
|---|-------------------|---------------------------------------------------------------------------------------------------------------|------------------|
| 1 | FLARE atmosphere | fetches the two NCPA G2S hours bracketing the event and interpolates them in time onto the event epoch | seconds |
| 2 | FLARE lookup | runs one infraGA 3d prop point source per altitude level and converts the arrivals to memory-mapped .npy | minutes to hours |
| 3 | FLARE mcmc | emcee inversion for the trajectory, using the store as a Green's-function lookup | hours |
| 4 | FLARE postprocess | chain -> posterior table, MAP trajectory, per-station residuals, figures | seconds |
|---|-------------------|---------------------------------------------------------------------------------------------------------------|------------------|
FLARE run does all four in order. FLARE check validates a config and reports what already exists on disk.
Install
bash:
pip install -e ".[mpi,hdf5,plot]" # drop [mpi] if you only run multiprocessing
External tools, expected on PATH or given in the config:
- ncpag2s-clc — the G2S client
(paths.ncpag2s points at ncpag2s.py)
- infraGA/GeoAc — set
lookup.conda_env if it lives in its own conda environment, and the pipeline
will call it through conda run rather than needing an activated shell.
Quick start for a new event
bash:
FLARE init -o event.yaml # template config
$EDITOR event.yaml # event time/location, picks file, bounds
FLARE check -c event.yaml
FLARE atmosphere -c event.yaml
FLARE lookup -c event.yaml
mpirun -n 72 FLARE mcmc -c event.yaml
FLARE postprocess -c event.yaml
Everything lands under <paths.workdir>/<event.id>/:
atmosphere/ g2s__.met (raw hours) and <event.id>.met (blended)
lookup_ascii/ infraGA output, 0_0_traj.dat.arrivals.dat
lookup_npy/ /pts_aug.npy, vals_aug.npy <- memory mapped by the workers
mcmc/ mcmc.h5, mcmc_chain_physical.npy, mcmc_summary.txt, config_used.yaml
mcmc_posterior.csv, mcmc_residuals.csv, mcmc_trajectory.csv,
mcmc_trajectory_ci.csv, mcmc{corner,trace,residuals}.png
logs/ one log per stage, plus forward_errors.log
The config file
configs/event_template.yaml is fully commented. The fields that matter for a
new event are event, paths, picks.file, and the mcmc.parameters bounds.
Resolution knobs. Lookup-table cost scales as
n_levels x (az_range / az_step) x (incl_range / incl_step):
yaml:
lookup:
altitude_min_km: 15
altitude_max_km: 100
altitude_step_km: 1.0 # altitude level separation
azimuth: {min: -180, max: 180, step: 1.0}
inclination: {min: -90, max: 90, step: 1.0}
Sub-kilometre altitude steps work: the levels are discovered by scanning
lookup_npy/, and the forward model brackets each trajectory sample between
whichever two levels exist. A finer angular step lets you tighten
forward.knn.max_distance_deg, which is the main lever on interpolation error
in the arrival times.
Parameter bounds are written in physical units. log10: true makes the
sampler work in the logarithm while the bounds stay readable:
yaml:
ablation: {min: 2.5e-9, max: 5.0e-8, log10: true}
mass: {min: 300.0, max: 2500.0, log10: true}
Order in mcmc.start.guess is always: lon, lat, height, azimuth, inclination,
velocity, time_shift, ablation, spherical_factor, mass.
Running the MCMC
mcmc.pool selects mpi (schwimmbad MPIPool, for mpirun),
multiprocessing, or serial. With h5py installed the chain is written
incrementally to mcmc/mcmc.h5 and re-running the same command resumes
where it stopped. Delete the .h5 to start fresh.
Convergence: the run stops once total_steps >= target_tau_multiple * max(tau)
with a finite autocorrelation estimate in every dimension, or at
max_steps. Walkers whose acceptance fraction falls below
reseed_threshold are reseeded from the healthy ones.
Post-processing
bash:
FLARE postprocess -c koblenz.yaml --burn-in 0.3 --draws 500
--burn-in takes a fraction (< 1) or a step count. Besides the posterior
table it writes the MAP trajectory as CSV and an altitude-binned lat/lon
spread over --draws posterior samples and both are ready to feed straight into
PyGMT. mcmc_residuals.csv gives observed, predicted and residual per station
at the MAP solution, which is usually the fastest way to spot a mis-picked
station. Corner and trace plots need matplotlib and corner. Without them
the CSVs are still written.
Using the pieces directly
The stages are library code, not just CLI:
python:
from meteor_pipeline.config import load_config
from meteor_pipeline.context import ForwardContext
from meteor_pipeline.forward import forward_model
cfg = load_config("koblenz.yaml")
ctx = ForwardContext.from_config(cfg) # atmosphere + lookup + picks
pred = forward_model(ctx, lon=5.5, lat=49.2, height_km=85.0,
azimuth_deg=50.0, inclination_deg=-15.0,
velocity_ms=18000.0, time_shift_s=0.0,
ablation=1.7e-8, spherical_factor=1.0, mass_kg=1000.0)
Tests
bash:
python tests/test_smoke.py # or: python -m pytest tests -q
The smoke test builds a toy atmosphere and a synthetic straight-ray lookup
table, then runs conversion, the forward model, the posterior and a short
serial chain. It needs no infraGA, no network, and takes a few seconds.