use lox_math::series::InterpolationType;
use pyo3::exceptions::PyValueError;
use pyo3::types::PyType;
use pyo3::{Bound, PyResult, pyclass, pymethods};
use crate::math::python::{PySeriesError, PyUnknownInterpolationType};
use crate::time::python::time::PyTime;
use crate::time::series::TimeSeries;
use crate::time::time_scales::DynTimeScale;
#[pyclass(name = "TimeSeries", module = "lox_space", frozen, from_py_object)]
#[derive(Clone, Debug)]
pub struct PyTimeSeries(pub TimeSeries<DynTimeScale>);
#[pymethods]
impl PyTimeSeries {
#[new]
#[pyo3(signature = (times, values, interpolation="linear"))]
fn new(times: Vec<PyTime>, values: Vec<f64>, interpolation: &str) -> PyResult<Self> {
if times.is_empty() {
return Err(PyValueError::new_err("times must not be empty"));
}
let interpolation: InterpolationType =
interpolation.parse().map_err(PyUnknownInterpolationType)?;
let epoch = times[0].0;
let x: Vec<f64> = times
.iter()
.map(|t| (t.0 - epoch).to_seconds().to_f64())
.collect();
let ts = TimeSeries::try_new(epoch, x, values, interpolation).map_err(PySeriesError)?;
Ok(PyTimeSeries(ts))
}
#[classmethod]
#[pyo3(signature = (epoch, x, y, interpolation="linear"))]
fn from_offsets(
_cls: &Bound<'_, PyType>,
epoch: PyTime,
x: Vec<f64>,
y: Vec<f64>,
interpolation: &str,
) -> PyResult<Self> {
let interpolation: InterpolationType =
interpolation.parse().map_err(PyUnknownInterpolationType)?;
let ts = TimeSeries::try_new(epoch.0, x, y, interpolation).map_err(PySeriesError)?;
Ok(PyTimeSeries(ts))
}
fn interpolate(&self, time: PyTime) -> f64 {
self.0.interpolate(time.0)
}
#[getter]
fn epoch(&self) -> PyTime {
PyTime(self.0.epoch())
}
fn times(&self) -> Vec<PyTime> {
self.0.times().into_iter().map(PyTime).collect()
}
fn values(&self) -> Vec<f64> {
self.0.values().to_vec()
}
fn first(&self) -> (PyTime, f64) {
let (t, v) = self.0.first();
(PyTime(t), v)
}
fn last(&self) -> (PyTime, f64) {
let (t, v) = self.0.last();
(PyTime(t), v)
}
fn __repr__(&self) -> String {
let x = self.0.series().x();
let n = x.len();
format!(
"TimeSeries(epoch={}, [{}, ..., {}], {n} points)",
self.0.epoch(),
x[0],
x[n - 1],
)
}
}