Skip to content

Commit 5778fa6

Browse files
Merge pull request #1377 from nextstrain/feat/gap-alignment-left
2 parents 93a7146 + f77cd51 commit 5778fa6

File tree

3 files changed

+70
-6
lines changed

3 files changed

+70
-6
lines changed

docs/user/nextclade-cli/reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ For short help type: `nextclade -h`, for extended help type: `nextclade --help`.
167167

168168
* `--excess-bandwidth <EXCESS_BANDWIDTH>` — Excess bandwidth for internal stripes
169169
* `--terminal-bandwidth <TERMINAL_BANDWIDTH>` — Excess bandwidth for terminal stripes
170-
* `--gap-alignment-side <GAP_ALIGNMENT_SIDE>` — Whether to align gaps on the left or right side if equally parsimonious. Left aligning gaps is the convention, right align is Nextclade's historic default
170+
* `--gap-alignment-side <GAP_ALIGNMENT_SIDE>` — Whether to align gaps on the left or right side if equally parsimonious. Default: left
171171

172172
Possible values: `left`, `right`
173173

packages_rs/nextclade/src/align/params.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ pub enum GapAlignmentSide {
1313
Right,
1414
}
1515

16+
impl Default for GapAlignmentSide {
17+
fn default() -> Self {
18+
Self::Left
19+
}
20+
}
21+
1622
// NOTE: The `optfield` attribute creates a struct that have the same fields, but which are wrapped into `Option`,
1723
// as well as adds a method `.merge_opt(&opt)` to the original struct, which merges values from the optional counterpart
1824
// into self (mutably).
@@ -82,8 +88,7 @@ pub struct AlignPairwiseParams {
8288
#[clap(long)]
8389
pub terminal_bandwidth: i32,
8490

85-
/// Whether to align gaps on the left or right side if equally parsimonious.
86-
/// Left aligning gaps is the convention, right align is Nextclade's historic default
91+
/// Whether to align gaps on the left or right side if equally parsimonious. Default: left
8792
#[clap(long, value_enum)]
8893
pub gap_alignment_side: GapAlignmentSide,
8994

@@ -158,7 +163,7 @@ impl Default for AlignPairwiseParams {
158163
no_translate_past_stop: false,
159164
left_terminal_gaps_free: true,
160165
right_terminal_gaps_free: true,
161-
gap_alignment_side: GapAlignmentSide::Right,
166+
gap_alignment_side: GapAlignmentSide::default(),
162167
excess_bandwidth: 9,
163168
terminal_bandwidth: 50,
164169
min_seed_cover: 0.33,

packages_rs/nextclade/src/align/score_matrix.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ pub fn score_matrix<T: Letter<T>>(
4040

4141
trace!("Score matrix: allocated alignment band of size={band_size}");
4242

43+
// The variable left_align changes the < effectively into <= in the conditions where it's used,
44+
// in order to select preferred alignment where there's two equally good possibilities.
4345
let left_align = match params.gap_alignment_side {
4446
GapAlignmentSide::Left => 1,
4547
GapAlignmentSide::Right => 0,
@@ -267,6 +269,63 @@ mod tests {
267269
],
268270
);
269271

272+
#[rustfmt::skip]
273+
let expected_paths = Band2d::<i8>::with_data(
274+
&stripes,
275+
&[
276+
0, 10, 10, 10,
277+
20, 1, 9, 9, 41,
278+
20, 17, 17, 25, 9,
279+
20, 1, 25, 1, 25, 34, 42,
280+
20, 17, 1, 25, 4, 9, 2, 10,
281+
20, 17, 25, 2, 25, 12, 9, 2,
282+
20, 17, 4, 25, 18, 25, 12, 9,
283+
20, 17, 25, 4, 17, 18, 26, 12,
284+
52, 17, 4, 17, 18, 28,
285+
52, 20, 20, 4, 17, 18,
286+
20, 20, 20, 4, 1,
287+
],
288+
);
289+
290+
assert_eq!(expected_scores, result.scores);
291+
assert_eq!(expected_paths, result.paths);
292+
293+
Ok(())
294+
}
295+
296+
#[rstest]
297+
fn pads_missing_left_with_alignment_gap_right(mut ctx: Context) -> Result<(), Report> {
298+
let qry_seq = to_nuc_seq("CTCGCTG")?;
299+
let ref_seq = to_nuc_seq("ACGCTCGCTG")?;
300+
301+
let band_width = 5;
302+
let mean_shift = 2;
303+
304+
let mut stripes = simple_stripes(mean_shift, band_width, ref_seq.len(), qry_seq.len());
305+
stripes[2].end = stripes[2].end - 1;
306+
stripes[8].begin = stripes[8].begin + 1;
307+
308+
ctx.params.gap_alignment_side = GapAlignmentSide::Right;
309+
let result = score_matrix(&qry_seq, &ref_seq, &ctx.gap_open_close, &stripes, &ctx.params);
310+
311+
#[rustfmt::skip]
312+
let expected_scores = Band2d::<i32>::with_data(
313+
&stripes,
314+
&[
315+
0, 0, 0, 0,
316+
0, -1, -1, -1, -1,
317+
0, 3, -2, 2, -2,
318+
0, -1, 2, -3, 5, -1, -1,
319+
0, 3, -2, 5, -1, 8, 2, 2,
320+
0, -1, 6, 0, 4, 2, 11, 5,
321+
0, 3, 0, 9, 3, 7, 5, 10,
322+
0, -1, 2, 3, 12, 6, 6, 10,
323+
0, 5, 6, 15, 9, 10,
324+
0, 3, 6, 9, 18, 12,
325+
3, 6, 9, 12, 21,
326+
],
327+
);
328+
270329
#[rustfmt::skip]
271330
let expected_paths = Band2d::<i8>::with_data(
272331
&stripes,
@@ -276,8 +335,8 @@ mod tests {
276335
20, 17, 17, 25, 9,
277336
20, 1, 25, 1, 25, 34, 42,
278337
20, 17, 1, 25, 2, 9, 2, 10,
279-
20, 17, 25, 2, 25, 12, 9, 2,
280-
20, 17, 4, 25, 18, 25, 12, 9,
338+
20, 17, 25, 2, 25, 12, 9, 2,
339+
20, 17, 4, 25, 18, 25, 12, 9,
281340
20, 17, 25, 4, 17, 18, 25, 12,
282341
52, 17, 4, 17, 18, 28,
283342
52, 20, 20, 4, 17, 18,

0 commit comments

Comments
 (0)