NANOGrav 15-year Data Set

The Hellings–Downs Signal in Pulsar Timing Data

Reconstructing the gravitational-wave background detection — the way NANOGrav did it — watching the quadrupolar correlation curve emerge, pair by pair, from data that shows nothing in any single pulsar.

Scroll to explore

Two Pulsars Know Nothing.
Two Thousand Know Everything.

A GW background imprints no signal on any individual pulsar — only on the correlations between pairs. This project makes that emergence visible.

A pulsar timing array detects a gravitational-wave background not in any individual pulsar, but in the correlations between pairs of pulsars. A real GW background imprints a specific quadrupolar pattern — the Hellings–Downs curve — on how strongly two pulsars' timing residuals correlate as a function of the angle between them.

No clock error, ephemeris error, or per-pulsar noise process can imitate that shape. This is what makes the NANOGrav 15-year result a genuine detection and not a systematic artifact.

This repository does two things: first, it injects a known GWB plus NANOGrav-realistic noise into 67 synthetic pulsars and recovers the HD curve from scratch. Second, it runs the NANOGrav collaboration's own optimal-statistic code on the real 15-year data — the real white-noise parameters and the real MCMC presampled chain.

NANOGrav 15-year Array — 67 Pulsars, All-Sky
Positive HD correlation Negative HD correlation · hover a pulsar to see its 66 pair arcs
Hammer–Aitoff equal-area projection. Hover any pulsar to draw arcs to all 66 partners, coloured by the expected Hellings–Downs sign. N = 67 pulsars yield N(N−1)/2 = 2,211 unique pairs, each contributing one ρab.

From Raw Residuals
to Detection

The pipeline follows the genuine NANOGrav methodology, step by step. See docs/METHODS.md for the full physics and statistics walkthrough.

01

Timing-Model Projection

Each pulsar's residuals still carry spin, astrometric, and binary parameters. These are removed analytically by projecting onto the null space of the timing-model design matrix — the same linear operation enterprise performs internally.

02

Frequency-Domain Reduction

Pulsars are observed at different, irregular epochs, so residuals are projected onto a common Fourier basis, inverse-variance weighted by TOA uncertainties.

f_k = k / T_span, k = 1 … 14
03

Cross-Correlation & Optimal Statistic

For every pulsar pair, the optimal statistic forms a noise-marginalized estimate of the correlation ρab. This is an estimator of A² · Γab, where Γab is the Hellings–Downs value for that pair and A² the GW background amplitude.

ρ_ab ≈ A²GWB · Γ_ab(θ_ab)
04

Noise Marginalization

The real intrinsic red noise of each pulsar is marginalized over using a presampled MCMC chain (curn_14f_pl_vg.core) from the NANOGrav release. This step separates a genuine detection from an artifact.

05

FFT Normalization (Simulation)

Converting a power-spectral density to a time-domain realization requires careful FFT normalization. The simulation includes an assertion verifying that the realized RMS matches the integrated PSD — getting the factor of N wrong would silently rescale every noise component.

σ = sqrt( N · P(f) / (4 · dt) )

The Curve Emerges

Simulation and real-data results are consistent with the published NANOGrav 15-year detection.

Simulation

67 Synthetic Pulsars

Injects a known GWB + NANOGrav-realistic noise, then recovers the Hellings–Downs curve and amplitude posterior. Detection significance is higher than the real ~3.5–4σ because the noise model is known exactly — the idealized upper bound.

2.6×10⁻¹⁵ AGWB recovered
Real NANOGrav Data

Full 67-Pulsar Array

Reproduces the published 2,211-pair Hellings–Downs detection at ~3.5–4σ on the real NANOGrav 15-year data, real white-noise parameters, and real presampled red-noise MCMC chain.

~3.5–4σ detection significance
Hellings–Downs Correlation Curve — Schematic
30° 60° 90° 120° 150° 180° 0 +0.5 −0.15 Angular separation θ Correlation Γ(θ) Hellings–Downs 1983

S/N grows with the number of pulsar pairs (≈ N²). A subset genuinely yields a lower-significance curve — that is real physics, not a bug.

Available RAM Pulsars Pairs Significance Notes
≥ 7.5 GB 67 (full) 2,211 ~3.5–4σ Published result
5–7.5 GB 45 990 reduced Subset
3.5–5 GB 30 435 reduced Subset
< 3.5 GB 22 231 reduced Minimum useful

Running the Code

Two paths: a self-contained simulation (~2 minutes, no data needed), and the full real-data pipeline with the NANOGrav 15-year dataset.

# No external data required — ~2 minutes
git clone https://github.com/meamresh/hd-pta.git
cd hd-pta
pip install -r requirements.txt

# Run simulation → figures/hd_simulation.png
python src/simulate_hd.py

# Animate pair-by-pair emergence → figures/hd_emergence_sim.gif
python src/animate_hd.py --sim

# Animate growing array (6 → 67 pulsars) → figures/hd_growing_array_sim.gif
python src/animate_npsr.py --sim
# System dependency for scikit-sparse
sudo apt-get install libsuitesparse-dev # Debian/Ubuntu
# brew install suite-sparse # macOS

pip install -r requirements.txt
pip install pandas pyarrow enterprise-pulsar "enterprise_extensions>=3.0.2" la_forge

# Fetch real NANOGrav 15-year data
./setup.sh

# Run optimal statistic → results/ng15_real_os.npz
python src/ng15_optimal_statistic.py

# Animate real-data emergence
python src/animate_hd.py --real
python src/animate_npsr.py --real
Open in Google Colab
Full real-data run, installs everything via conda, sufficient RAM for all 67 pulsars. Run top to bottom (~20–40 min).
Open notebooks/run_on_colab.ipynb →
hd-pta/
├── README.md
├── requirements.txt
├── setup.sh ← fetch real NANOGrav data
├── src/
│ ├── simulate_hd.py ← simulation + summary figure
│ ├── ng15_optimal_statistic.py ← real NANOGrav optimal statistic
│ ├── animate_hd.py ← pair-by-pair animation
│ └── animate_npsr.py ← growing array animation
├── notebooks/
│ └── run_on_colab.ipynb ← full real-data run on Colab
├── docs/
│ ├── METHODS.md ← physics + statistics walkthrough
│ └── examples/ ← example output figures
├── figures/ ← generated figures (gitignored)
└── results/ ← .npz outputs (gitignored)

Attribution

This repository contains no NANOGrav data. setup.sh downloads it from the NANOGrav collaboration's public repository. If you use the data, please cite: