mod evaluate;
mod make;
mod util;
mod validate;
use ndarray::{Array, ArrayView, ArrayView1, AsArray, Dimension};
use crate::{Real, RealRef, Result};
#[derive(Debug)]
pub struct NdGridSpline<'a, T, D>
where
T: Real<T>,
D: Dimension,
{
ndim: usize,
order: Vec<usize>,
pieces: Vec<usize>,
breaks: Vec<ArrayView1<'a, T>>,
coeffs: Array<T, D>,
}
impl<'a, T, D> NdGridSpline<'a, T, D>
where
T: Real<T>,
D: Dimension,
{
pub fn new(breaks: Vec<ArrayView1<'a, T>>, coeffs: Array<T, D>) -> Self {
let ndim = breaks.len();
let pieces: Vec<usize> = breaks.iter().map(|x| x.len() - 1).collect();
let order: Vec<usize> = pieces
.iter()
.zip(coeffs.shape().iter())
.map(|(p, s)| s / p)
.collect();
NdGridSpline {
ndim,
order,
pieces,
breaks,
coeffs,
}
}
pub fn ndim(&self) -> usize {
self.ndim
}
pub fn order(&self) -> &Vec<usize> {
&self.order
}
pub fn pieces(&self) -> &Vec<usize> {
&self.pieces
}
pub fn breaks(&self) -> &Vec<ArrayView1<'a, T>> {
&self.breaks
}
pub fn coeffs(&self) -> ArrayView<'_, T, D> {
self.coeffs.view()
}
pub fn evaluate(&self, xi: &'a [ArrayView1<'a, T>]) -> Array<T, D> {
self.evaluate_spline(xi)
}
}
pub struct GridCubicSmoothingSpline<'a, T, D>
where
T: Real<T>,
D: Dimension,
{
x: Vec<ArrayView1<'a, T>>,
y: ArrayView<'a, T, D>,
weights: Vec<Option<ArrayView1<'a, T>>>,
smooth: Vec<Option<T>>,
spline: Option<NdGridSpline<'a, T, D>>,
}
impl<'a, T, D> GridCubicSmoothingSpline<'a, T, D>
where
T: Real<T>,
for<'r> &'r T: RealRef<&'r T, T>,
D: Dimension,
{
pub fn new<Y>(x: &[ArrayView1<'a, T>], y: Y) -> Self
where
Y: AsArray<'a, T, D>,
{
let ndim = x.len();
GridCubicSmoothingSpline {
x: x.to_vec(),
y: y.into(),
weights: vec![None; ndim],
smooth: vec![None; ndim],
spline: None,
}
}
pub fn with_weights(mut self, weights: &[Option<ArrayView1<'a, T>>]) -> Self {
self.invalidate();
self.weights = weights.to_vec();
self
}
pub fn with_smooth(mut self, smooth: &[Option<T>]) -> Self {
self.invalidate();
self.smooth = smooth.to_vec();
self
}
pub fn with_smooth_fill(mut self, smooth: T) -> Self {
self.invalidate();
self.smooth = vec![Some(smooth); self.x.len()];
self
}
pub fn make(mut self) -> Result<Self> {
self.invalidate();
self.make_validate()?;
self.make_spline()?;
Ok(self)
}
pub fn evaluate(&self, xi: &[ArrayView1<'a, T>]) -> Result<Array<T, D>> {
self.evaluate_validate(xi)?;
let yi = self.evaluate_spline(xi);
Ok(yi)
}
pub fn smooth(&self) -> &Vec<Option<T>> {
&self.smooth
}
pub fn spline(&self) -> Option<&NdGridSpline<'a, T, D>> {
self.spline.as_ref()
}
fn invalidate(&mut self) {
self.spline = None;
}
}