High-performance Python bindings for the Outfit orbit-determination engine (Initial Orbit Determination, observation ingestion, orbital element conversions & batch processing) powered by Rust + PyO3.
pyOutfit exposes the Rust Outfit crate to Python with a thin, typed interface. It enables:
- Gauss-based Initial Orbit Determination (IOD) with configurable numerical & physical filters.
- Manipulation of multiple orbital element representations (Keplerian, Equinoctial, Cometary).
- Efficient ingest of astrometric observations (single trajectories or large batches) with zero-copy / single-conversion paths.
- Parallel batch processing for thousands of trajectories (opt-in).
- Access & registration of observatories (MPC code lookup & custom definitions).
Rust performs all heavy numerical work; Python orchestrates workflows with minimal overhead.
| Area | Highlights |
|---|---|
| IOD | Gauss method with configurable solver tolerances & physical filters |
| Elements | Keplerian / Equinoctial / Cometary conversions & wrappers |
| Observations | NumPy ingestion in radians or degrees (with automatic conversion) |
| Performance | Optional parallel batches, detached GIL region for compute-heavy steps |
| Safety | Rust error types mapped to Python RuntimeError (idiomatic try/except) |
| Extensibility | Builder pattern for IODParams & ergonomic container types |
# (Recommended) Create & activate a virtual environment first
python3.12 -m venv .venv
source .venv/bin/activate
# Install build backend (only needed for local builds)
pip install --upgrade pip maturin
# Build and install the extension in development mode
maturin developVerify the module loads:
python -c "import py_outfit; print('Classes:', [c for c in dir(py_outfit) if c[0].isupper()])"Until wheels are published on PyPI, build from source:
git clone <this-repo-url>
cd pyOutfit
pip install maturin
maturin develop # or: maturin build --release && pip install target/wheels/py_outfit-*.whlSystem requirements:
- Python 3.12 (matching the
pyproject.tomlrequirement) - Rust toolchain (β₯ 1.82)
- C toolchain (e.g.
build-essentialon Debian/Ubuntu)
Example (Debian/Ubuntu):
sudo apt update
sudo apt install -y build-essential python3.12-dev pkg-config libssl-devInstall Rust if needed: https://rustup.rs
Below: create an environment, register an observer, ingest synthetic observations, configure Gauss IOD, and estimate orbits.
pyOutfit/docs/tutorials/tutorial_snippets/quickstart_snippet.py
Lines 1 to 102 in f580716
pyOutfit/docs/tutorials/tutorial_snippets/iod_params_parallel.py
Lines 1 to 10 in f580716
pyOutfit/docs/tutorials/tutorial_snippets/trajectories_estimate_single.py
Lines 108 to 111 in f580716
| Class / Function | Purpose |
|---|---|
PyOutfit |
Global environment (ephemerides, error model, observatory catalog) |
Observer |
Observatory definition / MPC lookup handle |
IODParams / IODParams.builder() |
IOD configuration (physical filters, solver tolerances, parallelism) |
TrajectorySet |
Mapping-like container of trajectories (IDs β Observations) |
Observations |
Read-only per-trajectory access + NumPy export |
GaussResult |
Result wrapper (preliminary / corrected orbit + element extraction) |
KeplerianElements, EquinoctialElements, CometaryElements |
Different orbital element families |
- Core numerical routines run in Rust without the Python GIL (
py.detach). - Batch ingestion uses zero-copy (radian path) or a single conversion (degree path).
- Parallel processing is opt-in via
IODParams.builder().do_parallel()to avoid contention when working with small data. - Deterministic runs are achievable by passing a
seedtoTrajectorySet.estimate_all_orbits. - Error propagation: all
OutfitErrorvariants surface as PythonRuntimeErrorwith descriptive messages.
try:
env = PyOutfit("horizon:DE440", "VFCC17")
except RuntimeError as e:
print("Failed to init environment:", e)# 1. (one time) Setup
pip install maturin pytest
# 2. Rebuild after Rust changes
maturin develop
# 3. Run Python tests
pytest -q
# 4. Optional: run Rust unit tests (if added)
cargo testsrc/ # Rust sources (PyO3 classes & bindings)
py_outfit/ # Generated Python package (stub .pyi + compiled extension)
tests/ # Python tests (pytest)
Cargo.toml # Rust crate metadata
pyproject.toml # Python build config (maturin backend)
Contributions are welcome:
- Fork & create a feature branch.
- Add tests (Python or Rust) for new behavior.
- Keep public Python API backwards compatible when possible.
- Run
pytestbefore opening a PR.
Feel free to open an issue for design discussions first.
Distributed under the CeCILL-C license. See LICENSE for the full text.
Built on top of the Rust Outfit crate and the PyO3 + maturin ecosystem.
Questions, ideas, or issues? Open an issue or start a discussion β happy to help.