pub mod adapter_content;
pub mod basic_stats;
pub mod duplication_level;
pub mod gc_content;
pub mod kmer_content;
pub mod n_content;
pub mod overrepresented_seqs;
pub mod per_base_quality;
pub mod per_base_sequence_content;
pub mod per_sequence_quality;
pub mod per_tile_quality;
pub mod sequence_length_distribution;
use std::fmt;
use std::io;
use std::sync::{Arc, Mutex};
use crate::config::{FastQCConfig, Limits, LimitsExt};
use crate::sequence::Sequence;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModuleStatus {
Pass,
Warn,
Fail,
}
impl fmt::Display for ModuleStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ModuleStatus::Pass => write!(f, "PASS"),
ModuleStatus::Warn => write!(f, "WARN"),
ModuleStatus::Fail => write!(f, "FAIL"),
}
}
}
pub trait QCModule: Send {
fn process_sequence(&mut self, sequence: &Sequence);
fn name(&self) -> &str;
fn description(&self) -> &str;
fn reset(&mut self);
fn set_filename(&mut self, _name: &str) {}
fn finalize(&mut self) {}
fn raises_error(&self) -> bool;
fn raises_warning(&self) -> bool;
fn ignore_filtered_sequences(&self) -> bool;
fn ignore_in_report(&self) -> bool;
fn status(&self) -> ModuleStatus {
if self.raises_error() {
ModuleStatus::Fail
} else if self.raises_warning() {
ModuleStatus::Warn
} else {
ModuleStatus::Pass
}
}
fn chart_image_name(&self) -> Option<&str> {
None
}
fn chart_alt_text(&self) -> Option<&str> {
None
}
fn generate_chart_svg(&self) -> Option<String> {
None
}
fn write_text_report(&self, writer: &mut dyn io::Write) -> io::Result<()>;
fn write_html_report(&self, writer: &mut dyn io::Write) -> io::Result<()> {
if let Some(alt_text) = self.chart_alt_text() {
return crate::report::html::write_chart(self, alt_text, writer);
}
let mut text_buf = Vec::new();
self.write_text_report(&mut text_buf)?;
let text = String::from_utf8(text_buf)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
crate::report::html::write_default_html_table(&text, writer)
}
}
pub fn create_modules(config: &FastQCConfig, limits: &Limits) -> Vec<Box<dyn QCModule>> {
let mut modules: Vec<Box<dyn QCModule>> = Vec::new();
let ng = config.nogroup;
let eg = config.expgroup;
let adapters = config.load_adapters().unwrap_or_default();
let contaminants = config.load_contaminants().unwrap_or_default();
modules.push(Box::new(basic_stats::BasicStats::new(limits)));
if limits.is_module_enabled("quality_base") {
modules.push(Box::new(per_base_quality::PerBaseQualityScores::new(
limits,
ng,
eg,
config.min_length,
)));
}
if limits.is_module_enabled("tile") {
modules.push(Box::new(per_tile_quality::PerTileQualityScores::new(
limits,
ng,
eg,
config.min_length,
)));
}
if limits.is_module_enabled("quality_sequence") {
modules.push(Box::new(
per_sequence_quality::PerSequenceQualityScores::new(limits),
));
}
if limits.is_module_enabled("sequence") {
modules.push(Box::new(
per_base_sequence_content::PerBaseSequenceContent::new(
limits,
ng,
eg,
config.min_length,
),
));
}
if limits.is_module_enabled("gc_sequence") {
modules.push(Box::new(gc_content::PerSequenceGCContent::new(limits)));
}
if limits.is_module_enabled("n_content") {
modules.push(Box::new(n_content::NContent::new(
limits,
ng,
eg,
config.min_length,
)));
}
if limits.is_module_enabled("sequence_length") {
modules.push(Box::new(
sequence_length_distribution::SequenceLengthDistribution::new(limits, ng),
));
}
let shared_data = Arc::new(Mutex::new(overrepresented_seqs::OverRepresentedData::new()));
if limits.is_module_enabled("duplication") {
modules.push(Box::new(duplication_level::DuplicationLevel::new(
shared_data.clone(),
limits,
)));
}
if limits.is_module_enabled("overrepresented") {
modules.push(Box::new(overrepresented_seqs::OverRepresentedSeqs::new(
limits,
config.dup_length,
&contaminants,
shared_data.clone(),
)));
}
if limits.is_module_enabled("adapter") {
modules.push(Box::new(adapter_content::AdapterContent::new(
limits,
&adapters,
ng,
eg,
config.min_length,
)));
}
if limits.is_module_enabled("kmer") {
modules.push(Box::new(kmer_content::KmerContent::new(
limits,
config.kmer_size,
ng,
eg,
config.min_length,
)));
}
modules
}