Astronomical algorithms in Rust

Related tags

Utilities astronomy
Overview

astro-rust

Contents

API Docs

About

astro-rust is a library of advanced astronomical algorithms for the Rust programming language.

Implemented algorithms include:

  • planetary and solar positioning by the complete set of elements of Bretagnon and Francou's VSP087 theory
  • lunar positioning by the principle elements of Chapront's ELP-2000/82 theory
  • satellite positioning for Saturn and Jupiter
  • finding Julian dates, sidereal time, dynamical time, equinoxes, rising and setting times, times of lunar phases
  • coordinate transformations
  • corrections for precession, nutation, parallax, aberration, atmospheric refraction
  • calculation of the physical ephemeris for Mars, Jupiter, and the rings of Saturn
  • finding position angles, illuminated fractions, visual magnitudes
  • and much more.

Usage

  • Add the dependency astro in your Cargo.toml

    [dependencies]
    astro = "2.0.0"
  • Include the crate astro in your code

    extern crate astro;
    
    use astro::*;
  • Specify your time of interest using the Julian day

    // for example, the time of the Apollo 11 moon landing
    
    let day_of_month = time::DayOfMonth{day      : 20,
      			 			          hr       : 20,
                                        min      : 18,
                                        sec      : 4.0,
                                        time_zone: 0.0};
    
    let date = time::Date{year       : 1969,
                          month      : 7, // July
                          decimal_day: time::decimal_day(&day_of_month),
                          cal_type   : time::CalType::Gregorian};
    
    let julian_day = time::julian_day(&date);
    
    // for higher accuracy in specifying the time of interest,
    // find the Julian Ephemeris day; this slightly differs from
    // the Julian day by ΔT, which is usually a few seconds. you
    // can get a reported value of it from the Astronomical
    // Almanac, or calculate it using the built-in function
    
    let delta_t = time::delta_t(date.year, date.month);
    
    let julian_ephm_day = time::julian_ephemeris_day(julian_day, delta_t);
  • Find the position of the Sun and the Moon with respect to the Earth

    // geocentric ecliptic point and radius vector of the Sun
    let (sun_ecl_point, rad_vec_sun) = sun::geocent_ecl_pos(julian_day);
    
    // sun_ecl_point.long    - ecliptic longitude (radians)
    // sun_ecl_point.lat     - ecliptic latitude  (radians)
    // rad_vec_sun - distance between the Sun and the Earth (AU)
    
    // and similarly for the Moon
    let (moon_ecl_point, rad_vec_moon) = lunar::geocent_ecl_pos(julian_day);
    
  • Find the position of a planet with respect to the Sun

    // the heliocentric point and radius vector of a planet, like Jupiter
    let (jup_long, jup_lat, rad_vec) = planet::heliocent_pos(&planet::Planet::Jupiter, julian_day);
    
    // or neptune
    let (nep_long, nep_lat, rad_vec) = planet::heliocent_pos(&planet::Planet::Neptune, julian_day);
    
    // positioning for all the eight planets (and (the dwarf planet) Pluto) is supported
    let (plut_long, plut_lat, rad_vec) = pluto::heliocent_pos(julian_day);
  • Find the geodesic distance between two locations on Earth

      // geodesic distance between the Observatoire de Paris and
      // the US Naval Observatory at Washington DC
    
      let paris = coords::GeographPoint{long: angle::deg_frm_dms(-2, 20, 14.0).to_radians(),
                                        lat : angle::deg_frm_dms(48, 50, 11.0).to_radians()};
    
      let washington = coords::GeographPoint{long: angle::deg_frm_dms(77,  3, 56.0).to_radians(),
                                             lat : angle::deg_frm_dms(38, 55, 17.0).to_radians()};
    
      // angle::deg_frm_dms() converts degrees expressed in degrees,
      // minutes and seconds into a fractional degree
    
      let distance = planet::earth::geodesic_dist(&paris, &washington); // in meters
  • Convert equatorial coordinates to ecliptic coordinates

      // equatorial coordinates of the star Pollux
    
      let right_ascension = 116.328942_f64.to_radians();
      let declination = 28.026183_f64.to_radians();
    
      // mean obliquity of the ecliptic
    
      let oblq_eclip = 23.4392911_f64.to_radians();
    
      // you can also get oblq_eclip from ecliptic::mn_oblq_IAU(julian_day)
      // for the Julian day on which the coordinates of the star
      // were observed
    
      // also make sure to type #[macro_use] before including the crate
      // to use macros
    
      // now, convert equatorial coordinates to ecliptic coordinates
    
      let (ecl_long, ecl_lat) = ecl_frm_eq!(right_ascension, declination, oblq_eclip);
  • Convert equatorial coordinates to galactic coordinates

      // equatorial coordinates of the Nova Serpentis 1978
    
      let right_ascension = angle::deg_frm_hms(17, 48, 59.74).to_radians();
      let declination = angle::deg_frm_dms(-14, 43, 8.2).to_radians();
    
      // convert to galactic coordinates
    
      let (gal_long, gal_lat) = gal_frm_eq!(right_ascension, declination);
  • Correct for nutation in different coordinate systems

    // nutation in ecliptic longitude and obliquity of the ecliptic
    let (nut_in_long, nut_in_oblq) = nutation::nutation(julian_day);
    
    // nutation in equatorial coordinates
    let (nut_in_asc, nut_in_dec) = nutation::nutation_in_eq_coords(julian_day);

