Skip to content

Functions: Stars & Comets

Functions for computing topocentric positions of stars from catalog coordinates, propagating comets and asteroids on Keplerian orbits, and observing them from Earth.


Converts a J2000 equatorial position (right ascension and declination) to topocentric coordinates for an Earth-based observer. Applies sidereal time rotation and horizon transformation. Stars are treated as being at infinite distance, so topo_range is always 0.

star_observe(ra_hours float8, dec_deg float8, obs observer, t timestamptz) → topocentric
ParameterTypeUnitDescription
ra_hoursfloat8hoursRight Ascension in J2000 equatorial frame (0-24)
dec_degfloat8degreesDeclination in J2000 equatorial frame (-90 to +90)
obsobserverObserver location on Earth
ttimestamptzObservation time

A topocentric with azimuth and elevation in degrees. topo_range is 0 (infinite distance). topo_range_rate is 0.

-- Where is Sirius (RA 6h 45m 8.9s, Dec -16d 42m 58s)?
SELECT topo_azimuth(t) AS az,
topo_elevation(t) AS el
FROM star_observe(6.7525, -16.7161, '40.0N 105.3W 1655m'::observer, now()) AS t;
-- Which bright stars are above the horizon right now?
-- (Assumes a star_catalog table with ra_hours, dec_deg, magnitude columns)
SELECT name, magnitude,
round(topo_azimuth(t)::numeric, 1) AS az,
round(topo_elevation(t)::numeric, 1) AS el
FROM star_catalog,
star_observe(ra_hours, dec_deg, '40.0N 105.3W 1655m'::observer, now()) AS t
WHERE magnitude < 2.0
AND topo_elevation(t) > 0
ORDER BY magnitude;

Identical to star_observe, but returns NULL instead of raising an exception on invalid inputs (e.g., RA outside 0-24, Dec outside -90 to +90).

star_observe_safe(ra_hours float8, dec_deg float8, obs observer, t timestamptz) → topocentric
ParameterTypeUnitDescription
ra_hoursfloat8hoursRight Ascension (0-24)
dec_degfloat8degreesDeclination (-90 to +90)
obsobserverObserver location
ttimestamptzObservation time

A topocentric, or NULL if the input coordinates are invalid.

-- Batch-process a catalog, skipping any rows with bad coordinates
SELECT catalog_id, name,
topo_azimuth(t) AS az,
topo_elevation(t) AS el
FROM star_catalog,
star_observe_safe(ra_hours, dec_deg, '40.0N 105.3W 1655m'::observer, now()) AS t
WHERE t IS NOT NULL
AND topo_elevation(t) > 10;

Propagates an object on a Keplerian orbit (two-body problem) to a given time. Returns the heliocentric ecliptic J2000 position in AU. Handles elliptic (e < 1), parabolic (e = 1), and hyperbolic (e > 1) orbits.

kepler_propagate(
q_au float8,
ecc float8,
inc_deg float8,
arg_peri_deg float8,
long_node_deg float8,
perihelion_jd float8,
t timestamptz
) → heliocentric
ParameterTypeUnitDescription
q_aufloat8AUPerihelion distance
eccfloat8Eccentricity. 0 < e < 1 for elliptic, e = 1 for parabolic, e > 1 for hyperbolic
inc_degfloat8degreesOrbital inclination
arg_peri_degfloat8degreesArgument of perihelion
long_node_degfloat8degreesLongitude of ascending node
perihelion_jdfloat8JDTime of perihelion passage as Julian Date
ttimestamptzEvaluation time

A heliocentric position in AU (ecliptic J2000 frame).

-- Propagate Comet Halley (1P/Halley)
-- q=0.586 AU, e=0.967, i=162.3, w=111.3, node=58.4, T=2446467.4 (1986 Feb 9)
SELECT helio_x(h) AS x_au,
helio_y(h) AS y_au,
helio_z(h) AS z_au,
helio_distance(h) AS r_au
FROM kepler_propagate(
0.586, -- perihelion distance
0.967, -- eccentricity
162.3, -- inclination
111.3, -- argument of perihelion
58.4, -- longitude of ascending node
2446467.4, -- perihelion Julian Date
now()
) AS h;
-- Track a near-parabolic comet over 6 months
SELECT t,
helio_distance(h) AS r_au
FROM generate_series(
'2024-01-01'::timestamptz,
'2024-07-01'::timestamptz,
interval '1 day'
) AS t,
kepler_propagate(1.01, 0.9995, 45.0, 130.0, 210.0, 2460400.5, t) AS h;

Computes the topocentric position of a comet or asteroid as seen from an Earth-based observer. This function combines Keplerian propagation with the Earth’s heliocentric position to produce observer-relative coordinates.

comet_observe(
q_au float8,
ecc float8,
inc_deg float8,
arg_peri_deg float8,
long_node_deg float8,
perihelion_jd float8,
earth_x float8,
earth_y float8,
earth_z float8,
obs observer,
t timestamptz
) → topocentric
ParameterTypeUnitDescription
q_aufloat8AUPerihelion distance
eccfloat8Eccentricity
inc_degfloat8degreesOrbital inclination
arg_peri_degfloat8degreesArgument of perihelion
long_node_degfloat8degreesLongitude of ascending node
perihelion_jdfloat8JDTime of perihelion passage as Julian Date
earth_xfloat8AUEarth’s heliocentric X (ecliptic J2000)
earth_yfloat8AUEarth’s heliocentric Y (ecliptic J2000)
earth_zfloat8AUEarth’s heliocentric Z (ecliptic J2000)
obsobserverObserver location on Earth
ttimestamptzObservation time

A topocentric with azimuth, elevation, range (km), and range rate (km/s).

-- Observe Comet Halley from Boulder
WITH earth AS (
SELECT planet_heliocentric(3, now()) AS h
)
SELECT topo_azimuth(c) AS az,
topo_elevation(c) AS el,
topo_range(c) / 149597870.7 AS dist_au
FROM earth,
comet_observe(
0.586, 0.967, 162.3, 111.3, 58.4, 2446467.4,
helio_x(earth.h), helio_y(earth.h), helio_z(earth.h),
'40.0N 105.3W 1655m'::observer,
now()
) AS c;
-- Batch-observe all comets from a catalog
WITH earth AS (
SELECT planet_heliocentric(3, now()) AS h
)
SELECT name,
round(topo_azimuth(c)::numeric, 2) AS az,
round(topo_elevation(c)::numeric, 2) AS el,
round((topo_range(c) / 149597870.7)::numeric, 4) AS dist_au
FROM comet_catalog, earth,
comet_observe(
q_au, ecc, inc_deg, arg_peri_deg, long_node_deg, perihelion_jd,
helio_x(earth.h), helio_y(earth.h), helio_z(earth.h),
'40.0N 105.3W 1655m'::observer,
now()
) AS c
WHERE topo_elevation(c) > 0
ORDER BY topo_range(c);