use clap::{ArgGroup, Parser};
use std::path::PathBuf;
#[derive(Parser, Debug, Clone)]
#[command(name = "nanocov")]
#[command(about = "Calculates per-base coverage from a BAM file", long_about = None)]
#[command(group(
ArgGroup::new("mode")
.required(true)
.args(["input", "batch_tsv"])
))]
pub struct Cli {
#[arg(short, long)]
pub input: Option<PathBuf>,
#[arg(long = "batch-tsv")]
pub batch_tsv: Option<PathBuf>,
#[arg(short = 'b', long = "bed")]
pub bed: Option<PathBuf>,
#[arg(short = 't', long = "threads")]
pub threads: Option<usize>,
#[arg(short = 'o', long = "output-dir")]
pub output_dir: PathBuf,
#[arg(long = "prefix")]
pub prefix: Option<String>,
#[arg(long = "batch-output")]
pub batch_output: Option<PathBuf>,
#[arg(short = 'c', long = "chunk-size", default_value_t = 100_000)]
pub chunk_size: usize,
#[arg(long = "svg")]
pub svg_output: bool,
#[arg(long = "plot-bin-size")]
pub plot_bin_size: Option<u32>,
#[arg(long = "theme")]
pub theme: Option<String>,
#[arg(long = "show-zeros")]
pub show_zero_regions: bool,
#[arg(long = "overview-plot")]
pub overview_plot: bool,
#[arg(long = "per-chromosome-plot")]
pub per_chromosome_plot: bool,
#[arg(long = "non-canonical")]
pub include_non_canonical: bool,
#[arg(long = "invert-regions")]
pub invert_regions: bool,
#[arg(long = "linear")]
pub linear_scale: bool,
#[arg(long = "sequential-plots")]
pub sequential_plots: bool,
#[arg(long = "async-tasks")]
pub async_tasks: Option<usize>,
#[arg(long = "io-buffer-size")]
pub io_buffer_size_kb: Option<usize>,
#[arg(long = "mmap")]
pub use_mmap: bool,
#[arg(long = "adaptive-chunks")]
pub adaptive_chunks: bool,
}
impl Cli {
pub fn output_prefix(&self) -> String {
if let Some(prefix) = &self.prefix {
return prefix.clone();
}
self.input
.as_ref()
.and_then(|path| path.file_stem())
.and_then(|s| s.to_str())
.map(|s| s.to_string())
.unwrap_or_else(|| "coverage".to_string())
}
pub fn coverage_output_path(&self) -> PathBuf {
self.output_dir()
.join(format!("{}.tsv", self.output_prefix()))
}
pub fn output_dir(&self) -> PathBuf {
self.output_dir.clone()
}
pub fn batch_output_path(&self) -> PathBuf {
if let Some(path) = &self.batch_output {
path.clone()
} else {
self.output_dir().join("batch.statistics.tsv")
}
}
pub fn wants_overview_plot(&self) -> bool {
self.overview_plot
}
pub fn wants_per_chromosome_plot(&self) -> bool {
self.per_chromosome_plot
}
pub fn wants_any_plot(&self) -> bool {
self.wants_overview_plot() || self.wants_per_chromosome_plot()
}
pub fn use_concurrent_plots(&self) -> bool {
!self.sequential_plots
}
pub fn use_log_scale(&self) -> bool {
!self.linear_scale
}
pub fn input_path(&self) -> &std::path::Path {
self.input
.as_deref()
.expect("input BAM path must be set before processing")
}
}