mod validate;
mod make;
mod evaluate;
mod util;
use ndarray::{
Dimension,
AsArray,
Array,
ArrayView,
ArrayView1,
};
use crate::{Real, Result};
#[derive(Debug)]
pub struct NdGridSpline<'a, T, D>
where
T: Real,
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,
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,
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,
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;
}
}