moira

Planetary Reduction Pipeline

Engine baseline: Moira 6.1.0 Last verified: 2026-08-13 Primary implementation: moira/planets.py, moira/corrections.py, moira/coordinates.py, moira/precession.py, and moira/obliquity.py

Governing object

The planetary reduction pipeline transforms a state read from an admitted JPL SPK kernel into a declared observer-relative position. The caller chooses the physical mode, output centre, output frame, and optional topocentric observer. Those choices are part of the result’s meaning; they are not presentation options.

The public low-level entry point is planet_at(...). Moira.planet_at(...) binds that computation to the facade’s active reader. The website-facing REST alias is POST /v1/pipeline/positions/planet.

Time and kernel binding

planet_at(...) accepts a Julian Day in UT1. The engine converts it to the reader-bound TT coordinate used to evaluate the active kernel. Historical Delta-T translation is bound to the content-identified DE/LE product rather than inferred from a filename.

The ordinary planetary path accepts admitted DE430, DE440, and DE441 readers. Coverage is determined by the loaded kernel, not by this document.

Major-body target identity

The public body name does not always imply a planet-center SPK target. Moira returns the endpoint owned by the active reader’s admitted NAIF route:

Public body DE441 route endpoint Comparison identity
Sun 10 Sun center
Moon 301 Moon center
Mercury 199 Mercury center
Venus 299 Venus center
Mars 4 Mars system barycenter
Jupiter 5 Jupiter system barycenter
Saturn 6 Saturn system barycenter
Uranus 7 Uranus system barycenter
Neptune 8 Neptune system barycenter
Pluto 9 Pluto system barycenter

External comparisons must use that exact endpoint. Comparing a Moira system barycenter with a Horizons planet center tests two different physical targets and cannot establish kernel or reduction accuracy.

Execution-context ownership

planet_at(...) remains the public validation and routing wrapper. Its internal reduction path receives one opaque workspace that binds the reader, resolved TT epoch, apparent/geometric mode, nutation policy, derived Earth state, and the workspace-owned vector cache. Injected contexts are accepted only when those provenance fields match the active call. Reader-bound reusable contexts are bounded per reader and per thread, so a result computed for one explicit TT epoch or policy cannot poison another call.

This is internal correctness hardening. No REST route, request model, response model, or final planetary-position meaning is added or removed. The five legacy underscored Python workspace hooks remain accepted for the current compatibility cycle, are validated against the opaque workspace contract, and emit DeprecationWarning when used.

Apparent geocentric sequence

With the default apparent=True, center="geocentric", and frame="ecliptic" policy, the reduction proceeds through these named stages:

  1. Geometric geocentric state — subtract the Earth barycentric state from the target barycentric state at the reception epoch.
  2. Reception light-time iteration — evaluate the target at its retarded emission epoch until the travel-time solution converges.
  3. Gravitational deflection — apply the admitted Sun, Jupiter, and Saturn point-mass deflectors.
  4. Annual aberration — use Earth’s reception-epoch barycentric velocity in the relativistic aberration transform.
  5. IAU 2006 frame bias — rotate ICRF coordinates into the dynamical mean J2000 frame.
  6. IAU 2006 precession — rotate to the mean equator of date with the P03 Fukushima-Williams construction.
  7. IAU 2000A nutation — rotate from the mean to the true equator of date when nutation=True.
  8. Topocentric parallax — when a complete observer tuple is supplied, translate the geocentric vector by the WGS-84 observer position.
  9. Topocentric diurnal aberration — for that same observer, apply the rotational observer velocity under the engine’s Earth-rotation policy.
  10. Output projection — return ecliptic longitude, latitude, and distance, or equatorial-of-date Cartesian coordinates when frame="cartesian".

planet_reduction_breakdown_at(...) exposes the named stage list, enabled flags, per-stage longitude deltas, stage longitudes, and total applied longitude delta. It is an inspectability product over the same engine functions; the REST pipeline route serializes this result rather than re-implementing astronomy in the HTTP layer.

Policy switches

Result semantics

The default result is PlanetData. Its longitude and latitude describe the selected centre, physical mode, observer policy, and ecliptic-of-date frame. frame="cartesian" returns CartesianPosition in the corresponding equatorial-of-date frame.

PlanetData.speed remains the astrometric geocentric longitude rate even when the selected output centre is barycentric. Consumers must not reinterpret that field as a derivative of every selectable output surface.

Small-body names route through their admitted asteroid or comet readers. Their installed ephemeris availability is a different fact from catalog identity or asteroid-family membership; a metadata-only manifest does not make a body position-capable.

Validation boundary

The astronomy validation report records the external-reference suites for frame construction, apparent planetary positions, wide-range vectors, and topocentric positions. The public Mars J2000 reduction trace is a versioned historical receipt, not a claim that one example validates every body, epoch, kernel, observer, or policy combination.

The current major-body Horizons contracts were refreshed on 2026-08-13:

Product Matched contract Enforced envelope Recorded maximum
Apparent geocentric Same route endpoint; reader-resolved ephemeris JD sent as discrete Horizons TLIST with TIME_TYPE=TT 0.35"; 0.1 km 0.277781" (Saturn barycenter); 0.066846 km (Mercury center)
Geometric ICRF vector Same route endpoint; same numeric ephemeris JD sent as discrete TLIST with TIME_TYPE=TDB; VEC_CORR=NONE 0.001"; 0.01 km 0.000021829" (Moon center); 0.002937 km (Mercury center)

The apparent angular result is a cross-reduction-model envelope, not a direct measure of DE441 interpolation error: Moira uses IAU 2006 precession and IAU 2000A nutation, while Horizons apparent quantity 2 uses its documented EOP-corrected IAU 1976/1980 true-equator/equinox-of-date output. The geometric suite isolates target/vector geometry; because both services receive the same numeric ephemeris JD, it does not independently validate TT-to-TDB conversion. See the Horizons manual, the Horizons API documentation, and the astronomy validation report for the full qualification.

Relevant executable surfaces include:

See also: