pub struct GriddedData<const N: usize> { /* private fields */ }Expand description
This struct contains the N-dimensional grid data and provides interpolation methods which work on this data.
§Features
This struct can be serialized / deserialized if the serde feature is enabled.
See the docstring of the serde_impl module.
Implementations§
Source§impl<const N: usize> GriddedData<N>
impl<const N: usize> GriddedData<N>
Sourcepub fn new(axes: [Vec<f64>; N], data: Vec<f64>) -> Result<Self, Error>
pub fn new(axes: [Vec<f64>; N], data: Vec<f64>) -> Result<Self, Error>
Creates a new n-dimensional GriddedData with the number of dimensions defined by the input.
If the arguments are valid, this function creates a new instance of GriddedData with the number
of dimension equal to the length of axes. The given arguments must fulfil the following criteria:
- Each vector in the
axesarray must be strictly monotonic increasing - Each vector in the
axesmust have at least two values (if it doesn’t, the corresponding dimension collapses anyway and the vector can be omitted entirely). - The number of datapoints (
data.len()) must be equal to the product of the lengths of the axis vectors withinaxes.
The data must be given in row-major fashion (index of last dimension changes fastest). Some examples:
-
The 2D-matrix
1.0 3.0 5.0 2.0 4.0 6.0is represented by
data = [1.0, 3.0, 5.0, 2.0, 4.0, 6.0](first dimension is the row number, second one the column number). -
The 3D-matrix (| denotes a page / 3rd dimension separator)
1.0 3.0 5.0 | 7.0 9.0 11.0 2.0 4.0 6.0 | 8.0 10.0 12.0is represented by
data = [1.0, 7.0, 3.0, 9.0, 5.0, 11.0, 2.0, 8.0, 4.0, 10.0, 6.0, 12.0](first dimension is the row number, second one the column number, third one the page number).
§Examples
use gridded_data::GriddedData;
/*
2 x 3 x 3 matrix
z = 1.0 z = 2.0
y 3 4 6 3 4 6
x ------- -------
0 | 0 3 5 7 9 11
1 | 2 4 6 8 10 12
*/
let data = vec![1.0, 7.0, 3.0, 9.0, 5.0, 11.0, 2.0, 8.0, 4.0, 10.0, 6.0, 12.0];
let x = vec![0.0, 1.0];
let y = vec![3.0, 4.0, 6.0]; // Spacing does not need to be uniform!
let z = vec![1.0, 2.0];
assert!(GriddedData::new([x, y, z], data).is_ok());If the data is available in matrix form, consider using the
CartesianIndices
iterator from the cart_lin
library (which is a dependency of this library):
use cart_lin::CartesianIndices;
use gridded_data::GriddedData;
// 2 x 2 matrix
// 1.0 3.0
// 2.0 4.0
let matrix = [[1.0, 3.0], [2.0, 4.0]];
let mut data = Vec::with_capacity(4);
for idx in CartesianIndices::new([2, 2]) {
data.push(matrix[idx[0]][idx[1]]);
}
let x = vec![0.0, 1.0];
let y = vec![1.0, 2.0];
assert_eq!(data, vec![1.0, 3.0, 2.0, 4.0]);
assert!(GriddedData::new([x, y], data).is_ok());As an alternative for two-dimensional data, consider using GriddedData::from_slice_of_slices.
Sourcepub fn get_cart(&self, indices: &[usize; N]) -> Option<&f64>
pub fn get_cart(&self, indices: &[usize; N]) -> Option<&f64>
Access the raw underlying data via cartesian indices.
This function uses cart_to_lin from the cart_lin crate to convert the given cartesian
indices into a linear index and use that to access GriddedData::data. If the given cartesian index would
result in an out-of bounds access, None is returned instead.
Sourcepub fn get_cart_mut(&mut self, indices: &[usize; N]) -> Option<&mut f64>
pub fn get_cart_mut(&mut self, indices: &[usize; N]) -> Option<&mut f64>
Access the raw underlying data mutably via cartesian indices.
This function uses cart_to_lin from the cart_lin crate to convert the given cartesian
indices into a linear index and use that to access GriddedData::data_mut. If the given cartesian index would
result in an out-of bounds access, None is returned instead.
Sourcepub unsafe fn get_cart_unchecked(&self, indices: &[usize; N]) -> &f64
pub unsafe fn get_cart_unchecked(&self, indices: &[usize; N]) -> &f64
Like GriddedData::get_cart, but does not perform any bound checking and is therefore unsafe.
Sourcepub unsafe fn get_cart_unchecked_mut(
&mut self,
indices: &[usize; N],
) -> &mut f64
pub unsafe fn get_cart_unchecked_mut( &mut self, indices: &[usize; N], ) -> &mut f64
Like GriddedData::get_cart_mut, but does not perform any bound checking and is therefore unsafe.
Sourcepub fn get_lin(&self, index: usize) -> Option<&f64>
pub fn get_lin(&self, index: usize) -> Option<&f64>
Access the raw underlying data via a linear index.
This is a convenience wrapper around self.data().get().
Sourcepub fn get_lin_mut(&mut self, index: usize) -> Option<&mut f64>
pub fn get_lin_mut(&mut self, index: usize) -> Option<&mut f64>
Access the raw underlying data mutably via a linear index.
This is a convenience wrapper around self.get_mut().get().
Sourcepub unsafe fn get_lin_unchecked(&self, index: usize) -> &f64
pub unsafe fn get_lin_unchecked(&self, index: usize) -> &f64
Like GriddedData::get_lin, but does not perform bounds checking and is therefore unsafe.
Sourcepub unsafe fn get_lin_unchecked_mut(&mut self, index: usize) -> &mut f64
pub unsafe fn get_lin_unchecked_mut(&mut self, index: usize) -> &mut f64
Like GriddedData::get_lin_mut, but does not perform bounds checking and is therefore unsafe.
Sourcepub fn axes_values_cart(&self, indices: &[usize; N]) -> Option<[f64; N]>
pub fn axes_values_cart(&self, indices: &[usize; N]) -> Option<[f64; N]>
Returns the axes values which correspond to the given cartesian index.
use gridded_data::GriddedData;
let grid = GriddedData::new([vec![0.0, 1.0], vec![1.0, 2.0]], vec![1.0, 3.0, 2.0, 4.0]).expect("valid inputs");
assert_eq!(grid.axes_values_cart(&[1, 0]).expect("valid index"), [1.0, 1.0]);Sourcepub unsafe fn axes_values_cart_unchecked(
&self,
indices: &[usize; N],
) -> [f64; N]
pub unsafe fn axes_values_cart_unchecked( &self, indices: &[usize; N], ) -> [f64; N]
Like GriddedData::axes_values_cart, but does not perform bounds checking and is therefore unsafe.
Sourcepub fn cell_bounds(&self, point: &[f64; N]) -> Option<[[usize; 2]; N]>
pub fn cell_bounds(&self, point: &[f64; N]) -> Option<[[usize; 2]; N]>
Returns the cell / hypercuboid bounds containing the given point.
If the given point is within the grid, this function finds the indices of the node interval of each axis which contain the corresponding point value. Please see the top-level documentation for a discussion of the underlying concept.
§Examples
use gridded_data::GriddedData;
let data = vec![1.0, 7.0, 3.0, 9.0, 5.0, 11.0, 2.0, 8.0, 4.0, 10.0, 6.0, 12.0];
let x = vec![0.0, 1.0];
let y = vec![3.0, 4.0, 6.0]; // Spacing does not need to be uniform!
let z = vec![1.0, 2.0];
let grid = GriddedData::new([x, y, z], data).expect("valid input");
/*
The x-coordinate of the given point is between the 0th and the 1st node
of the x-axis, the y-coordinate is between the 1st and the 2nd node and the
z-coordinate is between the 0th and the 1st node.
*/
assert_eq!(grid.cell_bounds(&[0.5, 4.1, 1.5]), Some([[0, 1], [1, 2], [0, 1]]));
/*
x-coordinate directly on 0th node
y-coordinate directly on 1st node -> Two different intervals could be returned:
[0, 1] or [1, 2]. This function returns the "right-side" interval
z-coordinate directly on 1st node
*/
assert_eq!(grid.cell_bounds(&[0.0, 4.0, 2.0]), Some([[0, 1], [1, 2], [0, 1]]));
// y-coordinate outside grid -> Return None.
assert_eq!(grid.cell_bounds(&[0.5, 6.1, 1.5]), None);Sourcepub fn contains(&self, point: &[f64; N]) -> bool
pub fn contains(&self, point: &[f64; N]) -> bool
Returns whether the given point is inside the grid or not.
§Examples
use gridded_data::GriddedData;
let grid = GriddedData::new([vec![0.0, 1.0], vec![1.0, 2.0]], vec![1.0, 3.0, 2.0, 4.0]).expect("valid inputs");
assert!(grid.contains(&[0.5, 1.2]));
assert!(!grid.contains(&[1.5, 1.2]));Sourcepub fn nearest_neighbor_interp(&self, point: &[f64; N]) -> f64
pub fn nearest_neighbor_interp(&self, point: &[f64; N]) -> f64
Performs a nearest-neighbor interpolation for the given point.
This function first finds the “cell” (see GriddedData::cell_bounds) which contains
the given point. Afterwards, it calculates the Euclidian distance
of the point to each cell node and identifies the cartesian indices of the nearest node.
Finally, it returns the corresponding data value.
In case the point is outside the grid, the only difference is that there is just one node per dimension for each point value outside of the respective axis.
§Examples
use gridded_data::GriddedData;
let data = vec![1.0, 7.0, 3.0, 9.0, 5.0, 11.0, 2.0, 8.0, 4.0, 10.0, 6.0, 12.0];
let x = vec![0.0, 1.0];
let y = vec![3.0, 4.0, 6.0]; // Spacing does not need to be uniform!
let z = vec![1.0, 2.0];
let grid = GriddedData::new([x, y, z], data).expect("valid input");
/*
This point is inside the cell with the bounds x = [0.0, 1.0], y = [4.0, 6.0], z = [1.0, 2.0]
Within this cell, it is closest to the node [1.0, 4.0, 2.0], which corresponds to the data value 10.0
*/
assert_eq!(grid.nearest_neighbor_interp(&[0.9, 4.2, 1.7]), 10.0);
/*
The x-coordinate of this point is outside the grid -> Extrapolation by only considering the x-node with value 0.0
*/
assert_eq!(grid.nearest_neighbor_interp(&[-1.0, 4.2, 1.7]), 9.0);Sourcepub fn linear_interp(&self, point: &[f64; N]) -> f64
pub fn linear_interp(&self, point: &[f64; N]) -> f64
Performs a multivariate linear interpolation for the given point.
This function performs a generalized bilinear interpolation and calculates the return value as
output = num / denomwith
num = [ P11..11 * (a2-a) * (b2-b) * ... (n2-n) + P21..11 * (a-a1) * (b2-b) * ... (n2-n) + ... + P22..22 * (a-a1) * (b-b1) * ... (n-n1) ]
denom = [ (a2-a1) * (b2-b1) * ... (n2-n1) ]- 1 is the index of the smaller value, 2 is the index of the larger value
- P11..11 to P22..22 are the node values of the multidimensional grid
- a1, a2 are the two data values along the first axis, b1, b2 along the second axis and so on.
- a, b, …, n are the values of the input point for the corresponding dimensions.
If the point is outside the grid, a nearest-neighbor extrapolation is performed instead.
§Examples
use gridded_data::GriddedData;
let data = vec![1.0, 7.0, 3.0, 9.0, 5.0, 11.0, 2.0, 8.0, 4.0, 10.0, 6.0, 12.0];
let x = vec![0.0, 1.0];
let y = vec![3.0, 4.0, 6.0]; // Spacing does not need to be uniform!
let z = vec![1.0, 2.0];
let grid = GriddedData::new([x, y, z], data).expect("valid input");
// Values within the grid (tolerance accounts for limited floating-point accuracy)
assert!((grid.linear_interp(&[0.9, 4.2, 1.7]) - 8.3).abs() < 1e-10);
assert!((grid.linear_interp(&[0.8, 3.7, 1.2]) - 4.4).abs() < 1e-10);
// Value outside grid -> Nearest-neighbor extrapolation
assert_eq!(grid.linear_interp(&[-1.0, 4.2, 1.7]), 9.0);Source§impl GriddedData<2>
impl GriddedData<2>
Sourcepub fn from_slice_of_slices(
axes: [Vec<f64>; 2],
data: &[&[f64]],
) -> Result<Self, Error>
pub fn from_slice_of_slices( axes: [Vec<f64>; 2], data: &[&[f64]], ) -> Result<Self, Error>
Create a 2-dimensional GriddedData using a slices-of-slices matrix as data.
§Examples
use gridded_data::GriddedData;
let row1 = [1.0, 3.0];
let row2 = [2.0, 4.0];
let data = [row1.as_slice(), row2.as_slice()];
let grid = GriddedData::from_slice_of_slices([vec![0.0, 1.0], vec![1.0, 2.0]], data.as_slice()).expect("valid inputs");
assert_eq!(grid.data(), &[1.0, 2.0, 3.0, 4.0]);Sourcepub fn from_nalgebra_matrix<R: Dim, C: Dim, S: RawStorage<f64, R, C>>(
axes: [Vec<f64>; 2],
matrix: &Matrix<f64, R, C, S>,
) -> Result<Self, Error>
pub fn from_nalgebra_matrix<R: Dim, C: Dim, S: RawStorage<f64, R, C>>( axes: [Vec<f64>; 2], matrix: &Matrix<f64, R, C, S>, ) -> Result<Self, Error>
Create a 2-dimensional GriddedData using a nalgebra matrix.
§Examples
use gridded_data::GriddedData;
use nalgebra::Matrix2;
let row1 = [1.0, 3.0];
let row2 = [2.0, 4.0];
let data = Matrix2::from_vec(vec![1.0, 3.0, 2.0, 4.0]); // nalgebra is column-major!
let grid = GriddedData::from_nalgebra_matrix([vec![0.0, 1.0], vec![1.0, 2.0]], &data).expect("valid inputs");
assert_eq!(grid.data(), &[1.0, 2.0, 3.0, 4.0]); // The data within grid is stored row-major.§Features
Only available if the nalgebra feature is enabled.
Trait Implementations§
Source§impl<const N: usize> Clone for GriddedData<N>
impl<const N: usize> Clone for GriddedData<N>
Source§fn clone(&self) -> GriddedData<N>
fn clone(&self) -> GriddedData<N>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<const N: usize> Debug for GriddedData<N>
impl<const N: usize> Debug for GriddedData<N>
Source§impl<'de> Deserialize<'de> for GriddedData<1>
impl<'de> Deserialize<'de> for GriddedData<1>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<10>
impl<'de> Deserialize<'de> for GriddedData<10>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<11>
impl<'de> Deserialize<'de> for GriddedData<11>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<12>
impl<'de> Deserialize<'de> for GriddedData<12>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<13>
impl<'de> Deserialize<'de> for GriddedData<13>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<14>
impl<'de> Deserialize<'de> for GriddedData<14>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<15>
impl<'de> Deserialize<'de> for GriddedData<15>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<16>
impl<'de> Deserialize<'de> for GriddedData<16>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<2>
impl<'de> Deserialize<'de> for GriddedData<2>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<3>
impl<'de> Deserialize<'de> for GriddedData<3>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<4>
impl<'de> Deserialize<'de> for GriddedData<4>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<5>
impl<'de> Deserialize<'de> for GriddedData<5>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<6>
impl<'de> Deserialize<'de> for GriddedData<6>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<7>
impl<'de> Deserialize<'de> for GriddedData<7>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<8>
impl<'de> Deserialize<'de> for GriddedData<8>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for GriddedData<9>
impl<'de> Deserialize<'de> for GriddedData<9>
Source§fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where
D: Deserializer<'de>,
Source§impl Serialize for GriddedData<1>
impl Serialize for GriddedData<1>
Source§impl Serialize for GriddedData<10>
impl Serialize for GriddedData<10>
Source§impl Serialize for GriddedData<11>
impl Serialize for GriddedData<11>
Source§impl Serialize for GriddedData<12>
impl Serialize for GriddedData<12>
Source§impl Serialize for GriddedData<13>
impl Serialize for GriddedData<13>
Source§impl Serialize for GriddedData<14>
impl Serialize for GriddedData<14>
Source§impl Serialize for GriddedData<15>
impl Serialize for GriddedData<15>
Source§impl Serialize for GriddedData<16>
impl Serialize for GriddedData<16>
Source§impl Serialize for GriddedData<2>
impl Serialize for GriddedData<2>
Source§impl Serialize for GriddedData<3>
impl Serialize for GriddedData<3>
Source§impl Serialize for GriddedData<4>
impl Serialize for GriddedData<4>
Source§impl Serialize for GriddedData<5>
impl Serialize for GriddedData<5>
Source§impl Serialize for GriddedData<6>
impl Serialize for GriddedData<6>
Source§impl Serialize for GriddedData<7>
impl Serialize for GriddedData<7>
Source§impl Serialize for GriddedData<8>
impl Serialize for GriddedData<8>
Auto Trait Implementations§
impl<const N: usize> Freeze for GriddedData<N>
impl<const N: usize> RefUnwindSafe for GriddedData<N>
impl<const N: usize> Send for GriddedData<N>
impl<const N: usize> Sync for GriddedData<N>
impl<const N: usize> Unpin for GriddedData<N>
impl<const N: usize> UnwindSafe for GriddedData<N>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.