AstroUtils

AstroUtils is a small Elixir package for spherical geometry, vector and matrix math, circular statistics, Keplerian mechanics, and time-scale helper functions.

The library is pure computation: it performs no I/O, starts no processes, and has no runtime dependencies. It ships no ephemeris data — you supply the numbers, it does the trigonometry.

Installation

Add astro_utils to your dependencies:

def deps do
[
{:astro_utils, "~> 0.1.0"}
]
end

Modules

ModulePurpose
AstroUtils.AngleAngle normalization, conversion, angular distance, and signed deltas
AstroUtils.Vector3D vector operations on {x, y, z} tuples
AstroUtils.Matrix33x3 rotation matrices and vector multiplication
AstroUtils.CoordinatesSpherical coordinate transforms such as ecliptic longitude to altitude and azimuth
AstroUtils.KeplerKepler equation solving, true anomaly/radius conversion, and orbital-plane rotations
AstroUtils.CircularStatsCircular mean and minimal covering arc for angular samples
AstroUtils.TimeJulian-century helpers for time-dependent formulae
AstroUtils.MathSmall numeric helpers

Conventions

Examples

Angles, including the wrap-around cases that trip up naive arithmetic:

AstroUtils.Angle.normalize_360(725.0)
# => 5.0
AstroUtils.Angle.angular_distance(359.0, 1.0)
# => 2.0
AstroUtils.Angle.signed_delta(1.0, 359.0)
# => -2.0
AstroUtils.CircularStats.circular_mean([350.0, 10.0])
# => 0.0
AstroUtils.CircularStats.circular_mean([90.0, 270.0])
# => :undefined
AstroUtils.CircularStats.minimal_covering_arc([350.0, 10.0, 20.0])
# => {:arc, 30.0, 350.0}

Vectors and rotations. Rotation matrices act on vectors (an active rotation); transpose one to invert it:

alias AstroUtils.{Matrix3, Vector}
Vector.normalize({3.0, 4.0, 0.0})
# => {0.6, 0.8, 0.0}
Vector.cross({1.0, 0.0, 0.0}, {0.0, 1.0, 0.0})
# => {0.0, 0.0, 1.0}
Matrix3.rot_z(:math.pi() / 2) |> Matrix3.multiply_vector({1.0, 0.0, 0.0})
# => {6.123233995736766e-17, 1.0, 0.0}

Position a body from its orbital elements: solve Kepler's equation, convert to a true anomaly and radius, then rotate the orbital plane into the ecliptic frame.

alias AstroUtils.Kepler
a_au = 2.5
e = 0.15
mean_anomaly_rad = 0.75
eccentric = Kepler.solve_kepler(mean_anomaly_rad, e)
{true_anomaly, r} = Kepler.true_anomaly_and_radius(eccentric, e, a_au)
Kepler.orbital_to_ecliptic(
r * :math.cos(true_anomaly),
r * :math.sin(true_anomaly),
# argument of perihelion, inclination, longitude of ascending node (degrees)
60.0,
8.0,
120.0
)
# => {-1.231328244081215, -1.8698914150208263, 0.2812653910289619}

AstroUtils.Time.julian_centuries/1 produces the T argument that Meeus, IERS, and IAU polynomial series expect:

AstroUtils.Time.julian_centuries(2451545.0)
# => 0.0

Documentation

Published docs live at hexdocs.pm/astro_utils. Build them locally with mix docs.

License

MIT. See LICENSE.