use noodles::sam::alignment::Record;
use serde::Deserialize;
use serde::Serialize;
use crate::qc::results;
use crate::qc::ComputationalLoad;
use crate::qc::RecordBasedQualityControlFacet;
use crate::utils::histogram::Histogram;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SummaryMetrics {
pub template_length_unknown_pct: f64,
pub template_length_out_of_range_pct: f64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RecordMetrics {
pub processed: usize,
pub ignored: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TemplateLengthFacet {
pub histogram: Histogram,
pub records: RecordMetrics,
pub summary: Option<SummaryMetrics>,
}
impl TemplateLengthFacet {
pub fn with_capacity(capacity: usize) -> Self {
Self {
histogram: Histogram::zero_based_with_capacity(capacity),
records: RecordMetrics {
processed: 0,
ignored: 0,
},
summary: None,
}
}
}
impl RecordBasedQualityControlFacet for TemplateLengthFacet {
fn name(&self) -> &'static str {
"Template Length"
}
fn computational_load(&self) -> ComputationalLoad {
ComputationalLoad::Light
}
fn process(&mut self, record: &Record) -> anyhow::Result<()> {
let template_len = record.template_length() as usize;
match self.histogram.increment(template_len) {
Ok(()) => self.records.processed += 1,
Err(_) => self.records.ignored += 1,
}
Ok(())
}
fn summarize(&mut self) -> anyhow::Result<()> {
self.summary = Some(SummaryMetrics {
template_length_unknown_pct: (self.histogram.get(0) as f64
/ (self.records.processed as f64 + self.records.ignored as f64))
* 100.0,
template_length_out_of_range_pct: (self.records.ignored as f64
/ (self.records.processed as f64 + self.records.ignored as f64))
* 100.0,
});
Ok(())
}
fn aggregate(&self, results: &mut results::Results) {
results.template_length = Some(self.clone());
}
}