Astro

Library to help working with SPICE and ERFA libraries

Inner solar system with the main asteroid belt, true scaleThe nine planets, radially compressed

Real osculating orbits at a real epoch, drawn from JPL DE440 ephemerides by examples/orbits.livemd.

Rotating 3D map of the 100 nearest stellar systems, centered on Sol

The nearby-star map is generated by examples/stars.livemd from published catalog astrometry propagated through Astro.Star.

Installation

It is a bit more complicated then normal lib so pay attention:

def deps do
[
...
{:ex_astro, "~> 0.3"},
...
]
end
mix astro.kernels

Kernels

Configure kernels that should load when the application starts:

config :ex_astro,
spice_kernels: [
"priv/kernels/lsk/naif0012.tls",
"priv/kernels/pck/pck00011.tpc",
"priv/kernels/spk/planets/de440.bsp"
]

Kernels downloaded after startup can be managed at runtime:

:ok = Astro.Kernel.load("/path/to/kernel.bsp")
Astro.Kernel.loaded()
:ok = Astro.Kernel.unload("/path/to/kernel.bsp")

Missing configured files log a warning instead of preventing application startup, so they can be downloaded and loaded later. Kernel mutations are atomic against the library's single CSPICE pool and safe while other Astro calls are running.

Time API

Astro.Time represents Julian Dates as two-part tuples {jd1, jd2} rather than a single float. This follows ERFA/SOFA conventions and preserves much more precision for time-scale conversions.

iex> jd = Astro.Time.to_julian_date(~N[2000-01-01 12:00:00])
iex> jd
{2451544.5, 0.5}
iex> Astro.Time.day2sec(jd)
0.0

Ephemeris and Orbit APIs

Astro.Ephemeris provides the low-level SPICE state and conic operations. Astro.Orbit adds named osculating elements, propagation, derived quantities, anomaly calculations, and perifocal geometry:

# UTC timestamp -> SPICE ephemeris time
et = Astro.Time.to_et(~U[2026-08-14 00:00:00Z])
# osculating orbit of Earth around the Sun in the ecliptic frame
{:ok, orbit} =
Astro.Orbit.osculating("3", "10", et, frame: "ECLIPJ2000")
semi_major_axis_km = Astro.Orbit.semi_major_axis(orbit)
period_seconds = Astro.Orbit.period(orbit)

Astro.Support handles the metadata around these calls: body name/ID translation (bodn2c/1, bodc2n/1), scalar gravitational parameters (gm/1), general kernel-pool constants (bodvcd/2, bodvrd/2), and SPK file inspection (spkobj/1).

Star Catalog API

Astro.Star propagates caller-supplied Gaia, Hipparcos, and other star-catalog entries between two-part TDB Julian Date epochs. It also converts catalog coordinates to and from six-element BCRS position/velocity vectors. Catalog data is not bundled with the library.

iex> Astro.Star.starpv(ra, dec, pm_ra, pm_dec, parallax, radial_velocity)
{:ok, [x, y, z, vx, vy, vz]}

Examples

The examples/ directory contains Livebooks that explain and run the library together:

Open them in Livebook. The notebooks download their data on first run and write the SVG snapshots next to themselves.