VALIDATION_CASE_STELLAR_HELIACAL_RISING - TheDaniel166/moira GitHub Wiki
Validation Case: Stellar Heliacal Rising — Sirius and the Four Royal Stars (Babylon 2025)
Subject: First morning visibility (heliacal rising) of five fixed stars
Stars: Sirius, Aldebaran, Regulus, Antares, Fomalhaut (classical Royal Stars + Sirius)
Substrate: Moira stars.heliacal_rising_event / DE441 (Sun) / ICRS J2000 + Hipparcos proper motion (star)
Oracle: astropy 7.2.0 / ERFA IAU 2006 — fully independent solar and stellar pipelines
Criterion layer: Schoch/Ptolemy arcus visionis stepped table
Status: VERIFIED — 20/20 exact across four years (2023–2026)
Verified: 2026-03-25 (baseline); 2026-04-10 (multi-year + elongation guard fix)
1. What is being tested
moira.stars.heliacal_rising_event(name, jd_start, lat, lon) predicts the first morning
on which a fixed star becomes geometrically visible above the apparent horizon at the
moment of morning twilight (Sun at −av° geometric altitude).
This is a completely separate code path from the planetary heliacal solver tested in the Mars and Venus cases. The stellar pipeline uses:
- ICRS J2000 catalog coordinates (Hipparcos) + proper motion propagation (
_propagate_icrs_vector) - Moira's own precession engine (
icrf_to_true_ecliptic→ ecliptic of date) ecliptic_to_equatorialusingtrue_obliquity- Local Apparent Sidereal Time via
apparent_sidereal_time(GAST + longitude, IAU 2006) - Geometric altitude formula (no atmospheric refraction in the body-check path)
- The solar twilight finder
_find_sun_at_alt(DE441-based); morning-sky guard (se >= 0.0skip)
The oracle exercises an entirely separate coordinate chain using only astropy/ERFA:
- Same Hipparcos ICRS J2000 catalog inputs
astropy SkyCoord.apply_space_motion()for proper motion to epoch- ERFA IAU 2006 precession/nutation via astropy's
AltAztransform pressure=0to suppress refraction (geometric altitude matching Moira's convention)get_body('sun', time, BABYLON)with ERFA full apparent solar position for twilight
The two pipelines share only the raw Hipparcos catalog coordinates.
2. Observer and epoch
- Site: Babylon — 32.55°N, 44.42°E, height 0 m
- Epoch: 2025 apparitions (modern scientific validation)
- Horizon threshold: geometric altitude −0.5667° = apparent altitude 0° (standard refraction 34′)
3. Arcus visionis assignments
From Moira's _default_arcus_for_star() (Schoch/Ptolemy stepped table):
| Star | HIP | V mag | Mag branch | av (°) |
|---|---|---|---|---|
| Sirius | 32349 | −1.46 | ≤ −1.0 | 7.5 |
| Aldebaran | 21421 | +0.86 | ≤ +1.0 | 10.0 |
| Regulus | 49669 | +1.40 | ≤ +2.0 | 11.0 |
| Antares | 80763 | +0.91 | ≤ +1.0 | 10.0 |
| Fomalhaut | 113368 | +1.16 | ≤ +2.0 | 11.0 |
4. Star catalog provenance
All five stars use SIMBAD/Hipparcos ICRS J2000 coordinates, PM, and parallax from Moira's sovereign catalog. The astropy oracle uses identical catalog inputs (same HIP RA/Dec/pm_ra_cosdec/pm_dec/parallax values), so any coordinate agreement or residual reflects the comparison between Moira's precession/nutation/GAST engine and ERFA's IAU 2006 pipeline given the same catalog source.
5. Elongation guard
Moira's heliacal_rising_event applies a morning-sky guard:
se = _heliacal_signed_elongation(name, jd_midnight + 0.5)
if se >= 0.0:
continue
se = star.longitude − sun.longitude (signed ecliptic elongation, degrees).
The se >= 0.0 check skips days when the star is in the evening sky (conjunction not yet
past, or star west of Sun). No further elongation magnitude filter is applied — the arcus
visionis altitude check (star_alt > −0.5667° at the −av° twilight) is the sole
visibility criterion.
Prior behaviour (removed 2026-04-10): An earlier version also skipped days with
abs(se) < 12.0°, a performance shortcut intended to avoid computing twilight near
conjunction. Because Regulus's arcus visionis (11°) is smaller than this fixed threshold,
the guard blocked the first valid rising day every year — a systematic +1-day offset
fully explained by the threshold, not a coordinate error. The guard was redundant with
the altitude check and has been removed from the rising solver. The setting solver retains
its own elongation logic, which is semantically distinct.
6. Validation results
Each oracle step finds the morning JD when sun_geometric_altitude = −av° (astropy
ERFA apparent Sun), then evaluates the star's geometric altitude at that JD.
First day with star altitude > −0.5667° is the oracle's heliacal rising date.
6.1 Sirius — av = 7.5°
| Date | Twilight UT | Astropy alt | Moira alt |
|---|---|---|---|
| 2025-Jul-26 | 1.622h | −7.943° | −7.949° |
| 2025-Jul-27 | 1.635h | −6.988° | −6.994° |
| 2025-Jul-28 | 1.647h | −6.035° | −6.041° |
| 2025-Jul-29 | 1.660h | −5.086° | −5.091° |
| 2025-Jul-30 | 1.672h | −4.137° | −4.143° |
| 2025-Jul-31 | 1.685h | −3.192° | −3.197° |
| 2025-Aug-01 | 1.698h | −2.249° | −2.255° |
| 2025-Aug-02 | 1.710h | −1.310° | −1.316° |
| 2025-Aug-03 | 1.723h | −0.375° | −0.381° |
| 2025-Aug-04 | 1.736h | +0.556° | +0.551° |
Oracle: 2025-Aug-03 = Moira: 2025-Aug-03 → EXACT
Altitude agreement at event JD: 0.006° (astropy vs Moira)
6.2 Aldebaran — av = 10.0°
| Date | Twilight UT | Astropy alt | Moira alt |
|---|---|---|---|
| 2025-Jun-15 | 1.049h | −3.671° | −3.675° |
| 2025-Jun-16 | 1.050h | −2.887° | −2.891° |
| 2025-Jun-17 | 1.052h | −2.097° | −2.101° |
| 2025-Jun-18 | 1.054h | −1.298° | −1.302° |
| 2025-Jun-19 | 1.056h | −0.490° | −0.494° |
| 2025-Jun-20 | 1.059h | +0.327° | +0.322° |
Oracle: 2025-Jun-19 = Moira: 2025-Jun-19 → EXACT
Altitude agreement at event JD: 0.004°
6.3 Regulus — av = 11.0°
| Date | Twilight UT | Astropy alt | Moira alt |
|---|---|---|---|
| 2025-Sep-01 | 1.792h | −2.526° | −2.531° |
| 2025-Sep-02 | 1.804h | −1.572° | −1.577° |
| 2025-Sep-03 | 1.816h | −0.508° | −0.513° |
| 2025-Sep-04 | 1.828h | +0.446° | +0.440° |
| 2025-Sep-05 | 1.840h | +1.403° | +1.397° |
Oracle: 2025-Sep-03 = Moira: 2025-Sep-03 → EXACT
Altitude agreement at event JD: 0.005° (astropy vs Moira)
Regulus's altitude on Sep-03 (−0.508°) clears the −0.5667° apparent-horizon threshold. Prior to 2026-04-10 a 12° elongation magnitude guard in the rising solver blocked this day (Sep-03 elongation −11.06° < 12°), producing a systematic +1-day offset. That guard has been removed; see §5.
6.4 Antares — av = 10.0°
| Date | Twilight UT | Astropy alt | Moira alt |
|---|---|---|---|
| 2025-Dec-12 | 3.116h | −2.929° | −2.934° |
| 2025-Dec-13 | 3.127h | −2.090° | −2.096° |
| 2025-Dec-14 | 3.138h | −1.259° | −1.264° |
| 2025-Dec-15 | 3.149h | −0.437° | −0.442° |
| 2025-Dec-16 | 3.159h | +0.377° | +0.372° |
Oracle: 2025-Dec-15 = Moira: 2025-Dec-15 → EXACT
Altitude agreement at event JD: 0.005°
6.5 Fomalhaut — av = 11.0°
| Date | Twilight UT | Astropy alt | Moira alt |
|---|---|---|---|
| 2025-Apr-15 | 1.715h | −1.586° | −1.589° |
| 2025-Apr-16 | 1.693h | −1.128° | −1.132° |
| 2025-Apr-17 | 1.671h | −0.671° | −0.674° |
| 2025-Apr-18 | 1.650h | −0.214° | −0.217° |
| 2025-Apr-19 | 1.629h | +0.242° | +0.239° |
Oracle: 2025-Apr-18 = Moira: 2025-Apr-18 → EXACT
Altitude agreement at event JD: 0.003°
7. Summary table
| Star | HIP | V mag | av | Moira | Oracle | Match |
|---|---|---|---|---|---|---|
| Sirius | 32349 | −1.46 | 7.5° | 2025-Aug-03 | 2025-Aug-03 | EXACT |
| Aldebaran | 21421 | +0.86 | 10.0° | 2025-Jun-19 | 2025-Jun-19 | EXACT |
| Regulus | 49669 | +1.40 | 11.0° | 2025-Sep-03 | 2025-Sep-03 | EXACT |
| Antares | 80763 | +0.91 | 10.0° | 2025-Dec-15 | 2025-Dec-15 | EXACT |
| Fomalhaut | 113368 | +1.16 | 11.0° | 2025-Apr-18 | 2025-Apr-18 | EXACT |
8. Oracle pipeline architecture
Catalog input (Hipparcos ICRS J2000):
ra_j2000, dec_j2000, pmra, pmdec, parallax
│
▼
astropy SkyCoord (frame='icrs', obstime=J2000.0)
→ apply_space_motion(new_obstime = twilight_JD)
→ SkyCoord at epoch of observation
│
▼ (each star)
AltAz(obstime=t, location=BABYLON, pressure=0) ← geometric altitude
→ .alt.deg
Sun twilight:
For each date, bisect Sun geometric altitude = −av°
using get_body('sun', t, BABYLON) → AltAz(pressure=0)
(ERFA/SOFA full apparent position: precession + nutation + aberration)
Convergence: 1-second (30 bisection iterations)
9. Prior oracle error: J2000 astrometric vs epoch-of-date apparent Sun
An earlier version of this validation script used JPL Horizons QUANTITIES="1" (which
returns J2000 ICRF astrometric RA/Dec — no precession, nutation, or annual aberration
applied) combined with an IAU 1982 GMST formula. This produced a systematic solar altitude
bias of approximately +0.33° at 2025 dates, caused by the ~26′ ecliptic-longitude
precession offset between J2000 and 2025.6. The resulting ~1.75-minute twilight time shift
was large enough to flip the date for rapidly-rising stars (Sirius, Aldebaran, Antares
rise at ~11°/hr near Babylon's horizon) but not for slowly-rising ones (Regulus, Fomalhaut).
The corrected oracle uses astropy.coordinates.get_body('sun'), which applies the full
apparent position pipeline (ERFA IAU 2006 precession/nutation/aberration), eliminating
this bias and producing results consistent with Moira's sky_position_at() pipeline.
10. Coordinate agreement between Moira and astropy/ERFA
At each twilight JD, the table above shows both astropy and Moira stellar altitude. The consistent 0.003°–0.007° agreement reflects the comparison of:
- Moira: ICRF J2000 →
_propagate_icrs_vectorproper motion →icrf_to_true_ecliptic(Moira precession) →ecliptic_to_equatorial(true obliquity) → IAU 2006 GAST altitude - Oracle: ICRF J2000 →
apply_space_motion→ ERFA IAU 2006 precession/nutation →AltAz
The residual (∼0.005°) is consistent with expected numerical differences between Moira's precession series and ERFA's full IAU 2006 model, and is well within any practical observational margin.
11. Validation script
tmp/stellar_heliacal_validation.py
Key parameters:
- Observer: Babylon 32.55°N 44.42°E
- Time scale: UTC (both Moira and astropy)
- Morning window searched: UT 01:00 – 06:30 per day
- Solar twilight bisection: 30 iterations, 1-second convergence
- Star coordinate epoch: J2000.0 proper motion propagated to observation date
- Atmospheric refraction: suppressed (
pressure=0) in both pipelines
12. Multi-year coverage — 2023, 2024, 2026
Validation was extended to three additional apparition years (2023, 2024, 2026) using the same astropy/ERFA oracle, same observer (Babylon), and same five stars. This provides a 4-year sample (including the 2025 baseline) per star — 20 cases total.
Script: tmp/stellar_heliacal_multiyear.py
12.1 Results
| Star | Year | av | Moira | Oracle | Match |
|---|---|---|---|---|---|
| Sirius | 2023 | 7.5° | 2023-Aug-04 | 2023-Aug-04 | EXACT |
| Sirius | 2024 | 7.5° | 2024-Aug-03 | 2024-Aug-03 | EXACT |
| Sirius | 2026 | 7.5° | 2026-Aug-04 | 2026-Aug-04 | EXACT |
| Aldebaran | 2023 | 10.0° | 2023-Jun-20 | 2023-Jun-20 | EXACT |
| Aldebaran | 2024 | 10.0° | 2024-Jun-19 | 2024-Jun-19 | EXACT |
| Aldebaran | 2026 | 10.0° | 2026-Jun-20 | 2026-Jun-20 | EXACT |
| Regulus | 2023 | 11.0° | 2023-Sep-04 | 2023-Sep-04 | EXACT |
| Regulus | 2024 | 11.0° | 2024-Sep-03 | 2024-Sep-03 | EXACT |
| Regulus | 2026 | 11.0° | 2026-Sep-04 | 2026-Sep-04 | EXACT |
| Antares | 2023 | 10.0° | 2023-Dec-16 | 2023-Dec-16 | EXACT |
| Antares | 2024 | 10.0° | 2024-Dec-15 | 2024-Dec-15 | EXACT |
| Antares | 2026 | 10.0° | 2026-Dec-16 | 2026-Dec-16 | EXACT |
| Fomalhaut | 2023 | 11.0° | 2023-Apr-18 | 2023-Apr-18 | EXACT |
| Fomalhaut | 2024 | 11.0° | 2024-Apr-17 | 2024-Apr-17 | EXACT |
| Fomalhaut | 2026 | 11.0° | 2026-Apr-18 | 2026-Apr-18 | EXACT |
15 of 15 EXACT.
12.2 Regulus — elongation guard removal
Prior to 2026-04-10, heliacal_rising_event skipped days with abs(se) < 12.0°.
Because Regulus's arcus visionis (11°) is below that threshold, the guard blocked the
first altitude-valid day every year, producing a systematic +1-day offset. After removing
the redundant guard (see §5), all four Regulus years are now exact:
| Year | Oracle | Moira (fixed) | Regulus elongation at event date |
|---|---|---|---|
| 2023 | Sep-04 | Sep-04 | ≈ −11.1° |
| 2024 | Sep-03 | Sep-03 | ≈ −11.0° |
| 2025 | Sep-03 | Sep-03 | −11.06° (measured; see §6.3) |
| 2026 | Sep-04 | Sep-04 | ≈ −11.1° |
The altitude agreement between Moira and astropy at the event twilight JD is 0.005°–0.007° in all four years — identical to before the fix, confirming the change is isolated to the elongation guard logic only.
12.3 Four-year combined summary (2023–2026)
Including the 2025 baseline from §7:
| Star | 2023 | 2024 | 2025 | 2026 | Exact / 4 |
|---|---|---|---|---|---|
| Sirius | Aug-04 ✓ | Aug-03 ✓ | Aug-03 ✓ | Aug-04 ✓ | 4 / 4 |
| Aldebaran | Jun-20 ✓ | Jun-19 ✓ | Jun-19 ✓ | Jun-20 ✓ | 4 / 4 |
| Regulus | Sep-04 ✓ | Sep-03 ✓ | Sep-03 ✓ | Sep-04 ✓ | 4 / 4 |
| Antares | Dec-16 ✓ | Dec-15 ✓ | Dec-15 ✓ | Dec-16 ✓ | 4 / 4 |
| Fomalhaut | Apr-18 ✓ | Apr-17 ✓ | Apr-18 ✓ | Apr-18 ✓ | 4 / 4 |
20 of 20 exact across four years.
All five stars match the astropy/ERFA oracle exactly across every tested year.
The Regulus offset documented in earlier sessions was caused by a redundant elongation
magnitude guard in heliacal_rising_event; that guard has been removed. See §5 and §12.2.