Crate outfit

Crate outfit 

Source
Expand description

githubcrates-iodocs-rs


§Outfit

Outfit is a modern Rust library for orbit determination and propagation of small Solar System bodies.

It provides a memory-safe, modular, and extensible implementation of algorithms that transform raw astrometric observations into orbital solutions, and propagate them through time.

§Why Outfit?

  • Safe Rust: strong typing, memory safety, and explicit error handling.
  • Modular: interchangeable ephemerides, error models, and IOD algorithms.
  • Scientific grounding: consistent with established astronomical standards.
  • Scalable workflows: designed for survey-scale batch processing.

§Features

  • Initial Orbit Determination (IOD):
    • Classical Gauss method for three observations.
  • Orbital elements:
    • Classical Keplerian elements,
    • Equinoctial elements with conversions and two-body solver.
  • Reference frames & preprocessing:
    • Precession, nutation (IAU 1980), aberration, and light-time correction,
    • Ecliptic ↔ equatorial conversions, RA/DEC parsing, time systems.
  • Ephemerides:
    • Built-in support for JPL DE440 (NAIF/SPICE kernels and Horizons format).
  • Observation I/O:
    • MPC 80-column, ADES XML, and Parquet (batch) readers,
    • Optimized batched loading, automatic per-observer error assignments.
  • Observer management:
    • Build from MPC observatory code or custom geodetic coordinates.
  • Residuals & quality metrics:
    • RMS computation of normalized astrometric residuals, filtering utilities.
  • Examples & benches:
    • End-to-end examples in examples/, Criterion benchmarks for IOD.
  • Parallel IOD (feature parallel):
    • Batched multi-core execution via Rayon, optional global progress bar when combined with the progress feature.

§Planned extensions

  • Vaisalä method for short arcs,
  • Full support for hyperbolic trajectories,

§Workflow at a Glance

  1. Load observations (MPC/ADES/Parquet).
  2. Initialize an Outfit environment with JPL ephemerides.
  3. Form triplets and run the Gauss IOD solver.
  4. Evaluate residuals (RMS) and select the best candidate.
  5. Propagate using Keplerian dynamics or convert to equinoctial elements as needed.

§Example (MPC 80-column)

use camino::Utf8Path;
use rand::{rngs::StdRng, SeedableRng};
use outfit::{Outfit, ErrorModel, IODParams};
use outfit::constants::ObjectNumber;
use outfit::TrajectorySet;
use outfit::prelude::*; // TrajectoryExt, ObservationIOD

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut env = Outfit::new("horizon:DE440", ErrorModel::FCCT14)?;

    // Load observations (80-col MPC).
    let mut trajs = TrajectorySet::new_from_80col(
        &mut env,
        Utf8Path::new("tests/data/2015AB.obs"),
    );
    trajs.add_from_80col(&mut env, Utf8Path::new("tests/data/8467.obs"));

    // Select an object.
    let obj = ObjectNumber::String("K09R05F".into());
    let obs = trajs.get_mut(&obj).expect("object not found");

    // Configure IOD.
    let params = IODParams::builder()
        .n_noise_realizations(10)
        .noise_scale(1.1)
        .max_obs_for_triplets(obs.len())
        .max_triplets(30)
        .build()?;

    let mut rng = StdRng::seed_from_u64(42);

    // Run Gauss IOD.
    let (best_orbit, best_rms) = obs.estimate_best_orbit(
        &mut env,
        &ErrorModel::FCCT14,
        &mut rng,
        &params,
    )?;

    println!("Best orbit: {:?}", best_orbit);
    println!("RMS: {}", best_rms);
    Ok(())
}

For more end-to-end flows, see the examples/ folder (e.g. parquet_to_orbit.rs).

§Example (Parallel batched IOD)

This example requires the parallel feature (and optionally progress for a global progress bar).

use camino::Utf8Path;
use rand::{rngs::StdRng, SeedableRng};
use outfit::{Outfit, ErrorModel, IODParams};
use outfit::constants::ObjectNumber;
use outfit::TrajectorySet;
use outfit::TrajectoryFit;
use outfit::prelude::*; // TrajectoryExt, ObservationIOD

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut env = Outfit::new("horizon:DE440", ErrorModel::FCCT14)?;
     
    let test_data = "tests/data/test_from_fink.parquet";
    let path_file = Utf8Path::new(test_data);
     
    let ztf_observer = env.get_observer_from_mpc_code(&"I41".into());
    let mut traj_set = TrajectorySet::new_from_parquet(
        &mut env,
        path_file,
        ztf_observer,
        0.5,
        0.5,
        None
    )?;

    let params = IODParams::builder()
        .max_obs_for_triplets(12)
        .n_noise_realizations(10)
        .build()?;

    let mut rng = StdRng::seed_from_u64(42);
    let batch_size = 256; // tune for locality & memory

    let results = traj_set.estimate_all_orbits_in_batches_parallel(&env, &mut rng, &params, batch_size);

    for (obj, res) in results {
        match res {
            Ok((gauss, rms)) => {
                println!("{} → RMS = {rms:.4}", obj);
                println!("{gauss}");
            }
            Err(e) => eprintln!("{} → error: {e}", obj),
        }
    }

    Ok(())
}

