use ::std::cmp;
use ::std::path::Path;
use ::wavelet_matrix::WaveletMatrix;
pub fn quality_to_proba(q: u8, qmin: u8) -> f64 {
10_f64.powf((qmin - q) as f64 / 10.0_f64)
}
#[inline]
fn remap_quality8(q: u8) -> u8 {
if q > 0x37 {
7
} else if q < 0x25 {
return 0;
} else {
let nqf = (cmp::min(q, 0x37) - 0x25) as f32 * 6.0_f32 / 18.0_f32;
1 + nqf.floor() as u8
}
}
pub enum QualityMode {
Raw,
WM,
}
#[allow(clippy::len_without_is_empty)]
pub trait QSequence {
fn get_mode(&self) -> QualityMode;
fn get_read_num(&self) -> usize;
fn len(&self) -> usize;
}
pub struct QSequenceWM {
read_num: usize,
pub qseq: WaveletMatrix,
}
impl QSequence for QSequenceWM {
fn get_mode(&self) -> QualityMode {
QualityMode::WM
}
fn get_read_num(&self) -> usize {
self.read_num
}
fn len(&self) -> usize {
self.qseq.len()
}
}
impl QSequenceWM {
pub fn new(read_n: usize, qv: &[u8]) -> QSequenceWM {
let remapped: Vec<u64> = qv.iter().map(|q| remap_quality8(*q) as u64).collect();
let qseqt = WaveletMatrix::new(&remapped);
QSequenceWM {
read_num: read_n,
qseq: qseqt,
}
}
pub fn decompress(&self) -> QSequenceRaw {
let len = self.qseq.len();
let mut vq = Vec::<u8>::with_capacity(len);
for i in 0..len {
vq.push(self.qseq.lookup(i) as u8);
}
QSequenceRaw {
read_num: self.read_num,
qseq: vq,
}
}
pub fn bit_len(&self) -> u8 {
self.qseq.bit_len()
}
}
pub struct QSequenceRaw {
pub read_num: usize,
pub qseq: Vec<u8>,
}
impl QSequence for QSequenceRaw {
fn get_mode(&self) -> QualityMode {
QualityMode::Raw
}
fn get_read_num(&self) -> usize {
self.read_num
}
fn len(&self) -> usize {
self.qseq.len()
}
}
impl QSequenceRaw {
pub fn compress_wm(&self) -> QSequenceWM {
QSequenceWM::new(self.read_num, &(self.qseq))
}
}
pub fn load_quality_wm(filename: &String) -> Result<Vec<QSequenceWM>, &'static str> {
println!("quality loading with needletail file : {} ", filename);
let path = Path::new(&filename);
let f_info_res = path.metadata();
match f_info_res {
Ok(_meta) => (),
Err(_e) => {
println!("file does not exist: {:?}", filename);
return Err("file does not exist");
}
}
let default_len = 1_000_000;
let mut seq_array: Vec<QSequenceWM> = Vec::with_capacity(default_len);
let mut n_qual = 0;
let mut n_read = 0;
let mut nb_bad_read = 0;
let mut reader = needletail::parse_fastx_file(path).expect("expecting valid filename");
while let Some(record) = reader.next() {
n_read += 1;
let seqrec = record.expect("invalid record");
if let Some(qual) = seqrec.qual() {
n_qual += qual.len();
let newseq = QSequenceWM::new(n_read, qual);
seq_array.push(newseq);
} else {
nb_bad_read += 1;
}
if seq_array.capacity() <= seq_array.len() + 100 {
let old_len = seq_array.len() as f64;
seq_array.reserve((old_len * 1.5) as usize);
}
if seq_array.len() % 200000 == 0 {
println!(" nb rec read = {} ", seq_array.len());
}
}
println!(" shrinking");
seq_array.shrink_to_fit();
println!(" shrinked ");
println!(" nb rec loaded = {} ", seq_array.len());
println!("nb_qual {:?}", n_qual);
println!("nb_read without quality {:?}", nb_bad_read);
Ok(seq_array)
}