1 unstable release
new 0.1.0-alpha.1 | Apr 12, 2025 |
---|
#700 in Math
103 downloads per month
Used in 2 crates
2MB
40K
SLoC
SciRS2 Interpolation Module
The scirs2-interpolate
crate provides a comprehensive set of interpolation methods for scientific computing in Rust. It aims to provide functionality similar to SciPy's interpolation module while leveraging Rust's performance and safety features.
Features
-
1D Interpolation
- Linear interpolation
- Nearest neighbor interpolation
- Cubic interpolation
-
Spline Interpolation
- Natural cubic splines
- Not-a-knot cubic splines
- Akima splines (robust to outliers)
-
Multi-dimensional Interpolation
- Regular grid interpolation
- Scattered data interpolation
- Map coordinates (similar to SciPy's
map_coordinates
)
-
Advanced Interpolation Methods
- Radial Basis Function (RBF) interpolation with multiple kernel types
- Kriging (Gaussian process regression) with uncertainty quantification
- Barycentric interpolation for stable polynomial fitting
-
Grid Transformation and Resampling
- Resample scattered data onto regular grids
- Convert between grids of different resolutions
- Map grid data to arbitrary points
-
Tensor Product Interpolation
- Efficient high-dimensional interpolation on structured grids
- Higher-order interpolation using Lagrange polynomials
-
Utility Functions
- Error estimation for interpolation methods
- Parameter optimization
- Differentiation of interpolated functions
- Integration of interpolated functions
Usage Examples
1D Interpolation
use ndarray::array;
use scirs2_interpolate::{Interp1d, InterpolationMethod};
// Create sample data
let x = array![0.0, 1.0, 2.0, 3.0, 4.0];
let y = array![0.0, 1.0, 4.0, 9.0, 16.0];
// Create a 1D interpolator with linear interpolation
let interp = Interp1d::new(&x.view(), &y.view(), InterpolationMethod::Linear).unwrap();
// Evaluate at a specific point
let y_interp = interp.evaluate(2.5).unwrap();
println!("Interpolated value at x=2.5: {}", y_interp);
// Evaluate at multiple points
let x_new = array![1.5, 2.5, 3.5];
let y_new = interp.evaluate_array(&x_new.view()).unwrap();
println!("Interpolated values: {:?}", y_new);
Cubic Spline Interpolation
use ndarray::array;
use scirs2_interpolate::{CubicSpline, make_interp_spline};
// Create sample data
let x = array![0.0, 1.0, 2.0, 3.0, 4.0];
let y = array![0.0, 1.0, 4.0, 9.0, 16.0];
// Create a cubic spline
let spline = make_interp_spline(&x.view(), &y.view()).unwrap();
// Evaluate at a specific point
let y_interp = spline.evaluate(2.5).unwrap();
println!("Spline interpolated value at x=2.5: {}", y_interp);
// Compute the derivative
let y_prime = spline.derivative(2.5).unwrap();
println!("Spline derivative at x=2.5: {}", y_prime);
Multidimensional Regular Grid Interpolation
use ndarray::{array, Array2};
use scirs2_interpolate::{make_interp_nd, InterpolationMethod};
// Create sample grid coordinates
let x = array![0.0, 1.0, 2.0];
let y = array![0.0, 1.0, 2.0];
// Create 2D grid values (z = x^2 + y^2)
let mut grid_values = Array2::zeros((3, 3));
for i in 0..3 {
for j in 0..3 {
grid_values[[i, j]] = x[i].powi(2) + y[j].powi(2);
}
}
// Create interpolator
let interp = make_interp_nd(
&[x, y],
&grid_values.view(),
InterpolationMethod::Linear
).unwrap();
// Points to evaluate
let points = Array2::from_shape_vec((2, 2), vec![
0.5, 0.5,
1.5, 1.5
]).unwrap();
// Interpolate
let results = interp.evaluate(&points.view()).unwrap();
println!("Interpolated values: {:?}", results);
Radial Basis Function Interpolation
use ndarray::{array, Array2};
use scirs2_interpolate::{RBFInterpolator, RBFKernel};
// Create scattered data points
let points = Array2::from_shape_vec((5, 2), vec![
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.5, 0.5
]).unwrap();
// Values at those points (z = x^2 + y^2)
let values = array![0.0, 1.0, 1.0, 2.0, 0.5];
// Create RBF interpolator with Gaussian kernel
let interp = RBFInterpolator::new(
&points.view(),
&values.view(),
RBFKernel::Gaussian,
1.0 // epsilon parameter
).unwrap();
// Interpolate at new points
let test_points = Array2::from_shape_vec((2, 2), vec![
0.25, 0.25,
0.75, 0.75
]).unwrap();
let results = interp.interpolate(&test_points.view()).unwrap();
println!("RBF interpolated values: {:?}", results);
Kriging Interpolation with Uncertainty
use ndarray::{array, Array2};
use scirs2_interpolate::{KrigingInterpolator, CovarianceFunction};
// Create scattered data points
let points = Array2::from_shape_vec((5, 2), vec![
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.5, 0.5
]).unwrap();
// Values at those points (z = x^2 + y^2)
let values = array![0.0, 1.0, 1.0, 2.0, 0.5];
// Create Kriging interpolator
let interp = KrigingInterpolator::new(
&points.view(),
&values.view(),
CovarianceFunction::SquaredExponential,
1.0, // signal variance
0.5, // length scale
1e-10, // nugget
1.0 // alpha (for RationalQuadratic)
).unwrap();
// Interpolate with uncertainty estimates
let test_points = Array2::from_shape_vec((1, 2), vec![0.25, 0.25]).unwrap();
let result = interp.predict(&test_points.view()).unwrap();
println!("Kriging prediction at (0.25, 0.25): {}", result.value[0]);
println!("Prediction uncertainty: {}", result.variance[0]);
Grid Resampling
use ndarray::{array, Array2};
use scirs2_interpolate::{resample_to_grid, GridTransformMethod};
// Create scattered data points
let points = Array2::from_shape_vec((5, 2), vec![
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
0.5, 0.5
]).unwrap();
// Values at those points (z = x^2 + y^2)
let values = array![0.0, 1.0, 1.0, 2.0, 0.5];
// Resample to a 10x10 grid
let (grid_coords, grid_values) = resample_to_grid(
&points.view(),
&values.view(),
&[10, 10],
&[(0.0, 1.0), (0.0, 1.0)],
GridTransformMethod::Linear,
0.0
).unwrap();
println!("Resampled grid size: {:?}", grid_values.shape());
Advanced Features
Akima Spline (Robust to Outliers)
use ndarray::array;
use scirs2_interpolate::{AkimaSpline, make_akima_spline};
// Data with an outlier at x=3
let x = array![0.0, 1.0, 2.0, 3.0, 4.0, 5.0];
let y = array![0.0, 1.0, 4.0, 20.0, 16.0, 25.0];
// Create Akima spline which handles outliers better than cubic spline
let spline = make_akima_spline(&x.view(), &y.view()).unwrap();
// Evaluate at some test points
for x_val in [1.5, 2.5, 3.5, 4.5].iter() {
println!("Akima spline at x={}: {}", x_val, spline.evaluate(*x_val).unwrap());
}
Tensor Product Interpolation
use ndarray::{array, Array2};
use scirs2_interpolate::{tensor_product_interpolate, InterpolationMethod};
// Create coordinates for each dimension
let x = array![0.0, 1.0, 2.0, 3.0, 4.0];
let y = array![0.0, 1.0, 2.0, 3.0];
// Create values on the grid (z = sin(x) * cos(y))
let mut values = ndarray::ArrayD::zeros(vec![5, 4]);
for i in 0..5 {
for j in 0..4 {
values[[i, j]] = (x[i]).sin() * (y[j]).cos();
}
}
// Points to interpolate
let points = Array2::from_shape_vec((2, 2), vec![
2.5, 1.5,
1.5, 2.5
]).unwrap();
// Interpolate using tensor product method
let results = tensor_product_interpolate(
&[x, y],
&values,
&points.view(),
InterpolationMethod::Linear
).unwrap();
println!("Tensor product interpolation results: {:?}", results);
Error Estimation and Differentiation
use ndarray::array;
use scirs2_interpolate::{utils, interp1d::linear_interpolate};
// Create sample data
let x = array![0.0, 1.0, 2.0, 3.0, 4.0];
let y = array![0.0, 1.0, 4.0, 9.0, 16.0];
// Estimate error of linear interpolation
let error = utils::error_estimate(&x.view(), &y.view(), linear_interpolate).unwrap();
println!("Linear interpolation error estimate: {}", error);
// Create a function that evaluates the interpolation
let eval_fn = |x_val| {
linear_interpolate(&x.view(), &y.view(), &array![x_val].view())
.map(|arr| arr[0])
};
// Compute the derivative at x=2.5
let derivative = utils::differentiate(2.5, 0.001, eval_fn).unwrap();
println!("Numerical derivative at x=2.5: {}", derivative);
// Compute the integral from x=1 to x=3
let integral = utils::integrate(1.0, 3.0, 100, eval_fn).unwrap();
println!("Numerical integral from x=1 to x=3: {}", integral);
Error Handling
The module uses the InterpolateResult
and InterpolateError
types for error handling:
pub enum InterpolateError {
/// Computation error (generic error)
ComputationError(String),
/// Domain error (input outside valid domain)
DomainError(String),
/// Value error (invalid value)
ValueError(String),
/// Not implemented error
NotImplementedError(String),
}
pub type InterpolateResult<T> = Result<T, InterpolateError>;
Performance Considerations
The module is designed with performance in mind:
- Efficient memory usage with
ndarray
- Specialized algorithms for different interpolation needs
- Carefully optimized numerical computations
- Future support for parallel processing with Rayon
License
This crate is part of the SciRS2 project and is licensed under the Apache License 2.0.
Dependencies
~73MB
~1M SLoC