1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
//! Interfaces and implementations specific to integration with `ndarray`. //! //! This module introduces the trait [`IntoNdArray`], which is implemented for //! all NIfTI volume types and enable their mapping into an [`Array`] with a //! dynamic number of dimensions and an abitrary element type. The affine //! scaling of the values (from the `scl_slope` and `scl_inter` attributes) are //! also considered in this transformation. //! //! A target [element type] needs to be provided at compile time, which is //! usually the data type that the user wishes to work the array with. If the //! source and target types do not match, each voxel is cast in a way as to //! avoid loss of precision. //! //! #### Note on memory order //! //! NIfTI volumes are usually stored in disk in column major order (also called //! Fortran order). As such, the array resulting from this operation will also //! be in this memory order, rather than the usual row major order (AKA C //! ordering). When accessing the array, one should consider any potential //! bottlenecks emerging from this ordering in their data processing pipelines. //! Namely, it might be faster to produce output arrays in column major order //! as well. //! //! [`IntoNdArray`]: ./trait.IntoNdArray.html //! [`Array`]: ../../../ndarray/type.Array.html //! [element type]: ../element/trait.DataElement.html //! use crate::error::Result; use crate::volume::element::DataElement; use crate::volume::NiftiVolume; use ndarray::{Array, Axis, Ix, IxDyn}; use num_traits::AsPrimitive; use std::ops::{Add, Mul}; /// Trait for volumes which can be converted to an ndarray. /// /// Please see the [module-level documentation](index.html) for more details. pub trait IntoNdArray { /// Consume the volume into an ndarray with the same number of dimensions /// and the given target element type `T`. fn into_ndarray<T>(self) -> Result<Array<T, IxDyn>> where T: Mul<Output = T>, T: Add<Output = T>, T: DataElement, u8: AsPrimitive<T>, i8: AsPrimitive<T>, u16: AsPrimitive<T>, i16: AsPrimitive<T>, u32: AsPrimitive<T>, i32: AsPrimitive<T>, u64: AsPrimitive<T>, i64: AsPrimitive<T>, f32: AsPrimitive<T>, f64: AsPrimitive<T>; } impl<V> IntoNdArray for super::SliceView<V> where V: NiftiVolume + IntoNdArray, { fn into_ndarray<T>(self) -> Result<Array<T, IxDyn>> where T: Mul<Output = T>, T: Add<Output = T>, T: DataElement, u8: AsPrimitive<T>, i8: AsPrimitive<T>, u16: AsPrimitive<T>, i16: AsPrimitive<T>, u32: AsPrimitive<T>, i32: AsPrimitive<T>, u64: AsPrimitive<T>, i64: AsPrimitive<T>, f32: AsPrimitive<T>, f64: AsPrimitive<T>, { // TODO optimize this implementation (we don't need the whole volume) let volume = self.volume.into_ndarray()?; Ok(volume.into_subview(Axis(self.axis as Ix), self.index as usize)) } }