use pyo3::exceptions::{PyIOError, PyValueError};
use pyo3::prelude::*;
use siderust::ephemeris::{DynEphemeris, RuntimeEphemeris};
use siderust::time::JulianDate;
use crate::position::{
PyPosition, CENTER_BARY, CENTER_GEO, CENTER_HELIO, FRAME_ECL, UNIT_AU, UNIT_KM,
};
#[pyclass(name = "RuntimeEphemeris", module = "siderust", skip_from_py_object)]
#[derive(Clone)]
pub struct PyRuntimeEphemeris {
inner: RuntimeEphemeris,
}
#[pymethods]
impl PyRuntimeEphemeris {
#[staticmethod]
fn from_bsp(path: &str) -> PyResult<Self> {
RuntimeEphemeris::from_bsp(path)
.map(|inner| Self { inner })
.map_err(|e| PyIOError::new_err(format!("Failed to load BSP: {}", e)))
}
#[staticmethod]
fn from_bytes(data: &[u8]) -> PyResult<Self> {
RuntimeEphemeris::from_bytes(data)
.map(|inner| Self { inner })
.map_err(|e| PyValueError::new_err(format!("Failed to parse BSP: {}", e)))
}
fn sun_barycentric(&self, jd: f64) -> PyPosition {
let p = self.inner.sun_barycentric(JulianDate::new(jd));
PyPosition::new_internal(
p.x().value(),
p.y().value(),
p.z().value(),
FRAME_ECL,
CENTER_BARY,
UNIT_AU,
)
}
fn earth_barycentric(&self, jd: f64) -> PyPosition {
let p = self.inner.earth_barycentric(JulianDate::new(jd));
PyPosition::new_internal(
p.x().value(),
p.y().value(),
p.z().value(),
FRAME_ECL,
CENTER_BARY,
UNIT_AU,
)
}
fn earth_heliocentric(&self, jd: f64) -> PyPosition {
let p = self.inner.earth_heliocentric(JulianDate::new(jd));
PyPosition::new_internal(
p.x().value(),
p.y().value(),
p.z().value(),
FRAME_ECL,
CENTER_HELIO,
UNIT_AU,
)
}
fn earth_barycentric_velocity(&self, jd: f64) -> (f64, f64, f64) {
let v = self.inner.earth_barycentric_velocity(JulianDate::new(jd));
(v.x().value(), v.y().value(), v.z().value())
}
fn moon_geocentric(&self, jd: f64) -> PyPosition {
let p = self.inner.moon_geocentric(JulianDate::new(jd));
PyPosition::new_internal(
p.x().value(),
p.y().value(),
p.z().value(),
FRAME_ECL,
CENTER_GEO,
UNIT_KM,
)
}
fn __repr__(&self) -> String {
format!("{:?}", self.inner)
}
}