Notes

  • Batches are processed in parallel; each batch is handled sequentially to preserve cache locality.
  • Per-object RNG seeds are deterministically derived from a single base seed.
  • Set RAYON_NUM_THREADS=N to cap threads if needed.

§Data Formats

§Cargo Features

  • jpl-download
    Automatically download JPL ephemerides (NAIF/Horizons) into a local cache.

    Cache layout (Linux):

    ~/.cache/outfit_cache/jpl_ephem/
    ├── jpl_horizon/
    │   └── DE440.bsp
    └── naif/
        └── de440.bsp

    This feature enables some integration tests and pulls reqwest, tokio, tokio-stream.

  • progress (optional)
    Enables lightweight progress bars (via indicatif) and loop timing utilities for long-running jobs.

  • parallel (optional)
    Enables multi-core IOD via Rayon, exposing TrajectorySet::estimate_all_orbits_in_batches_parallel. Combine with progress for a thread-safe global progress bar.

[dependencies]
outfit = { version = "...", features = ["jpl-download"] }
# with progress indicators
outfit = { version = "...", features = ["jpl-download", "progress"] }
# with multi-core IOD
outfit = { version = "...", features = ["parallel"] }
# combine as needed
outfit = { version = "...", features = ["jpl-download", "progress", "parallel"] }

§Error Handling

Outfit uses thiserror for descriptive error types and idiomatic Result<T, E> returns, with transparent conversions via #[from] where appropriate.

§MSRV & Platforms

  • Tested on stable Rust (see Cargo.toml and CI for the current MSRV policy).
  • Linux/macOS are primary targets; Windows is expected to work but may have different I/O performance.

§Scientific Background

  • Milani, A. & Gronchi, G. F. (2010), Theory of Orbit Determination, Cambridge University Press.
  • The open-source OrbFit software suite.

§License

Distributed under the CeCILL-C license. See LICENSE.

§Authors

Developed by FusRoman and contributors.

§Useful Modules (See also)


Re-exports§

pub use crate::outfit::Outfit;
pub use crate::constants::Observations;
pub use crate::constants::ArcSec;
pub use crate::constants::Degree;
pub use crate::constants::ObjectNumber;
pub use crate::constants::MJD;
pub use crate::observers::Observer;
pub use crate::trajectories::TrajectorySet;
pub use crate::orbit_type::cometary_element::CometaryElements;
pub use crate::orbit_type::equinoctial_element::EquinoctialElements;
pub use crate::orbit_type::keplerian_element::KeplerianElements;
pub use crate::orbit_type::OrbitalElements;
pub use crate::error_models::ErrorModel;
pub use crate::outfit_errors::OutfitError;
pub use crate::initial_orbit_determination::gauss_result::GaussResult;
pub use crate::initial_orbit_determination::IODParams;
pub use crate::observations::display::ObservationsDisplayExt;
pub use crate::observations::observations_ext::ObservationIOD;
pub use crate::trajectories::trajectory_file::TrajectoryFile;
pub use crate::trajectories::trajectory_fit::FullOrbitResult;
pub use crate::trajectories::trajectory_fit::TrajectoryFit;
pub use crate::constants::AU;
pub use crate::constants::GAUSS_GRAV;
pub use crate::constants::RADEG;
pub use crate::constants::RADH;
pub use crate::constants::RADSEC;
pub use crate::constants::SECONDS_PER_DAY;
pub use crate::constants::T2000;
pub use crate::constants::VLIGHT_AU;
pub use crate::jpl_ephem::JPLEphem;

Modules§

constants
Constants and astronomical unit conversions.
conversion
Coordinate conversions (RA/DEC, spherical ↔ cartesian, etc.).
earth_orientation
Earth orientation parameters and related corrections (nutation, precession).
env_state
Environment state: ephemerides, dynamical models, configuration.
error_models
Error models used for weighting astrometric residuals.
initial_orbit_determination
Initial Orbit Determination algorithms (Gauss method).
jpl_ephem
JPL ephemerides management (Horizon/NAIF kernels). Unified access to JPL ephemerides (legacy DE binaries and NAIF SPK/DAF).
kepler
Keplerian solver for propagation.
observations
Observation handling (RA, DEC, times).
observers
Observers and observatory positions.
orb_elem
Orbital elements utilities (conversion, normalization).
orbit_type
Orbital types and conversions between them.
outfit
Main Outfit struct: central orchestrator for orbit determination.
outfit_errors
Errors returned by Outfit operations.
prelude
Prelude with common imports for quick-start users.
ref_system
Reference frame transformations.
time
Time management and conversions (UTC, TDB, TT).
trajectories
Trajectory management and file I/O.

Type Aliases§

Result