Skip to content

Commit 6558f82

Browse files
committed
Fix abundances
1 parent e25cc07 commit 6558f82

6 files changed

Lines changed: 165 additions & 12 deletions

File tree

crates/assembler_pipeline/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ support_kmer_counters = [
5555
"io/support_kmer_counters",
5656
"colors/support_kmer_counters",
5757
"structs/support_kmer_counters",
58+
"sequence_output/support_kmer_counters",
5859
]
5960

6061
# Features used to filter ggcat capabilites

crates/assembler_pipeline/src/compute_matchtigs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ pub fn compute_matchtigs_thread<CX: ColorsManager, BK: StructuredSequenceBackend
514514
next_sequence,
515515
&handle.1,
516516
bases_offset,
517-
first_data.is_forwards(),
517+
edge_data.is_forwards(),
518518
&storage.extra_buffer,
519519
None,
520520
);

crates/assembler_pipeline/src/eulertigs.rs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,17 @@ impl CircularUnitig {
133133
) {
134134
let children_count = self.base_children.len();
135135

136+
#[cfg(feature = "support_kmer_counters")]
137+
let mut counted_orig_indexes = std::collections::HashSet::with_capacity(children_count);
138+
136139
#[cfg(feature = "support_kmer_counters")]
137140
{
138141
let first_unitig_entry = unitigs.get(&self.base_children[0].orig_index).unwrap();
139-
_out_abundance.first = first_unitig_entry.2.first;
142+
_out_abundance.first = if self.base_children[0].rc {
143+
first_unitig_entry.2.last
144+
} else {
145+
first_unitig_entry.2.first
146+
};
140147
}
141148

142149
for child in self.base_children.iter().take(children_count - 1) {
@@ -146,7 +153,9 @@ impl CircularUnitig {
146153

147154
#[cfg(feature = "support_kmer_counters")]
148155
{
149-
_out_abundance.sum += _abundance.sum;
156+
if counted_orig_indexes.insert(child.orig_index) {
157+
_out_abundance.sum += _abundance.sum;
158+
}
150159
}
151160

152161
let should_rc = child.rc;
@@ -178,7 +187,9 @@ impl CircularUnitig {
178187
#[cfg(feature = "support_kmer_counters")]
179188
{
180189
let abundance = &last_part_entry.2;
181-
_out_abundance.sum += abundance.sum;
190+
if counted_orig_indexes.insert(last.orig_index) {
191+
_out_abundance.sum += abundance.sum;
192+
}
182193
_out_abundance.last = if last.rc {
183194
abundance.first
184195
} else {
@@ -909,6 +920,11 @@ mod tests {
909920
use hashes::cn_seqhash::u128::CanonicalSeqHashFactory;
910921
use io::compressed_read::CompressedRead;
911922

923+
#[cfg(feature = "support_kmer_counters")]
924+
fn build_abundance(first: u64, sum: u64, last: u64) -> SequenceAbundanceType {
925+
SequenceAbundanceType { first, sum, last }
926+
}
927+
912928
#[test]
913929
fn test_rc_rotation() {
914930
let k = 31;
@@ -984,4 +1000,60 @@ mod tests {
9841000
}
9851001
}
9861002
}
1003+
1004+
#[cfg(feature = "support_kmer_counters")]
1005+
#[test]
1006+
fn rotated_circular_unitig_counts_split_abundance_once() {
1007+
let k = 5;
1008+
let mut stream = Vec::new();
1009+
let sequence = b"AACCGGTTAAC";
1010+
CompressedRead::compress_from_plain(sequence, |b| stream.extend_from_slice(b));
1011+
let read = CompressedRead::new_from_compressed(&stream, sequence.len());
1012+
1013+
let unitigs_hashmap = DashMap::new();
1014+
unitigs_hashmap.insert(
1015+
0,
1016+
(
1017+
CompressedReadIndipendent::from_read_inplace(&read, &stream),
1018+
NonColoredManager,
1019+
build_abundance(3, 21, 7),
1020+
),
1021+
);
1022+
1023+
let mut circular_unitig = CircularUnitig::new();
1024+
circular_unitig.base_children.push(CircularUnitigPart {
1025+
orig_index: 0,
1026+
start_pos: 0,
1027+
length: sequence.len() - (k - 1),
1028+
rc: false,
1029+
});
1030+
1031+
circular_unitig.rotate_with_rc(0, 3, false);
1032+
assert_eq!(
1033+
circular_unitig
1034+
.base_children
1035+
.iter()
1036+
.filter(|part| part.orig_index == 0)
1037+
.count(),
1038+
2
1039+
);
1040+
1041+
let mut writer = AlignedDynamicCompressedRead::new();
1042+
let dummy_buffer = color_types::PartialUnitigsColorStructure::<NonColoredManager>::new_temp_buffer();
1043+
let mut colors_buffer = color_types::PartialUnitigsColorStructure::<NonColoredManager>::new_temp_buffer();
1044+
let mut abundance = SequenceAbundanceType::default();
1045+
1046+
circular_unitig.write_packed::<CanonicalSeqHashFactory, NonColoredManager>(
1047+
&stream,
1048+
&unitigs_hashmap,
1049+
&mut writer,
1050+
&dummy_buffer,
1051+
&mut colors_buffer,
1052+
k,
1053+
true,
1054+
&mut abundance,
1055+
);
1056+
1057+
assert_eq!(abundance.sum, 21);
1058+
}
9871059
}

crates/sequence_output/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@ serde = "1.0.228"
3131

3232

3333
[features]
34-
support_kmer_counters = []
34+
support_kmer_counters = [
35+
"io/support_kmer_counters",
36+
"colors/support_kmer_counters",
37+
"structs/support_kmer_counters",
38+
]

crates/sequence_output/src/indirect_reads_extractor.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ mod tests {
232232
bundles::multifile_building::ColorBundleMultifileBuilding,
233233
colors_manager::color_types::PartialUnitigsColorStructure,
234234
};
235+
#[cfg(feature = "support_kmer_counters")]
236+
use io::partial_unitigs_extra_data::SequenceAbundance;
235237
use io::{
236238
compressed_read::CompressedReadIndipendent,
237239
concurrent::temp_reads::extra_data::{
@@ -288,7 +290,7 @@ mod tests {
288290
colors,
289291
mode: PartialUnitigMode::Inline,
290292
#[cfg(feature = "support_kmer_counters")]
291-
counters: sequence_output::structured_sequences::SequenceAbundance {
293+
counters: SequenceAbundance {
292294
first: 1,
293295
sum: runs.iter().map(|(_, count)| *count as u64).sum(),
294296
last: 1,

crates/sequence_output/src/sequences_joiner.rs

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,14 @@ impl<CX: ColorsManager> IndirectSequencesJoiner<CX> {
286286
} else {
287287
(extra.counters.first, extra.counters.last)
288288
};
289+
let overlapping_kmers = (overlapping_characters >= self.k) as u64;
289290

290291
self.counters.first = if self.sequence.bases_count == 0 {
291292
other_first
292293
} else {
293294
self.counters.first
294295
};
295-
self.counters.sum += extra.counters.sum - other_first;
296+
self.counters.sum += extra.counters.sum - (other_first * overlapping_kmers);
296297
self.counters.last = other_last;
297298
}
298299

@@ -473,21 +474,29 @@ mod tests {
473474
};
474475

475476
use super::IndirectSequencesJoiner;
477+
#[cfg(feature = "support_kmer_counters")]
478+
use io::partial_unitigs_extra_data::SequenceAbundance;
476479
use io::partial_unitigs_extra_data::{PartialUnitigExtraData, PartialUnitigMode};
477480

478-
fn inline_extra() -> PartialUnitigExtraData<NonColoredManager> {
481+
fn inline_extra_with_multiplicity(
482+
multiplicity: u64,
483+
) -> PartialUnitigExtraData<NonColoredManager> {
479484
PartialUnitigExtraData {
480485
colors: NonColoredManager,
481486
mode: PartialUnitigMode::Inline,
482487
#[cfg(feature = "support_kmer_counters")]
483-
counters: sequence_output::structured_sequences::SequenceAbundance {
484-
first: 1,
485-
sum: 1,
486-
last: 1,
488+
counters: SequenceAbundance {
489+
first: multiplicity,
490+
sum: multiplicity,
491+
last: multiplicity,
487492
},
488493
}
489494
}
490495

496+
fn inline_extra() -> PartialUnitigExtraData<NonColoredManager> {
497+
inline_extra_with_multiplicity(1)
498+
}
499+
491500
fn new_temp_path(prefix: &str) -> PathBuf {
492501
let now = SystemTime::now()
493502
.duration_since(UNIX_EPOCH)
@@ -516,6 +525,29 @@ mod tests {
516525
);
517526
}
518527

528+
#[cfg(feature = "support_kmer_counters")]
529+
fn append_plain_with_multiplicity(
530+
joiner: &mut IndirectSequencesJoiner<NonColoredManager>,
531+
seq: &str,
532+
overlap: usize,
533+
is_rc: bool,
534+
multiplicity: u64,
535+
) {
536+
let mut storage = Vec::new();
537+
let read = CompressedReadIndipendent::from_plain(seq.as_bytes(), &mut storage);
538+
let mut extra = inline_extra_with_multiplicity(multiplicity);
539+
extra.counters.sum = multiplicity * (seq.len() - joiner.k + 1) as u64;
540+
let extra_buffer = <PartialUnitigExtraData<NonColoredManager>>::new_temp_buffer();
541+
joiner.append_sequence(
542+
read.as_reference(&storage),
543+
&extra,
544+
overlap,
545+
is_rc,
546+
&extra_buffer,
547+
None,
548+
);
549+
}
550+
519551
#[test]
520552
fn inline_join_various_lengths_forward() {
521553
let k = 5;
@@ -564,4 +596,46 @@ mod tests {
564596

565597
fs::remove_file(&temp_path).unwrap();
566598
}
599+
600+
#[cfg(feature = "support_kmer_counters")]
601+
#[test]
602+
fn abundance_keeps_all_kmers_for_k_minus_one_overlap() {
603+
let k = 5;
604+
let temp_path = new_temp_path("joiner_abundance_k_minus_one_overlap");
605+
let writer = ConcurrentFileWriter::create(&temp_path).unwrap();
606+
let mut joiner = IndirectSequencesJoiner::<NonColoredManager>::new(k, writer.clone());
607+
608+
append_plain_with_multiplicity(&mut joiner, "AACCTGGA", 0, false, 2);
609+
append_plain_with_multiplicity(&mut joiner, "TGGAACCC", k - 1, false, 5);
610+
611+
let joined = joiner.get_sequence();
612+
613+
assert_eq!(joined.sequence.to_string(), "AACCTGGAACCC");
614+
assert_eq!(joined.extra.counters.first, 2);
615+
assert_eq!(joined.extra.counters.last, 5);
616+
assert_eq!(joined.extra.counters.sum, 28);
617+
618+
fs::remove_file(&temp_path).unwrap();
619+
}
620+
621+
#[cfg(feature = "support_kmer_counters")]
622+
#[test]
623+
fn abundance_drops_one_kmer_for_exact_k_overlap() {
624+
let k = 5;
625+
let temp_path = new_temp_path("joiner_abundance_k_overlap");
626+
let writer = ConcurrentFileWriter::create(&temp_path).unwrap();
627+
let mut joiner = IndirectSequencesJoiner::<NonColoredManager>::new(k, writer.clone());
628+
629+
append_plain_with_multiplicity(&mut joiner, "AAACCCCTA", 0, false, 2);
630+
append_plain_with_multiplicity(&mut joiner, "CCCTAT", k, false, 5);
631+
632+
let joined = joiner.get_sequence();
633+
634+
assert_eq!(joined.sequence.to_string(), "AAACCCCTAT");
635+
assert_eq!(joined.extra.counters.first, 2);
636+
assert_eq!(joined.extra.counters.last, 5);
637+
assert_eq!(joined.extra.counters.sum, 15);
638+
639+
fs::remove_file(&temp_path).unwrap();
640+
}
567641
}

0 commit comments

Comments
 (0)