#![warn(missing_docs)]
use std::path::Path;
use anyhow::Result;
use clap::Parser;
pub mod library;
pub mod counter;
pub mod results;
pub mod permutes;
pub mod offsetter;
pub mod count;
pub mod genemap;
pub mod progress;
pub mod utils;
pub use count::count;
pub use counter::Counter;
pub use fxread::initialize_reader;
pub use genemap::GeneMap;
pub use library::Library;
use offsetter::entropy_offset_group;
pub use offsetter::{entropy_offset, Offset};
pub use permutes::Permuter;
use progress::{finish_progress_bar, initialize_progress_bar, start_progress_bar};
use utils::{generate_sample_names, set_threads};
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[clap(short, long, value_parser)]
library_path: String,
#[clap(short, long, value_parser, required = true, num_args = 1..)]
input_paths: Vec<String>,
#[clap(short = 'n', long, value_parser, required = false, num_args = 1..)]
sample_names: Option<Vec<String>>,
#[clap(short, long, value_parser)]
output_path: Option<String>,
#[clap(short, long, value_parser)]
genemap: Option<String>,
#[clap(short = 'a', long, value_parser)]
offset: Option<usize>,
#[clap(short = 'p', long)]
no_position_recursion: bool,
#[clap(short = 'r', long)]
reverse: bool,
#[clap(short = 'x', long)]
exact: bool,
#[clap(short = 's', long)]
subsample: Option<usize>,
#[clap(short = 't', long, default_value = "1")]
threads: usize,
#[clap(short = 'q', long)]
quiet: bool,
#[clap(short = 'z', long)]
include_zero: bool,
}
fn calculate_offset(
library_path: &str,
input_paths: &[String],
subsample: Option<usize>,
quiet: bool,
) -> Result<Vec<Offset>> {
let subsample = subsample.unwrap_or(5000);
let pb = if quiet {
None
} else {
Some(initialize_progress_bar())
};
start_progress_bar(&pb, "Calculating Offset".to_string());
let offset = entropy_offset_group(library_path, input_paths, subsample)?;
finish_progress_bar(&pb, format!("Calculated Offsets: {:?}", offset));
Ok(offset)
}
fn validate_paths(input_paths: &[String]) {
for x in input_paths.iter() {
if !Path::new(x).exists() {
assert!(
Path::new(x).exists(),
"Provided filepath does not exist: {}",
x
);
}
}
}
fn main() -> Result<()> {
let args = Args::parse();
set_threads(args.threads);
validate_paths(&args.input_paths);
let sample_names = match args.sample_names {
Some(s) => {
if s.len() == args.input_paths.len() {
s
} else {
panic!("Must provide as many sample names as there are input files")
}
}
None => generate_sample_names(&args.input_paths),
};
let offset = match args.offset {
Some(o) => {
if args.reverse {
vec![Offset::Reverse(o); args.input_paths.len()]
} else {
vec![Offset::Forward(o); args.input_paths.len()]
}
}
None => calculate_offset(
&args.library_path,
&args.input_paths,
args.subsample,
args.quiet,
)?,
};
let genemap = match args.genemap {
Some(g) => Some(GeneMap::new(&g)?),
None => None,
};
let position_recursion = !args.no_position_recursion;
count(
&args.library_path,
args.input_paths,
&sample_names,
args.output_path,
offset,
args.exact,
&genemap,
position_recursion,
args.include_zero,
args.quiet,
)?;
Ok(())
}