Skip to content

Commit

Permalink
Merge pull request #106 from twitzelbos/feature/write-complex-valued-…
Browse files Browse the repository at this point in the history
…data

Feature/write complex valued data
  • Loading branch information
Enet4 authored Jul 4, 2023
2 parents 23c69a9 + 2c3ce84 commit 341f830
Show file tree
Hide file tree
Showing 12 changed files with 981 additions and 177 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ flate2 = "1.0"
num-derive = "0.3"
num-traits = "0.2"
quick-error = "2.0"
safe-transmute = "0.11"
either = "1.6"
num-complex = {version = "0.4.3", features=["bytemuck"]}
rgb = "0.8.36"
bytemuck = {version = "1.13.1", features=["extern_crate_alloc"]}

[dependencies.nalgebra]
optional = true
Expand Down
Binary file added resources/complex/complex32.nii
Binary file not shown.
Binary file added resources/complex/complex64.nii
Binary file not shown.
Binary file added resources/rgba/4D.nii
Binary file not shown.
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ quick_error! {
display("Could not reserve {} bytes of memory for extended data", bytes)
source(err)
}

/// Attempted a type conversion that is not supported by this crate
InvalidTypeConversion(from: NiftiType, to: &'static str) {
display("Invalid type conversion from {:?} to {}", from, to)
}
}
}

Expand Down
24 changes: 13 additions & 11 deletions src/typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! converted to these types and vice-versa.
use crate::error::{NiftiError, Result};
use crate::volume::element::{DataElement, LinearTransform};
use crate::volume::element::{DataElement, NiftiDataRescaler};
use byteordered::{Endian, Endianness};
use num_derive::FromPrimitive;
use std::io::Read;
Expand Down Expand Up @@ -96,88 +96,90 @@ impl NiftiType {
T: Mul<Output = T>,
T: Add<Output = T>,
T: DataElement,
T: NiftiDataRescaler<T>,
{
match self {
NiftiType::Uint8 => {
let raw = u8::from_raw(source, endianness)?;
Ok(<u8 as DataElement>::Transform::linear_transform(
Ok(<u8 as DataElement>::DataRescaler::nifti_rescale(
T::from_u8(raw),
slope,
inter,
))
}
NiftiType::Int8 => {
let raw = i8::from_raw(source, endianness)?;
Ok(<i8 as DataElement>::Transform::linear_transform(
Ok(<i8 as DataElement>::DataRescaler::nifti_rescale(
T::from_i8(raw),
slope,
inter,
))
}
NiftiType::Uint16 => {
let raw = endianness.read_u16(source)?;
Ok(<u16 as DataElement>::Transform::linear_transform(
Ok(<u16 as DataElement>::DataRescaler::nifti_rescale(
T::from_u16(raw),
slope,
inter,
))
}
NiftiType::Int16 => {
let raw = endianness.read_i16(source)?;
Ok(<i16 as DataElement>::Transform::linear_transform(
Ok(<i16 as DataElement>::DataRescaler::nifti_rescale(
T::from_i16(raw),
slope,
inter,
))
}
NiftiType::Uint32 => {
let raw = endianness.read_u32(source)?;
Ok(<u32 as DataElement>::Transform::linear_transform(
Ok(<u32 as DataElement>::DataRescaler::nifti_rescale(
T::from_u32(raw),
slope,
inter,
))
}
NiftiType::Int32 => {
let raw = endianness.read_i32(source)?;
Ok(<i32 as DataElement>::Transform::linear_transform(
Ok(<i32 as DataElement>::DataRescaler::nifti_rescale(
T::from_i32(raw),
slope,
inter,
))
}
NiftiType::Uint64 => {
let raw = endianness.read_u64(source)?;
Ok(<u64 as DataElement>::Transform::linear_transform(
Ok(<u64 as DataElement>::DataRescaler::nifti_rescale(
T::from_u64(raw),
slope,
inter,
))
}
NiftiType::Int64 => {
let raw = endianness.read_i64(source)?;
Ok(<i64 as DataElement>::Transform::linear_transform(
Ok(<i64 as DataElement>::DataRescaler::nifti_rescale(
T::from_i64(raw),
slope,
inter,
))
}
NiftiType::Float32 => {
let raw = endianness.read_f32(source)?;
Ok(<f32 as DataElement>::Transform::linear_transform(
Ok(<f32 as DataElement>::DataRescaler::nifti_rescale(
T::from_f32(raw),
slope,
inter,
))
}
NiftiType::Float64 => {
let raw = endianness.read_f64(source)?;
Ok(<f64 as DataElement>::Transform::linear_transform(
Ok(<f64 as DataElement>::DataRescaler::nifti_rescale(
T::from_f64(raw),
slope,
inter,
))
}

// TODO(#3) add support for more data types
_ => Err(NiftiError::UnsupportedDataType(self)),
}
Expand Down
10 changes: 3 additions & 7 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,24 @@ use crate::NiftiHeader;
use byteordered::Endian;
use either::Either;
use flate2::bufread::GzDecoder;
use safe_transmute::{transmute_vec, TriviallyTransmutable};
use std::borrow::Cow;
use std::fs::File;
use std::io::{BufReader, Read, Result as IoResult, Seek};
use std::mem;
use std::path::{Path, PathBuf};

/// A trait that is both Read and Seek.
pub trait ReadSeek: Read + Seek {}
impl<T: Read + Seek> ReadSeek for T {}

pub fn convert_bytes_to<T, E>(mut a: Vec<u8>, e: E) -> Vec<T>
where
T: TriviallyTransmutable,
T: bytemuck::Pod,
E: Endian,
{
adapt_bytes_inline::<T, _>(&mut a, e);
match transmute_vec(a) {
match bytemuck::allocation::try_cast_vec(a) {
Ok(v) => v,
Err(safe_transmute::Error::IncompatibleVecTarget(e)) => e.copy(),
Err(safe_transmute::Error::Unaligned(e)) => e.copy(),
_ => unreachable!(),
Err((_, v)) => bytemuck::allocation::pod_collect_to_vec(&v),
}
}

Expand Down
Loading

0 comments on commit 341f830

Please sign in to comment.