use anyhow::Result; use docopt::Docopt; use rand::{rngs::SmallRng, Rng, SeedableRng}; use trk_io::{Reader, Writer}; static USAGE: &'static str = " Subsample a TrackVis (.trk) file Usage: trk_subsampler (--percent=

| --number=) [--seed=] trk_subsampler (-h | --help) trk_subsampler (-v | --version) Options: -p --percent=

Keep only p% of streamlines. Based on rand. -n --number= Keep exactly n streamlines. Based on rand. -s --seed= Make randomness deterministic. -h --help Show this screen. -v --version Show version. "; fn main() -> Result<()> { 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 reader = Reader::new(args.get_str(""))?; let mut writer = Writer::new(args.get_str(""), Some(&reader.header))?; let mut rng = match args.get_str("--seed").parse::() { Ok(seed) => SmallRng::from_seed([seed; 32]), Err(_) => SmallRng::from_entropy(), }; if let Ok(percent) = args.get_str("--percent").parse::() { let percent = percent / 100.0; for item in reader { if rng.gen::() < percent { writer.write(item); } } } else if let Ok(nb) = args.get_str("--number").parse::() { let size = reader.header.nb_streamlines; let number = size.min(nb); if number == 0 { panic!( "You requested a subsampling of 0 streamline. Please ask for any non-zero \ positive number." ); } else if number >= size { println!( "You requested a subsampling of {} streamlines, which is more than the total \ number of streamlines. The input file will simply be copied to the output file.", nb ); reader.into_iter().for_each(|item| writer.write(item)); } else { sampling_write(&mut writer, reader, number, &mut rng); } } else { panic!("--percent or --number can't be parsed to a positive number"); } Ok(()) } fn sampling_write(writer: &mut Writer, reader: Reader, number: usize, rng: &mut SmallRng) { let mut sampled_indices = rand::seq::index::sample(rng, reader.header.nb_streamlines, number).into_vec(); sampled_indices.sort(); let mut reader_iter = reader.into_iter(); let mut last = 0; for idx in sampled_indices { writer.write(reader_iter.nth(idx - last).unwrap()); last = idx + 1; } }