pub mod html;
pub mod json;
pub use html::{
write_html_report, write_html_report_filtering, write_html_report_from_filtering_stats,
write_html_report_with_config, HtmlConfig,
};
pub use json::{
write_filtering_json_report, write_full_json_report, write_json_report,
write_json_report_with_config, AdapterStats, BeforeAfterSummary, ContentCurves,
CorrectionInfo, DuplicationHistogram, DuplicationInfo, FilteringResult, InsertSizeInfo,
JsonConfig, JsonReport, LengthBin, LengthHistogram, OverrepresentedSeq, ReadStats, Summary,
TimingInfo,
};
#[derive(Debug, Clone)]
pub struct ReportConfig {
pub json: JsonConfig,
pub html: HtmlConfig,
pub generate_json: bool,
pub generate_html: bool,
pub output_prefix: Option<String>,
}
impl Default for ReportConfig {
fn default() -> Self {
Self {
json: JsonConfig::default(),
html: HtmlConfig::default(),
generate_json: true,
generate_html: true,
output_prefix: None,
}
}
}
impl ReportConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_output_prefix(mut self, prefix: impl Into<String>) -> Self {
self.output_prefix = Some(prefix.into());
self
}
pub fn with_json(mut self, enabled: bool) -> Self {
self.generate_json = enabled;
self
}
pub fn with_html(mut self, enabled: bool) -> Self {
self.generate_html = enabled;
self
}
pub fn with_json_config(mut self, config: JsonConfig) -> Self {
self.json = config;
self
}
pub fn with_html_config(mut self, config: HtmlConfig) -> Self {
self.html = config;
self
}
pub fn with_pretty_json(mut self, pretty: bool) -> Self {
self.json.pretty = pretty;
self
}
pub fn with_html_title(mut self, title: impl Into<String>) -> Self {
self.html.title = title.into();
self
}
pub fn json_path(&self) -> String {
match &self.output_prefix {
Some(prefix) => format!("{}.json", prefix),
None => "fastars_report.json".to_string(),
}
}
pub fn html_path(&self) -> String {
match &self.output_prefix {
Some(prefix) => format!("{}.html", prefix),
None => "fastars_report.html".to_string(),
}
}
}
use crate::qc::{FilteringStats, QcStats};
use std::fs::File;
use std::io::BufWriter;
pub fn generate_reports(stats: &QcStats, config: &ReportConfig) -> anyhow::Result<()> {
if config.generate_json {
let path = config.json_path();
let file = File::create(&path)?;
let mut writer = BufWriter::new(file);
write_json_report_with_config(stats, &config.json, &mut writer)?;
log::info!("JSON report written to: {}", path);
}
if config.generate_html {
let path = config.html_path();
let file = File::create(&path)?;
let mut writer = BufWriter::new(file);
write_html_report_with_config(stats, None, &config.html, &mut writer)?;
log::info!("HTML report written to: {}", path);
}
Ok(())
}
pub fn generate_filtering_reports(
filtering_stats: &FilteringStats,
config: &ReportConfig,
) -> anyhow::Result<()> {
if config.generate_json {
let path = config.json_path();
let file = File::create(&path)?;
let mut writer = BufWriter::new(file);
write_filtering_json_report(filtering_stats, "", &mut writer)?;
log::info!("JSON report written to: {}", path);
}
if config.generate_html {
let path = config.html_path();
let file = File::create(&path)?;
let mut writer = BufWriter::new(file);
write_html_report_from_filtering_stats(filtering_stats, &mut writer)?;
log::info!("HTML report written to: {}", path);
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::qc::Mode;
#[test]
fn test_report_module_exists() {
assert!(true);
}
#[test]
fn test_report_config_default() {
let config = ReportConfig::default();
assert!(config.generate_json);
assert!(config.generate_html);
assert!(config.output_prefix.is_none());
}
#[test]
fn test_report_config_builder() {
let config = ReportConfig::new()
.with_output_prefix("test_output")
.with_json(true)
.with_html(false)
.with_pretty_json(false)
.with_html_title("Custom Title");
assert_eq!(config.output_prefix, Some("test_output".to_string()));
assert!(config.generate_json);
assert!(!config.generate_html);
assert!(!config.json.pretty);
assert_eq!(config.html.title, "Custom Title");
}
#[test]
fn test_report_config_paths() {
let config = ReportConfig::new().with_output_prefix("results/sample");
assert_eq!(config.json_path(), "results/sample.json");
assert_eq!(config.html_path(), "results/sample.html");
}
#[test]
fn test_report_config_default_paths() {
let config = ReportConfig::new();
assert_eq!(config.json_path(), "fastars_report.json");
assert_eq!(config.html_path(), "fastars_report.html");
}
#[test]
fn test_json_report_reexport() {
let _config = JsonConfig::new();
let _filtering_result = FilteringResult::default();
}
#[test]
fn test_html_report_reexport() {
let _config = HtmlConfig::new();
}
#[test]
fn test_generate_reports_creates_files() {
use tempfile::TempDir;
let temp_dir = TempDir::new().unwrap();
let prefix = temp_dir.path().join("test_report");
let mut stats = QcStats::new(Mode::Short);
stats.update_raw(b"ATGC", b"IIII");
let config = ReportConfig::new()
.with_output_prefix(prefix.to_str().unwrap());
generate_reports(&stats, &config).unwrap();
assert!(temp_dir.path().join("test_report.json").exists());
assert!(temp_dir.path().join("test_report.html").exists());
}
#[test]
fn test_generate_filtering_reports() {
use tempfile::TempDir;
let temp_dir = TempDir::new().unwrap();
let prefix = temp_dir.path().join("filter_report");
let mut filtering_stats = FilteringStats::new(Mode::Short);
filtering_stats.before.update_raw(b"ATGC", b"IIII");
filtering_stats.after.update_raw(b"ATGC", b"IIII");
let config = ReportConfig::new()
.with_output_prefix(prefix.to_str().unwrap());
generate_filtering_reports(&filtering_stats, &config).unwrap();
assert!(temp_dir.path().join("filter_report.json").exists());
assert!(temp_dir.path().join("filter_report.html").exists());
}
#[test]
fn test_json_only_report() {
use tempfile::TempDir;
let temp_dir = TempDir::new().unwrap();
let prefix = temp_dir.path().join("json_only");
let stats = QcStats::new(Mode::Short);
let config = ReportConfig::new()
.with_output_prefix(prefix.to_str().unwrap())
.with_json(true)
.with_html(false);
generate_reports(&stats, &config).unwrap();
assert!(temp_dir.path().join("json_only.json").exists());
assert!(!temp_dir.path().join("json_only.html").exists());
}
#[test]
fn test_html_only_report() {
use tempfile::TempDir;
let temp_dir = TempDir::new().unwrap();
let prefix = temp_dir.path().join("html_only");
let stats = QcStats::new(Mode::Short);
let config = ReportConfig::new()
.with_output_prefix(prefix.to_str().unwrap())
.with_json(false)
.with_html(true);
generate_reports(&stats, &config).unwrap();
assert!(!temp_dir.path().join("html_only.json").exists());
assert!(temp_dir.path().join("html_only.html").exists());
}
}