pub mod element;
pub mod inmem;
pub mod shape;
pub mod streamed;
pub use self::inmem::*;
pub use self::streamed::StreamedNiftiVolume;
mod util;
use crate::error::{NiftiError, Result};
use crate::header::NiftiHeader;
use crate::typedef::NiftiType;
use std::io::Read;
#[cfg(feature = "ndarray_volumes")]
pub mod ndarray;
pub trait NiftiVolume {
fn dim(&self) -> &[u16];
fn dimensionality(&self) -> usize {
self.dim().len()
}
fn data_type(&self) -> NiftiType;
}
pub trait RandomAccessNiftiVolume: NiftiVolume {
fn get_f64(&self, coords: &[u16]) -> Result<f64>;
#[inline]
fn get_f32(&self, coords: &[u16]) -> Result<f32> {
self.get_f64(coords).map(|v| v as f32)
}
#[inline]
fn get_u8(&self, coords: &[u16]) -> Result<u8> {
self.get_f64(coords).map(|v| v as u8)
}
#[inline]
fn get_i8(&self, coords: &[u16]) -> Result<i8> {
self.get_f64(coords).map(|v| v as i8)
}
#[inline]
fn get_u16(&self, coords: &[u16]) -> Result<u16> {
self.get_f64(coords).map(|v| v as u16)
}
#[inline]
fn get_i16(&self, coords: &[u16]) -> Result<i16> {
self.get_f64(coords).map(|v| v as i16)
}
#[inline]
fn get_u32(&self, coords: &[u16]) -> Result<u32> {
self.get_f64(coords).map(|v| v as u32)
}
#[inline]
fn get_i32(&self, coords: &[u16]) -> Result<i32> {
self.get_f64(coords).map(|v| v as i32)
}
#[inline]
fn get_u64(&self, coords: &[u16]) -> Result<u64> {
self.get_f64(coords).map(|v| v as u64)
}
#[inline]
fn get_i64(&self, coords: &[u16]) -> Result<i64> {
self.get_f64(coords).map(|v| v as i64)
}
}
pub trait Sliceable {
type Slice: NiftiVolume;
fn get_slice(&self, axis: u16, index: u16) -> Result<Self::Slice>;
}
pub trait FromSourceOptions {
type Options: Clone + Default;
}
pub trait FromSource<R>: FromSourceOptions + Sized {
fn from_reader(reader: R, header: &NiftiHeader, options: Self::Options) -> Result<Self>
where
R: Read;
}
#[derive(Debug, Clone)]
pub struct SliceView<T> {
volume: T,
axis: u16,
index: u16,
dim: Vec<u16>,
}
impl<'a, T> Sliceable for &'a T
where
&'a T: NiftiVolume,
{
type Slice = SliceView<&'a T>;
fn get_slice(&self, axis: u16, index: u16) -> Result<Self::Slice> {
let mut coords: Vec<_> = self.dim().into();
if let Some(d) = coords.get(axis as usize) {
if *d <= index {
return Err(NiftiError::OutOfBounds(util::hot_vector(
self.dimensionality(),
axis as usize,
index,
)));
}
} else {
return Err(NiftiError::AxisOutOfBounds(axis));
}
let _ = coords.remove(axis as usize);
Ok(SliceView {
volume: *self,
axis,
index,
dim: coords,
})
}
}
impl<V> NiftiVolume for SliceView<V>
where
V: NiftiVolume,
{
#[inline]
fn dim(&self) -> &[u16] {
&self.dim
}
#[inline]
fn dimensionality(&self) -> usize {
self.dim.len()
}
#[inline]
fn data_type(&self) -> NiftiType {
self.volume.data_type()
}
}
impl<V> RandomAccessNiftiVolume for SliceView<V>
where
V: RandomAccessNiftiVolume,
{
fn get_f32(&self, coords: &[u16]) -> Result<f32> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_f32(&coords)
}
fn get_f64(&self, coords: &[u16]) -> Result<f64> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_f64(&coords)
}
fn get_u8(&self, coords: &[u16]) -> Result<u8> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_u8(&coords)
}
fn get_i8(&self, coords: &[u16]) -> Result<i8> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_i8(&coords)
}
fn get_u16(&self, coords: &[u16]) -> Result<u16> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_u16(&coords)
}
fn get_i16(&self, coords: &[u16]) -> Result<i16> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_i16(&coords)
}
fn get_u32(&self, coords: &[u16]) -> Result<u32> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_u32(&coords)
}
fn get_i32(&self, coords: &[u16]) -> Result<i32> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_i32(&coords)
}
fn get_u64(&self, coords: &[u16]) -> Result<u64> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_u64(&coords)
}
fn get_i64(&self, coords: &[u16]) -> Result<i64> {
let mut coords = Vec::from(coords);
coords.insert(self.axis as usize, self.index);
self.volume.get_i64(&coords)
}
}