A high-precision astrophysical auditing tool for testing the Simulation Hypothesis.
Correlates LIGO/Virgo/KAGRA gravitational wave events with sub-microsecond pulsar timing residuals
from the NANOGrav 15-year dataset to search for coherent "simulation lag" artifacts.
- Overview
- The Hypothesis
- Architecture
- Getting Started
- Usage
- Project Structure
- Scientific Details
- Contributing
- License
- Disclaimer
Demiurge Trace bridges two domains of astrophysics:
- High-energy physics — Confirmed gravitational wave merger events detected by LIGO/Virgo/KAGRA.
- Precision timing — Sub-microsecond timing residuals from millisecond pulsars (MSPs) in the NANOGrav 15-year dataset.
The tool performs a statistical audit to determine whether coherent timing anomalies appear across a pulsar array during gravitational wave events — a signature that would be consistent with computational "lag" in a simulated universe.
If our universe operates on finite computational resources, extremely high-load events — such as binary neutron star or black hole mergers — could theoretically produce measurable "simulation lag." This lag would manifest as a coherent, synchronized timing deviation across the galaxy's most stable natural clocks: millisecond pulsars.
A genuine simulation artifact would be:
- Temporally Correlated — Occurring precisely within the GW merger event window.
- Spatially Invariant — Affecting the entire observable pulsar array simultaneously, regardless of sky position.
Unlike individual pulsar jitter or instrumentation noise, a coherent artifact would stand out as a statistically significant ensemble-wide deviation.
The system is built as a modular pipeline with four stages:
graph TD
subgraph "Data Acquisition"
A1[LIGO GWOSC Catalog] -->|gwpy| B1(GW Strain Data)
A2[NANOGrav 15-Year Dataset] -->|setup_array.py| B2(Pulsar .par/.tim Files)
end
subgraph "Processing Engine"
B2 --> C1{Pulsar Module}
C1 -->|PINT| D1[High-Precision Residuals]
B1 --> C2[LIGO Module]
C2 -->|Signal Analysis| D2[Event GPS Timestamps]
end
subgraph "Analysis & Verification"
D1 & D2 --> E[Auditor Engine]
E -->|audit_ensemble| F{Statistical Audit}
F -->|> 3σ| G[🚨 Coherent Artifact]
F -->|< 3σ| H[✓ Null Hypothesis]
end
subgraph "Visualization"
H & G --> I[Visualizer]
I -->|Matplotlib| J[Result Plots]
end
| Dependency | Purpose |
|---|---|
| Python 3.9+ | Runtime |
| PINT | Pulsar timing model loading & residual calculation |
| GWpy | LIGO/GWOSC data access & strain retrieval |
| Matplotlib | Visualization |
| Astropy | Time coordinate transformations (GPS ↔ MJD/TDB) |
# Clone the repository
git clone https://github.com/ericmaddox/demiurge-trace.git
cd demiurge-trace
# Create and activate a virtual environment
python -m venv .venv
# Linux / macOS
source .venv/bin/activate
# Windows
.\.venv\Scripts\activate
# Install dependencies
pip install pint-pulsar gwpy matplotlib numpy requests dash plotlyThe auditor requires real millisecond pulsar timing data. Run the setup script to automatically download, extract, and patch the NANOGrav 15-year narrowband dataset from Zenodo:
python setup_array.pyThis script handles:
- Downloading the dataset tarball (~600 MB) from Zenodo Record 8423265
- Extracting
.parand.timfiles for the target pulsar ensemble - Patching binary model parameters for PINT compatibility (e.g.,
T2→DDK)
Data is saved to data/real/.
Run the full pulsar array audit against a specific gravitational wave event:
python main.py --event GW170817 --ensemble --window 432000 --output results/audit_GW170817.pngNote: A window of
432000seconds (5 days) is recommended to account for the sparse cadence of pulsar timing array observations.
Audit a single pulsar against an event:
python main.py --event GW150914 --pulsar J1713+0747Inject a synthetic 10 µs lag spike across the ensemble to validate detection sensitivity:
python main.py --event GW170817 --ensemble --simulate-lag --output results/sim_detection.pngLaunch the web-based Plotly Dash dashboard for interactive exploration:
python dashboard.pyYour default browser will open automatically once data pre-loading completes (~60s).
After clicking ▶ Run Audit, the dashboard populates eight tabs:
| Element | What it shows |
|---|---|
| Top subplot (purple) | Raw LIGO strain data from the H1 (Hanford) detector centered on the GW event. The red vertical line marks the exact merger time (t = 0). |
| Bottom subplot (colored dots) | Timing residuals for all pulsars in the ensemble, normalized to units of σ (standard deviations). Each color is a different pulsar. |
| Yellow shaded region | The analysis window — the time range being compared to the baseline. |
| What to look for | If the simulation hypothesis were true, you'd see a coordinated cluster of elevated residuals (dots far from y = 0) inside the yellow window across multiple pulsars simultaneously. Scattered, random dots are normal — that's pulsar noise. |
| Element | What it shows |
|---|---|
| Grey dots | Baseline residuals (outside the analysis window) in microseconds (µs). This is the pulsar's normal timing noise. |
| Purple dots | Residuals inside the analysis window, highlighted for comparison against the baseline. |
| Title bar stats | σ = how many standard deviations the window RMS deviates from the baseline RMS. p = Monte Carlo p-value. log₁₀(BF) = Bayesian evidence ratio. |
| What to look for | If σ ≈ 0, the window residuals are indistinguishable from normal noise — no artifact. If σ > 3, the window shows statistically significant excess timing variation that warrants investigation. |
| Element | What it shows |
|---|---|
| Colored lines | Each line is one pulsar's σ deviation as the analysis window slides across the entire observation timeline. The x-axis is time offset from the GW event in days. |
| Red vertical line | Marks the exact GW event time (offset = 0). |
| Yellow dashed line | The 3σ threshold. Any spike above this line would be statistically significant. |
| What to look for | If no pulsar's line spikes at offset = 0, the GW event time is not special — the residuals there are no different from any other random time in the dataset. A coordinated spike at offset = 0 across multiple pulsars would suggest a simulation artifact. |
| Element | What it shows |
|---|---|
| Scatter plot | Each marker is a pulsar plotted by Right Ascension and Declination (celestial coordinates). |
| Marker size & color | Scaled by the absolute σ deviation — larger/brighter markers indicate higher deviations. |
| What to look for | A simulation artifact would appear as uniformly elevated markers across the entire sky. If only one region is elevated, it's more likely local noise or instrumental. |
| Element | What it shows |
|---|---|
| Heatmap | Pairwise Pearson correlation coefficients between pulsar timing residuals within the analysis window. |
| Color scale | Red = positive correlation, Blue = negative correlation, White = no correlation. |
| What to look for | A coherent simulation artifact would produce strong positive correlations across all pulsar pairs (uniformly red). Real physics should show near-zero correlations for most pairs. |
| Element | What it shows |
|---|---|
| Histogram | Distribution of ensemble σ values computed at 100 random GPS times (the null distribution). |
| Red vertical line | The observed ensemble σ at the actual GW event time. |
| Green dashed line | Mean of the null distribution. |
| What to look for | If the observed σ (red line) falls well within the histogram, the GW event time is statistically unremarkable. If it falls far in the tail, the event time is anomalous. |
| Element | What it shows |
|---|---|
| Yellow dashed curve | The theoretical Hellings-Downs curve — the expected cross-correlation pattern for a gravitational wave background. |
| Purple dots | Measured cross-correlations between pulsar pairs plotted against their angular separation. |
| What to look for | If the measured correlations follow the HD curve, it would indicate a genuine GW signal. Random scatter indicates noise. A simulation artifact would show correlations inconsistent with both the HD curve and pure noise. |
| Column | Meaning |
|---|---|
| Pulsar | NANOGrav pulsar designation (J-name). |
| σ | Number of standard deviations between window RMS and baseline RMS. Values near 0 = normal; > 3 = anomalous. |
| p-value | Monte Carlo significance (10,000 permutation trials). Low p-values (< 0.05) suggest the deviation is unlikely due to chance. |
| log₁₀(BF) | Bayesian evidence ratio. Negative values favor the null hypothesis; positive values favor artifact detection. |
| Bayes Verdict | Jeffreys' scale interpretation of the Bayes Factor (e.g., "Decisive evidence for NULL"). |
| Window RMS | Root-mean-square of timing residuals inside the analysis window (seconds). |
| Baseline RMS | Root-mean-square of residuals outside the window (seconds). |
| Artifact | ✓ No = consistent with real physics. 🚨 YES = anomalous deviation detected. |
Interpreting results: A σ near 0 across all pulsars confirms that the universe's natural clocks (pulsars) show no timing anomalies coincident with the gravitational wave event — consistent with real physics, not a simulation.
usage: main.py [-h] [--event EVENT] [--pulsar PULSAR] [--ensemble]
[--window WINDOW] [--simulate-lag] [--output OUTPUT]
Demiurge Trace — Simulation Hypothesis Auditor
options:
--event EVENT GW event name (default: GW150914)
--pulsar PULSAR Pulsar name for single-pulsar mode (default: J1713+0747)
--ensemble Run audit on the entire pulsar array
--window WINDOW Analysis window in seconds (default: 86400)
--simulate-lag Inject a synthetic lag spike for testing
--output OUTPUT Output plot filename (default: audit_result.png)
demiurge-trace/
├── main.py # CLI entry point
├── dashboard.py # Interactive Plotly Dash web dashboard
├── setup_array.py # NANOGrav data acquisition & patching
├── setup_data.py # Alternative data setup utilities
├── get_data_urls.py # Zenodo URL resolver
├── dashboard_figures.py # Plotly figure builders (sky map, heatmap, etc.)
├── demiurge_trace/ # Core library
│ ├── __init__.py
│ ├── ligo_module.py # GW event lookup & strain data fetching
│ ├── pulsar_module.py # PINT model loading & residual calculation
│ ├── auditor.py # Statistical audit engine (MC, Bayes, HD, etc.)
│ └── visualizer.py # Matplotlib plotting (single + ensemble)
├── assets/ # Dashboard screenshots for README
├── .github/workflows/ci.yml # GitHub Actions CI smoke test
├── data/
│ └── real/ # NANOGrav .par/.tim files (generated by setup)
├── results/ # Output plots
└── tools/ # Diagnostic & debugging utilities
- Planetary Shapiro Correction: TOAs are loaded with
planets=Trueto include Solar System ephemeris data (DE421), essential for sub-microsecond residual accuracy. - BIPM Clock Corrections: Observatory clock corrections are applied using the latest BIPM2023 timescale.
All LIGO timestamps (GPS) are synchronized with pulsar timing coordinates (MJD/TDB) using astropy.time, maintaining sub-millisecond alignment across the two data domains.
The data setup pipeline includes an automated patching layer to handle non-standard NANOGrav parameter names and binary models (e.g., T2 → DDK conversion) for full PINT compatibility.
The auditor computes timing residual RMS within a configurable window around each GW event and compares it against the baseline RMS distribution. An ensemble-wide sigma score is derived by averaging individual pulsar deviations. A coherent artifact is flagged when:
- The ensemble sigma exceeds 3.0σ, or
- Three or more pulsars simultaneously exceed 1.0σ (in arrays of ≥ 5 pulsars)
Each pulsar's observed sigma is validated against 10,000 random permutation trials. Residuals are shuffled (breaking the time association), and the window sigma is recomputed for each trial. The p-value is the fraction of trials producing a sigma ≥ the observed value — providing a rigorous, distribution-free measure of statistical significance.
The analysis window is swept across the entire observation timeline at 200 evenly-spaced positions. This produces a sigma-vs-offset curve for each pulsar. If the GW event time is unremarkable, the sigma at offset = 0 should be indistinguishable from the background — confirming that the event coincidence is not special.
| Pulsar | Type | Notes |
|---|---|---|
| J1713+0747 | MSP | DDK binary model |
| J1909-3744 | MSP | High-precision timing standard |
| J0437-4715 | MSP | Closest and brightest MSP |
| J1614-2230 | MSP | Massive neutron star |
| J1744-1134 | MSP | Isolated MSP |
| B1937+21 | MSP | Original millisecond pulsar |
| B1855+09 | MSP | Long timing baseline |
| J1600-3053 | MSP | Wideband timing target |
| J2145-0750 | MSP | Southern sky pulsar |
| J1857+0943 | MSP | NANOGrav array member |
Contributions are welcome! Here are some areas where help is needed:
- Multi-event sweep — Automate auditing across the full GWOSC catalog (~90 events)
- Multi-detector strain — Add L1 (Livingston) and V1 (Virgo) alongside H1
- Additional PTA data — EPTA, PPTA, and IPTA integration
- Dark/Light theme toggle — User-selectable themes in the dashboard
- Progress indicator — Visual progress bar for long-running Monte Carlo computations
To contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/your-feature) - Commit your changes (
git commit -m "Add your feature") - Push to the branch (
git push origin feature/your-feature) - Open a Pull Request
This project is currently unlicensed. See choosealicense.com to select an appropriate open-source license.
This project is an experimental tool for testing the limits of astrophysical data in the context of the Simulation Hypothesis. It is not intended as a proof of simulation, but as a rigorous statistical audit of physical consistency using real observational data.
- Fixed Sliding Window tab — resolved duplicate
hovermodekeyword causing Plotly rendering failure - Fixed Sky Map tab — replaced
Scattergeo/Mollweide projection with RA/DEC scatter for Plotly compatibility - Fixed Correlations tab — converted numpy matrix to plain lists for proper heatmap text rendering
- All 8 dashboard tabs now render correctly after audit
- Sky Map tab — Mollweide projection of all pulsars color-coded by σ deviation
- Correlation Matrix tab — Pairwise Pearson correlation heatmap between pulsar residuals
- Null Distribution tab — Histogram of ensemble σ at 100 random GPS times vs observed
- Hellings-Downs tab — Angular separation vs cross-correlation with theoretical HD curve
- Bayesian Evidence Ratio — Bayes factor (log₁₀ BF) and Jeffreys' scale verdict per pulsar
- CSV/JSON export — Download results directly from the dashboard sidebar
- GitHub Actions CI — Automated smoke tests on push/PR with synthetic data
- Code refactor — Figure builders extracted to
dashboard_figures.py - 8-tab dashboard — Ensemble, Per-Pulsar, Sliding Window, Sky Map, Correlations, Null Dist, Hellings-Downs, Results
- Monte Carlo significance testing — 10,000-iteration permutation test per pulsar with p-values
- Sliding window sweep — New dashboard tab showing σ vs time-offset across the full timeline
- p-value column added to Results Table for statistical rigor
- Interactive Plotly Dash dashboard with 4 tabs (Ensemble, Per-Pulsar, Sliding Window, Results)
- Fixed missing pulsar J1857+0943 — alias mapping for NANOGrav B-name
B1857+09 - Server-side data architecture — eliminated JSON serialization bottleneck
- Auto-open browser on dashboard startup
- Initial release with CLI-based auditor
- NANOGrav 15-year data acquisition (
setup_array.py) - LIGO GWOSC strain data integration
- 9-pulsar ensemble analysis for GW150914 and GW170817
- Professional README with badges and documentation








