Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP len check #16

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions examples/trk_len_check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use std::time::Instant;
use std::{fs::File, path::Path, str};

use docopt::Docopt;

use trk_io::Reader;

static USAGE: &'static str = "
Binary to test that reserving a number of points, scalars and properties is
possible and works 100% of the time.

Usage:
trk_len_check <input> [options]
trk_len_check (-h | --help)
trk_len_check (-v | --version)

Options:
-h --help Show this screen.
-v --version Show version.
";

fn main() {
let version = String::from(env!("CARGO_PKG_VERSION"));
let args = Docopt::new(USAGE)
.and_then(|dopt| dopt.version(Some(version)).parse())
.unwrap_or_else(|e| e.exit());
let input = Path::new(args.get_str("<input>"));
if !input.exists() {
panic!("Input trk '{:?}' doesn't exist.", input);
}

let f = File::open(args.get_str("<input>")).expect("Can't read trk file.");
let metadata = f.metadata().unwrap();
let nb_bytes = metadata.len() as usize;

let reader = Reader::new(args.get_str("<input>")).expect("Read header");
let header = &reader.header;
let nb_scalars = header.scalars_name.len();
let nb_properties = header.properties_name.len();
let nb_streamlines = header.nb_streamlines;
let header_size = header.raw_header().hdr_size as usize;

let nb_f32s = (nb_bytes - header_size) / 4;
let guessed_nb_properties = nb_streamlines * nb_properties;

// We remove the nb_points count and the properties, se we only have the points and scalars
let nb_f32s = nb_f32s - nb_streamlines - guessed_nb_properties;
let guessed_nb_points = nb_f32s / (3 + nb_scalars);
let guessed_nb_scalars = nb_f32s - (3 * guessed_nb_points);

let mut real_nb_points = 0;
let mut real_nb_scalars = 0;
let mut real_nb_properties = 0;
for (streamline, scalars, properties) in reader.into_iter() {
real_nb_points += streamline.len();
for s in &scalars {
real_nb_scalars += s.len();
}
real_nb_properties += properties.len();
}

assert_eq!(guessed_nb_points, real_nb_points);
assert_eq!(guessed_nb_scalars, real_nb_scalars);
assert_eq!(guessed_nb_properties, real_nb_properties);

let mut reader = Reader::new(args.get_str("<input>")).expect("Read header");
let now1 = Instant::now();
let _ = reader.read_all();
let elapsed1 = now1.elapsed();
println!("{}s {}ms", elapsed1.as_secs(), elapsed1.subsec_millis());

let mut reader = Reader::new(args.get_str("<input>")).expect("Read header");
let now2 = Instant::now();
let _ = reader.read_all_alloc();
let elapsed2 = now2.elapsed();
println!("{}s {}ms", elapsed2.as_secs(), elapsed2.subsec_millis());

let diff = elapsed1 - elapsed2;
println!("{}ms OR {}ns", diff.subsec_millis(), diff.subsec_nanos())
}
43 changes: 41 additions & 2 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct Reader {
pub affine_to_rasmm: Affine,
pub translation: Translation,

nb_bytes: usize,
nb_scalars: usize,
nb_properties: usize,
nb_floats_per_point: usize,
Expand All @@ -28,7 +29,10 @@ pub struct Reader {

impl Reader {
pub fn new<P: AsRef<Path>>(path: P) -> Result<Reader> {
let mut reader = BufReader::new(File::open(&path)?);
let f = File::open(&path)?;
let nb_bytes = f.metadata().unwrap().len() as usize;

let mut reader = BufReader::new(f);
let (header, endianness) = Header::read(&mut reader)?;
let affine_to_rasmm = header.affine_to_rasmm;
let translation = header.translation;
Expand All @@ -42,6 +46,7 @@ impl Reader {
header,
affine_to_rasmm,
translation,
nb_bytes,
nb_scalars,
nb_properties,
nb_floats_per_point,
Expand All @@ -66,7 +71,6 @@ impl Reader {
}

fn read_all_<E: ByteOrder>(&mut self) -> Tractogram {
// TODO Anything we can do to reerve?
let mut lengths = Vec::new();
let mut v = Vec::with_capacity(300);
let mut scalars = ArraySequence::with_capacity(300);
Expand All @@ -81,6 +85,41 @@ impl Reader {
Tractogram::new(Streamlines::new(lengths, v), scalars, properties)
}

pub fn read_all_alloc(&mut self) -> Tractogram {
match self.endianness {
Endianness::Little => self.read_all_alloc_::<LittleEndian>(),
Endianness::Big => self.read_all_alloc_::<BigEndian>(),
}
}

fn read_all_alloc_<E: ByteOrder>(&mut self) -> Tractogram {
let nb_scalars = self.header.scalars_name.len();
let nb_properties = self.header.properties_name.len();
let nb_streamlines = self.header.nb_streamlines;
let header_size = self.header.raw_header().hdr_size as usize;

// We remove the nb_points count and the properties from nb_f32s, se we only have the
// points and scalars
let guessed_nb_properties = nb_streamlines * nb_properties;
let nb_f32s = (self.nb_bytes - header_size) / 4;
let nb_f32s = nb_f32s - nb_streamlines - guessed_nb_properties;
let guessed_nb_points = nb_f32s / (3 + nb_scalars);
let guessed_nb_scalars = nb_f32s - (3 * guessed_nb_points);

let mut lengths = Vec::with_capacity(nb_streamlines);
let mut v = Vec::with_capacity(guessed_nb_points);
let mut scalars = ArraySequence::with_capacity(guessed_nb_scalars);
let mut properties = ArraySequence::with_capacity(guessed_nb_properties);
while let Ok(nb_points) = self.reader.read_i32::<E>() {
lengths.push(nb_points as usize);
self.read_streamline::<E>(&mut v, &mut scalars, nb_points as usize);
self.read_properties_to_arr::<E>(&mut properties);
}

self.float_buffer = vec![];
Tractogram::new(Streamlines::new(lengths, v), scalars, properties)
}

fn read_streamline<E: ByteOrder>(
&mut self,
points: &mut Points,
Expand Down