1use strum_macros::{Display, EnumString};
9
10#[derive(Clone, Copy, Debug, EnumString, Display)]
12pub enum AlignmentAlgorithm {
13 Wavefront,
15
16 WavefrontAdaptive,
17
18 SWG,
20}
21
22#[derive(Debug, PartialEq, Eq, Clone)]
24pub struct Penalties {
25 pub mismatch_pen: u32,
28
29 pub open_pen: u32,
31
32 pub extd_pen: u32,
34}
35
36#[derive(Debug, Eq, PartialEq, Clone)]
39pub struct Alignment {
40 pub score: u32,
41 pub query_aligned: String,
42 pub text_aligned: String,
43}
44
45#[derive(Debug, Eq, PartialEq)]
47pub enum AlignmentError {
48 ZeroLength(String),
50
51 QueryTooLong(String),
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum AlignmentLayer {
58 Matches,
59 Inserts,
60 Deletes,
61}
62
63pub(crate) trait Wavefront {
65 fn extend(&mut self);
66 fn next(&mut self);
67 fn increment_score(&mut self);
68 fn is_finished(&self) -> bool;
69 fn backtrace(&self) -> Result<Alignment, AlignmentError>;
70}
71
72#[derive(Debug, Eq, PartialEq)]
76pub(crate) struct WavefrontGrid {
77 diags: Vec<(i32, i32)>,
80
81 offsets: Vec<usize>,
84
85 matches: Vec<Option<(u32, AlignmentLayer)>>,
86 inserts: Vec<Option<(u32, AlignmentLayer)>>,
87 deletes: Vec<Option<(u32, AlignmentLayer)>>,
88}
89
90pub(crate) fn new_wavefront_grid() -> WavefrontGrid {
93 let diags = vec![(0, 0)];
94 let matches = vec![Some((0, AlignmentLayer::Matches)); 1];
99 let inserts = vec![None; 1];
100 let deletes = vec![None; 1];
101
102 let offsets = vec![0, 1];
103 WavefrontGrid {
116 diags,
117 offsets,
118 matches,
119 inserts,
120 deletes,
121 }
122}
123
124impl WavefrontGrid {
125 pub(crate) fn add_layer(&mut self, lo: i32, hi: i32) {
128 self.diags.push((lo, hi));
129
130 let new_width: usize = (hi - lo + 1) as usize;
131 self.offsets
132 .push(self.offsets[self.offsets.len() - 1] + new_width);
133
134 for _ in lo..=hi {
135 self.matches.push(None);
136 self.inserts.push(None);
137 self.deletes.push(None);
138 }
139 }
140
141 pub(crate) fn get(
143 &self,
144 layer: AlignmentLayer,
145 score: u32,
146 diag: i32,
147 ) -> Option<(u32, AlignmentLayer)> {
148 let score = score as usize;
149 if score >= self.offsets.len() || diag < self.diags[score].0 || diag > self.diags[score].1 {
150 None
153 } else {
154 let diag_offset = (diag - self.diags[score].0) as usize;
155 let position: usize = self.offsets[score] + diag_offset;
156 match layer {
157 AlignmentLayer::Matches => self.matches[position],
158 AlignmentLayer::Inserts => self.inserts[position],
159 AlignmentLayer::Deletes => self.deletes[position],
160 }
161 }
162 }
163
164 pub(crate) fn set(
165 &mut self,
166 layer: AlignmentLayer,
167 score: u32,
168 diag: i32,
169 value: Option<(u32, AlignmentLayer)>,
170 ) {
171 let score = score as usize;
172 if score < self.offsets.len() && diag >= self.diags[score].0 && diag <= self.diags[score].1
173 {
174 let position = self.offsets[score] + (diag - self.diags[score].0) as usize;
175 match layer {
176 AlignmentLayer::Matches => self.matches[position] = value,
177 AlignmentLayer::Inserts => self.inserts[position] = value,
178 AlignmentLayer::Deletes => self.deletes[position] = value,
179 };
180 }
181 }
182
183 pub(crate) fn get_diag_range(&self, score: u32) -> Option<&(i32, i32)> {
184 self.diags.get(score as usize)
185 }
186
187 pub(crate) fn increment(&mut self, score: u32, diag: i32) {
188 let score = score as usize;
189 let position = self.offsets[score] + (diag - self.diags[score].0) as usize;
190 self.matches[position] = match self.matches[position] {
191 Some((score, direction)) => Some((score + 1, direction)),
192 None => Some((1, AlignmentLayer::Matches)),
193 };
194 }
195}
196
197#[cfg(test)]
198mod tests_wfgrid {
199 use super::*;
200
201 #[test]
202 fn test_new_wfgrid() {
203 let grid: WavefrontGrid = new_wavefront_grid();
204 assert_eq!(grid.diags[0], (0, 0));
205 assert_eq!(grid.offsets[0], 0);
206 assert_eq!(grid.offsets[1], 1);
207 assert_eq!(grid.matches[0], Some((0, AlignmentLayer::Matches)));
208 assert_eq!(grid.inserts[0], None);
209 assert_eq!(grid.deletes[0], None);
210 }
211
212 #[test]
213 fn test_add_layer() {
214 let mut grid: WavefrontGrid = new_wavefront_grid();
215 grid.add_layer(-3, 3);
216 assert_eq!(grid.diags[0], (0, 0));
217 assert_eq!(grid.diags[1], (-3, 3));
218 assert_eq!(grid.offsets[0], 0);
219 assert_eq!(grid.offsets[1], 1);
220 assert_eq!(grid.offsets[2], 8);
221 assert_eq!(grid.matches.len(), 8); assert_eq!(grid.inserts.len(), 8);
223 assert_eq!(grid.deletes.len(), 8);
224 }
225}