Functions: Stars, Comets & Asteroids
Functions for computing topocentric positions of stars from catalog coordinates, propagating comets and asteroids on Keplerian orbits, and observing them from Earth. The orbital_elements type (v0.8.0) bundles Keplerian elements into a first-class PostgreSQL datum, with oe_from_mpc() for bulk-loading the MPC catalog and small_body_observe() for ergonomic topocentric observation.
star_observe
Section titled “star_observe”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.
Signature
Section titled “Signature”star_observe(ra_hours float8, dec_deg float8, obs observer, t timestamptz) → topocentricParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
ra_hours | float8 | hours | Right Ascension in J2000 equatorial frame (0-24) |
dec_deg | float8 | degrees | Declination in J2000 equatorial frame (-90 to +90) |
obs | observer | Observer location on Earth | |
t | timestamptz | Observation time |
Returns
Section titled “Returns”A topocentric with azimuth and elevation in degrees. topo_range is 0 (infinite distance). topo_range_rate is 0.
Example
Section titled “Example”-- Where is Sirius (RA 6h 45m 8.9s, Dec -16d 42m 58s)?SELECT topo_azimuth(t) AS az, topo_elevation(t) AS elFROM 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 elFROM star_catalog, star_observe(ra_hours, dec_deg, '40.0N 105.3W 1655m'::observer, now()) AS tWHERE magnitude < 2.0 AND topo_elevation(t) > 0ORDER BY magnitude;star_observe_safe
Section titled “star_observe_safe”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).
Signature
Section titled “Signature”star_observe_safe(ra_hours float8, dec_deg float8, obs observer, t timestamptz) → topocentricParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
ra_hours | float8 | hours | Right Ascension (0-24) |
dec_deg | float8 | degrees | Declination (-90 to +90) |
obs | observer | Observer location | |
t | timestamptz | Observation time |
Returns
Section titled “Returns”A topocentric, or NULL if the input coordinates are invalid.
Example
Section titled “Example”-- Batch-process a catalog, skipping any rows with bad coordinatesSELECT catalog_id, name, topo_azimuth(t) AS az, topo_elevation(t) AS elFROM star_catalog, star_observe_safe(ra_hours, dec_deg, '40.0N 105.3W 1655m'::observer, now()) AS tWHERE t IS NOT NULL AND topo_elevation(t) > 10;kepler_propagate
Section titled “kepler_propagate”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.
Signature
Section titled “Signature”kepler_propagate( q_au float8, ecc float8, inc_deg float8, arg_peri_deg float8, long_node_deg float8, perihelion_jd float8, t timestamptz) → heliocentricParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
q_au | float8 | AU | Perihelion distance |
ecc | float8 | Eccentricity. 0 < e < 1 for elliptic, e = 1 for parabolic, e > 1 for hyperbolic | |
inc_deg | float8 | degrees | Orbital inclination |
arg_peri_deg | float8 | degrees | Argument of perihelion |
long_node_deg | float8 | degrees | Longitude of ascending node |
perihelion_jd | float8 | JD | Time of perihelion passage as Julian Date |
t | timestamptz | Evaluation time |
Returns
Section titled “Returns”A heliocentric position in AU (ecliptic J2000 frame).
Example
Section titled “Example”-- 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_auFROM 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 monthsSELECT t, helio_distance(h) AS r_auFROM 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;comet_observe
Section titled “comet_observe”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.
Signature
Section titled “Signature”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) → topocentricParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
q_au | float8 | AU | Perihelion distance |
ecc | float8 | Eccentricity | |
inc_deg | float8 | degrees | Orbital inclination |
arg_peri_deg | float8 | degrees | Argument of perihelion |
long_node_deg | float8 | degrees | Longitude of ascending node |
perihelion_jd | float8 | JD | Time of perihelion passage as Julian Date |
earth_x | float8 | AU | Earth’s heliocentric X (ecliptic J2000) |
earth_y | float8 | AU | Earth’s heliocentric Y (ecliptic J2000) |
earth_z | float8 | AU | Earth’s heliocentric Z (ecliptic J2000) |
obs | observer | Observer location on Earth | |
t | timestamptz | Observation time |
Returns
Section titled “Returns”A topocentric with azimuth, elevation, range (km), and range rate (km/s).
Example
Section titled “Example”-- Observe Comet Halley from BoulderWITH 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_auFROM 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 catalogWITH 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_auFROM 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 cWHERE topo_elevation(c) > 0ORDER BY topo_range(c);oe_from_mpc
Section titled “oe_from_mpc”Parses one line of the MPC MPCORB.DAT fixed-width format into an orbital_elements type. The MPC publishes orbital elements for over 1.3 million numbered asteroids in this format.
Signature
Section titled “Signature”oe_from_mpc(line text) → orbital_elementsParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
line | text | One complete line from MPCORB.DAT (at least 103 characters) |
Returns
Section titled “Returns”An orbital_elements with all nine fields populated. The parser performs several conversions at parse time:
- Packed epoch (e.g.
K24AM) is decoded to a Julian date. The century letter (I=1800,J=1900,K=2000), two-digit year, packed month (1-9,A-C), and packed day (1-9,A-V) are expanded to a calendar date. - Perihelion distance is derived from the MPC’s semi-major axis and eccentricity: q = a × (1 − e).
- Perihelion time is computed from the epoch and mean anomaly via Gauss’s constant: tp = epoch − M / n, where n = k / a^(3/2).
Example
Section titled “Example”-- Parse Ceres, extract semi-major axis and periodWITH ceres AS ( SELECT oe_from_mpc( '00001 3.33 0.12 K24AM 60.07966 73.42937 80.26860 10.58664 0.0789126 0.21406048 2.7660961 0 MPO838504 8738 115 1801-2024 0.65 M-v 30k MPCLINUX 0000 (1) Ceres 20240825' ) AS oe)SELECT round(oe_semi_major_axis(oe)::numeric, 4) AS a_au, round(oe_period_years(oe)::numeric, 2) AS period_yr, round(oe_inclination(oe)::numeric, 3) AS inc_deg, round(oe_h_mag(oe)::numeric, 2) AS h_magFROM ceres;small_body_heliocentric
Section titled “small_body_heliocentric”Propagates an orbital_elements to a heliocentric ecliptic J2000 position at a given time using two-body Keplerian mechanics. Extracts q, e, inc, omega, Omega, and tp from the type and calls the internal Kepler solver.
Signature
Section titled “Signature”small_body_heliocentric(oe orbital_elements, t timestamptz) → heliocentricParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
oe | orbital_elements | Bundled orbital elements |
t | timestamptz | Evaluation time |
Returns
Section titled “Returns”A heliocentric position in AU (ecliptic J2000 frame). Identical to calling kepler_propagate() with the individual fields extracted from the type.
Example
Section titled “Example”-- Propagate Ceres to 2025-01-01, check heliocentric distanceWITH ceres AS ( SELECT oe_from_mpc( '00001 3.33 0.12 K24AM 60.07966 73.42937 80.26860 10.58664 0.0789126 0.21406048 2.7660961 0 MPO838504 8738 115 1801-2024 0.65 M-v 30k MPCLINUX 0000 (1) Ceres 20240825' ) AS oe)SELECT round(helio_x(h)::numeric, 4) AS x_au, round(helio_y(h)::numeric, 4) AS y_au, round(helio_z(h)::numeric, 4) AS z_au, round(helio_distance(h)::numeric, 3) AS dist_auFROM ceres, small_body_heliocentric(oe, '2025-01-01 00:00:00+00') AS h;small_body_observe
Section titled “small_body_observe”Computes the topocentric position of a comet or asteroid from its orbital_elements as seen by an Earth-based observer. Auto-fetches Earth’s heliocentric position via VSOP87, matching the ergonomics of planet_observe().
Signature
Section titled “Signature”small_body_observe(oe orbital_elements, obs observer, t timestamptz) → topocentricParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
oe | orbital_elements | Bundled orbital elements |
obs | observer | Observer location on Earth |
t | timestamptz | Observation time |
Returns
Section titled “Returns”A topocentric with azimuth, elevation (degrees), range (km), and range rate (km/s).
Example
Section titled “Example”-- Observe Ceres from BoulderWITH ceres AS ( SELECT oe_from_mpc( '00001 3.33 0.12 K24AM 60.07966 73.42937 80.26860 10.58664 0.0789126 0.21406048 2.7660961 0 MPO838504 8738 115 1801-2024 0.65 M-v 30k MPCLINUX 0000 (1) Ceres 20240825' ) AS oe)SELECT round(topo_azimuth(t)::numeric, 1) AS az, round(topo_elevation(t)::numeric, 1) AS el, round((topo_range(t) / 149597870.7)::numeric, 3) AS dist_auFROM ceres, small_body_observe(oe, '40.0N 105.3W 1655m'::observer, now()) AS t;-- Which asteroids in the catalog are above 20 degrees tonight?SELECT name, round(topo_elevation(t)::numeric, 1) AS el, round(topo_azimuth(t)::numeric, 1) AS azFROM asteroid_catalog, small_body_observe(oe, '40.0N 105.3W 1655m'::observer, now()) AS tWHERE topo_elevation(t) > 20ORDER BY topo_elevation(t) DESC;star_equatorial
Section titled “star_equatorial”Computes the apparent equatorial coordinates (RA/Dec) of a star at a given time by precessing J2000 catalog coordinates to the date of observation via IAU 1976 precession. Does not account for proper motion.
Signature
Section titled “Signature”star_equatorial(ra_hours float8, dec_deg float8, t timestamptz) → equatorialParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
ra_hours | float8 | hours | Right Ascension in J2000 (0-24) |
dec_deg | float8 | degrees | Declination in J2000 (-90 to +90) |
t | timestamptz | Evaluation time |
Returns
Section titled “Returns”An equatorial with RA (hours) and Dec (degrees) precessed to the date of observation. Distance is 0 (infinite).
Example
Section titled “Example”-- Precessed RA/Dec of Sirius at current dateSELECT round(eq_ra(e)::numeric, 6) AS ra_hours, round(eq_dec(e)::numeric, 6) AS dec_degFROM star_equatorial(6.7525, -16.7161, now()) AS e;star_observe_pm
Section titled “star_observe_pm”Computes the topocentric position of a star with full proper motion, parallax, and radial velocity corrections. The proper motion convention follows Hipparcos/Gaia: pm_ra is mu_alpha * cos(delta) in milliarcseconds per year. Cos(dec) is clamped near the poles to avoid division by zero.
Signature
Section titled “Signature”star_observe_pm( ra_hours float8, dec_deg float8, pm_ra_masyr float8, pm_dec_masyr float8, parallax_mas float8, rv_kms float8, obs observer, t timestamptz) → topocentricParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
ra_hours | float8 | hours | J2000 Right Ascension (0-24) |
dec_deg | float8 | degrees | J2000 Declination (-90 to +90) |
pm_ra_masyr | float8 | mas/yr | Proper motion in RA (mu_alpha * cos(delta), Hipparcos/Gaia convention) |
pm_dec_masyr | float8 | mas/yr | Proper motion in Declination |
parallax_mas | float8 | mas | Trigonometric parallax (0 if unknown) |
rv_kms | float8 | km/s | Radial velocity (0 if unknown) |
obs | observer | Observer location | |
t | timestamptz | Observation time |
Returns
Section titled “Returns”A topocentric with azimuth, elevation, range (km from parallax, or 0 if parallax is 0), and range rate (km/s).
Example
Section titled “Example”-- Observe Barnard's Star (large proper motion: 10.3 arcsec/yr total)-- Hipparcos: RA 17h 57m 48.5s, Dec +4d 41m 36.2s-- pm_ra = -798.58 mas/yr, pm_dec = 10328.12 mas/yr-- parallax = 548.31 mas, rv = -110.6 km/sSELECT round(topo_azimuth(t)::numeric, 2) AS az, round(topo_elevation(t)::numeric, 2) AS el, round(topo_range(t)::numeric, 0) AS dist_kmFROM star_observe_pm( 17.9635, 4.6934, -- J2000 RA/Dec -798.58, 10328.12, -- proper motion (mas/yr) 548.31, -110.6, -- parallax (mas), RV (km/s) '40.0N 105.3W 1655m'::observer, now()) AS t;star_equatorial_pm
Section titled “star_equatorial_pm”Computes the apparent equatorial coordinates of a star with proper motion, parallax, and radial velocity corrections. Returns precessed coordinates of date. Distance is derived from parallax if greater than zero.
Signature
Section titled “Signature”star_equatorial_pm( ra_hours float8, dec_deg float8, pm_ra_masyr float8, pm_dec_masyr float8, parallax_mas float8, rv_kms float8, t timestamptz) → equatorialParameters
Section titled “Parameters”| Parameter | Type | Unit | Description |
|---|---|---|---|
ra_hours | float8 | hours | J2000 Right Ascension (0-24) |
dec_deg | float8 | degrees | J2000 Declination (-90 to +90) |
pm_ra_masyr | float8 | mas/yr | Proper motion in RA (mu_alpha * cos(delta)) |
pm_dec_masyr | float8 | mas/yr | Proper motion in Declination |
parallax_mas | float8 | mas | Trigonometric parallax (0 if unknown) |
rv_kms | float8 | km/s | Radial velocity (0 if unknown) |
t | timestamptz | Evaluation time |
Returns
Section titled “Returns”An equatorial with RA (hours) and Dec (degrees) corrected for proper motion and precessed to date. Distance in km from parallax (0 if parallax is 0 or unknown).
Example
Section titled “Example”-- RA/Dec of Barnard's Star, corrected for proper motionSELECT round(eq_ra(e)::numeric, 6) AS ra_hours, round(eq_dec(e)::numeric, 6) AS dec_deg, round(eq_distance(e)::numeric, 0) AS dist_kmFROM star_equatorial_pm( 17.9635, 4.6934, -798.58, 10328.12, 548.31, -110.6, now()) AS e;-- Track the motion of Barnard's Star over 50 yearsSELECT extract(year from t) AS year, round(eq_ra(e)::numeric, 6) AS ra_h, round(eq_dec(e)::numeric, 6) AS dec_degFROM generate_series( '2000-01-01'::timestamptz, '2050-01-01'::timestamptz, interval '10 years' ) AS t, star_equatorial_pm(17.9635, 4.6934, -798.58, 10328.12, 548.31, -110.6, t) AS e;small_body_equatorial
Section titled “small_body_equatorial”Computes the geocentric apparent equatorial coordinates (RA/Dec) of a comet or asteroid from its orbital_elements. The body is propagated on a Keplerian orbit, and Earth’s position is obtained from VSOP87.
Signature
Section titled “Signature”small_body_equatorial(oe orbital_elements, t timestamptz) → equatorialParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
oe | orbital_elements | Bundled orbital elements |
t | timestamptz | Evaluation time |
Returns
Section titled “Returns”An equatorial with RA (hours), Dec (degrees), and distance (km) from Earth’s center.
Example
Section titled “Example”-- RA/Dec of CeresWITH ceres AS ( SELECT oe_from_mpc( '00001 3.33 0.12 K24AM 60.07966 73.42937 80.26860 10.58664 0.0789126 0.21406048 2.7660961 0 MPO838504 8738 115 1801-2024 0.65 M-v 30k MPCLINUX 0000 (1) Ceres 20240825' ) AS oe)SELECT round(eq_ra(e)::numeric, 4) AS ra_hours, round(eq_dec(e)::numeric, 4) AS dec_deg, round(eq_distance(e)::numeric, 0) AS dist_kmFROM ceres, small_body_equatorial(oe, now()) AS e;small_body_observe_apparent
Section titled “small_body_observe_apparent”Computes the topocentric position of a comet or asteroid with single-iteration light-time correction. The body is propagated at the retarded time (observation time minus light travel time), while Earth’s position is evaluated at the observation time via VSOP87.
Signature
Section titled “Signature”small_body_observe_apparent(oe orbital_elements, obs observer, t timestamptz) → topocentricParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
oe | orbital_elements | Bundled orbital elements |
obs | observer | Observer location on Earth |
t | timestamptz | Observation time |
Returns
Section titled “Returns”A topocentric with azimuth, elevation, range (km), and range rate (km/s), corrected for light travel time.
Example
Section titled “Example”-- Observe Ceres with light-time correction from BoulderWITH ceres AS ( SELECT oe_from_mpc( '00001 3.33 0.12 K24AM 60.07966 73.42937 80.26860 10.58664 0.0789126 0.21406048 2.7660961 0 MPO838504 8738 115 1801-2024 0.65 M-v 30k MPCLINUX 0000 (1) Ceres 20240825' ) AS oe)SELECT round(topo_azimuth(t)::numeric, 2) AS az, round(topo_elevation(t)::numeric, 2) AS el, round((topo_range(t) / 149597870.7)::numeric, 4) AS dist_auFROM ceres, small_body_observe_apparent(oe, '40.0N 105.3W 1655m'::observer, now()) AS t;small_body_equatorial_apparent
Section titled “small_body_equatorial_apparent”Computes the geocentric apparent equatorial coordinates (RA/Dec) of a comet or asteroid with light-time correction. The body is propagated at the retarded time.
Signature
Section titled “Signature”small_body_equatorial_apparent(oe orbital_elements, t timestamptz) → equatorialParameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
oe | orbital_elements | Bundled orbital elements |
t | timestamptz | Evaluation time |
Returns
Section titled “Returns”An equatorial with RA (hours), Dec (degrees), and distance (km), corrected for light travel time.
Example
Section titled “Example”-- Light-time corrected RA/Dec of CeresWITH ceres AS ( SELECT oe_from_mpc( '00001 3.33 0.12 K24AM 60.07966 73.42937 80.26860 10.58664 0.0789126 0.21406048 2.7660961 0 MPO838504 8738 115 1801-2024 0.65 M-v 30k MPCLINUX 0000 (1) Ceres 20240825' ) AS oe)SELECT round(eq_ra(e)::numeric, 4) AS ra_hours, round(eq_dec(e)::numeric, 4) AS dec_deg, round(eq_distance(e)::numeric, 0) AS dist_kmFROM ceres, small_body_equatorial_apparent(oe, now()) AS e;