mod base;
mod count;
use clap::Parser;
use std::path::{Path, PathBuf};
#[derive(Parser)]
#[clap(about, version, author)]
struct Opts {
#[clap(short, long, parse(from_occurrences))]
verbose: i32,
#[clap(subcommand)]
subcmd: SubCommand,
}
#[derive(Parser)]
enum SubCommand {
Base(Base),
Count(Count),
}
#[derive(Parser)]
struct Base {
#[clap(short = 'g', long = "count-indel", help = "Count indel?")]
indel: bool,
#[clap(short = 't', long = "target", help = "input bed file..", validator = file_path_validation)]
bed: PathBuf,
#[clap(short = 'r', long = "reference", help = "input fa file..", validator = file_path_validation)]
fa: PathBuf,
#[clap(
short = 'i',
long = "input",
help = "input bam files..",
required = true,
parse(from_os_str),
takes_value = true, multiple_values = true, validator = file_path_validation,
)]
bam: Vec<PathBuf>,
#[clap(
short = 'd',
long = "min-depth",
help = "Set min depth for output. Note: anyone of the samples passing the cutoff is ok.",
default_value = "0"
)]
min_depth: u32,
#[clap(
short = 'm',
long = "mean-depth",
help = "Set min cutoff of mean depth for output",
default_value = "0"
)]
mean_depth: u32,
#[clap(
short = 'q',
long = "min-qual",
help = "Set min quality for base. (greater or equal to)",
default_value = "0"
)]
qual: u8,
#[clap(
short = 'H',
long = "headless",
help = "Write without header in the output"
)]
headless: bool,
#[clap(
short = 'S',
long = "strandless",
help = "Calcualte counts ignore strand info"
)]
strandless: bool,
#[clap(
short = 's',
long = "split-strand",
help = "Split counts into different rows by strand"
)]
bystrand: bool,
#[clap(
short = 'c',
long = "--chunk-size",
default_value = "8",
help = "Start the job in multiple threads"
)]
chunk: u32,
#[clap(
short = 'j',
long = "--threads",
default_value = "8",
help = "Start the job in multiple threads"
)]
njobs: usize,
#[clap(
short = 'l',
long = "--log-type",
default_value = "0",
help = "Log type. 0: no log; 1: spans; 2: progress bar"
)]
logtype: u8,
}
#[derive(Parser)]
struct Count {
#[clap(short, long, help = "debug")]
debug: bool,
#[clap(short = 't', long = "target", help = "input bed file..")]
bed: PathBuf,
#[clap(short = 'r', long = "reference", help = "input fa file..")]
fa: PathBuf,
#[clap(short = 'i', long = "input", help = "input bam file..")]
bam: PathBuf,
}
impl SubCommand {}
fn main() {
let opts: Opts = Opts::parse();
match opts.verbose {
0 => print!(""),
1 => println!("Some verbose info"),
2 => println!("Tons of verbose info"),
_ => println!("Don't be ridiculous"),
}
match opts.subcmd {
SubCommand::Base(o) => {
base::run(
o.bed,
o.fa,
o.bam,
o.min_depth,
o.mean_depth,
o.qual,
o.indel,
o.headless,
o.strandless,
o.bystrand,
o.chunk,
o.njobs,
o.logtype,
);
}
SubCommand::Count(o) => {
count::run(o.bed, o.fa, o.bam);
}
}
}
fn file_path_validation(path: &str) -> Result<(), String> {
let path = Path::new(path);
if !path.exists() {
Err(format!("{path:?} file doesn't exists"))
} else if !path.is_file() {
Err(format!("{path:?} is not a file"))
} else {
Ok(())
}
}