GRB Afterglow Detection¶
This page summarizes GRB afterglow detection simulations for both ZTF and Rubin LSST, covering on-axis (gamma-ray-associated) and off-axis (orphan) afterglows.
Summary of results¶
On-axis afterglows (blind discovery)¶
| Survey | Duration | Injections | Efficiency | Expected (R=1.0) | Observed |
|---|---|---|---|---|---|
| ZTF | 1.16 yr (Feb 2020 – Mar 2021) | 1M | 1.52% | 9.5 | 5 (ZTFReST) |
| Rubin | 10 yr | 1M | 0.88% | 44.3 (4.4/yr) | — |
Off-axis (orphan) afterglows (blind discovery)¶
| Survey | Duration | Injections | Efficiency | Expected (R=100) | Observed |
|---|---|---|---|---|---|
| ZTF | 1.16 yr (Feb 2020 – Mar 2021) | 1M | 0.0076% | 0.6 | 2 (ZTFReST) |
| Rubin | 10 yr | 1M | 0.0071% | 4.7 (0.5/yr) | — |
Combined predictions for Rubin (10 years)¶
| Type | Rate (Gpc⁻³ yr⁻¹) | Expected (10yr) | Per year |
|---|---|---|---|
| On-axis | 1.0 | 44 | 4.4 |
| Off-axis (orphan) | 100 | 5 | 0.5 |
| Total | — | ~49 | ~5 |
Blind discovery vs. gamma-ray-triggered detection¶
Important distinction: These predictions count afterglows that can be independently discovered as fast-fading transients from survey photometry alone, without prior knowledge of a gamma-ray trigger. This is a fundamentally different question from "how many GRB afterglows will a survey serendipitously image."
For example, Burns+ (2025) estimate ~75 on-axis GRBs/yr for Rubin by scaling the all-sky prompt GRB rate (~340/yr) by Rubin's ~24% sky coverage over 3 nights and ~90% recovery efficiency. That calculation assumes the GRB time and sky position are already known from Swift/Fermi, and simply checks whether Rubin has data at that location.
Our blind-discovery rate of ~4.4 on-axis/yr is lower because it requires the afterglow to independently pass fast-transient detection criteria (fading rate ≥0.3 mag/day, multiple detections, SNR thresholds) from Rubin's WFD cadence alone, without any external trigger information.
Both numbers are valid but answer different questions:
- Triggered follow-up (~75/yr): "How many GRB afterglows will Rubin image, given alerts from gamma-ray satellites?"
- Blind discovery (~5/yr): "How many afterglows will Rubin find as new fast transients, without any GRB alert?"
Background¶
GRB afterglows arise from the interaction of a relativistic jet with the circumburst medium, producing broadband synchrotron radiation that fades over days to weeks. The forward shock (FS) dominates at late times, while the reverse shock (RS) can produce a bright optical flash at early times (t ≲ 1 day).
On-axis vs. off-axis¶
- On-axis (θ_v ≤ θ_j): The observer is within the jet opening angle. The prompt gamma-ray emission is visible, and the afterglow is bright from the start. These are classical GRBs detected by Swift/Fermi.
- Off-axis (θ_v > θ_j): The observer is outside the jet cone. The prompt gamma rays are beamed away, but the afterglow becomes visible as the jet decelerates and spreads — these are "orphan afterglows."
The beaming factor (~1/f_b, where f_b ~ 0.006 for a typical jet half-angle of ~6°) means the true GRB rate is ~100–800× the observed on-axis rate.
Lightcurve model¶
We use the fiesta neural network surrogate (blastwave_rs_gaussian_CVAE) trained on the blastwave Rust crate, which includes both forward shock (FS) and reverse shock (RS) components. The surrogate predicts spectral flux density on a 2D grid (frequency × time), integrated through filter transmission curves to produce per-band magnitudes.
| Parameter | Typical range |
|---|---|
| Isotropic energy E_iso | 10⁴⁷–10⁵⁴ erg |
| Lorentz factor Γ₀ | 1–500 |
| Jet half-opening angle θ_c | 0.01–0.6 rad |
| ISM density n₀ | 10⁻⁴–10² cm⁻³ |
| Electron energy fraction ε_e | 10⁻³–10⁰ |
| Magnetic energy fraction ε_B | 10⁻⁵–10⁰ |
| Electron spectral index p | 2.0–3.0 |
Population generators¶
GRB catalog¶
The GRB population is drawn from a pre-computed catalog of 42,803 parameter sets at GRB_afterglows_argus.csv, generated by Monte Carlo population synthesis. The catalog includes both on-axis (~15%) and off-axis (~85%) viewing angles with isotropic sampling.
Three population types¶
| Class | Redshift | Viewing angle | Use case |
|---|---|---|---|
GrbPopulation |
From catalog | From catalog | Legacy (mixed on/off-axis) |
OnAxisGrbPopulation |
From catalog | θ_v ≤ θ_j only | On-axis afterglows (gamma-ray detected) |
OffAxisGrbPopulation |
Volumetric (uniform in comoving volume) | Isotropic, θ_v > θ_j | Orphan afterglows |
The OnAxisGrbPopulation filters the catalog to on-axis rows and uses the catalog's redshift distribution (from gamma-ray-detected GRBs). The OffAxisGrbPopulation resamples redshift volumetrically (up to z_max, typically 1.0) and viewing angles isotropically, since orphan afterglows are not subject to the gamma-ray detection selection.
Rates¶
| Rate | Value | Description |
|---|---|---|
| On-axis (observed) | ~1.0 Gpc⁻³ yr⁻¹ | Prompt-detected long GRB rate |
| Off-axis | ~100 Gpc⁻³ yr⁻¹ | Beaming-corrected, off-axis only |
ZTF afterglow detection¶
Survey setup¶
- Period: Feb 2020 – Mar 2021 (1.16 yr), matching the ZTFReST analysis
- Observations: ~211,000 in g/r/i
- Sky fraction: 47%
- Detection criteria: ZTFReST-like (2 detections, ≥3h separation, ≥0.3 mag/day fading, |b| > 15°)
On-axis¶
from survey_sim import OnAxisGrbPopulation, load_ztf_survey
survey = load_ztf_survey(start="202002", end="202103", nside=64)
grb_pop = OnAxisGrbPopulation("GRB_afterglows_argus.csv", rate=1.0, z_max=6.0)
Results (1M injections): 15,199 detected, efficiency = 1.52%
| Rate (Gpc⁻³ yr⁻¹) | Expected |
|---|---|
| 0.5 | 4.7 |
| 1.0 | 9.5 |
| 1.3 | 12.3 |
ZTFReST observed 5 on-axis afterglows. The R=0.5 prediction (4.7) is the best match.
Off-axis (orphan)¶
from survey_sim import OffAxisGrbPopulation
grb_pop = OffAxisGrbPopulation("GRB_afterglows_argus.csv", rate=100.0, z_max=1.0)
Results (1M injections): 76 detected, efficiency = 0.0076%
Expected at R=100: 0.6 orphan afterglows. ZTFReST observed 2 orphan afterglows.
Rubin LSST afterglow detection¶
Survey setup¶
- Survey: Rubin LSST baseline_v5.1.1, 10-year
- Observations: ~2.06M in ugrizy
- Sky fraction: 44%
- Detection criteria: 2 detections, ≥0.5h separation, ≥0.3 mag/day fading, |b| > 15°
On-axis¶
from survey_sim import SurveyStore, OnAxisGrbPopulation
survey = SurveyStore.from_rubin("baseline_v5.1.1_10yrs.db", nside=64)
grb_pop = OnAxisGrbPopulation("GRB_afterglows_argus.csv", rate=1.0, z_max=6.0)
Results (1M injections): 8,831 detected, efficiency = 0.88%
| Rate (Gpc⁻³ yr⁻¹) | Expected (10yr) | Per year |
|---|---|---|
| 0.5 | 22.1 | 2.2 |
| 1.0 | 44.3 | 4.4 |
| 1.3 | 56.1 | 5.6 |
Off-axis (orphan)¶
from survey_sim import OffAxisGrbPopulation
grb_pop = OffAxisGrbPopulation("GRB_afterglows_argus.csv", rate=100.0, z_max=1.0)
Results (1M injections): 71 detected, efficiency = 0.0071%
Expected at R=100: 4.7 orphan afterglows in 10yr (0.5/yr).
Why is Rubin's on-axis efficiency lower than ZTF's?¶
Rubin's per-event on-axis efficiency (0.88%) is lower than ZTF's (1.52%) despite Rubin being ~4 magnitudes deeper. This is because:
- Cadence: ZTF revisits fields nightly; Rubin WFD has ~3-day inter-night gaps, missing the fast-fading early afterglow
- Fast-transient criteria: The ≥0.3 mag/day fading requirement needs detections at multiple epochs during the rapid decline phase
- Intra-night pairs: Rubin takes pairs ~6 min apart (same night), which helps confirm detection but doesn't sample the fading
However, Rubin's 10-year baseline and slightly larger V_eff more than compensate, giving 44 total on-axis vs ZTF's ~10 over 1 year.
GPU requirements¶
The fiesta afterglow surrogate requires JAX with GPU support:
import survey_sim.gpu_setup # auto-configures CUDA for JAX
from survey_sim.fiesta_afterglow_model import FiestaAfterglowModel, ZTF_BAND_MAP, LSST_BAND_MAP
model = FiestaAfterglowModel(name="blastwave_rs_gaussian_CVAE", band_map=ZTF_BAND_MAP)
Performance: ~200s for 1M injections on GPU (700K spatial matches → lightcurve eval).
Scripts¶
| Script | Description |
|---|---|
python/scripts/run_grb_onaxis_ztf.py |
ZTF on-axis afterglows (1.16yr, R=1.0) |
python/scripts/run_grb_onaxis_rubin.py |
Rubin on-axis afterglows (10yr, R=1.0) |
python/scripts/run_grb_offaxis_ztf.py |
ZTF off-axis orphan afterglows (1.16yr, R=100) |
python/scripts/run_grb_offaxis_rubin.py |
Rubin off-axis orphan afterglows (10yr, R=100) |