# `Astro.Ephemeris`
[🔗](https://github.com/kipcole9/astro/blob/v2.1.0/lib/astro/ephemeris/ephemeris.ex#L1)

Computes the geocentric position of the Moon using a JPL DE440s (or
compatible) SPK binary ephemeris kernel.

The SPK file provides positions in ICRF/J2000 Cartesian coordinates (km).
This module chains the available segments to produce the Moon's position
relative to the Earth's centre, then applies IAU 1980 precession and
nutation to yield apparent geocentric RA, Dec, and distance in the true
equator and equinox of date.

## Segment chaining (DE440s)

`de440s.bsp` supplies:
  - Body 301 (Moon) relative to body 3 (Earth-Moon Barycenter, EMB)
  - Body 399 (Earth) relative to body 3 (EMB)

Moon relative to Earth = Moon/EMB − Earth/EMB.

## Setup

Load the kernel once at application startup and pass it to all calls:

    # This step is performed automatically at application start
    {:ok, kernel} = Astro.Ephemeris.Kernel.load("priv/de440s.bsp")

    {:ok, {ra, dec, dist}} = Astro.Ephemeris.moon_position(utc_dt)

## Accuracy

Position accuracy is limited by the ephemeris itself: DE440 achieves
sub-centimetre accuracy for the Moon relative to current-epoch laser
ranging data. The dominant remaining error sources for rise/set timing are:
- Atmospheric refraction model (~1 arcmin, ~2 s of time near horizon)
- Topocentric correction residuals at high solar-altitude latitudes

This represents a 10–100× improvement over the truncated Chapront series
used in Meeus that was the core of the Astro 1.x library.

# `equatorial_horizontal_parallax`

```elixir
@spec equatorial_horizontal_parallax(float()) :: float()
```

Returns the equatorial horizontal parallax for a given geocentric
distance.

Computed as `asin(R_earth / distance)` using the WGS-84
equatorial radius of 6378.137 km.

### Arguments

* `distance_km` is the geocentric distance in kilometers.

### Returns

* The equatorial horizontal parallax in degrees.

# `moon_position`
*since 2.0.0* 

```elixir
@spec moon_position(DateTime.t()) ::
  {:ok, {right_ascension :: Astro.angle(), float(), float()}} | {:error, term()}
```

Computes the apparent geocentric position of the Moon for the given
datetime.

Chains the Moon/EMB and Earth/EMB segments from the loaded JPL
ephemeris, then applies IAU 1980 precession and nutation to
produce coordinates in the true equator and equinox of date.

### Arguments

* `date_time` is a `DateTime` in any time zone (converted
  internally to a moment and then to dynamical time).

### Returns

* `{:ok, {ra_deg, dec_deg, distance_km}}` where right ascension
  is in degrees in the range [0, 360), declination is in degrees
  in the range [-90, 90], and distance is in kilometers.

* `{:error, reason}` if a required ephemeris segment is not found.

# `moon_position_dt`

```elixir
@spec moon_position_dt(float()) ::
  {:ok, {float(), float(), float()}} | {:error, term()}
```

Computes the apparent geocentric position of the Moon for the given
dynamical time.

### Arguments

* `dynamical_time` is TDB seconds past J2000.0.

### Returns

* `{:ok, {ra_deg, dec_deg, distance_km}}` where right ascension
  is in degrees in the range [0, 360), declination is in degrees
  in the range [-90, 90], and distance is in kilometers.

* `{:error, reason}` if a required ephemeris segment is not found.

# `sun_position`

```elixir
@spec sun_position(DateTime.t()) ::
  {:ok, {float(), float(), float()}} | {:error, term()}
```

Computes the apparent geocentric position of the Sun for the given
datetime.

Chains the Sun/SSB, EMB/SSB and Earth/EMB segments from the loaded
JPL ephemeris (Sun/SSB − EMB/SSB + Earth/EMB), then applies
IAU 1980 precession and nutation.

### Arguments

* `date_time` is a `DateTime` in any time zone.

### Returns

* `{:ok, {ra_deg, dec_deg, distance_km}}` where right ascension
  is in degrees in the range [0, 360), declination is in degrees
  in the range [-90, 90], and distance is in kilometers.

* `{:error, reason}` if a required ephemeris segment is not found.

# `sun_position_dt`

```elixir
@spec sun_position_dt(float()) ::
  {:ok, {float(), float(), float()}} | {:error, term()}
```

Computes the apparent geocentric position of the Sun for the given
dynamical time.

### Arguments

* `dynamical_time` is TDB seconds past J2000.0.

### Returns

* `{:ok, {ra_deg, dec_deg, distance_km}}` where right ascension
  is in degrees in the range [0, 360), declination is in degrees
  in the range [-90, 90], and distance is in kilometers.

* `{:error, reason}` if a required ephemeris segment is not found.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
