From 587b0cb11d112d32a59b931a4f774ccbf57b6f5c Mon Sep 17 00:00:00 2001 From: Vince Buffalo Date: Thu, 7 Mar 2024 13:56:48 -0800 Subject: [PATCH] New GRanges::coverage() method, and metadata support for TSV output. --- src/commands.rs | 10 ++++++++++ src/granges.rs | 23 ++++++++++++++++++++++- src/io/tsv.rs | 2 ++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/commands.rs b/src/commands.rs index 771135e..45a1ef9 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -57,6 +57,14 @@ pub fn build_tsv_writer_with_config( None => Box::new(io::stdout()), }; + // Write metadata, if there. + if let Some(metadata_rows) = &config.metadata { + for metadata_row in metadata_rows { + writeln!(writer_boxed, "#{}", metadata_row)?; + } + } + + // Write headers, if there. if let Some(headers) = &config.headers { writeln!(writer_boxed, "{}", headers.join("\t"))?; } @@ -955,6 +963,7 @@ impl FeatureDensity { let config = TsvConfig { no_value_string: "NA".to_string(), headers: Some(headers), + metadata: None, }; window_counts.write_to_tsv(self.output.as_ref(), &config)?; } @@ -966,6 +975,7 @@ impl FeatureDensity { let config = TsvConfig { no_value_string: "NA".to_string(), headers: Some(headers), + metadata: None, }; window_counts.write_to_tsv(self.output.as_ref(), &config)?; } diff --git a/src/granges.rs b/src/granges.rs index 9f386b1..43b487e 100644 --- a/src/granges.rs +++ b/src/granges.rs @@ -133,11 +133,14 @@ where std::mem::take(&mut self.ranges) } + /// Take both the ranges and data from a [`GRanges`] object, + /// returning them in a tuple. pub fn take_both(&mut self) -> Result<(GenomeMap, T), GRangesError> { let data = std::mem::take(&mut self.data).ok_or(GRangesError::NoDataContainer)?; let ranges = std::mem::take(&mut self.ranges); Ok((ranges, data)) } + } impl GRanges @@ -219,8 +222,9 @@ impl<'a, C, T> AsGRangesRef<'a, C, T> for GRanges { } } -impl<'a, T> GenomicRangesTsvSerialize<'a, VecRangesIndexed> for GRanges +impl<'a, C, T> GenomicRangesTsvSerialize<'a, C> for GRanges where + C: IterableRangeContainer, T: IndexedDataContainer + 'a, ::Item<'a>: Serialize, { @@ -439,6 +443,18 @@ where } Ok(all_midpoints) } + + /// Get the total coverage (the sum of all range widths). + pub fn coverage(&self) -> Position { + let mut coverage = 0; + for (_seqname, ranges) in self.ranges.iter() { + for range in ranges.iter_ranges() { + coverage += range.width() + } + } + coverage + } + } impl GRanges @@ -702,6 +718,11 @@ where pub fn midpoints(&self) -> Result>, GRangesError> { self.0.midpoints() } + + /// Get the total coverage (the sum of all range widths). + pub fn coverage(&self) -> Position { + self.0.coverage() + } } impl GRanges> { diff --git a/src/io/tsv.rs b/src/io/tsv.rs index 0f99fb7..c5f737a 100644 --- a/src/io/tsv.rs +++ b/src/io/tsv.rs @@ -7,6 +7,7 @@ lazy_static! { pub static ref BED_TSV: TsvConfig = TsvConfig { no_value_string: ".".to_string(), headers: None, + metadata: None, }; } @@ -17,4 +18,5 @@ lazy_static! { pub struct TsvConfig { pub no_value_string: String, pub headers: Option>, + pub metadata: Option> }