From c759540149dbcd1a8d34b5d9c9d3f9e2f9dd8d84 Mon Sep 17 00:00:00 2001 From: Nil Goyette Date: Mon, 24 Jan 2022 12:45:32 -0500 Subject: [PATCH 1/3] Reserve the right length on read_all --- src/reader.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/reader.rs b/src/reader.rs index 6cbbe32..51e489c 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -19,6 +19,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, @@ -27,7 +28,10 @@ pub struct Reader { impl Reader { pub fn new>(path: P) -> Result { - 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; @@ -41,6 +45,7 @@ impl Reader { header, affine_to_rasmm, translation, + nb_bytes, nb_scalars, nb_properties, nb_floats_per_point, @@ -56,11 +61,23 @@ impl Reader { } fn read_all_(&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); - let mut properties = ArraySequence::with_capacity(300); + 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::() { lengths.push(nb_points as usize); self.read_streamline::(&mut v, &mut scalars, nb_points as usize); From 13d6198ebe4822082795d4b336a37ad737e48120 Mon Sep 17 00:00:00 2001 From: Nil Goyette Date: Mon, 24 Jan 2022 12:46:05 -0500 Subject: [PATCH 2/3] Binary to check the guessed lengths --- examples/trk_len_check.rs | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 examples/trk_len_check.rs diff --git a/examples/trk_len_check.rs b/examples/trk_len_check.rs new file mode 100644 index 0000000..06d53d1 --- /dev/null +++ b/examples/trk_len_check.rs @@ -0,0 +1,64 @@ +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 [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("")); + if !input.exists() { + panic!("Input trk '{:?}' doesn't exist.", input); + } + + let f = File::open(args.get_str("")).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("")).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); +} From 1b3cfcf17e24b66d4d59dc3f2187a2a16bb4d0f4 Mon Sep 17 00:00:00 2001 From: Nil Goyette Date: Thu, 31 Mar 2022 15:59:04 -0400 Subject: [PATCH 3/3] read_all_alloc and print loading time difference --- examples/trk_len_check.rs | 16 ++++++++++++++++ src/reader.rs | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/examples/trk_len_check.rs b/examples/trk_len_check.rs index 06d53d1..2b709ac 100644 --- a/examples/trk_len_check.rs +++ b/examples/trk_len_check.rs @@ -1,3 +1,4 @@ +use std::time::Instant; use std::{fs::File, path::Path, str}; use docopt::Docopt; @@ -61,4 +62,19 @@ fn main() { 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("")).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("")).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()) } diff --git a/src/reader.rs b/src/reader.rs index 51e489c..44238b5 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -61,6 +61,28 @@ impl Reader { } fn read_all_(&mut self) -> Tractogram { + let mut lengths = Vec::new(); + let mut v = Vec::with_capacity(300); + let mut scalars = ArraySequence::with_capacity(300); + let mut properties = ArraySequence::with_capacity(300); + while let Ok(nb_points) = self.reader.read_i32::() { + lengths.push(nb_points as usize); + self.read_streamline::(&mut v, &mut scalars, nb_points as usize); + self.read_properties_to_arr::(&mut properties); + } + + self.float_buffer = vec![]; + 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_::(), + Endianness::Big => self.read_all_alloc_::(), + } + } + + fn read_all_alloc_(&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;