use clap::{Parser, Subcommand}; #[cfg(feature = "movie")] use ndarray::SliceInfoElem; use ndbioimage::error::Error; #[cfg(feature = "movie")] use ndbioimage::movie::MovieOptions; use ndbioimage::reader::{split_path_and_series, Reader}; #[cfg(feature = "tiff")] use ndbioimage::tiff::TiffOptions; use ndbioimage::view::View; use std::path::PathBuf; #[derive(Parser)] #[command(arg_required_else_help = true, version, about, long_about = None, propagate_version = true)] struct Cli { #[command(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { /// Print some metadata Info { #[arg(value_name = "FILE", num_args(1..))] file: Vec, }, /// save ome metadata as xml ExtractOME { #[arg(value_name = "FILE", num_args(1..))] file: Vec, }, /// Save the image as tiff file #[cfg(feature = "tiff")] Tiff { #[arg(value_name = "FILE", num_args(1..))] file: Vec, #[arg(short, long, value_name = "COLOR", num_args(1..))] colors: Vec, #[arg(short, long, value_name = "OVERWRITE")] overwrite: bool, }, /// Save the image as mp4 file #[cfg(feature = "movie")] Movie { #[arg(value_name = "FILE", num_args(1..))] file: Vec, #[arg(short, long, value_name = "VELOCITY", default_value = "3.6")] velocity: f64, #[arg(short, long, value_name = "BRIGHTNESS", num_args(1..))] brightness: Vec, #[arg(short, long, value_name = "SCALE", default_value = "1.0")] scale: f64, #[arg(short = 'C', long, value_name = "COLOR", num_args(1..))] colors: Vec, #[arg(short, long, value_name = "OVERWRITE")] overwrite: bool, #[arg(short, long, value_name = "REGISTER")] register: bool, #[arg(short, long, value_name = "CHANNEL")] channel: Option, #[arg(short, long, value_name = "ZSLICE")] zslice: Option, #[arg(short, long, value_name = "TIME")] time: Option, #[arg(short, long, value_name = "NO-SCALE-BRIGHTNESS")] no_scaling: bool, }, /// Download the BioFormats jar into the correct folder DownloadBioFormats { #[arg(short, long, value_name = "GPL_FORMATS")] gpl_formats: bool, }, } #[cfg(feature = "movie")] fn parse_slice(s: &str) -> Result { let mut t = s .trim() .replace("..", ":") .split(":") .map(|i| i.parse().ok()) .collect::>>(); if t.len() > 3 { return Err(Error::Parse(s.to_string())); } while t.len() < 3 { t.push(None); } match t[..] { [Some(start), None, None] => Ok(SliceInfoElem::Index(start)), [Some(start), end, None] => Ok(SliceInfoElem::Slice { start, end, step: 1, }), [Some(start), end, Some(step)] => Ok(SliceInfoElem::Slice { start, end, step }), [None, end, None] => Ok(SliceInfoElem::Slice { start: 0, end, step: 1, }), [None, end, Some(step)] => Ok(SliceInfoElem::Slice { start: 0, end, step, }), _ => Err(Error::Parse(s.to_string())), } } pub(crate) fn main() -> Result<(), Error> { let cli = Cli::parse(); match &cli.command { Commands::Info { file } => { for f in file { let (path, series) = split_path_and_series(f)?; let view = View::from_path(path, series.unwrap_or(0))?.squeeze()?; println!("{}", view.summary()?); } } Commands::ExtractOME { file } => { for f in file { let (path, series) = split_path_and_series(f)?; let reader = Reader::new(&path, series.unwrap_or(0))?; let xml = reader.get_ome_xml()?; std::fs::write(path.with_extension("xml"), xml)?; } } #[cfg(feature = "tiff")] Commands::Tiff { file, colors, overwrite, } => { let mut options = TiffOptions::new(true, None, colors.clone(), *overwrite)?; options.enable_bar()?; for f in file { let (path, series) = split_path_and_series(f)?; let view = View::from_path(path, series.unwrap_or(0))?; view.save_as_tiff(f.with_extension("tiff"), &options)?; } } #[cfg(feature = "movie")] Commands::Movie { file, velocity: speed, brightness, scale, colors, overwrite, register, channel, zslice, time, no_scaling, } => { let options = MovieOptions::new( *speed, brightness.to_vec(), *scale, colors.to_vec(), *overwrite, *register, *no_scaling, )?; for f in file { let (path, series) = split_path_and_series(f)?; let view = View::from_path(path, series.unwrap_or(0))?; let mut s = [SliceInfoElem::Slice { start: 0, end: None, step: 1, }; 5]; if let Some(channel) = channel { s[0] = SliceInfoElem::Index(*channel); }; if let Some(zslice) = zslice { s[1] = parse_slice(zslice)?; } if let Some(time) = time { s[2] = parse_slice(time)?; } view.into_dyn() .slice(s.as_slice())? .save_as_movie(f.with_extension("mp4"), &options)?; } } Commands::DownloadBioFormats { gpl_formats } => { ndbioimage::download_bioformats(*gpl_formats)? } } Ok(()) }