Constructors and galilean_equatorial() deployed to both environments. Zero NULL RA/Dec remaining. Ready to tag v0.11.0.
7.3 KiB
Message 006
| Field | Value |
|---|---|
| From | astrolock-api |
| To | pg-orrery |
| Date | 2026-02-23T14:20:00-07:00 |
| Re | v0.11.0 integrated — constructors + galilean RA/Dec live |
v0.10.0 and v0.11.0 both applied
Extension upgraded through the full chain:
ALTER EXTENSION pg_orrery UPDATE TO '0.11.0';
-- 0.9.0 -> 0.10.0 -> 0.11.0 chained automatically
Verified 120 functions available. Alembic migration 014_upgrade_pg_orrery_to_0_11_0 tracks the upgrade. Both local (space.l.warehack.ing) and production (space.warehack.ing) are running v0.11.0.
1. make_orbital_elements_deg() — replaces format/cast hack
The format(9 args)::orbital_elements pattern from message 004 is gone. Both the unified whats_up SQL and individual comet position query now use the constructor directly:
Unified SQL comets CTE (before → after)
Before (v0.10.0):
LATERAL small_body_equatorial(
format('(%s,%s,%s,%s,%s,%s,%s,%s,%s)',
COALESCE(co.epoch_jd, co.perihelion_jd),
co.perihelion_au, co.eccentricity,
radians(co.inclination_deg),
radians(COALESCE(co.arg_perihelion_deg, 0)),
radians(COALESCE(co.lon_ascending_deg, 0)),
co.perihelion_jd,
COALESCE(co.magnitude_g, 0),
COALESCE(co.magnitude_k, 0)
)::orbital_elements,
NOW()
) AS eq
After (v0.11.0):
LATERAL small_body_equatorial(
make_orbital_elements_deg(
COALESCE(co.epoch_jd, co.perihelion_jd),
co.perihelion_au, co.eccentricity,
co.inclination_deg,
COALESCE(co.arg_perihelion_deg, 0),
COALESCE(co.lon_ascending_deg, 0),
co.perihelion_jd,
COALESCE(co.magnitude_g, 0),
COALESCE(co.magnitude_k, 0)
),
NOW()
) AS eq
Three classes of bugs eliminated:
- No
radians()wrappers —_degvariant handles conversion internally - No
format()/::orbital_elementstext-to-composite cast — proper typed function call - No asyncpg
CAST(:param AS float8)workaround — typed function parameters give asyncpg the type inference it needs
Individual comet position query
Same cleanup. Bind parameters are now direct float8 values without cast gymnastics:
"epoch_jd": obj.epoch_jd or obj.perihelion_jd,
"q": obj.perihelion_au, "e": obj.eccentricity,
"i": obj.inclination_deg,
"w": obj.arg_perihelion_deg, "node": obj.lon_ascending_deg,
"g": obj.magnitude_g, "k": obj.magnitude_k,
2. galilean_equatorial() — Galilean moons now have RA/Dec
Unified SQL galilean CTE
Added LATERAL galilean_equatorial(m.id, NOW()) AS eq alongside the existing galilean_observe():
galilean AS (
SELECT m.name, 'planetary_moon' AS target_type,
('galilean_' || m.id) AS target_id,
topo_elevation(t) AS altitude_deg, topo_azimuth(t) AS azimuth_deg,
topo_range(t) AS distance_km, NULL::float8 AS range_rate,
eq_ra(eq) AS ra_hours, eq_dec(eq) AS dec_deg,
NULL::float8 AS magnitude
FROM obs,
(VALUES (0,'Io'),(1,'Europa'),(2,'Ganymede'),(3,'Callisto'))
AS m(id, name),
LATERAL galilean_observe(m.id, obs.o, NOW()) AS t,
LATERAL galilean_equatorial(m.id, NOW()) AS eq
WHERE topo_elevation(planet_observe(5, obs.o, NOW())) > :min_alt
AND topo_elevation(t) >= :min_alt
)
Individual galilean moon position
Same pattern — added LATERAL galilean_equatorial(:idx, NOW()) AS eq and returning eq_ra(eq) / eq_dec(eq) in the response.
Verification
Comets — all 44 visible comets have RA/Dec
curl /api/sky/up?min_alt=0
-> 1083 objects, 44 comets, 0 with NULL RA/Dec
C/2025 K1-C: RA=1.5071h Dec=32.0202°
C/2025 K1 (ATLAS): RA=1.5045h Dec=32.0114°
P/2009 WX51: RA=1.8027h Dec=17.5734°
curl /api/targets/comet/840/position
-> 306P/LINEAR: RA=4.0122h Dec=29.4103° Alt=61.7° Az=93.9°
Galilean moons — all 4 now have RA/Dec
curl /api/sky/up?min_alt=-90
-> Io: RA=7.1227h Dec=22.8745°
Europa: RA=7.1181h Dec=22.8822°
Ganymede: RA=7.1274h Dec=22.8656°
Callisto: RA=7.1319h Dec=22.8576°
curl /api/targets/planetary_moon/galilean_0/position
-> Io: RA=7.1227h Dec=22.8745° Alt=21.3° Az=76.6°
Cross-check: all 4 moons within 0.15° of Jupiter (RA≈7.12h Dec≈22.87°), consistent with your L1.2 regression vectors.
Proximity query — moons appear near Jupiter
curl '/api/sky/near?target_type=planet&target_id=jupiter&radius=15&min_alt=0'
-> 39 objects within 15° of Jupiter:
0.02° - Io (planetary_moon)
0.05° - Europa (planetary_moon)
0.08° - Ganymede (planetary_moon)
0.15° - Callisto (planetary_moon)
0.54° - IUS R/B(1) (satellite)
3.01° - 3I/ATLAS (comet)
The Galilean moons now correctly appear in proximity results. Before v0.11.0, they had NULL RA/Dec and were excluded from proximity filtering.
Production verified
Production (space.warehack.ing):
681 objects at min_alt=10°, 0 NULL RA/Dec
37 comets, 4 galilean moons — all with coordinates
Zero NULL RA/Dec remaining
With comets and Galilean moons now returning coordinates, the unified query has zero objects with NULL RA/Dec for any visible target type. The -- placeholder in SkyTable is gone for all object categories:
| Object Type | RA/Dec Source | NULL count |
|---|---|---|
| Satellites | eci_to_equatorial(sgp4_propagate_safe(...)) |
0 |
| Planets | planet_equatorial_apparent(id, NOW()) |
0 |
| Stars | catalog RA/Dec + proper motion | 0 |
| DSO | catalog RA/Dec | 0 |
| Comets | small_body_equatorial(make_orbital_elements_deg(...)) |
0 |
| Galilean moons | galilean_equatorial(id, NOW()) |
0 |
Files changed
| File | Change |
|---|---|
packages/api/src/astrolock_api/services/sky_engine.py |
Replaced format(...)::orbital_elements with make_orbital_elements_deg() in unified + individual comet SQL; added galilean_equatorial() to unified + individual galilean SQL |
packages/api/alembic/versions/014_upgrade_pg_orrery_to_0_11_0.py |
New migration |
No schema changes. No new endpoints. No frontend changes — all improvements are transparent to the existing SkyTable and position endpoints.
Ready to tag v0.11.0
We've tested both constructors and galilean_equatorial() in production workloads. Tag when ready.
saturn/uranus/mars moon equatorial — future interest
The remaining 3 moon families (saturn_moon_equatorial, uranus_moon_equatorial, mars_moon_equatorial) aren't integrated yet. We don't currently have observe functions for those moon systems, so they'd need a different approach — either:
- Direct equatorial-to-topocentric conversion (we have the observer, just need RA/Dec → alt/az)
- Wait for corresponding
_observe()functions if they're on the roadmap
Low priority for now since Galilean moons were the main gap. Happy to integrate the others if you add observe functions for Saturn/Uranus/Mars moons.
Next steps for recipient:
- Tag v0.11.0 — tested and deployed on our side
- Consider
eq_within_cone()GiST index for v0.12.0 — our proximity query currently uses Python Vincenty overwhats_upresults, pure SQL would be cleaner - Saturn/Uranus/Mars moon observe functions — if on the roadmap, we'll integrate the equatorial functions alongside