Packages

Elixir ephemeris library backed by NAIF CSPICE and JPL kernels.

Current section

Files

Jump to
angelus lib angelus.ex
Raw

lib/angelus.ex

defmodule Angelus do
@moduledoc """
Geocentric tropical ephemerides backed by SPICE/JPL.
{:ok, ephemeride} = Angelus.get_ephemeride(~U[1998-01-01 00:00:00Z])
"""
@doc """
Returns the fixed 14-body geocentric tropical ephemeris for `datetime`.
The supplied instant is normalized to UTC. A `NaiveDateTime` is rejected,
because it has no offset from which UTC can be determined. Kernel loading is
managed internally; run `mix angelus.prepare` once to install runtime data.
"""
@spec get_ephemeride(DateTime.t()) :: {:ok, Angelus.Ephemeride.t()} | {:error, term()}
def get_ephemeride(%DateTime{} = datetime) do
utc = DateTime.from_unix!(DateTime.to_unix(datetime, :microsecond), :microsecond)
previous_utc = DateTime.add(utc, -86_400, :second)
with :ok <- ensure_kernels_loaded(),
{:ok, positions} <-
Angelus.Astro.get_positions(source_bodies(), utc, Angelus.Astro.Adapters.Spice),
{:ok, previous_positions} <-
Angelus.Astro.get_positions(
source_bodies(),
previous_utc,
Angelus.Astro.Adapters.Spice
) do
{:ok, Angelus.Ephemeride.from_positions(utc, positions, previous_positions)}
end
end
def get_ephemeride(_datetime), do: {:error, :datetime_must_include_offset}
defp source_bodies do
Angelus.Ephemeride.bodies()
|> List.delete(:south_node)
|> Enum.map(fn
:north_node -> :true_node
body -> body
end)
end
defp ensure_kernels_loaded do
case Angelus.Motor.load_kernels() do
{:ok, _metadata} -> :ok
{:error, :kernels_already_loaded} -> :ok
{:error, reason} -> {:error, reason}
end
end
end