1use bit_set::BitSet;
5use indicatif::{ProgressBar, ProgressIterator, ProgressStyle};
6use log::debug;
7use std::collections::VecDeque;
8use std::fmt::Debug;
9use std::marker::PhantomData;
10use std::mem;
11use std::time::Instant;
12
13use crate::dna_string::DnaString;
14use crate::graph::{BaseGraph, DebruijnGraph};
15use crate::summarizer::SummaryData;
16use crate::{Dir, EdgeMap, EdgeMult, PROGRESS_STYLE, SingleDirEdgeMap, SingleDirEdgeMult};
17use crate::Exts;
18use crate::Kmer;
19use crate::Vmer;
20use boomphf::hashmap::BoomHashMap2;
21
22#[derive(Clone)]
23enum ExtMode<K: Kmer> {
24 Unique(K, Dir, Exts),
25 Terminal(TerminalExt),
26}
27
28#[derive(Clone)]
29enum ExtModeNode {
30 Unique(usize, Dir, Exts),
31 Terminal(TerminalExt),
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
35struct TerminalExt {
36 exts: Exts,
37 edge_mults: Option<SingleDirEdgeMult>,
38 edge_maps: Option<SingleDirEdgeMap>
39}
40
41impl TerminalExt {
42 fn new(exts: Exts, edge_mults: Option<SingleDirEdgeMult>, edge_maps: Option<SingleDirEdgeMap>) -> Self {
43 TerminalExt { exts, edge_mults, edge_maps }
44 }
45}
46
47pub trait CompressionSpec<D> {
53 fn reduce(&self, path_object: D, kmer_object: &D) -> D;
55 fn join_test(&self, d1: &D, d2: &D) -> bool;
57}
58
59pub struct SimpleCompress<D, F> {
61 func: F,
62 d: PhantomData<D>,
63}
64
65impl<D, F> SimpleCompress<D, F> {
66 pub fn new(func: F) -> SimpleCompress<D, F> {
67 SimpleCompress {
68 func,
69 d: PhantomData,
70 }
71 }
72}
73
74impl<D, F> CompressionSpec<D> for SimpleCompress<D, F>
75where
76 for<'r> F: Fn(D, &'r D) -> D,
77{
78 fn reduce(&self, d: D, other: &D) -> D {
79 (self.func)(d, other)
80 }
81
82 fn join_test(&self, _: &D, _: &D) -> bool {
83 true
84 }
85}
86
87pub struct ScmapCompress<D> {
89 d: PhantomData<D>,
90}
91
92impl<D> ScmapCompress<D> {
93 pub fn new() -> ScmapCompress<D> {
94 ScmapCompress { d: PhantomData }
95 }
96}
97
98impl<D> Default for ScmapCompress<D> {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104impl<D: PartialEq> CompressionSpec<D> for ScmapCompress<D>
105where
106 D: Debug,
107{
108 fn reduce(&self, d: D, other: &D) -> D {
109 if d != *other {
110 panic!("{:?} != {:?}, Should not happen", d, *other);
111 }
112 d
113 }
114
115 fn join_test(&self, d1: &D, d2: &D) -> bool {
116 d1 == d2
117 }
118}
119
120pub struct CheckCompress<D, F1, F2> {
122 reduce_func: F1,
123 join_func: F2,
124 d: PhantomData<D>
125}
126
127impl<D, F1, F2> CheckCompress<D, F1, F2>
128where
129 for<'r> F1: Fn(D, &'r D) -> D,
130 for<'r> F2: Fn(&'r D, &'r D) -> bool
131{
132 pub fn new(reduce_func: F1, join_func: F2) -> Self {
138 CheckCompress {
139 reduce_func,
140 join_func,
141 d: PhantomData,
142 }
143 }
144}
145
146impl<D, F1, F2> CompressionSpec<D> for CheckCompress<D, F1, F2>
147where
148 for<'r> F1: Fn(D, &'r D) -> D,
149 for<'r> F2: Fn(&'r D, &'r D) -> bool
150{
151 fn reduce(&self, d: D, other: &D) -> D {
152 (self.reduce_func)(d, other)
153 }
154
155 fn join_test(&self, d: &D, other: &D) -> bool {
156 (self.join_func)(d, other)
157 }
158}
159
160
161struct CompressFromGraph<'a, 'b, K: 'a + Kmer, D: 'a + PartialEq + SummaryData<DI>, DI, S: CompressionSpec<D>> {
162 stranded: bool,
163 d: PhantomData<D>,
164 di: PhantomData<DI>,
165 spec: &'b S,
166 available_nodes: BitSet,
167 graph: &'a DebruijnGraph<K, D>,
168}
169
170impl<K, D: SummaryData<DI>, DI, S> CompressFromGraph<'_, '_, K, D, DI, S>
171where
172 K: Kmer + Send + Sync,
173 D: Debug + Clone + PartialEq,
174 S: CompressionSpec<D>,
175{
176 #[inline(never)]
177 fn try_extend_node(&mut self, node: usize, dir: Dir) -> ExtModeNode {
178 let node = self.graph.get_node(node);
179 let bases = node.sequence();
180 let exts = node.exts();
181 let data = node.data();
182
183 if exts.num_ext_dir(dir) != 1
184 || (!self.stranded && node.len() == K::k() && bases.get_kmer::<K>(0).is_palindrome())
185 {
186 ExtModeNode::Terminal( TerminalExt::new(
187 exts.single_dir(dir),
188 data.edge_mults().map(|em| em.single_dir(dir)),
189 data.mapped_edge_ids().map(|em| em.single_dir(dir))
190 ))
191 } else {
192 let ext_base = exts.get_unique_extension(dir).expect("should be unique");
194 let end_kmer: K = bases.term_kmer(dir);
195
196 let next_kmer = end_kmer.extend(ext_base, dir);
197 let (next_node_id, next_side_incoming, rc) = match self.graph.find_link(next_kmer, dir)
198 {
199 Some(e) => e,
200 None => {
201 println!("dir: {:?}, Lmer: {:?}, exts: {:?}", dir, bases, exts);
202 println!("end kmer: {:?}", end_kmer);
203 println!("No kmer: {:?}", next_kmer);
204 println!("rc: {:?}", next_kmer.min_rc());
205 panic!("No kmer: {:?}", next_kmer)
206 }
207 };
208
209 let next_node = self.graph.get_node(next_node_id);
210 let next_exts = next_node.exts();
211
212 let consistent = (next_node.len() == K::k())
213 || match (dir, next_side_incoming, rc) {
214 (Dir::Left, Dir::Right, false) => true,
215 (Dir::Left, Dir::Left, true) => true,
216 (Dir::Right, Dir::Left, false) => true,
217 (Dir::Right, Dir::Right, true) => true,
218 _ => {
219 println!("dir: {:?}, Lmer: {:?}, exts: {:?}", dir, bases, exts);
220 println!("end kmer: {:?}", end_kmer);
221 println!("next kmer: {:?}", next_kmer);
222 println!("rc: {:?}", next_kmer.min_rc());
223 println!(
224 "next bases: {:?}, next_side_incoming: {:?}, rc: {:?}",
225 next_node.sequence(),
226 next_side_incoming,
227 rc
228 );
229 false
230 }
231 };
232 assert!(consistent);
233
234 if !self.available_nodes.contains(next_node_id)
241 || (!self.stranded && next_kmer.is_palindrome())
242 || !self.spec.join_test(node.data(), next_node.data())
243 {
244 return ExtModeNode::Terminal( TerminalExt::new(
249 exts.single_dir(dir),
250 data.edge_mults().map(|em| em.single_dir(dir)),
251 data.mapped_edge_ids().map(|em| em.single_dir(dir))
252 ));
253 }
254
255 let next_side_outgoing = next_side_incoming.flip();
257
258 let incoming_count = next_exts.num_ext_dir(next_side_incoming);
259 let outgoing_exts = next_exts.single_dir(next_side_outgoing);
260
261 if incoming_count == 0 {
262 println!("dir: {:?}, Lmer: {:?}, exts: {:?}", dir, bases, exts);
263 println!("end kmer: {:?}", end_kmer);
264 println!("next_node: {:?}", next_node);
265 println!("next_node data: {:?}", next_node.sequence());
266 panic!("unreachable");
267 } else if incoming_count == 1 {
268 ExtModeNode::Unique(next_node_id, next_side_outgoing, outgoing_exts)
270 } else {
271 ExtModeNode::Terminal( TerminalExt::new(
274 exts.single_dir(dir),
275 data.edge_mults().map(|em| em.single_dir(dir)),
276 data.mapped_edge_ids().map(|em| em.single_dir(dir))
277 ))
278 }
279 }
280 }
281
282 fn extend_node(&mut self, start_node: usize, start_dir: Dir) -> (Vec<(usize, Dir)>, TerminalExt) {
284 let mut current_dir = start_dir;
285 let mut current_node = start_node;
286 let mut path = Vec::new();
287 let terminal: TerminalExt;
289
290 self.available_nodes.remove(start_node);
291
292 loop {
293 let ext_result = self.try_extend_node(current_node, current_dir);
294
295 match ext_result {
296 ExtModeNode::Unique(next_node, next_dir_outgoing, _) => {
297 let next_dir_incoming = next_dir_outgoing.flip();
298 path.push((next_node, next_dir_incoming));
299 self.available_nodes.remove(next_node);
300 current_node = next_node;
301 current_dir = next_dir_outgoing;
302 }
303 ExtModeNode::Terminal(term) => {
304 terminal = term;
305
306 break;
307 }
308 }
309 }
310
311 (path, terminal)
312 }
313
314 #[inline(never)]
317 fn build_node(&mut self, seed_node: usize) -> (DnaString, Exts, VecDeque<(usize, Dir)>, D) {
318 let (l_path, l_terminal) = self.extend_node(seed_node, Dir::Left);
319 let (r_path, r_terminal) = self.extend_node(seed_node, Dir::Right);
320
321 let mut node_path = VecDeque::new();
323
324 let mut node_data: D = self.graph.get_node(seed_node).data().clone();
325 node_path.push_back((seed_node, Dir::Left));
326
327 for &(next_node, incoming_dir) in l_path.iter() {
329 node_path.push_front((next_node, incoming_dir.flip()));
330 node_data = self
331 .spec
332 .reduce(node_data, self.graph.get_node(next_node).data());
333 }
334
335 for &(next_node, incoming_dir) in r_path.iter() {
337 node_path.push_back((next_node, incoming_dir));
338 node_data = self
339 .spec
340 .reduce(node_data, self.graph.get_node(next_node).data());
341 }
342
343 let left_terminal = match l_path.last() {
344 None => l_terminal,
345 Some(&(_, Dir::Left)) => TerminalExt::new(
346 l_terminal.exts.complement(),
347 l_terminal.edge_mults.map(|em| em.complement()),
348 l_terminal.edge_maps.map(|em| em.complement())
349 ),
350 Some(&(_, Dir::Right)) => l_terminal,
351 };
352
353 let right_terminal = match r_path.last() {
354 None => r_terminal,
355 Some(&(_, Dir::Left)) => r_terminal,
356 Some(&(_, Dir::Right)) => TerminalExt::new(
357 r_terminal.exts.complement(),
358 r_terminal.edge_mults.map(|em| em.complement()),
359 r_terminal.edge_maps.map(|em| em.complement())
360 )
361 };
362
363 let path_seq = self.graph.sequence_of_path(node_path.iter());
364
365 let new_em = EdgeMult::from_single_dirs(&left_terminal.edge_mults, &right_terminal.edge_mults);
366 let new_emap = EdgeMap::from_single_dirs(&left_terminal.edge_maps, &right_terminal.edge_maps);
367
368 node_data.set_edge_mults(new_em);
369 node_data.set_mapped_edge_ids(new_emap);
370
371 (
373 path_seq,
374 Exts::from_single_dirs(left_terminal.exts, right_terminal.exts),
375 node_path,
376 node_data,
377 )
378 }
379
380 fn compress_graph(
383 stranded: bool,
384 compression: &S,
385 mut old_graph: DebruijnGraph<K, D>,
386 censor_nodes: Option<Vec<usize>>,
387 ) -> DebruijnGraph<K, D> {
388 let n_nodes = old_graph.len();
389 let mut available_nodes = BitSet::with_capacity(n_nodes);
390 for i in 0..n_nodes {
391 available_nodes.insert(i);
392 }
393
394 if let Some(c) = censor_nodes {
395 for censor in c {
396 available_nodes.remove(censor);
397 }
398 }
399
400 old_graph.fix_exts(Some(&available_nodes));
401
402 let mut comp = CompressFromGraph {
403 spec: compression,
404 stranded,
405 graph: &old_graph,
406 available_nodes,
407 d: PhantomData,
408 di: PhantomData
409 };
410
411 let mut graph = BaseGraph::new(stranded);
413
414 for node_counter in 0..n_nodes {
415 if comp.available_nodes.contains(node_counter) {
416 let (seq, exts, _, data) = comp.build_node(node_counter);
417 graph.add(&seq, exts, data);
418 }
419 }
420
421 let mut dbg = graph.finish();
423 dbg.fix_exts(None);
424 debug_assert!(dbg.is_compressed(compression).is_none());
425 dbg
426 }
427}
428
429pub fn compress_graph<
431 K: Kmer + Send + Sync,
432 D: Clone + Debug + PartialEq + SummaryData<DI>,
433 DI,
434 S: CompressionSpec<D>,
435>(
436 stranded: bool,
437 spec: &S,
438 old_graph: DebruijnGraph<K, D>,
439 censor_nodes: Option<Vec<usize>>,
440) -> DebruijnGraph<K, D> {
441 CompressFromGraph::<K, D, DI, S>::compress_graph(stranded, spec, old_graph, censor_nodes)
442}
443
444struct CompressFromHash<'a, 'b, K: 'a + Kmer, D: 'a + SummaryData<DI>, DI, S: CompressionSpec<D>> {
449 stranded: bool,
450 k: PhantomData<K>,
451 d: PhantomData<D>,
452 di: PhantomData<DI>,
453 spec: &'b S,
454 available_kmers: BitSet,
455 index: &'a BoomHashMap2<K, Exts, D>,
456}
457
458impl<K: Kmer, D: Clone + Debug + Send + Sync + SummaryData<DI>, DI, S: CompressionSpec<D> + Sync> CompressFromHash<'_, '_, K, D, DI, S> {
460 fn get_kmer_data(&self, kmer: &K) -> (&Exts, &D) {
461 match self.index.get(kmer) {
462 Some(data) => data,
463 None => panic!("couldn't find kmer {:?}", kmer),
464 }
465 }
466
467 fn get_kmer_id(&self, kmer: &K) -> Option<usize> {
468 self.index.get_key_id(kmer)
469 }
470
471 fn try_extend_kmer(&self, kmer: K, dir: Dir) -> ExtMode<K> {
477 let (exts, kmer_data) = self.get_kmer_data(&kmer);
479
480 if exts.num_ext_dir(dir) != 1 || (!self.stranded && kmer.is_palindrome()) {
483 ExtMode::Terminal( TerminalExt::new(
484 exts.single_dir(dir),
485 kmer_data.edge_mults().map(|em| em.single_dir(dir)),
486 kmer_data.mapped_edge_ids().map(|em| em.single_dir(dir))
487 ))
488 } else {
489 let ext_base = exts.get_unique_extension(dir).expect("should be unique");
491
492 let mut next_kmer = kmer.extend(ext_base, dir);
493
494 let mut do_flip = false;
495
496 if !self.stranded {
498 let flip_rc = next_kmer.min_rc_flip();
499 do_flip = flip_rc.1;
500 next_kmer = flip_rc.0;
501 }
502
503 let next_dir = dir.cond_flip(do_flip);
504 let is_palindrome = !self.stranded && next_kmer.is_palindrome();
505
506 match self.get_kmer_id(&next_kmer) {
512 Some(id) if self.available_kmers.contains(id) => (),
513
514 _ => return ExtMode::Terminal( TerminalExt::new(
516 exts.single_dir(dir),
517 kmer_data.edge_mults().map(|em| em.single_dir(dir)),
518 kmer_data.mapped_edge_ids().map(|em| em.single_dir(dir))
519 )),
520 }
521
522 let new_incoming_dir = dir.flip().cond_flip(do_flip);
525 let next_kmer_r = self.get_kmer_data(&next_kmer);
526 let (next_kmer_exts, ref next_kmer_data) = next_kmer_r;
527 let incoming_count = next_kmer_exts.num_ext_dir(new_incoming_dir);
528 let outgoing_exts = next_kmer_exts.single_dir(new_incoming_dir.flip());
529
530 let can_join = self.spec.join_test(kmer_data, next_kmer_data);
532
533 if incoming_count == 0 && !is_palindrome {
534 println!("{:?}, {:?}, {:?}", kmer, exts, kmer_data);
535 println!(
536 "{:?}, {:?}, {:?}",
537 next_kmer, next_kmer_exts, next_kmer_data
538 );
539 panic!("unreachable");
540 } else if can_join && incoming_count == 1 && !is_palindrome {
541 ExtMode::Unique(next_kmer, next_dir, outgoing_exts)
543 } else {
544 ExtMode::Terminal( TerminalExt::new(
547 exts.single_dir(dir),
548 kmer_data.edge_mults().map(|em| em.single_dir(dir)),
549 kmer_data.mapped_edge_ids().map(|em| em.single_dir(dir))
550 ))
551 }
552 }
553 }
554
555 #[inline(never)]
559 fn extend_kmer(&mut self, kmer: K, start_dir: Dir, path: &mut Vec<(K, Dir)>) -> TerminalExt {
560 let mut current_dir = start_dir;
561 let mut current_kmer = kmer;
562 path.clear();
563
564 let terminal: TerminalExt;
566
567 let id = self.get_kmer_id(&kmer).expect("should have this kmer");
569 let _ = self.available_kmers.remove(id);
570
571 loop {
572 let ext_result = self.try_extend_kmer(current_kmer, current_dir);
573
574 match ext_result {
575 ExtMode::Unique(next_kmer, next_dir, _) => {
576 path.push((next_kmer, next_dir));
577 let next_id = self.get_kmer_id(&next_kmer).expect("should have this kmer");
578 self.available_kmers.remove(next_id);
579 current_kmer = next_kmer;
580 current_dir = next_dir;
581 }
582 ExtMode::Terminal(term) => {
583 terminal = term;
584 break;
585 }
586 }
587 }
588
589 terminal
590 }
591
592 #[inline(never)]
594 fn build_node(
595 &mut self,
596 seed_id: usize,
597 path: &mut Vec<(K, Dir)>,
598 edge_seq: &mut VecDeque<u8>,
599 ) -> (Exts, D) {
600 let seed: K = *self.index.get_key(seed_id).expect("Index out of bound");
601 edge_seq.clear();
602 for i in 0..K::k() {
603 edge_seq.push_back(seed.get(i));
604 }
605
606 let mut node_data = self.get_kmer_data(&seed).1.clone();
607
608 let l_term = self.extend_kmer(seed, Dir::Left, path);
610
611
612 for &(next_kmer, dir) in path.iter() {
614 let kmer = match dir {
615 Dir::Left => next_kmer,
616 Dir::Right => next_kmer.rc(),
617 };
618
619 edge_seq.push_front(kmer.get(0));
620
621 let (_, kmer_data) = self.get_kmer_data(&next_kmer);
623 node_data = self.spec.reduce(node_data, kmer_data)
624 }
625
626 let left_terminal = match path.last() {
627 None => l_term,
628 Some(&(_, Dir::Left)) => l_term,
629 Some(&(_, Dir::Right)) => TerminalExt::new(
630 l_term.exts.complement(),
631 l_term.edge_mults.map(|em| em.complement()),
632 l_term.edge_maps.map(|em| em.complement())
633 )
634 };
635
636
637 let r_term = self.extend_kmer(seed, Dir::Right, path);
639
640 for &(next_kmer, dir) in path.iter() {
642 let kmer = match dir {
643 Dir::Left => next_kmer.rc(),
644 Dir::Right => next_kmer,
645 };
646
647 edge_seq.push_back(kmer.get(K::k() - 1));
648
649 let (_, kmer_data) = self.get_kmer_data(&next_kmer);
650 node_data = self.spec.reduce(node_data, kmer_data)
651 }
652
653 let right_terminal = match path.last() {
654 None => r_term,
655 Some(&(_, Dir::Left)) => TerminalExt::new(
656 r_term.exts.complement(),
657 r_term.edge_mults.map(|em| em.complement()),
658 r_term.edge_maps.map(|em| em.complement())
659 ),
660 Some(&(_, Dir::Right)) => r_term,
661 };
662
663 let new_em = EdgeMult::from_single_dirs(&left_terminal.edge_mults, &right_terminal.edge_mults);
664 let new_emap = EdgeMap::from_single_dirs(&left_terminal.edge_maps, &right_terminal.edge_maps);
665 node_data.set_edge_mults(new_em);
666 node_data.set_mapped_edge_ids(new_emap);
667
668 (Exts::from_single_dirs(left_terminal.exts, right_terminal.exts), node_data)
669 }
670
671 #[inline(never)]
673 pub fn compress_kmers(
674 stranded: bool,
675 spec: &S,
676 index: BoomHashMap2<K, Exts, D>,
677 progress: bool,
678 ) -> BaseGraph<K, D> {
679
680 let n_kmers = index.len();
681 let mut available_kmers = BitSet::with_capacity(n_kmers);
682 let progress = if n_kmers < 128 { false } else { progress };
683
684 for i in 0..n_kmers {
685 available_kmers.insert(i);
686 }
687
688 let mut comp = CompressFromHash {
689 stranded,
690 spec,
691 k: PhantomData,
692 d: PhantomData,
693 di: PhantomData,
694 available_kmers,
695 index: &index,
696 };
697
698 let mut graph = BaseGraph::new(stranded);
700
701 let mut path_buf = Vec::new();
703
704 let mut edge_seq_buf = VecDeque::new();
706
707 debug!("n of kmers: {}", n_kmers);
708
709 let steps = n_kmers as f32 / 128.;
710
711 if progress {
712 println!("Compressing kmers");
713 for _i in 0..127 {
714 print!("-");
715 }
716 println!("|");
717 }
718
719 let pb = ProgressBar::new(n_kmers as u64);
720 pb.set_style(ProgressStyle::with_template(PROGRESS_STYLE).unwrap().progress_chars("#/-"));
721 pb.set_message(format!("{:<32}", "compressing graph"));
722
723
724 for kmer_counter in (0..n_kmers).progress_with(pb) {
725 if progress && (kmer_counter as f32 % steps >= 0.) & (kmer_counter as f32 % steps < 1.) { print!("|")}
726
727 if (kmer_counter as f32 % steps >= 0.) & (kmer_counter as f32 % steps < 1.) {
728 debug!("another 1/128 done: {}, data graph size: {}", (kmer_counter as f32 / steps) as i32, mem::size_of_val(&*graph.data));
729 }
730
731 if comp.available_kmers.contains(kmer_counter) {
732 let (node_exts, node_data) =
733 comp.build_node(kmer_counter, &mut path_buf, &mut edge_seq_buf);
734 graph.add(&edge_seq_buf, node_exts, node_data);
735 }
736 }
737
738 graph.shrink_to_fit();
739
740 if progress { println!() };
741
742 graph
743 }
744}
745
746
747#[inline(never)]
749pub fn compress_kmers_with_hash<K: Kmer, D: Clone + Debug + Send + Sync + SummaryData<DI>, DI, S: CompressionSpec<D> + Send + Sync>(
750 stranded: bool,
751 spec: &S,
752 index: BoomHashMap2<K, Exts, D>,
753 time: bool,
754 progress: bool,
755) -> BaseGraph<K, D> {
756 let before_compression = Instant::now();
757 let graph = CompressFromHash::<K, D, DI, S>::compress_kmers(stranded, spec, index, progress);
758 if time { println!("time compression (s): {}", before_compression.elapsed().as_secs_f32()) }
759 graph
760}
761
762#[inline(never)]
764pub fn compress_kmers<K: Kmer, D: Clone + Debug + Send + Sync + SummaryData<DI>, DI, S: CompressionSpec<D> + Send + Sync>(
765 stranded: bool,
766 spec: &S,
767 kmer_exts: &[(K, (Exts, D))],
768) -> BaseGraph<K, D> {
769 let mut keys = Vec::with_capacity(kmer_exts.len());
770 let mut exts = Vec::with_capacity(kmer_exts.len());
771 let mut data = Vec::with_capacity(kmer_exts.len());
772
773 for (k, (e, d)) in kmer_exts {
774 keys.push(*k);
775 data.push(d.clone());
776 exts.push(*e);
777 }
778
779 let index = BoomHashMap2::new(keys, exts, data);
780 CompressFromHash::<K, D, DI, S>::compress_kmers(stranded, spec, index, false)
781}
782
783#[inline(never)]
785pub fn compress_kmers_no_exts<K: Kmer + Send + Sync, D: Clone + Debug + Send + Sync + SummaryData<DI>, DI, S: CompressionSpec<D> + Send + Sync>(
786 stranded: bool,
787 spec: &S,
788 kmer_exts: &[(K, D)],
789) -> BaseGraph<K, D> {
790 let kmer_set: std::collections::HashSet<_> = kmer_exts.iter().map(|(k, _)| k).collect();
791
792 let can = |k: K| k.min_rc();
793
794 let mut keys = Vec::with_capacity(kmer_exts.len());
795 let mut exts = Vec::with_capacity(kmer_exts.len());
796 let mut data = Vec::with_capacity(kmer_exts.len());
797 for (k, d) in kmer_exts {
798 let mut e = Exts::empty();
799
800 for l in 0..4 {
801 let new = can(k.extend_left(l));
802
803 if kmer_set.contains(&new) {
804 e = e.set(Dir::Left, l);
805 }
806 }
807
808 for r in 0..4 {
809 let new = can(k.extend_right(r));
810
811 if kmer_set.contains(&new) {
812 e = e.set(Dir::Right, r);
813 }
814 }
815
816 keys.push(*k);
817 data.push(d.clone());
818 exts.push(e);
819 }
820
821 assert_eq!(kmer_set.len(), keys.len());
822
823 let index = BoomHashMap2::new(keys, exts, data);
824 CompressFromHash::<K, D, DI, S>::compress_kmers(stranded, spec, index,false)
825}
826
827pub fn uncompressed_graph<K: Kmer, D: Clone + Debug>(
829 index: BoomHashMap2<K, Exts, D>,
830 stranded: bool
831) -> BaseGraph<K, D> {
832
833 let mut graph: BaseGraph<K, D> = BaseGraph::new(stranded);
834 let mut kmer_seq: VecDeque<u8> = VecDeque::with_capacity(K::k());
835
836 for (kmer, exts, data) in index.into_iter() {
837 kmer_seq.clear();
838 for i in 0..K::k() {
839 kmer_seq.push_back(kmer.get(i));
840 }
841 graph.add(&kmer_seq, *exts, data.clone());
842 }
843
844 graph.shrink_to_fit();
845
846 graph
847}
848
849pub fn rebuild_uncompressed_graph<K: Kmer + Sync + Send, D: Debug + Clone>(
851 stranded: bool,
852 old_graph: DebruijnGraph<K, D>,
853 censor_nodes: Vec<usize>,
854) -> DebruijnGraph<K, D>
855{
856 let mut available_node = BitSet::with_capacity(old_graph.len());
858 for i in 0..old_graph.len() {
859 available_node.insert(i);
860 }
861
862 for node in censor_nodes {
863 available_node.remove(node);
864 }
865
866 let mut graph: BaseGraph<K, D> = BaseGraph::new(stranded);
867
868 for i in 0..old_graph.len() {
869 if available_node.contains(i) {
870 let node = old_graph.get_node(i);
871 let seq = node.sequence();
872 let exts = node.exts();
873 let data = node.data();
874
875 graph.add(&seq, exts, data.clone());
876 }
877 }
878
879 let mut graph = graph.finish();
880 graph.fix_exts(None);
881
882 graph
883}