Skip to main content

cyto_cli/map/
input.rs

1use anyhow::{Context, Result};
2use binseq::BinseqReader;
3use clap::Parser;
4
5pub use anyhow::bail;
6use log::error;
7use paraseq::{fastx, BoxedReader};
8
9#[derive(Parser, Debug)]
10#[clap(next_help_heading = "Paired input options")]
11pub struct MultiPairedInput {
12    /// Paths to input files to process.
13    ///
14    /// If using BINSEQ input (*.bq/*.vbq), the ordering of files or number of files does not matter.
15    ///
16    /// If using FASTX input, the input files are expected to be paired and sequentially ordered (`S1_R1`, `S1_R2`, `S2_R1`, `S2_R2`, ...).
17    /// This is expecting an even number of files.
18    #[clap(num_args = 1.., required=true)]
19    pub inputs: Vec<String>,
20}
21impl MultiPairedInput {
22    pub fn is_binseq(&self) -> bool {
23        self.inputs
24            .iter()
25            .all(|path| path.ends_with(".bq") || path.ends_with(".vbq") || path.ends_with("cbq"))
26    }
27
28    pub fn to_binseq_readers(&self) -> Result<Vec<BinseqReader>> {
29        let mut readers = Vec::new();
30        for path in &self.inputs {
31            let reader = BinseqReader::new(path)
32                .context(format!("Failed to open BINSEQ reader for path: {path}"))?;
33            if !reader.is_paired() {
34                error!(
35                    "Provided BINSEQ path is not paired. All inputs are expected to be paired: {path}"
36                );
37                bail!("Input file is not paired: {path}");
38            }
39            readers.push(reader);
40        }
41        Ok(readers)
42    }
43
44    pub fn to_paraseq_collection(&self) -> Result<fastx::Collection<BoxedReader>> {
45        if !self.inputs.len().is_multiple_of(2) {
46            error!(
47                "Found {} inputs, expecting an even number of file pairs",
48                self.inputs.len()
49            );
50            bail!("Number of pairs must be even");
51        }
52        let collection =
53            fastx::Collection::from_paths(&self.inputs, fastx::CollectionType::Paired)?;
54        Ok(collection)
55    }
56}