| Crates.io | outfit |
| lib.rs | outfit |
| version | 2.1.0 |
| created_at | 2025-09-08 15:15:53.545144+00 |
| updated_at | 2025-09-18 17:15:31.642309+00 |
| description | Orbit determination toolkit in Rust. Provides astrometric parsing, observer management, and initial orbit determination (Gauss method) with JPL ephemeris support. |
| homepage | https://github.com/FusRoman/Outfit |
| repository | https://github.com/FusRoman/Outfit |
| max_upload_size | |
| id | 1829392 |
| size | 2,315,311 |
A fast, safe, and extensible Rust library for managing astrometric observations and determining preliminary orbits of small bodies. Outfit reads common observation formats (MPC 80-column, ADES XML, Parquet), performs initial orbit determination (IOD) with the Gauss method, manages observers (topocentric geometry), and interfaces with JPL ephemerides for accurate state propagation.
Why Outfit?
Modern asteroid pipelines need a library that is fast (Rust), reproducible, and easy to integrate in data-intensive workflows (batch files, Parquet, CI/benchmarks). Outfit re-implements classic OrbFit IOD logic with a memory-safe, modular design and production-grade ergonomics (features, docs, tests, benches). It is built to:
- ingest large datasets efficiently (columnar Parquet, batch APIs);
- run deterministic IOD with controlled noise and repeatable seeds;
- interface cleanly with JPL ephemerides (e.g., DE440);
- provide a clean API that composes well across projects.
parallel)Add Outfit to your Cargo.toml:
[dependencies]
outfit = "2.0.0"
Enable automatic ephemeris download (JPL DE440) with the jpl-download feature:
[dependencies]
outfit = { version = "2.0.0", features = ["jpl-download"] }
Enable a CLI-style progress bar for long loops:
[dependencies]
outfit = { version = "2.0.0", features = ["progress"] }
Combine features as needed (example):
[dependencies]
outfit = { version = "2.0.0", features = ["jpl-download", "progress", "parallel"] }
The crate ships with several ready-to-run examples in the examples/ directory.
They demonstrate end-to-end workflows such as:
TrajectorySet (now via TrajectoryFile ingestion helpers)Run an example directly with Cargo:
cargo run --release --example parquet_to_orbit --features jpl-download
This will:
Load observations from a Parquet file,
Identify the observer by MPC code,
Run the Gauss IOD pipeline,
Print the best-fit orbit with its RMS value.
MPC 80-column – Minor Planet Center fixed-width astrometry format
Parquet – Apache Parquet columnar format for large batch processing
Typical columns: ra, dec, jd or mjd, trajectory_id (configurable)
Outfit implements the Gauss method on observation triplets:
(i, j, k) with spacing/quality heuristics.Designed for robustness and speed in survey-scale use (LSST, ZTF, ...).
Compile with --features parallel and prefer the adaptive batching API for very large sets:
cargo run --release --example parquet_to_orbit --features "jpl-download,parallel"
Then call estimate_all_orbits_in_batches_parallel (same signature + extra batch_size argument) for improved throughput when trajectory sets exceed CPU cache friendliness.
Access individual solutions ergonomically:
use outfit::trajectories::trajectory_fit::{gauss_result_for, take_gauss_result};
// Borrow without moving:
if let Some(Ok((g, rms))) = gauss_result_for(&results, &some_object) {
println!("Semi-major axis: {} AU (rms={rms:.3})", g.keplerian.a);
}
Errors are explicit (no Option inside Result); pathological numeric scores (NaN, inf) surface as OutfitError::NonFiniteScore.
The crate keeps the feature surface intentionally small and orthogonal. All core parsing (MPC 80-col, ADES XML, Parquet) and Gauss IOD logic are always compiled; features only toggle optional runtime dependencies.
| Feature | Adds | Notes |
|---|---|---|
jpl-download |
reqwest, tokio (multi-thread RT), on-demand fetch |
Downloads and caches JPL ephemerides (e.g. DE440) in the user data dir on first access. Offline re-use afterward. |
progress |
indicatif progress bars + moving average timing |
Enabled in long batch IOD loops; zero cost when not used. |
parallel |
rayon |
Enables TrajectoryFit::estimate_all_orbits_in_batches_parallel; set IODParams.batch_size to tune batch granularity. |
Planned (not yet implemented): least-squares refinement and alternative IOD methods will likely get their own feature gates.
Tips
--release for production.jpl-download enabled) to avoid I/O stalls.progress feature to instrument long loops without cluttering core logic.ObservationBatch conversions (deg/arcsec → rad) happen once; avoid re-normalizing angles inside tight loops.OutfitError::NonFiniteScore to prevent propagating invalid states.IODParams.batch_size (with parallel) so each batch fits comfortably in cache (start with 4–8 and benchmark).See the issue tracker for the latest details and discussion.
Contributions are welcome!
Please open an issue to discuss substantial changes. For PRs, please:
cargo fmt and cargo clippy pass (-D warnings recommended)A typical dev loop:
cargo fmt --all
cargo clippy --all-targets --all-features
cargo test --all-features
cargo bench --features jpl-download
This project is licensed under the CeCILL-C Free Software License Agreement. See the LICENSE file.