pg_orrery/test/expected/star_observe.out
Ryan Malloy 0544a78276 pg_orbit 0.2.0: Full solar system computation at the SQL layer
Phase 1 — Stars, comets, Keplerian propagation:
- star_observe() / star_observe_safe(): fixed star alt/az via IAU 1976
  precession, equatorial-to-horizontal transform
- kepler_propagate(): two-body Keplerian orbit propagation for
  elliptic, parabolic, and hyperbolic orbits
- comet_observe(): observe comets/asteroids from orbital elements
- heliocentric type: ecliptic J2000 position (x, y, z in AU)

Phase 2 — VSOP87 planets, ELP82B Moon, Sun:
- planet_heliocentric(): VSOP87 heliocentric ecliptic J2000 positions
  for Mercury through Neptune (Bretagnon & Francou, MIT)
- planet_observe(): full observation pipeline for any planet
- sun_observe(): Sun position from negated Earth VSOP87
- moon_observe(): ELP2000-82B lunar position (Chapront-Touzé, MIT)
- Clean-room precession (IAU 2006) and sidereal time (IERS 2010)
- elliptic_to_rectangular utility (Stellarium, MIT)

All Stellarium extractions are MIT-licensed, thread-safe (static
caching removed for PARALLEL SAFE), zero external data files.

All 9 regression tests pass (90ms total).
2026-02-16 01:36:27 -07:00

106 lines
4.5 KiB
Plaintext

-- star_observe regression tests
--
-- Tests IAU 1976 precession and equatorial-to-horizontal transform.
-- Reference time: J2000.0 (2000-01-01 12:00:00 UTC) simplifies
-- precession checks (should be identity at epoch).
-- Setup: common observer location (Boulder, CO)
\set boulder '''40.015N 105.270W 1655m'''::observer
-- ============================================================
-- Test 1: Star at J2000.0 epoch (precession should be ~identity)
-- Polaris: RA 2h 31m 49.09s = 2.530303h, Dec +89.2641 deg
-- At J2000.0 from Boulder, should be at high elevation (~49 deg)
-- because observer lat ~40N and Polaris dec ~89.26 deg
-- ============================================================
SELECT 'polaris_j2000' AS test,
round(topo_azimuth(star_observe(2.530303, 89.2641, :boulder,
'2000-01-01 12:00:00+00'))::numeric, 1) AS az_deg,
round(topo_elevation(star_observe(2.530303, 89.2641, :boulder,
'2000-01-01 12:00:00+00'))::numeric, 1) AS el_deg;
test | az_deg | el_deg
---------------+--------+--------
polaris_j2000 | 359.4 | 39.5
(1 row)
-- ============================================================
-- Test 2: Star on the celestial equator at RA=LST should transit
-- at elevation = (90 - observer_lat) from the south.
-- For Boulder (lat ~40): transit elevation ~50 deg, az ~180
-- We pick RA such that it's on the meridian at our test time.
-- ============================================================
-- Test 3: Polaris from different times (precession moves it)
-- At 2025-06-15, precession has shifted by ~0.35 deg over 25 years.
-- Elevation should change by a fraction of a degree.
SELECT 'polaris_2025' AS test,
round(topo_elevation(star_observe(2.530303, 89.2641, :boulder,
'2025-06-15 04:00:00+00'))::numeric, 1) AS el_deg;
test | el_deg
--------------+--------
polaris_2025 | 39.4
(1 row)
-- ============================================================
-- Test 4: Sirius (brightest star)
-- RA 6h 45m 08.92s = 6.752478h, Dec -16.7161 deg
-- From Boulder at 2024-01-15 03:00 UTC (evening, winter)
-- Should be visible (positive elevation)
-- ============================================================
SELECT 'sirius_winter' AS test,
round(topo_azimuth(star_observe(6.752478, -16.7161, :boulder,
'2024-01-15 03:00:00+00'))::numeric, 0) AS az_deg,
round(topo_elevation(star_observe(6.752478, -16.7161, :boulder,
'2024-01-15 03:00:00+00'))::numeric, 0) AS el_deg;
test | az_deg | el_deg
---------------+--------+--------
sirius_winter | 132 | 18
(1 row)
-- ============================================================
-- Test 5: Vega
-- RA 18h 36m 56.34s = 18.615650h, Dec +38.7837 deg
-- ============================================================
SELECT 'vega' AS test,
round(topo_elevation(star_observe(18.615650, 38.7837, :boulder,
'2024-07-15 04:00:00+00'))::numeric, 0) AS el_deg;
test | el_deg
------+--------
vega | 66
(1 row)
-- ============================================================
-- Test 6: star_observe_safe with invalid RA returns NULL
-- ============================================================
SELECT 'safe_null' AS test,
star_observe_safe(25.0, 45.0, :boulder, '2024-01-01 00:00:00+00') IS NULL AS is_null;
test | is_null
-----------+---------
safe_null | t
(1 row)
-- ============================================================
-- Test 7: Heliocentric type I/O round-trip
-- ============================================================
SELECT 'helio_io' AS test,
'(1.0000000000,0.0000000000,0.0000000000)'::heliocentric::text AS val;
test | val
----------+------------------------------------------
helio_io | (1.0000000000,0.0000000000,0.0000000000)
(1 row)
SELECT 'helio_accessors' AS test,
round(helio_x(h)::numeric, 4) AS x,
round(helio_y(h)::numeric, 4) AS y,
round(helio_z(h)::numeric, 4) AS z,
round(helio_distance(h)::numeric, 4) AS dist
FROM (SELECT '(0.3000000000,0.4000000000,0.0000000000)'::heliocentric AS h) sub;
test | x | y | z | dist
-----------------+--------+--------+--------+--------
helio_accessors | 0.3000 | 0.4000 | 0.0000 | 0.5000
(1 row)
-- ============================================================
-- Test 8: star_observe with error input
-- ============================================================
SELECT 'error_ra' AS test, star_observe(30.0, 0.0, :boulder, now());
ERROR: right ascension out of range: 30.000000
HINT: RA must be in [0, 24) hours.