Contributing

Anyone interested to contribute in any way possible is encouraged to do so. Not all the algorithms in Meeus's book have been implemented yet. Documentation and tests need to be written for them as well. Refactored code and minor optimizations for the existing code are also welcome.

The end goal (of this project) is to build a modern, well-tested, well-documented library of algorithms for future use in astronomy. And Rust is very much the right choice for building that.

A fun suggestion is the addition of the recent IAU 2000/2006 precession-nutation model. This method improves upon the existing model implemented here "by taking into account the effect of mantle anelasticity, ocean tides, electromagnetic couplings produced between the fluid outer core and the mantle as well as between the solid inner core and fluid outer core".

References

The main reference used as the source of algorithms is the famous book Astronomical Algorithms by Jean Meeus, whose almost every chapter has been addressed here, with functions that are well-documented and tests that use example data from the book; in some cases, such as ΔT approximation and planetary heliocentric positioning, more accurate methods have been implemented.

You might also like...
A Rust library for calculating sun positions

sun A rust port of the JS library suncalc. Install Add the following to your Cargo.toml [dependencies] sun = "0.2" Usage pub fn main() { let unixti

Macro for Python-esque comprehensions in Rust

Cute Macro for Python-esque list comprehensions in Rust. The c! macro implements list and hashmap comprehensions similar to those found in Python, all

Language Integrated Query in Rust.

Linq in Rust Language Integrated Query in Rust (created by declarative macros). Inspired by LINQ in .NET. What's LINQ This project is under developmen

A cross-platform serial port library in Rust.

Introduction serialport-rs is a general-purpose cross-platform serial port library for Rust. It provides a blocking I/O interface and port enumeration

A Rust macro for writing regex pattern matching.

regexm A Rust macro for writing regex pattern matching.

Simple ray tracer written in Rust
Simple ray tracer written in Rust

Simple ray tracer written in Rust from scratch I've just finished my first semester at the Faculty of Applied Mathematics and Computer Science at the

A high level diffing library for rust based on diffs
A high level diffing library for rust based on diffs

Similar: A Diffing Library Similar is a dependency free crate for Rust that implements different diffing algorithms and high level interfaces for it.

A reactive DOM library for Rust in WASM

maple A VDOM-less web library with fine-grained reactivity. Getting started The recommended build tool is Trunk. Start by adding maple-core to your Ca

A library to compile USDT probes into a Rust library
A library to compile USDT probes into a Rust library

sonde sonde is a library to compile USDT probes into a Rust library, and to generate a friendly Rust idiomatic API around it. Userland Statically Defi

Comments
  • Differences between astro-rust and ERFA in AltAz -> (Hour angle, Dec) conversion

    Differences between astro-rust and ERFA in AltAz -> (Hour angle, Dec) conversion

    Hi! I want to use this library, but I noticed some differences with others (notably ERFA https://github.com/liberfa/erfa). I didn't go through the differences in the mathematics, but I did do a quick comparison in python by converting both the C and rust codes: https://gist.github.com/cjordan/d0909a3ed4e726e720d99761dfa6591f

    In the rust code, it looks like a az.cos() needs to be changed to alt.cos(), as well as changing a couple of signs. I wanted to raise this as an issue in case I'm being naive here and this is working as intended. If these changes should be applied to the code, then I'm happy to give a PR to fix them.

    Also, if I require both the hour angle and declination from a AltAz pair, would it make sense to make another function to provide both? I would be using such a function in a hot loop.

    opened by cjordan 0
  • decimal_day is broken

    decimal_day is broken

    The existing code in decimal_day is incorrect. It doesn't divide minutes by minutes/day, but by minutes per hour, and seconds not by seconds/day but by seconds/minute.

    Corrected version:

    fn decimal_day(day: &astro::time::DayOfMonth) -> f64 {
        (day.day as f64)
     + (day.hr as f64) / 24.0
      + (day.min as f64) / (60.0 * 24.0)
      + day.sec / (60.0 * 60.0 * 24.0)
      - day.time_zone / 24.0
    }
    

    With this fix, the following program will print the correct Julian Ephemeris Date for UTC now.

    extern crate astro;
    extern crate chrono;
    
    use chrono::prelude::*;
    
    fn decimal_day(day: &astro::time::DayOfMonth) -> f64 {
        (day.day as f64)
      + (day.hr as f64) / 24.0
      + (day.min as f64) / (60.0 * 24.0)
      + day.sec / (60.0 * 60.0 * 24.0)
      - day.time_zone / 24.0
    }
    
    fn tm_to_date(now: DateTime<Utc>) -> astro::time::Date
    {
        let day_of_month = astro::time::DayOfMonth {
            day : now.day() as u8,
            hr  : now.hour() as u8,
            min : now.minute() as u8,
            sec : 0f64,//now.second() as f64,
            time_zone : 0.0 };
    
        astro::time::Date {
            year : now.year() as i16,
            month : now.month() as u8,
            decimal_day : decimal_day(&day_of_month),
            cal_type : astro::time::CalType::Gregorian }
    }
    
    fn now_utc() -> astro::time::Date
    {
        let utc: DateTime<Utc> = Utc::now(); 
        println!("{:?}", utc);
        tm_to_date(utc)
    }
    
    fn main() {
        let date = now_utc();
        let julian_day = astro::time::julian_day(&date);
        let delta_t = astro::time::delta_t(date.year as i32, date.month);
        let julian_ephm_day = astro::time::julian_ephemeris_day(julian_day, delta_t);
        println!("{}", julian_ephm_day);
    }
    
    opened by meshula 4
  • Use VSOP87 crate

    Use VSOP87 crate

    Hi there,

    I just found out about astro-rust, and I wanted to let you know about the VSOP87 crate. I think it could be useful, since it can be used for almost anything related to planetary positions. I have seen that you already calculate those things, but I haven gotten into depth.

    I hope you find it useful!

    opened by Razican 0
  • How to calculate sunset?

    How to calculate sunset?

    I'm trying to use this library to calculate sunset times for locations on Earth on a given date but I don't have a background in astronomy and I can't figure out how to calculate four of the values needed as input to the astro::transit::time function. Here's what I have so far:

    extern crate astro;
    extern crate chrono;
    
    use astro::coords::GeographPoint;
    use astro::time;
    use astro::transit::{self, TransitBody, TransitType};
    use chrono::{Datelike, Timelike, UTC};
    
    fn main() {
        let coords: (f64, f64) = (40.7128, -74.0059);  // GPS coords of New York City
        let now = UTC::now();
        let day_of_month = time::DayOfMonth {
            day: now.day() as u8,
            hr: now.hour() as u8,
            min: now.minute() as u8,
            sec: now.second() as f64,
            time_zone: 0.0,
        };
        let date = time::Date {
            year: now.year() as i16,                                                                                                     
            month: now.month() as u8,                                                                                                    
            decimal_day: time::decimal_day(&day_of_month),                                                                               
            cal_type: time::CalType::Gregorian,                                                                                          
        };                                                                                                                               
        let julian_day = time::julian_day(&date);                                                                                        
        let delta_t = time::delta_t(date.year as i32, date.month);                                                                       
        let julian_ephm_day = time::julian_ephemeris_day(julian_day, delta_t);                                                           
        let sunset_time = astro::transit::time(&TransitType::Set,
                                               &TransitBody::Sun,
                                               &GeographPoint {
                                                   lat: coords.0.to_radians(),
                                                   long: coords.1.to_radians(),
                                               },
                                               // How do I calculate the next four args?
                                               eq_point1,
                                               eq_point2,
                                               eq_point3,
                                               apprnt_greenwhich_sidr,
                                               // End of missing args
                                               delta_t,
                                               0f64); // moon_eq_hz_parallax not needed
        println!("{:?}", sunset_time);                                                                                                   
    }
    

    Any pointers would be greatly appreciated. Thanks!

    opened by emosenkis 2
Owner
Saurav Sachidanand
Interned at HackerRank '19, previously at GSoC '18 with CERN and '17 with Performance Co-Pilot
Saurav Sachidanand
An efficient async condition variable for lock-free algorithms

async-event An efficient async condition variable for lock-free algorithms, a.k.a. "eventcount". Overview Eventcount-like primitives are useful to mak

Asynchronics 3 Jul 10, 2023
k-mer counter in Rust using the rust-bio and rayon crates

krust is a k-mer counter written in Rust and run from the command line that will output canonical k-mers and their frequency across the records in a f

null 14 Jan 7, 2023
Experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code

Diplomat is an experimental Rust tool for generating FFI definitions allowing many other languages to call Rust code. With Diplomat, you can simply define Rust APIs to be exposed over FFI and get high-level C, C++, and JavaScript bindings automatically!

null 255 Dec 30, 2022
Aws-sdk-rust - AWS SDK for the Rust Programming Language

The AWS SDK for Rust This repo contains the new AWS SDK for Rust (the SDK) and its public roadmap. Please Note: The SDK is currently released as a dev

Amazon Web Services - Labs 2k Jan 3, 2023
Rust + Yew + Axum + Tauri, full-stack Rust development for Desktop apps.

rust-yew-axum-tauri-desktop template Rust + Yew + Axum + Tauri, full-stack Rust development for Desktop apps. Crates frontend: Yew frontend app for de

Jet Li 54 Dec 23, 2022
A lightning fast version of tmux-fingers written in Rust, copy/pasting tmux like vimium/vimperator

tmux-thumbs A lightning fast version of tmux-fingers written in Rust for copy pasting with vimium/vimperator like hints. Usage Press ( prefix + Space

Ferran Basora 598 Jan 2, 2023
A command-line tool collection to assist development written in RUST

dtool dtool is a command-line tool collection to assist development Table of Contents Description Usage Tips Installation Description Now dtool suppor

GB 314 Dec 18, 2022
Rust mid-level IR Abstract Interpreter

MIRAI MIRAI is an abstract interpreter for the Rust compiler's mid-level intermediate representation (MIR). It is intended to become a widely used sta

Facebook Experimental 793 Jan 2, 2023
Migrate C code to Rust

C2Rust helps you migrate C99-compliant code to Rust. The translator (or transpiler) produces unsafe Rust code that closely mirrors the input C code. T

Immunant 3k Jan 8, 2023
C to Rust translator

Corrode: Automatic semantics-preserving translation from C to Rust This program reads a C source file and prints an equivalent module in Rust syntax.

Jamey Sharp 2.1k Dec 14, 2022