// ahda: Pseudoalignment compression and conversion between formats.
//
// Copyright 2025 Tommi Mäklin [tommi@maklin.fi].
//
// Copyrights in this project are retained by contributors. No copyright assignment
// is required to contribute to this project.
//
// Except as otherwise noted (below and/or in individual files), this
// project is licensed under the Apache License, Version 2.0
// <LICENSE-APACHE> or <http://www.apache.org/licenses/LICENSE-2.0> or
// the MIT license, <LICENSE-MIT> or <http://opensource.org/licenses/MIT>,
// at your option.
//
//! Parser for reading plain text data into memory from [Read].
//!
//! Reads in 1 [PseudoAln] at a time using next(), in the order they appear in
//! the input.
//!
//! The input format is detected automatically based on rules in [Format::from_bytes].
//! Some input formats may be ambiguous, in which case the format needs to be
//! specified using [new_with_format](Parser::new_with_format).
//!
//! If the input format includes header data, this will be consumed by Parser on
//! when next() is called for the first time.
//!
//! ## Usage
//!
//! Read in plain text data
//!
//! ```rust
//! use ahda::parser::Parser;
//! use ahda::{decode_from_read, PseudoAln};
//! use std::io::{Cursor, Seek, Write};
//!
//! // Mock inputs that will be stored in FileHeader and FileFlags
//! let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
//! let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
//! let name = "sample".to_string();
//!
//! // Have this plain text:
//! // 3 r7543 chr.fasta:virus.fasta
//! // 0 r1 virus.fasta
//! // 4 r16 chr.fasta:plasmid.fasta:virus.fasta
//! // 2 r651903
//! //
//! let mut plaintext: Vec<u8> = Vec::new();
//! plaintext.append(&mut b"0\tr1\tvirus.fasta\n".to_vec());
//! plaintext.append(&mut b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec());
//! plaintext.append(&mut b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec());
//! plaintext.append(&mut b"2\tr651903\t\n".to_vec());
//!
//! let mut input: Cursor<Vec<u8>> = Cursor::new(plaintext.clone());
//!
//! // Create a Parser to convert the plain text data to PseudoAlns
//! let mut it = queries.into_iter();
//! let mut t_it = targets.into_iter();
//! let mut parser = Parser::new(&mut input, Some(&mut it), Some(&mut t_it)).unwrap();
//!
//! let mut alns: Vec<PseudoAln> = Vec::new();
//!
//! // Push all records to `alns`
//! for record in parser.by_ref() {
//! alns.push(record.unwrap());
//! }
//!
//! assert_eq!(alns[1], PseudoAln { ones: Some(vec![0, 2]), ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()]), query_id: Some(3), query_name: Some("r7543".as_bytes().to_vec()) });
//! assert_eq!(alns[0], PseudoAln { ones: Some(vec![2]), ones_names: Some(vec!["virus.fasta".as_bytes().to_vec()]), query_id: Some(0), query_name: Some("r1".as_bytes().to_vec()) });
//! assert_eq!(alns[2], PseudoAln { ones: Some(vec![0, 1, 2]), ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()]), query_id: Some(4), query_name: Some("r16".as_bytes().to_vec()) });
//! assert_eq!(alns[3], PseudoAln { ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(2), query_name: Some("r651903".as_bytes().to_vec()) });
//! assert_eq!(alns.len(), 4);
//! ```
// Format specific implementations
pub mod ahda_tsv;
pub mod bifrost;
pub mod fulgor;
pub mod metagraph;
#[cfg(feature = "sam")]
pub mod sam;
pub mod themisto;
use crate::Format;
use crate::PseudoAln;
use crate::parser::ahda_tsv::read_ahda_tsv;
use crate::parser::bifrost::read_bifrost;
use crate::parser::fulgor::read_fulgor;
use crate::parser::fulgor::read_fulgor_v4;
use crate::parser::metagraph::read_metagraph;
#[cfg(feature = "sam")]
use crate::parser::sam::read_sam;
use crate::parser::themisto::read_themisto;
use indexmap::IndexSet;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Cursor;
use std::io::Seek;
use std::io::Read;
type E = Box<dyn std::error::Error>;
use crate::errors::{
CorruptedInputErr,
NeedTargetSequences,
KeyNotFound,
MapDoesNotContainIndex,
PseudoAlnQueryNameIsNone,
PseudoAlnQueryIdIsNone,
PseudoAlnOnesIsNone,
PseudoAlnOnesNamesIsNone,
};
/// Parser for plain text data.
pub struct Parser<'a, R: Read> {
reader: BufReader<&'a mut R>,
buf: Cursor<Vec<u8>>,
pub format: Format,
query_to_pos: Option<IndexSet<Vec<u8>>>,
target_to_pos: IndexSet<Vec<u8>>,
// What values to fill in the records
fill_query_id: bool,
fill_query_name: bool,
fill_target_ids: bool,
fill_target_names: bool,
}
impl<'a, R: Read> Parser<'a, R> {
/// Initialize from a [Read] and optional query, target sequence names.
///
/// Attempts to automatically detect the input format.
///
/// ## Errors
///
/// Returns [NeedTargetsSequences] if the detected format requires supplying
/// the target sequence names.
///
/// ## Usage
///
/// ### Initialize with query and target names
///
/// This initialization will work for all input [Format]s.
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// ```
///
/// ### Initialize without query names
///
/// Works for all formats but encoding the data may require supplying the
/// query names if the plain text format does not include the query index.
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let queries_it = None::<&mut std::iter::Empty<Vec<u8>>>;
/// let parser = Parser::new(&mut data, queries_it, Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// ```
///
/// ### Initialize without target names
///
/// Works for the AhdaTSV Bifrost, and SAM formats.
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// // Format: AhdaTSV
/// let plaintext: Vec<u8> = vec![
/// b"query_index\tquery_name\tchromosome.fasta\tplasmid.fasta\n".to_vec(),
/// b"0\tFastqQuery.1\t0\t0\n".to_vec(),
/// b"1\tFastqQuery.2\t0\t0\n".to_vec(),
/// b"2\tFastqQuery.3\t1\t0\n".to_vec(),
/// b"135608\tFastqQuery.135609\t1\t1\n".to_vec(),
/// b"100818\tFastqQuery.100819\t0\t1\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let targets_it = None::<&mut std::iter::Empty<Vec<u8>>>;
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), targets_it);
///
/// assert!(parser.is_ok());
/// ```
///
pub fn new<T: Iterator<Item=Vec<u8>>, Q: Iterator<Item=Vec<u8>>>(
conn_pseudoalns: &'a mut R,
conn_query_names: Option<&mut Q>,
targets: Option<&mut T>,
) -> Result<Self, E> {
// Guess the input format
let mut reader = BufReader::new(conn_pseudoalns);
let mut buf = Cursor::new(Vec::<u8>::new());
reader.read_until(b'\n', buf.get_mut())?;
let format = Format::from_bytes(buf.get_ref())?;
let mut ret = Self {
reader, buf, format,
query_to_pos: None,
target_to_pos: IndexSet::new(),
fill_query_id: true,
fill_query_name: true,
fill_target_ids: true,
fill_target_names: true,
};
let targets_from_header = ret.read_header()?;
if let Some(targets) = targets {
ret.target_to_pos = IndexSet::<Vec<u8>>::from_iter(targets);
} else if let Some(targets) = targets_from_header {
ret.target_to_pos = IndexSet::<Vec<u8>>::from_iter(targets);
} else {
return Err(Box::new(NeedTargetSequences{ format: ret.format }))
}
if let Some(conn_query_names) = conn_query_names {
ret.query_to_pos = Some(IndexSet::<Vec<u8>>::from_iter(conn_query_names));
}
Ok(ret)
}
/// Initialize with a specified input [Format].
///
/// ## Errors
///
/// Returns [NeedTargetsSequences] if the detected format requires supplying
/// the target sequence names.
///
/// ## Usage
///
/// ### Initialize with forced format
///
/// ```
/// use ahda::Format;
/// use ahda::parser::Parser;
/// use std::io::{Cursor, Seek};
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// // Format: Fulgor
/// let plaintext: Vec<u8> = vec![
/// b"11301\t0".to_vec(),
/// b"4995\t0".to_vec(),
/// b"7542\t1\t1".to_vec(),
/// b"15782\t0".to_vec(),
/// b"652016\t2\t0\t1".to_vec(),
/// b"100817\t1\t1".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
///
/// // We can force the format since we know what it is
///
/// let format = Format::Fulgor;
/// let parser = Parser::new_with_format(&mut data, Some(&mut queries_it), Some(&mut targets_it), format);
/// assert!(parser.is_ok());
/// ```
///
pub fn new_with_format<T: Iterator<Item=Vec<u8>>, Q: Iterator<Item=Vec<u8>>>(
conn_pseudoalns: &'a mut R,
conn_query_names: Option<&mut Q>,
targets: Option<&mut T>,
format: Format,
) -> Result<Self, E> {
// Guess the input format
let mut reader = BufReader::new(conn_pseudoalns);
let mut buf = Cursor::new(Vec::<u8>::new());
reader.read_until(b'\n', buf.get_mut())?;
let mut ret = Self {
reader, buf, format,
query_to_pos: None,
target_to_pos: IndexSet::new(),
fill_query_id: true,
fill_query_name: true,
fill_target_ids: true,
fill_target_names: true,
};
let targets_from_header = ret.read_header()?;
if let Some(targets) = targets {
ret.target_to_pos = IndexSet::<Vec<u8>>::from_iter(targets);
} else if let Some(targets) = targets_from_header {
ret.target_to_pos = IndexSet::<Vec<u8>>::from_iter(targets);
} else {
return Err(Box::new(NeedTargetSequences{ format: ret.format }))
}
if let Some(conn_query_names) = conn_query_names {
ret.query_to_pos = Some(IndexSet::<Vec<u8>>::from_iter(conn_query_names));
}
Ok(ret)
}
}
impl<R: Read> Parser<'_, R> {
/// Consumes the header line and returns the target sequence names.
///
/// The header line is only present in Bifrost and Metagraph output. For
/// Themisto and Fulgor, this will return None.
///
/// Returns None if the header has already been consumed by calling [Parser::next].
/// This is checked by looking whether target_to_pos contains anything.
///
/// ## Errors
///
/// - [CorruptedInputErr] if the header should be present but it can't be parsed.
///
fn read_header(
&mut self,
) -> Result<Option<Vec<Vec<u8>>>, E> {
if !self.target_to_pos.is_empty() || self.buf.get_ref().is_empty() {
return Ok(None)
}
match self.format {
Format::Themisto => Ok(None),
Format::Fulgor => Ok(None),
Format::FulgorV4 => Ok(None),
Format::Metagraph => Ok(None),
Format::Bifrost => {
let separator: char = '\t';
let contents: String = self.buf.get_ref().iter().map(|x| *x as char).collect();
let mut records = contents.split(separator);
// Consume `query_name`
records.next().ok_or(CorruptedInputErr{})?;
let mut target_names: Vec<Vec<u8>> = Vec::new();
for record in records {
target_names.push(record.as_bytes().to_vec());
}
let n_targets = target_names.len();
target_names[n_targets - 1].pop();
self.buf.get_mut().clear();
Ok(Some(target_names))
}
#[cfg(feature = "sam")]
Format::SAM => {
let mut header_contents = Cursor::new(self.buf.get_mut().clone());
let mut next_line: Cursor<Vec<u8>> = Cursor::new(Vec::new());
loop {
self.reader.read_until(b'\n', next_line.get_mut())?;
if next_line.get_ref().is_empty() {
break;
}
if next_line.get_ref()[0] == b'@' {
header_contents.get_mut().append(next_line.get_mut());
} else {
self.buf = next_line.clone();
break;
}
}
let mut reader = noodles_sam::io::reader::Builder::default().build_from_reader(&mut header_contents)?;
let header = reader.read_header()?;
let target_names: Vec<Vec<u8>> = header.reference_sequences().iter().map(|x| x.0.to_vec()).collect();
Ok(Some(target_names))
},
Format::AhdaTSV => {
let separator: char = '\t';
let contents: String = self.buf.get_ref().iter().map(|x| *x as char).collect();
let mut records = contents.split(separator);
// Consume `query_index`
records.next().ok_or(CorruptedInputErr{})?;
// Consume `query_name`
records.next().ok_or(CorruptedInputErr{})?;
let mut target_names: Vec<Vec<u8>> = Vec::new();
for record in records {
target_names.push(record.as_bytes().to_vec());
}
let n_targets = target_names.len();
target_names[n_targets - 1].pop();
self.buf.get_mut().clear();
Ok(Some(target_names))
},
}
}
/// Returns the number of query records in the input fastX file.
///
/// Will return None if the Parser was initialized without query names.
///
/// ## Usage
///
/// ### Initialized with query names
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
/// let n_queries = queries.len();
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.as_ref().is_ok());
/// assert!(parser.as_ref().unwrap().len().is_some());
/// assert!(parser.as_ref().unwrap().len().unwrap() == n_queries);
/// ```
///
/// ### Initialized without query names
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let queries_it = None::<&mut std::iter::Empty<Vec<u8>>>;
/// let parser = Parser::new(&mut data, queries_it, Some(&mut targets_it));
///
/// assert!(parser.as_ref().is_ok());
/// assert!(parser.as_ref().unwrap().len().is_none());
/// ```
pub fn len(
&self,
) -> Option<usize> {
self.query_to_pos.as_ref().map(|x| x.len())
}
/// Does the input contain any queries?
///
/// Will return None if the Parser was initialized without query names.
///
/// Will return Some(true) if the parser was initialized with query names of length 0.
///
/// ## Usage
///
/// ### Initialized with query names
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
/// let n_queries = queries.len();
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.as_ref().is_ok());
/// assert!(parser.as_ref().unwrap().is_empty().is_some());
/// assert!(parser.as_ref().unwrap().is_empty().unwrap() == false);
/// ```
///
/// ### Initialized without query names
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let queries_it = None::<&mut std::iter::Empty<Vec<u8>>>;
/// let parser = Parser::new(&mut data, queries_it, Some(&mut targets_it));
///
/// assert!(parser.as_ref().is_ok());
/// assert!(parser.as_ref().unwrap().is_empty().is_none());
/// ```
///
/// ### Initialized with empty query names
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![];
/// let n_queries = queries.len();
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.as_ref().is_ok());
/// assert!(parser.as_ref().unwrap().is_empty().is_some());
/// assert!(parser.as_ref().unwrap().is_empty().unwrap() == true);
/// ```
pub fn is_empty(
&self,
) -> Option<bool> {
self.len().map(|len| len == 0)
}
/// Returns the target sequence names.
///
/// ## Usage
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
///
/// // Format: Metagraph
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.clone().into_iter();
/// let queries_it = None::<&mut std::iter::Empty<Vec<u8>>>;
/// let parser = Parser::new(&mut data, queries_it, Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// assert_eq!(parser.unwrap().get_targets().unwrap(), targets);
/// ```
pub fn get_targets(
&self,
) -> Option<Vec<Vec<u8>>> {
if self.target_to_pos.is_empty() {
unreachable!("Parser cannot be initialized without target sequence names.")
} else {
Some(self.target_to_pos.iter().cloned().collect())
}
}
/// Fill the empty fields in a [PseudoAln].
///
/// ## Errors
///
/// - [KeyNotFound]
/// - [PseudoAlnQueryNameIsNone]
/// - [MapDoesNotContainIndex]
/// - [PseudoAlnQueryIdIsNone]
/// - [PseudoAlnOnesIsNone]
/// - [PseudoAlnOnesNamesIsNone]
///
fn fill_record(
&mut self,
record: &mut PseudoAln,
) -> Result<(), E> {
if record.query_id.is_none() && self.fill_query_id {
if let Some(query_name) = record.query_name.as_ref() {
let key: Vec<u8> = query_name.to_vec();
match self.query_to_pos.as_ref().unwrap().get_index_of(&key) {
Some(query_index) => {
record.query_id = Some(query_index as u32);
},
None => {
return Err(Box::new(KeyNotFound { key, map_name: "Parser::query_to_pos".to_string() }))
},
}
} else {
return Err(Box::new(PseudoAlnQueryNameIsNone{}))
}
}
if record.query_name.is_none() && self.fill_query_name {
if let Some(query_id) = record.query_id.as_ref() {
match self.query_to_pos.as_ref().unwrap().get_index(*query_id as usize) {
Some(query_name) => {
record.query_name = Some(query_name.to_vec());
},
None => {
return Err(Box::new(MapDoesNotContainIndex { index: *query_id as usize, map_name: "Parser::query_to_pos".to_string() }))
}
}
} else {
return Err(Box::new(PseudoAlnQueryIdIsNone{}))
}
}
if record.ones_names.is_none() && record.ones.is_some() && self.fill_target_names {
if let Some(ones) = record.ones.as_ref() {
let mut ones_names: Vec<Vec<u8>> = Vec::with_capacity(ones.len());
for target_idx in ones {
let target_name = match self.target_to_pos.get_index(*target_idx as usize) {
Some(target_name) => target_name,
None => return Err(Box::new(MapDoesNotContainIndex { index: *target_idx as usize, map_name: "Parser::target_to_pos".to_string() })),
};
ones_names.push(target_name.clone());
}
record.ones_names = Some(ones_names);
} else {
return Err(Box::new(PseudoAlnOnesIsNone{}))
}
}
if record.ones_names.is_some() && record.ones.is_none() && self.fill_target_ids{
if let Some(ones_names) = record.ones_names.as_ref() {
let mut ones: Vec<u32> = Vec::with_capacity(ones_names.len());
for target_name in ones_names {
let target_idx = match self.target_to_pos.get_index_of(target_name) {
Some(target_idx) => target_idx,
None => return Err(Box::new(KeyNotFound { key: target_name.clone(), map_name: "Parser::target_to_pos".to_string() })),
};
ones.push(target_idx as u32);
}
record.ones = Some(ones);
} else {
return Err(Box::new(PseudoAlnOnesNamesIsNone{}))
}
}
if !self.fill_query_id {
record.query_id = None;
}
if !self.fill_query_name {
record.query_name = None;
}
if !self.fill_target_ids {
record.ones = None;
}
if !self.fill_target_names {
record.ones_names = None;
}
Ok(())
}
/// Should Parser fill the `query_id` field for each record?
///
/// Suggest to try to fill the field `query_id` if the input does not
/// contain this information.
///
/// Will be overriden if the Parser was initialized without query names, as
/// [Parser::fill_record] needs them to fill the field.
///
/// ## Usage
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// let plaintext: Vec<u8> = vec![
/// b"query_name\tchromosome.fasta\tplasmid.fasta\n".to_vec(),
/// b"r1\t0\n".to_vec(),
/// b"r2\t0\n".to_vec(),
/// b"r651903\t1\t1\n".to_vec(),
/// b"r16\t0\n".to_vec(),
/// b"r7543\t2\t0\t1\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// let mut parser = parser.unwrap();
///
/// // Default is to fill
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().query_id.is_some());
///
/// // We can change it
/// parser.fill_query_id(false);
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().query_id.is_none());
/// ```
pub fn fill_query_id(
&mut self,
val: bool,
) {
self.fill_query_id = val && self.query_to_pos.is_some();
}
/// Should Parser fill the `query_name` field for each record?
///
/// Suggest to try to fill the field `query_name` if the input does not
/// contain this information.
///
/// Will be overriden if the Parser was initialized without query names, as
/// [Parser::fill_record] needs them to fill the field.
///
/// ## Usage
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// let plaintext: Vec<u8> = vec![
/// b"1 0\n".to_vec(),
/// b"2 0\n".to_vec(),
/// b"651903 1\n".to_vec(),
/// b"16 0\n".to_vec(),
/// b"7543 2 0 1\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// let mut parser = parser.unwrap();
///
/// // Default is to fill
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().query_name.is_some());
///
/// // We can change it
/// parser.fill_query_name(false);
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().query_name.is_none());
/// ```
pub fn fill_query_name(
&mut self,
val: bool,
) {
self.fill_query_name = val && self.query_to_pos.is_some();
}
/// Should Parser fill the `ones` field for each record?
///
/// Suggest to try to fill the field `ones` if the input does not
/// contain this information.
///
/// ## Usage
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// let plaintext: Vec<u8> = vec![
/// b"0\tr1\tvirus.fasta\n".to_vec(),
/// b"3\tr7543\tchr.fasta:virus.fasta\n".to_vec(),
/// b"4\tr16\tchr.fasta:plasmid.fasta:virus.fasta\n".to_vec(),
/// b"2\tr651903\t\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// let mut parser = parser.unwrap();
///
/// // Default is to fill
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().ones.is_some());
///
/// // We can change it
/// parser.fill_target_ids(false);
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().ones.is_none());
/// ```
pub fn fill_target_ids(
&mut self,
val: bool,
) {
self.fill_target_ids = val;
}
/// Should Parser fill the `ones_names` field for each record?
///
/// Suggest to try to fill the field `ones_names` if the input does not
/// contain this information.
///
/// ## Usage
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// let plaintext: Vec<u8> = vec![
/// b"1 0\n".to_vec(),
/// b"2 0\n".to_vec(),
/// b"651903 1\n".to_vec(),
/// b"16 0\n".to_vec(),
/// b"7543 2 0 1\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// let mut parser = parser.unwrap();
///
/// // Default is to fill
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().ones_names.is_some());
///
/// // We can change it
/// parser.fill_target_names(false);
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
/// assert!(record.unwrap().unwrap().ones_names.is_none());
/// ```
pub fn fill_target_names(
&mut self,
val: bool,
) {
self.fill_target_names = val;
}
}
impl<R: Read> Iterator for Parser<'_, R> {
type Item = Result<PseudoAln, E>;
/// Parse the next record
///
/// ## Usage
///
/// ```rust
/// use ahda::parser::Parser;
/// use std::io::Cursor;
///
/// let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec(), "virus.fasta".as_bytes().to_vec()];
/// let queries = vec![b"r1".to_vec(), b"r2".to_vec(), b"r651903".to_vec(), b"r7543".to_vec(), b"r16".to_vec()];
///
/// let plaintext: Vec<u8> = vec![
/// b"query_name\tchromosome.fasta\tplasmid.fasta\n".to_vec(),
/// b"r1\t0\n".to_vec(),
/// b"r2\t0\n".to_vec(),
/// ].into_iter().flatten().collect();
///
/// let mut data: Cursor<Vec<u8>> = Cursor::new(plaintext);
/// let mut targets_it = targets.into_iter();
/// let mut queries_it = queries.into_iter();
/// let parser = Parser::new(&mut data, Some(&mut queries_it), Some(&mut targets_it));
///
/// assert!(parser.is_ok());
/// let mut parser = parser.unwrap();
///
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
///
/// let record = parser.next();
/// assert!(record.as_ref().is_some());
///
/// let record = parser.next();
/// assert!(record.as_ref().is_none());
/// ```
fn next(
&mut self,
) -> Option<Result<PseudoAln, E>> {
if self.buf.get_ref().is_empty() {
let ret = self.reader.read_until(b'\n', self.buf.get_mut());
if ret.is_err() || self.buf.get_ref().is_empty() {
return None
}
match self.buf.rewind() {
Ok(_) => (),
Err(e) => return Some(Err(Box::new(e))),
}
}
self.buf.get_mut().pop();
let try_record = match self.format {
Format::Themisto => read_themisto(&mut self.buf),
Format::Fulgor => read_fulgor(&mut self.buf),
Format::FulgorV4 => read_fulgor_v4(&mut self.buf),
Format::Metagraph => read_metagraph(&mut self.buf),
Format::Bifrost => read_bifrost(&mut self.buf),
#[cfg(feature = "sam")]
Format::SAM => read_sam(&mut self.buf),
Format::AhdaTSV => read_ahda_tsv(&mut self.buf),
};
let mut record = match try_record {
Ok(record) => record,
Err(e) => return Some(Err(e)),
};
self.buf.get_mut().clear();
match self.fill_record(&mut record) {
Ok(_) => Some(Ok(record)),
Err(e) => Some(Err(e)),
}
}
}
// Tests
#[cfg(test)]
mod tests {
#[test]
fn consume_bifrost_header_with_next() {
use super::Parser;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"query_name\tchr.fasta\tplasmid.fasta\n".to_vec();
data.append(&mut b"ERR4035126.1\t121\t0\n".to_vec());
let expected: PseudoAln = PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(0), ones: Some(vec![0]), query_name: Some("ERR4035126.1".as_bytes().to_vec()) };
let mut cursor = Cursor::new(data);
let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let queries = vec!["ERR4035126.1".as_bytes().to_vec()];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let got: PseudoAln = reader.next().unwrap().unwrap();
assert_eq!(got, expected);
}
#[test]
fn read_bifrost_header() {
use super::Parser;
use std::io::Cursor;
let mut data: Vec<u8> = b"query_name\tchr.fasta\tplasmid.fasta\n".to_vec();
data.append(&mut b"ERR4035126.1\t121\t0\n".to_vec());
let expected: Vec<Vec<u8>> = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let mut cursor = Cursor::new(data);
let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let queries = vec!["ERR4035126.1".as_bytes().to_vec()];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let got = reader.get_targets().unwrap();
assert_eq!(got, expected);
}
#[test]
#[cfg(feature = "sam")]
fn read_sam_header() {
use super::Parser;
use std::io::Cursor;
let mut data: Vec<u8> = b"@HD\tVN:1.5\tSO:unsorted\tGO:query\n".to_vec();
data.append(&mut b"@SQ\tSN:OZ038621.1\tLN:5535987\n".to_vec());
data.append(&mut b"@SQ\tSN:OZ038622.1\tLN:104814\n".to_vec());
data.append(&mut b"@PG\tID:bwa\tPN:bwa\tVN:0.7.19-r1273\tCL:bwa mem -t 10 -o fwd_test.sam GCA_964037205.1_30348_1_60_genomic.fna ERR4035126_1.fastq.gz\n".to_vec());
data.append(&mut b"ERR4035126.1\t16\tOZ038621.1\t4541508\t60\t151M\t*\t0\t0\tAGTATTTAGTGACCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGC FJ<<JJFJAA<-JFAJFAF<JFFJJJJJJJFJFJJA<A<AJJAAAFFJJJJFJJFJFJAJJ7JJJJJFJJJJJFFJFFJFJJJJJJFJ7FFJAJJJJJJJJFJJFJJFJFJJJJFJJFJJJJJJJJJFFJJJJJJJJJJJJJFJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
let expected: Vec<Vec<u8>> = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let mut cursor = Cursor::new(data);
let targets = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let queries = vec!["ERR4035126.1".as_bytes().to_vec()];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let got = reader.get_targets().unwrap();
assert_eq!(got, expected);
}
#[test]
#[cfg(feature = "sam")]
fn consume_sam_header_with_next() {
use super::Parser;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"@HD\tVN:1.5\tSO:unsorted\tGO:query\n".to_vec();
data.append(&mut b"@SQ\tSN:OZ038621.1\tLN:5535987\n".to_vec());
data.append(&mut b"@SQ\tSN:OZ038622.1\tLN:104814\n".to_vec());
data.append(&mut b"@PG\tID:bwa\tPN:bwa\tVN:0.7.19-r1273\tCL:bwa mem -t 10 -o fwd_test.sam GCA_964037205.1_30348_1_60_genomic.fna ERR4035126_1.fastq.gz\n".to_vec());
data.append(&mut b"ERR4035126.1\t16\tOZ038621.1\t4541508\t60\t151M\t*\t0\t0\tAGTATTTAGTGACCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGC FJ<<JJFJAA<-JFAJFAF<JFFJJJJJJJFJFJJA<A<AJJAAAFFJJJJFJJFJFJAJJ7JJJJJFJJJJJFFJFFJFJJJJJJFJ7FFJAJJJJJJJJFJJFJJFJFJJJJFJJFJJJJJJJJJFFJJJJJJJJJJJJJFJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
let expected = PseudoAln{ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), query_id: Some(0), ones: Some(vec![0]), query_name: Some("ERR4035126.1".as_bytes().to_vec()) };
let mut cursor = Cursor::new(data);
let targets = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let queries = vec!["ERR4035126.1".as_bytes().to_vec()];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let got: PseudoAln = reader.next().unwrap().unwrap();
assert_eq!(got, expected);
}
#[test]
#[cfg(feature = "sam")]
fn read_sam_header_and_first_line() {
use super::Parser;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"@HD\tVN:1.5\tSO:unsorted\tGO:query\n".to_vec();
data.append(&mut b"@SQ\tSN:OZ038621.1\tLN:5535987\n".to_vec());
data.append(&mut b"@SQ\tSN:OZ038622.1\tLN:104814\n".to_vec());
data.append(&mut b"@PG\tID:bwa\tPN:bwa\tVN:0.7.19-r1273\tCL:bwa mem -t 10 -o fwd_test.sam GCA_964037205.1_30348_1_60_genomic.fna ERR4035126_1.fastq.gz\n".to_vec());
data.append(&mut b"ERR4035126.1\t16\tOZ038621.1\t4541508\t60\t151M\t*\t0\t0\tAGTATTTAGTGACCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGC FJ<<JJFJAA<-JFAJFAF<JFFJJJJJJJFJFJJA<A<AJJAAAFFJJJJFJJFJFJAJJ7JJJJJFJJJJJFFJFFJFJJJJJJFJ7FFJAJJJJJJJJFJJFJJFJFJJJJFJJFJJJJJJJJJFFJJJJJJJJJJJJJFJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
let expected_header: Vec<Vec<u8>> = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let expected_aln = PseudoAln{ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), query_id: Some(0), ones: Some(vec![0]), query_name: Some("ERR4035126.1".as_bytes().to_vec()) };
let mut cursor = Cursor::new(data);
let targets = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let queries = vec!["ERR4035126.1".as_bytes().to_vec()];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let got_header = reader.get_targets().unwrap();
assert_eq!(got_header, expected_header);
let got_aln: PseudoAln = reader.next().unwrap().unwrap();
assert_eq!(got_aln, expected_aln);
}
#[test]
#[cfg(feature = "sam")]
fn read_sam_multiple() {
use super::Parser;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"@HD\tVN:1.5\tSO:unsorted\tGO:query\n".to_vec();
data.append(&mut b"@SQ\tSN:OZ038621.1\tLN:5535987\n".to_vec());
data.append(&mut b"@SQ\tSN:OZ038622.1\tLN:104814\n".to_vec());
data.append(&mut b"@PG\tID:bwa\tPN:bwa\tVN:0.7.19-r1273\tCL:bwa mem -t 10 -o fwd_test.sam GCA_964037205.1_30348_1_60_genomic.fna ERR4035126_1.fastq.gz\n".to_vec());
data.append(&mut b"ERR4035126.1\t16\tOZ038621.1\t4541508\t60\t151M\t*\t0\t0\tAGTATTTAGTGACCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGC FJ<<JJFJAA<-JFAJFAF<JFFJJJJJJJFJFJJA<A<AJJAAAFFJJJJFJJFJFJAJJ7JJJJJFJJJJJFFJFFJFJJJJJJFJ7FFJAJJJJJJJJFJJFJJFJFJJJJFJJFJJJJJJJJJFFJJJJJJJJJJJJJFJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.2\t16\tOZ038621.1\t4541557\t60\t151M\t*\t0\t0\tAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGGTGATATTTTTTTCAATATCATGCAGCAAACGGTGCA JAFJFJJJFFJFAJJJJJJJJJJFFA<JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJFF-FFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.3\t16\tOZ038622.1\t4541521\t60\t151M\t*\t0\t0\tCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGG JJJJJJJFJFFFJJJJJJAJJJF7JJJJJ<JJFFJJJJJJJFJJJJJJJJJFFFJJJFJJJJJJJJJJJJJJJJAJFJJJJFJJJJJJJJJJJJJJJJJJJJJJAJJJJJJJJJJJJJJJJJAJFJFJJJJJJJJJJJJJJJJJFJFAFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
let expected = vec![
PseudoAln{ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), query_id: Some(0), ones: Some(vec![0]), query_name: Some("ERR4035126.1".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), query_id: Some(1), ones: Some(vec![0]), query_name: Some("ERR4035126.2".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["OZ038622.1".as_bytes().to_vec()]), query_id: Some(2), ones: Some(vec![1]), query_name: Some("ERR4035126.3".as_bytes().to_vec()) },
];
let mut cursor = Cursor::new(data);
let targets = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let queries = vec!["ERR4035126.1".as_bytes().to_vec(), "ERR4035126.2".as_bytes().to_vec(), "ERR4035126.3".as_bytes().to_vec()];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut got: Vec<PseudoAln> = Vec::new();
while let Some(record) = reader.next() {
got.push(record.unwrap());
}
assert_eq!(got, expected);
}
#[test]
fn parse_themisto_output() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let data: Vec<u8> = vec![b"128 0 7 11 3\n".to_vec(),
b"7 3 2 1 0\n".to_vec(),
b"8\n".to_vec(),
b"0\n".to_vec(),
b"1 4 2 9 7\n".to_vec(),
].concat();
let expected = vec![
PseudoAln{ones_names: Some(vec!["0".as_bytes().to_vec(), "7".as_bytes().to_vec(), "11".as_bytes().to_vec(), "3".as_bytes().to_vec()]), query_id: Some(128), ones: Some(vec![0, 7, 11, 3]), query_name: Some("128".as_bytes().to_vec())},
PseudoAln{ones_names: Some(vec!["3".as_bytes().to_vec(), "2".as_bytes().to_vec(), "1".as_bytes().to_vec(), "0".as_bytes().to_vec()]), query_id: Some(7), ones: Some(vec![3, 2, 1, 0]), query_name: Some("7".as_bytes().to_vec())},
PseudoAln{ones_names: Some(vec![]), query_id: Some(8), ones: Some(vec![]), query_name: Some("8".as_bytes().to_vec())},
PseudoAln{ones_names: Some(vec![]), query_id: Some(0), ones: Some(vec![]), query_name: Some("0".as_bytes().to_vec())},
PseudoAln{ones_names: Some(vec!["4".as_bytes().to_vec(), "2".as_bytes().to_vec(), "9".as_bytes().to_vec(), "7".as_bytes().to_vec()]), query_id: Some(1), ones: Some(vec![4, 2, 9, 7]), query_name: Some("1".as_bytes().to_vec())},
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let targets = vec![
"0".as_bytes().to_vec(),
"1".as_bytes().to_vec(),
"2".as_bytes().to_vec(),
"3".as_bytes().to_vec(),
"4".as_bytes().to_vec(),
"5".as_bytes().to_vec(),
"6".as_bytes().to_vec(),
"7".as_bytes().to_vec(),
"8".as_bytes().to_vec(),
"9".as_bytes().to_vec(),
"10".as_bytes().to_vec(),
"11".as_bytes().to_vec(),
];
let queries = (0..129).map(|x| x.to_string().as_bytes().to_vec()).collect::<Vec<Vec<u8>>>();
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::Themisto);
assert_eq!(got, expected);
}
#[test]
fn parse_fulgor_output() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"ERR4035126.4996\t0\n".to_vec();
data.append(&mut b"ERR4035126.1262953\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262954\t1\t1\n".to_vec());
data.append(&mut b"ERR4035126.1262955\t1\t1\n".to_vec());
data.append(&mut b"ERR4035126.1262956\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262957\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262958\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262959\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.651965\t2\t0\t1\n".to_vec());
data.append(&mut b"ERR4035126.11302\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262960\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262961\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.1262962\t1\t0\n".to_vec());
data.append(&mut b"ERR4035126.651965\t2\t0\t1\n".to_vec());
let expected = vec![
PseudoAln{ones_names: Some(vec![]), query_id: Some(0), ones: Some(vec![]), query_name: Some("ERR4035126.4996".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(1), ones: Some(vec![0]), query_name: Some("ERR4035126.1262953".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(2), ones: Some(vec![1]), query_name: Some("ERR4035126.1262954".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(3), ones: Some(vec![1]), query_name: Some("ERR4035126.1262955".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(4), ones: Some(vec![0]), query_name: Some("ERR4035126.1262956".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(5), ones: Some(vec![0]), query_name: Some("ERR4035126.1262957".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(6), ones: Some(vec![0]), query_name: Some("ERR4035126.1262958".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(7), ones: Some(vec![0]), query_name: Some("ERR4035126.1262959".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(8), ones: Some(vec![0, 1]), query_name: Some("ERR4035126.651965".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec![]), query_id: Some(9), ones: Some(vec![]), query_name: Some("ERR4035126.11302".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(10), ones: Some(vec![0]), query_name: Some("ERR4035126.1262960".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(11), ones: Some(vec![0]), query_name: Some("ERR4035126.1262961".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(12), ones: Some(vec![0]), query_name: Some("ERR4035126.1262962".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(8), ones: Some(vec![0, 1]), query_name: Some("ERR4035126.651965".as_bytes().to_vec()) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let queries = vec![
"ERR4035126.4996".as_bytes().to_vec(),
"ERR4035126.1262953".as_bytes().to_vec(),
"ERR4035126.1262954".as_bytes().to_vec(),
"ERR4035126.1262955".as_bytes().to_vec(),
"ERR4035126.1262956".as_bytes().to_vec(),
"ERR4035126.1262957".as_bytes().to_vec(),
"ERR4035126.1262958".as_bytes().to_vec(),
"ERR4035126.1262959".as_bytes().to_vec(),
"ERR4035126.651965".as_bytes().to_vec(),
"ERR4035126.11302".as_bytes().to_vec(),
"ERR4035126.1262960".as_bytes().to_vec(),
"ERR4035126.1262961".as_bytes().to_vec(),
"ERR4035126.1262962".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::Fulgor);
assert_eq!(got, expected);
}
#[test]
fn parse_fulgor_v4_output() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"0\t0\n".to_vec();
data.append(&mut b"1\t1\t0\n".to_vec());
data.append(&mut b"2\t1\t1\n".to_vec());
data.append(&mut b"3\t1\t1\n".to_vec());
data.append(&mut b"4\t1\t0\n".to_vec());
data.append(&mut b"5\t1\t0\n".to_vec());
data.append(&mut b"6\t1\t0\n".to_vec());
data.append(&mut b"7\t1\t0\n".to_vec());
data.append(&mut b"8\t2\t0\t1\n".to_vec());
data.append(&mut b"9\t0\n".to_vec());
data.append(&mut b"10\t1\t0\n".to_vec());
data.append(&mut b"11\t1\t0\n".to_vec());
data.append(&mut b"12\t1\t0\n".to_vec());
data.append(&mut b"8\t2\t0\t1\n".to_vec());
let expected = vec![
PseudoAln{ones_names: Some(vec![]), query_id: Some(0), ones: Some(vec![]), query_name: Some("ERR4035126.4996".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(1), ones: Some(vec![0]), query_name: Some("ERR4035126.1262953".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(2), ones: Some(vec![1]), query_name: Some("ERR4035126.1262954".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(3), ones: Some(vec![1]), query_name: Some("ERR4035126.1262955".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(4), ones: Some(vec![0]), query_name: Some("ERR4035126.1262956".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(5), ones: Some(vec![0]), query_name: Some("ERR4035126.1262957".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(6), ones: Some(vec![0]), query_name: Some("ERR4035126.1262958".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(7), ones: Some(vec![0]), query_name: Some("ERR4035126.1262959".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(8), ones: Some(vec![0, 1]), query_name: Some("ERR4035126.651965".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec![]), query_id: Some(9), ones: Some(vec![]), query_name: Some("ERR4035126.11302".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(10), ones: Some(vec![0]), query_name: Some("ERR4035126.1262960".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(11), ones: Some(vec![0]), query_name: Some("ERR4035126.1262961".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(12), ones: Some(vec![0]), query_name: Some("ERR4035126.1262962".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(8), ones: Some(vec![0, 1]), query_name: Some("ERR4035126.651965".as_bytes().to_vec()) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let queries = vec![
"ERR4035126.4996".as_bytes().to_vec(),
"ERR4035126.1262953".as_bytes().to_vec(),
"ERR4035126.1262954".as_bytes().to_vec(),
"ERR4035126.1262955".as_bytes().to_vec(),
"ERR4035126.1262956".as_bytes().to_vec(),
"ERR4035126.1262957".as_bytes().to_vec(),
"ERR4035126.1262958".as_bytes().to_vec(),
"ERR4035126.1262959".as_bytes().to_vec(),
"ERR4035126.651965".as_bytes().to_vec(),
"ERR4035126.11302".as_bytes().to_vec(),
"ERR4035126.1262960".as_bytes().to_vec(),
"ERR4035126.1262961".as_bytes().to_vec(),
"ERR4035126.1262962".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::FulgorV4);
assert_eq!(got, expected);
}
#[test]
fn parse_bifrost_output() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"query_name\tchromosome.fasta\tplasmid.fasta\n".to_vec();
data.append(&mut b"ERR4035126.724962\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1235744\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.431001\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.645400\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.3001\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.515778\t242\t0\n".to_vec());
data.append(&mut b"ERR4035126.886205\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.1254676\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.668031\t0\t121\n".to_vec());
data.append(&mut b"ERR4035126.388619\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.959743\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1146685\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1017809\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.788136\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1223924\t366\t9\n".to_vec());
data.append(&mut b"ERR4035126.910807\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.824748\t80\t0\n".to_vec());
let expected = vec![
PseudoAln{ query_name: Some("ERR4035126.724962".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(0) },
PseudoAln{ query_name: Some("ERR4035126.1235744".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(1) },
PseudoAln{ query_name: Some("ERR4035126.431001".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(2) },
PseudoAln{ query_name: Some("ERR4035126.645400".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(3) },
PseudoAln{ query_name: Some("ERR4035126.3001".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(4) },
PseudoAln{ query_name: Some("ERR4035126.515778".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(5) },
PseudoAln{ query_name: Some("ERR4035126.886205".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(6) },
PseudoAln{ query_name: Some("ERR4035126.1254676".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(7) },
PseudoAln{ query_name: Some("ERR4035126.668031".as_bytes().to_vec()), ones: Some(vec![1]), ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(8) },
PseudoAln{ query_name: Some("ERR4035126.388619".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(9) },
PseudoAln{ query_name: Some("ERR4035126.959743".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(10) },
PseudoAln{ query_name: Some("ERR4035126.1146685".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(11) },
PseudoAln{ query_name: Some("ERR4035126.1017809".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(12) },
PseudoAln{ query_name: Some("ERR4035126.788136".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(13) },
PseudoAln{ query_name: Some("ERR4035126.1223924".as_bytes().to_vec()), ones: Some(vec![0, 1]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(14) },
PseudoAln{ query_name: Some("ERR4035126.910807".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(15) },
PseudoAln{ query_name: Some("ERR4035126.824748".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(16) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let targets = vec!["chromosome.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let queries = vec![
"ERR4035126.724962".as_bytes().to_vec(),
"ERR4035126.1235744".as_bytes().to_vec(),
"ERR4035126.431001".as_bytes().to_vec(),
"ERR4035126.645400".as_bytes().to_vec(),
"ERR4035126.3001".as_bytes().to_vec(),
"ERR4035126.515778".as_bytes().to_vec(),
"ERR4035126.886205".as_bytes().to_vec(),
"ERR4035126.1254676".as_bytes().to_vec(),
"ERR4035126.668031".as_bytes().to_vec(),
"ERR4035126.388619".as_bytes().to_vec(),
"ERR4035126.959743".as_bytes().to_vec(),
"ERR4035126.1146685".as_bytes().to_vec(),
"ERR4035126.1017809".as_bytes().to_vec(),
"ERR4035126.788136".as_bytes().to_vec(),
"ERR4035126.1223924".as_bytes().to_vec(),
"ERR4035126.910807".as_bytes().to_vec(),
"ERR4035126.824748".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::Bifrost);
assert_eq!(got, expected);
}
#[test]
fn parse_bifrost_output_with_targets_from_data() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"query_name\tchromosome.fasta\tplasmid.fasta\n".to_vec();
data.append(&mut b"ERR4035126.724962\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1235744\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.431001\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.645400\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.3001\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.515778\t242\t0\n".to_vec());
data.append(&mut b"ERR4035126.886205\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.1254676\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.668031\t0\t121\n".to_vec());
data.append(&mut b"ERR4035126.388619\t121\t0\n".to_vec());
data.append(&mut b"ERR4035126.959743\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1146685\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1017809\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.788136\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.1223924\t366\t9\n".to_vec());
data.append(&mut b"ERR4035126.910807\t0\t0\n".to_vec());
data.append(&mut b"ERR4035126.824748\t80\t0\n".to_vec());
let expected = vec![
PseudoAln{ query_name: Some("ERR4035126.724962".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(0) },
PseudoAln{ query_name: Some("ERR4035126.1235744".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(1) },
PseudoAln{ query_name: Some("ERR4035126.431001".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(2) },
PseudoAln{ query_name: Some("ERR4035126.645400".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(3) },
PseudoAln{ query_name: Some("ERR4035126.3001".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(4) },
PseudoAln{ query_name: Some("ERR4035126.515778".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(5) },
PseudoAln{ query_name: Some("ERR4035126.886205".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(6) },
PseudoAln{ query_name: Some("ERR4035126.1254676".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(7) },
PseudoAln{ query_name: Some("ERR4035126.668031".as_bytes().to_vec()), ones: Some(vec![1]), ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(8) },
PseudoAln{ query_name: Some("ERR4035126.388619".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(9) },
PseudoAln{ query_name: Some("ERR4035126.959743".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(10) },
PseudoAln{ query_name: Some("ERR4035126.1146685".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(11) },
PseudoAln{ query_name: Some("ERR4035126.1017809".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(12) },
PseudoAln{ query_name: Some("ERR4035126.788136".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(13) },
PseudoAln{ query_name: Some("ERR4035126.1223924".as_bytes().to_vec()), ones: Some(vec![0, 1]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(14) },
PseudoAln{ query_name: Some("ERR4035126.910807".as_bytes().to_vec()), ones: Some(vec![]), ones_names: Some(vec![]), query_id: Some(15) },
PseudoAln{ query_name: Some("ERR4035126.824748".as_bytes().to_vec()), ones: Some(vec![0]), ones_names: Some(vec!["chromosome.fasta".as_bytes().to_vec()]), query_id: Some(16) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let queries = vec![
"ERR4035126.724962".as_bytes().to_vec(),
"ERR4035126.1235744".as_bytes().to_vec(),
"ERR4035126.431001".as_bytes().to_vec(),
"ERR4035126.645400".as_bytes().to_vec(),
"ERR4035126.3001".as_bytes().to_vec(),
"ERR4035126.515778".as_bytes().to_vec(),
"ERR4035126.886205".as_bytes().to_vec(),
"ERR4035126.1254676".as_bytes().to_vec(),
"ERR4035126.668031".as_bytes().to_vec(),
"ERR4035126.388619".as_bytes().to_vec(),
"ERR4035126.959743".as_bytes().to_vec(),
"ERR4035126.1146685".as_bytes().to_vec(),
"ERR4035126.1017809".as_bytes().to_vec(),
"ERR4035126.788136".as_bytes().to_vec(),
"ERR4035126.1223924".as_bytes().to_vec(),
"ERR4035126.910807".as_bytes().to_vec(),
"ERR4035126.824748".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), None::<&mut std::iter::Empty<Vec<u8>>>).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::Bifrost);
assert_eq!(got, expected);
}
#[test]
fn parse_metgraph_output() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"3\tERR4035126.2\tchr.fasta\n".to_vec();
data.append(&mut b"2\tERR4035126.1\tchr.fasta\n".to_vec());
data.append(&mut b"1303804\tERR4035126.651903\tchr.fasta:plasmid.fasta\n".to_vec());
data.append(&mut b"30\tERR4035126.16\t\n".to_vec());
data.append(&mut b"15084\tERR4035126.7543\tplasmid.fasta\n".to_vec());
let expected = vec![
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(3), ones: Some(vec![0]), query_name: Some("ERR4035126.2".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec()]), query_id: Some(2), ones: Some(vec![0]), query_name: Some("ERR4035126.1".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()]), query_id: Some(1303804), ones: Some(vec![0, 1]), query_name: Some("ERR4035126.651903".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec![]), query_id: Some(30), ones: Some(vec![]), query_name: Some("ERR4035126.16".as_bytes().to_vec()) },
PseudoAln{ones_names: Some(vec!["plasmid.fasta".as_bytes().to_vec()]), query_id: Some(15084), ones: Some(vec![1]), query_name: Some("ERR4035126.7543".as_bytes().to_vec()) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let targets = vec!["chr.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let queries = vec![
"ERR4035126.2".as_bytes().to_vec(),
"ERR4035126.1".as_bytes().to_vec(),
"ERR4035126.651903".as_bytes().to_vec(),
"ERR4035126.16".as_bytes().to_vec(),
"ERR4035126.7543".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::Metagraph);
assert_eq!(got, expected);
}
#[test]
#[cfg(feature = "sam")]
fn parse_sam_output() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"@HD\tVN:1.5\tSO:unsorted\tGO:query\n".to_vec();
data.append(&mut b"@SQ\tSN:OZ038621.1\tLN:5535987\n".to_vec());
data.append(&mut b"@SQ\tSN:OZ038622.1\tLN:104814\n".to_vec());
data.append(&mut b"@PG\tID:bwa\tPN:bwa\tVN:0.7.19-r1273\tCL:bwa mem -t 10 -o fwd_test.sam GCA_964037205.1_30348_1_60_genomic.fna ERR4035126_1.fastq.gz\n".to_vec());
data.append(&mut b"ERR4035126.1\t16\tOZ038621.1\t4541508\t60\t151M\t*\t0\t0\tAGTATTTAGTGACCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGC\tFJ<<JJFJAA<-JFAJFAF<JFFJJJJJJJFJFJJA<A<AJJAAAFFJJJJFJJFJFJAJJ7JJJJJFJJJJJFFJFFJFJJJJJJFJ7FFJAJJJJJJJJFJJFJJFJFJJJJFJJFJJJJJJJJJFFJJJJJJJJJJJJJFJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.2\t16\tOZ038621.1\t4541557\t60\t151M\t*\t0\t0\tAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGGTGATATTTTTTTCAATATCATGCAGCAAACGGTGCA\tJAFJFJJJFFJFAJJJJJJJJJJFFA<JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJFF-FFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.3\t16\tOZ038621.1\t4541521\t60\t151M\t*\t0\t0\tCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGG\tJJJJJJJFJFFFJJJJJJAJJJF7JJJJJ<JJFFJJJJJJJFJJJJJJJJJFFFJJJFJJJJJJJJJJJJJJJJAJFJJJJFJJJJJJJJJJJJJJJJJJJJJJAJJJJJJJJJJJJJJJJJAJFJFJJJJJJJJJJJJJJJJJFJFAFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.1261584\t16\tOZ038622.1\t66398\t60\t151M\t*\t0\t0\tGCCGCTGTCTGAACCATGATATTGGCGGAACCGATGCCCATGATGGATGCGCCCCACAGCATGACCAGTTGCGCCAGACTCCAGCCGGAAGCGGTGGGCACAATCATCAAAAATCCACTCACGACACTGAGTATGCCGACGACGTCCCGTC\tFFJJJJFFJFJFFFJJJJJJJJJJJ7FA<JJ<JFJJFJJJJF-FJJA<FJJJJAJJJJJJJJJJJJJJJJJJJJFFJJJFJJJJJJJJJJJJJJJJJJFJFJJJJJJJJJFJJJJJFJJFJFJFJJJJJJJJJJJJJJJJJJJJJJFFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.1213410\t16\tOZ038622.1\t3996\t60\t151M\t*\t0\t0\tGCTGGCGCTTCGGGGATATGTGTTTCGACGGCAGATGAATTTATTCCGGCGGGGGCTGATTCTGCCGTCTGTTCAGTAAATACAGGTGCGATAATATCTGTTTTTTCGGATAAGGACGGTGGCGAAAAAGTACGACGTTTTTTCACCACAA\tJJJJJJJJJJJJJJJJJJJJJJJJJJJFJFJFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFJJJJJJJJJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.1213410\t16\tOZ038621.1\t3996\t60\t151M\t*\t0\t0\tGCTGGCGCTTCGGGGATATGTGTTTCGACGGCAGATGAATTTATTCCGGCGGGGGCTGATTCTGCCGTCTGTTCAGTAAATACAGGTGCGATAATATCTGTTTTTTCGGATAAGGACGGTGGCGAAAAAGTACGACGTTTTTTCACCACAA\tJJJJJJJJJJJJJJJJJJJJJJJJJJJFJFJFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFJJJJJJJJJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.4\t0\tOZ038621.1\t4541351\t60\t151M\t*\t0\t0\tAGGTGCGGGCTTTTTTCTGTGTTTCCTGTACGCGTCAGCCCGCACCGTTACCTGTGGTAATGGTGATGGTGGTGGTAATGGTGGTGCTAATGCGTTTCATGGATGTTGTGTACTCTGTAATTTTTATCTGTCTGTGCGCTATGCCTATATT\tAAFFFJJJJJJJJJJJJJJJJJJJJJFFJJJJJJJJJJJJJJJJJJJFFJJJJJJJJFJJJJJJJJJJJ<JFJJJJJJJJJJJAJJJFJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJFFFJFAFJJJJF<FFFJJJJ\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.5\t16\tOZ038621.1\t4541533\t60\t151M\t*\t0\t0\tAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGGTGATATTTTTTT\tFJJJJJJJJFJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJFFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.6\t0\tOZ038621.1\t4541261\t60\t151M\t*\t0\t0\tTCTGCATTTGCCACTGATGTACCGCCGAACTTCAACACTCGCATGGTTGTTACCTCGTTACCTTTGGTCGAAAAAAAAGCCCGCACTGTCAGGTGCGGGCTTTTTTCTGTGTTTCCTGTACGCGTCAGCCCGCACCGTTACCTGTGGTAAT\tAAAFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJFJJJJJJJJ<FJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJFJJJJF7FJJJJJJJFJFJJJJJJJJFJJJJJJJJAJJJJFJFFFJFJF\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.973529\t16\tOZ038621.1\t3695316\t60\t66S85M\t*\t0\t0\tGGAGATGATTTCGTGTTTCTTCTCCGGGATGACCATGTCATCGATACCAACAGATGCACCAGAACGCGCCAAGTCGGGCAATCTGGTGAACTGGAAAGCCGGGGCGCTGTATCACCTGACGGAAAACGGCAATGTCTATATTAACTATGCC\tJJFJFF7-FFJJJA-FJFFFJJFAJJJJJJJJJJJJJJJJFJJJJJJJJFJJJJFJ<JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFJFJJJJJJJJFJJJJJJJJFAJJJJJJJJJJJJJFJJJJJFFJJJFJJJJJJFJJFFFAA\tNM:i:0\tMD:Z:85\tAS:i:85\tXS:i:0\tSA:Z:OZ038621.1,5194124,-,69M82S,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.973529\t2064\tOZ038621.1\t5194124\t60\t69M82H\t*\t0\t0\tGGAGATGATTTCGTGTTTCTTCTCCGGGATGACCATGTCATCGATACCAACAGATGCACCAGAACGCGC\tJJFJFF7-FFJJJA-FJFFFJJFAJJJJJJJJJJJJJJJJFJJJJJJJJFJJJJFJ<JJJJJJJJJJJJ\tNM:i:0\tMD:Z:69\tAS:i:69\tXS:i:0\tSA:Z:OZ038621.1,3695316,-,66S85M,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.621281\t16\tOZ038621.1\t1040569\t60\t39S86M26S\t*\t0\t0\tGCTCGACCGCGTCCCAGTTGAAATGCAACTCCCCAGCCAACTCGATAAACACGATGATTAACACGGCAGTCATGGTCAGAATGGAAACGGGATCGAAAATCGGCATACCAAATGACATCGGCGTGCCACAGCACAAACTGGACGCCCTGGC\tAFAJJJJJJJJJJJJFJJJJJJJJJJJJJJJJFJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFFAA\tNM:i:0\tMD:Z:86\tAS:i:86\tXS:i:0\tSA:Z:OZ038621.1,3172373,-,46M105S,60,0;OZ038621.1,1301509,+,33M118S,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.1178767\t4\t*\t0\t0\t*\t*\t0\t0\tACTTGGCTCATGTTCCGTCAATGCCGGAGAGACAATTGAAGTTGATTTAGGTGATGTCTTCGCTGCCAATTTCCGTGTTGTAGGGCATAAACCTCTTGGGGCCAGAACGGCAGAACTTGCAATTCCAGTCAGGTGTAACACGGGAAACGCG\tAAFFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\tAS:i:0\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.621281\t2064\tOZ038621.1\t3172373\t60\t46M105H\t*\t0\t0\tGCTCGACCGCGTCCCAGTTGAAATGCAACTCCCCAGCCAACTCGAT\tAFAJJJJJJJJJJJJFJJJJJJJJJJJJJJJJFJFJJJJJJJJJJJ\tNM:i:0\tMD:Z:46\tAS:i:46\tXS:i:0\tSA:Z:OZ038621.1,1040569,-,39S86M26S,60,0;OZ038621.1,1301509,+,33M118S,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.621281\t2048\tOZ038621.1\t1301509\t60\t33M118H\t*\t0\t0\tGCCAGGGCGTCCAGTTTGTGCTGTGGCACGCCG\tAAFFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\tNM:i:0\tMD:Z:33\tAS:i:33\tXS:i:0\tSA:Z:OZ038621.1,1040569,-,39S86M26S,60,0;OZ038621.1,3172373,-,46M105S,60,0;\n".to_vec());
let expected = vec![
PseudoAln{ query_id: Some(0), query_name: Some("ERR4035126.1".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(1), query_name: Some("ERR4035126.2".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(2), query_name: Some("ERR4035126.3".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(3), query_name: Some("ERR4035126.1261584".as_bytes().to_vec()), ones_names: Some(vec!["OZ038622.1".as_bytes().to_vec()]), ones: Some(vec![1]) },
PseudoAln{ query_id: Some(4), query_name: Some("ERR4035126.1213410".as_bytes().to_vec()), ones_names: Some(vec!["OZ038622.1".as_bytes().to_vec()]), ones: Some(vec![1]) },
PseudoAln{ query_id: Some(4), query_name: Some("ERR4035126.1213410".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(5), query_name: Some("ERR4035126.4".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(6), query_name: Some("ERR4035126.5".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(7), query_name: Some("ERR4035126.6".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(8), query_name: Some("ERR4035126.973529".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(8), query_name: Some("ERR4035126.973529".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(9), query_name: Some("ERR4035126.621281".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(10), query_name: Some("ERR4035126.1178767".as_bytes().to_vec()), ones_names: None, ones: None },
PseudoAln{ query_id: Some(9), query_name: Some("ERR4035126.621281".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(9), query_name: Some("ERR4035126.621281".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let targets = vec!["OZ038621.1".as_bytes().to_vec(), "OZ038622.1".as_bytes().to_vec()];
let queries = vec![
"ERR4035126.1".as_bytes().to_vec(),
"ERR4035126.2".as_bytes().to_vec(),
"ERR4035126.3".as_bytes().to_vec(),
"ERR4035126.1261584".as_bytes().to_vec(),
"ERR4035126.1213410".as_bytes().to_vec(),
"ERR4035126.4".as_bytes().to_vec(),
"ERR4035126.5".as_bytes().to_vec(),
"ERR4035126.6".as_bytes().to_vec(),
"ERR4035126.973529".as_bytes().to_vec(),
"ERR4035126.621281".as_bytes().to_vec(),
"ERR4035126.1178767".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut t_it = targets.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), Some(&mut t_it)).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::SAM);
got.iter().zip(expected.iter()).for_each(|(x, y)| { assert_eq!(x, y) });
assert_eq!(got, expected);
}
#[test]
#[cfg(feature = "sam")]
fn parse_sam_output_with_targets_from_data() {
use super::Parser;
use crate::Format;
use crate::PseudoAln;
use std::io::Cursor;
let mut data: Vec<u8> = b"@HD\tVN:1.5\tSO:unsorted\tGO:query\n".to_vec();
data.append(&mut b"@SQ\tSN:OZ038621.1\tLN:5535987\n".to_vec());
data.append(&mut b"@SQ\tSN:OZ038622.1\tLN:104814\n".to_vec());
data.append(&mut b"@PG\tID:bwa\tPN:bwa\tVN:0.7.19-r1273\tCL:bwa mem -t 10 -o fwd_test.sam GCA_964037205.1_30348_1_60_genomic.fna ERR4035126_1.fastq.gz\n".to_vec());
data.append(&mut b"ERR4035126.1\t16\tOZ038621.1\t4541508\t60\t151M\t*\t0\t0\tAGTATTTAGTGACCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGC\tFJ<<JJFJAA<-JFAJFAF<JFFJJJJJJJFJFJJA<A<AJJAAAFFJJJJFJJFJFJAJJ7JJJJJFJJJJJFFJFFJFJJJJJJFJ7FFJAJJJJJJJJFJJFJJFJFJJJJFJJFJJJJJJJJJFFJJJJJJJJJJJJJFJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.2\t16\tOZ038621.1\t4541557\t60\t151M\t*\t0\t0\tAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGGTGATATTTTTTTCAATATCATGCAGCAAACGGTGCA\tJAFJFJJJFFJFAJJJJJJJJJJFFA<JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJFF-FFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.3\t16\tOZ038621.1\t4541521\t60\t151M\t*\t0\t0\tCTAAGTCAATAAAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGG\tJJJJJJJFJFFFJJJJJJAJJJF7JJJJJ<JJFFJJJJJJJFJJJJJJJJJFFFJJJFJJJJJJJJJJJJJJJJAJFJJJJFJJJJJJJJJJJJJJJJJJJJJJAJJJJJJJJJJJJJJJJJAJFJFJJJJJJJJJJJJJJJJJFJFAFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.1261584\t16\tOZ038622.1\t66398\t60\t151M\t*\t0\t0\tGCCGCTGTCTGAACCATGATATTGGCGGAACCGATGCCCATGATGGATGCGCCCCACAGCATGACCAGTTGCGCCAGACTCCAGCCGGAAGCGGTGGGCACAATCATCAAAAATCCACTCACGACACTGAGTATGCCGACGACGTCCCGTC\tFFJJJJFFJFJFFFJJJJJJJJJJJ7FA<JJ<JFJJFJJJJF-FJJA<FJJJJAJJJJJJJJJJJJJJJJJJJJFFJJJFJJJJJJJJJJJJJJJJJJFJFJJJJJJJJJFJJJJJFJJFJFJFJJJJJJJJJJJJJJJJJJJJJJFFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.1213410\t16\tOZ038622.1\t3996\t60\t151M\t*\t0\t0\tGCTGGCGCTTCGGGGATATGTGTTTCGACGGCAGATGAATTTATTCCGGCGGGGGCTGATTCTGCCGTCTGTTCAGTAAATACAGGTGCGATAATATCTGTTTTTTCGGATAAGGACGGTGGCGAAAAAGTACGACGTTTTTTCACCACAA\tJJJJJJJJJJJJJJJJJJJJJJJJJJJFJFJFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFJJJJJJJJJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.1213410\t16\tOZ038621.1\t3996\t60\t151M\t*\t0\t0\tGCTGGCGCTTCGGGGATATGTGTTTCGACGGCAGATGAATTTATTCCGGCGGGGGCTGATTCTGCCGTCTGTTCAGTAAATACAGGTGCGATAATATCTGTTTTTTCGGATAAGGACGGTGGCGAAAAAGTACGACGTTTTTTCACCACAA\tJJJJJJJJJJJJJJJJJJJJJJJJJJJFJFJFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFJJJJJJJJJJJFFAAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.4\t0\tOZ038621.1\t4541351\t60\t151M\t*\t0\t0\tAGGTGCGGGCTTTTTTCTGTGTTTCCTGTACGCGTCAGCCCGCACCGTTACCTGTGGTAATGGTGATGGTGGTGGTAATGGTGGTGCTAATGCGTTTCATGGATGTTGTGTACTCTGTAATTTTTATCTGTCTGTGCGCTATGCCTATATT\tAAFFFJJJJJJJJJJJJJJJJJJJJJFFJJJJJJJJJJJJJJJJJJJFFJJJJJJJJFJJJJJJJJJJJ<JFJJJJJJJJJJJAJJJFJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJFFFJFAFJJJJF<FFFJJJJ\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.5\t16\tOZ038621.1\t4541533\t60\t151M\t*\t0\t0\tAATTTTAATTTACTCACGGCAGGTAACCAGTTCAGAAGCTGCTATCAGACACTCTTTTTTTAATCCACACAGAGACATATTGCCCGTTGCAGTCAGAATGAAAAGCTGAAAATCACTTACTAAGGCGTTTTTTATTTGGTGATATTTTTTT\tFJJJJJJJJFJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJFFFAA\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.6\t0\tOZ038621.1\t4541261\t60\t151M\t*\t0\t0\tTCTGCATTTGCCACTGATGTACCGCCGAACTTCAACACTCGCATGGTTGTTACCTCGTTACCTTTGGTCGAAAAAAAAGCCCGCACTGTCAGGTGCGGGCTTTTTTCTGTGTTTCCTGTACGCGTCAGCCCGCACCGTTACCTGTGGTAAT\tAAAFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJFJJJJJJJJ<FJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJFJJJJF7FJJJJJJJFJFJJJJJJJJFJJJJJJJJAJJJJFJFFFJFJF\tNM:i:0\tMD:Z:151\tAS:i:151\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.973529\t16\tOZ038621.1\t3695316\t60\t66S85M\t*\t0\t0\tGGAGATGATTTCGTGTTTCTTCTCCGGGATGACCATGTCATCGATACCAACAGATGCACCAGAACGCGCCAAGTCGGGCAATCTGGTGAACTGGAAAGCCGGGGCGCTGTATCACCTGACGGAAAACGGCAATGTCTATATTAACTATGCC\tJJFJFF7-FFJJJA-FJFFFJJFAJJJJJJJJJJJJJJJJFJJJJJJJJFJJJJFJ<JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFJFJJJJJJJJFJJJJJJJJFAJJJJJJJJJJJJJFJJJJJFFJJJFJJJJJJFJJFFFAA\tNM:i:0\tMD:Z:85\tAS:i:85\tXS:i:0\tSA:Z:OZ038621.1,5194124,-,69M82S,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.973529\t2064\tOZ038621.1\t5194124\t60\t69M82H\t*\t0\t0\tGGAGATGATTTCGTGTTTCTTCTCCGGGATGACCATGTCATCGATACCAACAGATGCACCAGAACGCGC\tJJFJFF7-FFJJJA-FJFFFJJFAJJJJJJJJJJJJJJJJFJJJJJJJJFJJJJFJ<JJJJJJJJJJJJ\tNM:i:0\tMD:Z:69\tAS:i:69\tXS:i:0\tSA:Z:OZ038621.1,3695316,-,66S85M,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.621281\t16\tOZ038621.1\t1040569\t60\t39S86M26S\t*\t0\t0\tGCTCGACCGCGTCCCAGTTGAAATGCAACTCCCCAGCCAACTCGATAAACACGATGATTAACACGGCAGTCATGGTCAGAATGGAAACGGGATCGAAAATCGGCATACCAAATGACATCGGCGTGCCACAGCACAAACTGGACGCCCTGGC\tAFAJJJJJJJJJJJJFJJJJJJJJJJJJJJJJFJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFFFAA\tNM:i:0\tMD:Z:86\tAS:i:86\tXS:i:0\tSA:Z:OZ038621.1,3172373,-,46M105S,60,0;OZ038621.1,1301509,+,33M118S,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.1178767\t4\t*\t0\t0\t*\t*\t0\t0\tACTTGGCTCATGTTCCGTCAATGCCGGAGAGACAATTGAAGTTGATTTAGGTGATGTCTTCGCTGCCAATTTCCGTGTTGTAGGGCATAAACCTCTTGGGGCCAGAACGGCAGAACTTGCAATTCCAGTCAGGTGTAACACGGGAAACGCG\tAAFFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\tAS:i:0\tXS:i:0\n".to_vec());
data.append(&mut b"ERR4035126.621281\t2064\tOZ038621.1\t3172373\t60\t46M105H\t*\t0\t0\tGCTCGACCGCGTCCCAGTTGAAATGCAACTCCCCAGCCAACTCGAT\tAFAJJJJJJJJJJJJFJJJJJJJJJJJJJJJJFJFJJJJJJJJJJJ\tNM:i:0\tMD:Z:46\tAS:i:46\tXS:i:0\tSA:Z:OZ038621.1,1040569,-,39S86M26S,60,0;OZ038621.1,1301509,+,33M118S,60,0;\n".to_vec());
data.append(&mut b"ERR4035126.621281\t2048\tOZ038621.1\t1301509\t60\t33M118H\t*\t0\t0\tGCCAGGGCGTCCAGTTTGTGCTGTGGCACGCCG\tAAFFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJ\tNM:i:0\tMD:Z:33\tAS:i:33\tXS:i:0\tSA:Z:OZ038621.1,1040569,-,39S86M26S,60,0;OZ038621.1,3172373,-,46M105S,60,0;\n".to_vec());
let expected = vec![
PseudoAln{ query_id: Some(0), query_name: Some("ERR4035126.1".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(1), query_name: Some("ERR4035126.2".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(2), query_name: Some("ERR4035126.3".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(3), query_name: Some("ERR4035126.1261584".as_bytes().to_vec()), ones_names: Some(vec!["OZ038622.1".as_bytes().to_vec()]), ones: Some(vec![1]) },
PseudoAln{ query_id: Some(4), query_name: Some("ERR4035126.1213410".as_bytes().to_vec()), ones_names: Some(vec!["OZ038622.1".as_bytes().to_vec()]), ones: Some(vec![1]) },
PseudoAln{ query_id: Some(4), query_name: Some("ERR4035126.1213410".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(5), query_name: Some("ERR4035126.4".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(6), query_name: Some("ERR4035126.5".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(7), query_name: Some("ERR4035126.6".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(8), query_name: Some("ERR4035126.973529".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(8), query_name: Some("ERR4035126.973529".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(9), query_name: Some("ERR4035126.621281".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(10), query_name: Some("ERR4035126.1178767".as_bytes().to_vec()), ones_names: None, ones: None },
PseudoAln{ query_id: Some(9), query_name: Some("ERR4035126.621281".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
PseudoAln{ query_id: Some(9), query_name: Some("ERR4035126.621281".as_bytes().to_vec()), ones_names: Some(vec!["OZ038621.1".as_bytes().to_vec()]), ones: Some(vec![0]) },
];
let mut cursor: Cursor<Vec<u8>> = Cursor::new(data);
let queries = vec![
"ERR4035126.1".as_bytes().to_vec(),
"ERR4035126.2".as_bytes().to_vec(),
"ERR4035126.3".as_bytes().to_vec(),
"ERR4035126.1261584".as_bytes().to_vec(),
"ERR4035126.1213410".as_bytes().to_vec(),
"ERR4035126.4".as_bytes().to_vec(),
"ERR4035126.5".as_bytes().to_vec(),
"ERR4035126.6".as_bytes().to_vec(),
"ERR4035126.973529".as_bytes().to_vec(),
"ERR4035126.621281".as_bytes().to_vec(),
"ERR4035126.1178767".as_bytes().to_vec(),
];
let mut it = queries.into_iter();
let mut reader = Parser::new(&mut cursor, Some(&mut it), None::<&mut std::iter::Empty<Vec<u8>>>).unwrap();
let mut res: Vec<PseudoAln> = Vec::new();
for record in reader.by_ref() {
res.push(record.unwrap());
}
let (got, got_format) = (res, reader.format);
assert_eq!(got_format, Format::SAM);
got.iter().zip(expected.iter()).for_each(|(x, y)| { assert_eq!(x, y) });
assert_eq!(got, expected);
}
}