1use serde::{Deserialize, Serialize};
2
3pub const DEFAULT_KMER: usize = 8;
4pub const DEFAULT_WINDOW: usize = 6;
5#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
8pub enum Banded {
9 #[default]
10 Normal,
11 Banded {
12 kmer: usize,
13 window: usize,
14 },
15}
16
17#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
19pub struct RustBio {
20 pub band: Banded,
21}
22
23#[cfg(feature = "bio")]
24pub const RUSTBIO_AVAILABLE: bool = true;
26#[cfg(not(feature = "bio"))]
27pub const RUSTBIO_AVAILABLE: bool = false;
29
30#[cfg(feature = "bio")]
31mod implemented {
32 use crate::{Align, AlignAlgorithm, CheckStatus, InternalMode, Op};
33 use bio::alignment::{
34 pairwise::{self, MatchFunc, Scoring},
35 AlignmentOperation,
36 };
37
38 use super::*;
39 fn scorer(
40 algo: &AlignAlgorithm,
41 mode: InternalMode,
42 ) -> Scoring<impl MatchFunc + Copy + Send + Sync> {
43 let match_score = algo.match_score;
44 let mismatch_score = algo.mismatch_score;
45 let score = move |a: u8, b: u8| {
46 if a == b {
47 match_score
48 } else {
49 mismatch_score
50 }
51 };
52 let scorer = Scoring::new(algo.gap_open, algo.gap_extend, score);
53 match mode {
54 InternalMode::Global => scorer,
55 InternalMode::Semiglobal => scorer.yclip(0),
56 }
57 }
58
59 impl Align for RustBio {
60 fn align(&self, algo: &AlignAlgorithm, mode: InternalMode, x: &[u8], y: &[u8]) -> Vec<Op> {
61 let scoring = scorer(algo, mode);
62 let res = match self.band {
63 Banded::Normal => {
64 pairwise::Aligner::with_scoring(scoring)
65 .custom(x, y)
66 .operations
67 }
68 Banded::Banded { kmer, window } => {
69 pairwise::banded::Aligner::with_scoring(scoring, kmer, window)
70 .custom(x, y)
71 .operations
72 }
73 };
74 res.into_iter()
75 .map(|op| match op {
76 AlignmentOperation::Match => Op::Match,
77 AlignmentOperation::Subst => Op::Subst,
78 AlignmentOperation::Del => Op::Del,
79 AlignmentOperation::Ins => Op::Ins,
80 AlignmentOperation::Xclip(x) => Op::Xclip(x),
81 AlignmentOperation::Yclip(y) => Op::Yclip(y),
82 })
83 .collect()
84 }
85
86 fn check_params(
87 &self,
88 _: &AlignAlgorithm,
89 _: InternalMode,
90 x_size: usize,
91 y_size: usize,
92 ) -> CheckStatus {
93 const SIZE_LIMIT: u64 = 1 << 30;
94 if x_size as u64 * y_size as u64 > SIZE_LIMIT {
95 return CheckStatus::MemoryWarning;
96 }
97 CheckStatus::Ok
98 }
99 }
100}
101
102#[cfg(not(feature = "bio"))]
103mod unimplemented {
104 use crate::{Align, CheckStatus, Op};
105
106 impl Align for super::RustBio {
107 fn align(
108 &self,
109 _algo: &crate::AlignAlgorithm,
110 _mode: crate::InternalMode,
111 _x: &[u8],
112 _y: &[u8],
113 ) -> Vec<Op> {
114 unimplemented!()
115 }
116
117 fn check_params(
118 &self,
119 _algo: &crate::AlignAlgorithm,
120 _mode: crate::InternalMode,
121 _x_size: usize,
122 _y_size: usize,
123 ) -> CheckStatus {
124 return CheckStatus::Error(String::from(
125 "Rust-bio is not available. Please recompile with the\n\
126 `bio` feature enabled or choose another algorithm.",
127 ));
128 }
129 }
130}