Astronomy literature and public software documentation checked through 2026-07-11. A same-day retry found no remote dev branch; the default main branch was cloned at commit fc6f27c5aead33fd01a8c2f24be507b7e2b2b176. Claims below describe that documented interface, not an archived Christmas 2025 binary or an executed deployment.

Summary

‘Tis the season to stare at light curves. While most people were unwrapping presents on December 25th, I was staring at synthetic flux drop-offs and debugging a limb-darkening model. The result is a browser-based simulator for exoplanet transit photometry, including binary eclipses and exomoon scenarios. It does not detect any real exomoons. It does, however, correctly model why detecting them is comically hard.

Source: sebastianspicker/exoplanet-exomoon-simulation


Background

The gift of transits

When a planet crosses in front of its host star, the observed stellar flux drops by a fraction proportional to the ratio of their projected areas:

\[ \delta = \left(\frac{R_p}{R_\star}\right)^2 \]

For Jupiter transiting the Sun, \( \delta \approx 1\% \). For Earth, about 84 ppm. For an exomoon orbiting a Jupiter-sized planet — well, unwrap that calculation yourself:

\[ \delta_m = \left(\frac{R_m}{R_\star}\right)^2 \]

A Moon-radius exomoon around a Sun-radius star gives about 6.2 ppm in this uniform-disc calculation. Kepler was designed for about 20 ppm combined differential photometric precision over 6.5 hours for a 12th-magnitude solar-type star; actual precision depends on target brightness, variability, cadence, and data treatment. Ho ho hold on — the single-event scale is below that benchmark.

Why stars are not uniformly bright (and why that ruins everything)

A star is not a flat disk of uniform intensity. It is darker at the limb than at the centre — an effect called limb darkening — because the line of sight through the stellar atmosphere is shallower at the edges, sampling cooler, less emissive layers. The quadratic limb-darkening law is:

\[ I(\mu) = I_0 \left[1 - u_1(1 - \mu) - u_2(1 - \mu)^2\right] \]

where \( \mu = \cos\theta \) is the cosine of the angle from disk centre, and \( u_1, u_2 \) are stellar-type-dependent coefficients. This matters for transit modelling because the depth of the light curve dip changes as the planet traverses from limb to centre to limb — the transit is not a flat-bottomed box, it is a rounded trough. Fitting it incorrectly biases \( R_p / R_\star \) and, more critically for exomoon searches, generates false residuals that look suspiciously like a secondary dip.

Exomoon detection: the indirect approach

NASA still described reported objects as exomoon candidates at this review cutoff; no object had an unambiguous confirmation. Two indirect signatures are:

Transit Timing Variations (TTV). The planet–moon system orbits their common barycentre. This causes the planet’s transit to arrive slightly early or late relative to a pure Keplerian ephemeris. The timing offset scales as:

\[ \delta t \sim \frac{m_m}{m_p} \cdot \frac{a_m}{v_p} \]

where \(m_m/m_p\) is the moon-to-planet mass ratio, \(a_m\) is a characteristic planet–moon separation, and \(v_p\) is the projected planetary transit speed. This is a scaling relation: geometry, the barycentric orbit, and the definition of timing amplitude supply factors omitted here.

Transit Duration Variations (TDV). The same barycentre wobble modulates the planet’s velocity along the line of sight at transit ingress, changing transit duration. For the ideal circular, coplanar velocity component analysed by Kipping, TDV and TTV are in quadrature. Inferring moon properties still requires sufficient transits, a specified dynamical model, and control of degeneracies and other perturbers.

Neither signal is clean in practice. Stellar activity, instrument systematics, and other planets in the system all contribute correlated noise at similar timescales. The residuals of the best exomoon candidate to date — Kepler-1625b-i (Teachey & Kipping, 2018) — remain contested. Season’s readings: disputed.


The Simulation

What it actually does

The simulator is a TypeScript application (Vite build, runs in-browser) built around a deterministic, SI-unit physics core. The main pipeline:

UI parameters
  → V4 normalisation
  → runtime creation  (realtime | reference)
  → orbital integrator (Kepler + N-body)
  → geometry & photometry
  → flux decomposition
  → canvas render + plots

Two runtime modes:

  • Realtime — fast integrator, interactive rendering, good for exploration
  • Reference — deterministic in-thread supersampling, intended for more reproducible comparisons at greater computational cost

The photometry layer computes quadratic limb-darkened transit flux, handles binary eclipse geometry (for eclipsing binary configurations), and exposes hooks for phase curves and instrument noise.

The diagnostics layer is the part I find most useful: energy conservation checks across the integration, radial velocity time series, astrometry, and transit timing outputs. An energy plot can reveal some numerical drift; a flat plot is not a complete accuracy validation.

The current repository documents a versioned real-systems.snapshot.json from the NASA Exoplanet Archive, including freshness metadata. A snapshot is dated input data, not a live archive query or a guarantee that every parameter is current.

What it deliberately does not do

The relativistic corrections are approximations. This is not a GR integrator, and the importance of relativistic precession depends on mass, semimajor axis, and eccentricity; short-period systems cannot be dismissed by comparison with Mercury alone. Do not use this path for compact objects or precision dynamical inference.

The atmospheric module exposes hooks but is not a radiative-transfer solver. If you want realistic transmission spectra, point yourself at something like petitRADTRANS and use this for the orbital geometry only.


Discussion

The simulation is educational in intent — hence the built-in didactic mode (black-box exploration → hypothesis → reveal → A/B comparison → rubric scoring). The documented implementation includes quadratic limb darkening, multi-body gravitational integration, and timing diagnostics. Those features make the model more instructive; their presence does not by itself establish numerical accuracy across the parameter space.

The thing I kept running into while building this is how much of exomoon detection reduces to a residuals-hunting problem. You fit the best planet-only model you can, examine the timing and duration residuals, and look for a coherent signal. The simulator documents synthetic planet–moon scenarios and configurable noise, letting you inspect residuals — the kind of intuition-building exercise that is tedious to set up from scratch with, say, a raw BATMAN lightcurve model and a custom integrator.

Limitations worth being honest about. The performance budget is real: some effects are profile-gated to keep the interactive mode responsive, which means the reference mode exists for more expensive deterministic comparisons, not “the full physics.” For a publication-quality simulation you would want a dedicated N-body code (REBOUND is the obvious choice), not a browser runtime. This is a tool for understanding the problem, not for writing papers about it — which, fitting for a Christmas project, is exactly what I have time for right now.


References


Merry Christmas. If you came here expecting warmth and cheer, I offer instead a synthetic light curve with a 6.2 ppm exomoon signal below a 20 ppm design benchmark over 6.5 hours. Practically the same thing.


For the physical version of this — a lamp, a ball, and a smartphone measuring real transit light curves in a classroom — see Hunting Exoplanets with Your Phone. For context on where those experiments came from, see The Lab Goes Home.


Changelog

  • 2026-03-05: Corrected the description of the limb-darkening variable from “$\mu = \cos\theta$ is the angle from disk centre” to “$\mu = \cos\theta$ is the cosine of the angle from disk centre.” $\theta$ is the angle; $\mu$ is its cosine.
  • 2026-03-05: Corrected Claret (2000) page range from 1081–1090 to 1081–1190. The paper contains extensive tables of limb-darkening coefficients spanning 109 pages.
  • 2026-07-11: Recalculated the Earth- and Moon-scale transit depths, bounded the Kepler precision and TTV/TDV approximations, reconciled the software description with current main commit fc6f27c5, and removed research-grade implications. The repository cloned successfully, but dependency installation remained execution-policy blocked.