fastqrab-steps 0.9.1

Pipeline building blocks for fastqrab: read transformations, filters, reports, and demultiplexing
Documentation
use fastqrab_config::NonAmbigousDNA;

use crate::transformations::prelude::*;

/// Include a report at this position
#[derive(JsonSchema)]
#[tpd]
#[derive(Debug)]
#[expect(
    clippy::struct_excessive_bools,
    reason = "It has a lot of on/off options"
)]
pub struct Report {
    pub name: String,
    pub count: bool,
    #[tpd(default)]
    pub base_statistics: bool,
    #[tpd(default)]
    pub length_distribution: bool,
    #[tpd(default)]
    pub duplicate_count_per_read: bool,
    #[tpd(default)]
    pub duplicate_count_per_fragment: bool,

    #[schemars(skip)]
    #[tpd(default)]
    pub debug_reproducibility: bool,

    #[schemars(with = "Option<std::collections::BTreeMap<String, String>>")]
    pub count_oligos: Option<IndexMap<String, NonAmbigousDNA>>,

    #[tpd(adapt_in_verify(String))]
    #[schemars(with = "String")]
    pub count_oligos_segment: SegmentIndexOrAll,

    /// Generate histograms for specified tags
    #[tpd(alias = "tag_histogram")]
    pub tag_histograms: Option<Vec<TagLabel>>,
}

impl VerifyIn<PartialConfig> for PartialReport {
    fn verify(
        &mut self,
        parent: &PartialConfig,
        _options: &VerifyOptions,
    ) -> std::result::Result<(), ValidationFailure>
    where
        Self: Sized + toml_pretty_deser::Visitor,
    {
        self.name.verify(|name: &String| {
            if name.is_empty() {
                Err(ValidationFailure::new("Name must not be empty", None))
            } else {
                Ok(())
            }
        });
        self.count.or(true);
        self.count_oligos_segment.or(SegmentIndexOrAll::All);
        self.count_oligos_segment.validate_segment(parent);

        Ok(())
    }
}
//
// cov:excl-start
impl TagUser for PartialTaggedVariant<PartialReport> {
    #[mutants::skip]
    fn get_tag_usage(
        &mut self,
        _tags_available: &IndexMap<TagLabel, TagMetadata>,
        _segment_order: &[String],
    ) -> Option<TagUsageInfo<'_>> {
        //reachable if report failed to validate
        Some(TagUsageInfo::default())
    }

    //report name dupliaction is being done in config verify_reports
}
// cov:excl-stop

// cov:excl-start
impl Step for Report {
    #[mutants::skip]
    fn init(
        &mut self,
        _input_info: &InputInfo,
        _output_files: StepOutputFiles,
        _demultiplex_info: &OptDemultiplex,
    ) -> Result<Option<DemultiplexBarcodes>> {
        unreachable!("Should not be reached - should be expanded into individual parts before");
    }

    fn apply(
        &self,
        _block: FastQBlocksCombined,
        _input_info: &InputInfo,
        _demultiplex_info: &OptDemultiplex,
    ) -> anyhow::Result<(FastQBlocksCombined, bool)> {
        panic!("Should not be reached - should be expanded into individual parts before");
    }
}
// cov:excl-stop