Skip to content

Commit 03165a2

Browse files
committed
simplify stitching
1 parent 323ea32 commit 03165a2

3 files changed

Lines changed: 28 additions & 39 deletions

File tree

src/align/stitch.rs

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Seed clustering and stitching via dynamic programming
22
use crate::align::score::AlignmentScorer;
33
use crate::align::seed::Seed;
4-
use crate::align::transcript::Transcript;
4+
use crate::align::transcript::{CigarOpExt, Transcript};
55
use crate::error::Error;
66
use crate::index::GenomeIndex;
77
use noodles::sam::alignment::record::cigar;
@@ -1754,6 +1754,16 @@ pub(crate) fn finalize_transcript(
17541754

17551755
use cigar::op::{Kind, Op};
17561756

1757+
fn append_match(ops: &mut Vec<Op>, len: usize) {
1758+
if let Some(op) = ops.last_mut()
1759+
&& op.kind() == Kind::Match
1760+
{
1761+
*op = op.with_added_len(len);
1762+
} else {
1763+
ops.push(Op::new(Kind::Match, len));
1764+
}
1765+
}
1766+
17571767
// Build final CIGAR from exon blocks
17581768
let mut final_cigar: Vec<Op> = Vec::new();
17591769

@@ -1779,14 +1789,7 @@ pub(crate) fn finalize_transcript(
17791789
// Shared match bases before the gap
17801790
let shared = read_gap.max(0) as usize;
17811791
if shared > 0 {
1782-
// TODO: replace with “extend_or_push_match” function call
1783-
if let Some(op) = final_cigar.last_mut()
1784-
&& op.kind() == Kind::Match
1785-
{
1786-
*op = Op::new(Kind::Match, op.len() + shared);
1787-
} else {
1788-
final_cigar.push(Op::new(Kind::Match, shared));
1789-
}
1792+
append_match(&mut final_cigar, shared);
17901793
}
17911794
let del = (genome_gap - read_gap.max(0)) as usize;
17921795
if del >= scorer.align_intron_min as usize
@@ -1800,14 +1803,7 @@ pub(crate) fn finalize_transcript(
18001803
// Insertion
18011804
let shared = genome_gap.max(0) as usize;
18021805
if shared > 0 {
1803-
// TODO: replace with “extend_or_push_match” function call
1804-
if let Some(op) = final_cigar.last_mut()
1805-
&& op.kind() == Kind::Match
1806-
{
1807-
*op = Op::new(Kind::Match, op.len() + shared);
1808-
} else {
1809-
final_cigar.push(Op::new(Kind::Match, shared));
1810-
}
1806+
append_match(&mut final_cigar, shared);
18111807
}
18121808
let ins = (read_gap - genome_gap.max(0)) as usize;
18131809
final_cigar.push(Op::new(Kind::Insertion, ins));
@@ -1818,27 +1814,13 @@ pub(crate) fn finalize_transcript(
18181814
// This exon's match region
18191815
let match_len = exon.read_end - exon.read_start;
18201816
if match_len > 0 {
1821-
// TODO: replace with “extend_or_push_match” function call
1822-
if let Some(op) = final_cigar.last_mut()
1823-
&& op.kind() == Kind::Match
1824-
{
1825-
*op = Op::new(Kind::Match, op.len() + match_len);
1826-
} else {
1827-
final_cigar.push(Op::new(Kind::Match, match_len));
1828-
}
1817+
append_match(&mut final_cigar, match_len);
18291818
}
18301819
}
18311820

18321821
// Right extension match
18331822
if right_extend.extend_len > 0 {
1834-
// TODO: replace with “extend_or_push_match” function call
1835-
if let Some(op) = final_cigar.last_mut()
1836-
&& op.kind() == Kind::Match
1837-
{
1838-
*op = Op::new(Kind::Match, op.len() + right_extend.extend_len);
1839-
} else {
1840-
final_cigar.push(Op::new(Kind::Match, right_extend.extend_len));
1841-
}
1823+
append_match(&mut final_cigar, right_extend.extend_len);
18421824
}
18431825

18441826
// Right soft clip

src/align/transcript.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ pub struct Exon {
5555
pub i_frag: u8,
5656
}
5757

58+
pub(crate) trait CigarOpExt {
59+
fn with_added_len(&self, len: usize) -> Self;
60+
}
61+
impl CigarOpExt for cigar::Op {
62+
fn with_added_len(&self, len: usize) -> Self {
63+
cigar::Op::new(self.kind(), self.len() + len)
64+
}
65+
}
66+
5867
fn cigar_char(kind: cigar::op::Kind) -> char {
5968
use cigar::op::Kind;
6069
match kind {

src/quant/transcriptome.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! only substantive divergence that rustar-aligner builds the transcript tables on
1111
//! the fly from the input GTF instead of loading persisted
1212
//! `transcriptInfo.tab`/`exonInfo.tab` files.
13-
use crate::align::transcript::{Exon, Transcript};
13+
use crate::align::transcript::{CigarOpExt, Exon, Transcript};
1414
use crate::error::Error;
1515
use crate::genome::Genome;
1616
use crate::junction::gtf::GtfRecord;
@@ -1301,8 +1301,7 @@ fn rebuild_cigar_without_softclips(
13011301
if i == 0 && left_clip > 0 {
13021302
// Fold left_clip into the first op if it's match-like.
13031303
match op.kind() {
1304-
Kind::Match => out.push(Op::new(Kind::Match, op.len() + left_clip)),
1305-
Kind::SequenceMatch => out.push(Op::new(Kind::SequenceMatch, op.len() + left_clip)),
1304+
Kind::Match | Kind::SequenceMatch => out.push(op.with_added_len(left_clip)),
13061305
_ => {
13071306
// Extension landed on a non-match op (shouldn't normally
13081307
// happen). Emit as Match.
@@ -1312,9 +1311,8 @@ fn rebuild_cigar_without_softclips(
13121311
}
13131312
} else if i + 1 == body.len() && right_clip > 0 {
13141313
match op.kind() {
1315-
Kind::Match => out.push(Op::new(Kind::Match, op.len() + right_clip)),
1316-
Kind::SequenceMatch => {
1317-
out.push(Op::new(Kind::SequenceMatch, op.len() + right_clip));
1314+
Kind::Match | Kind::SequenceMatch => {
1315+
out.push(op.with_added_len(right_clip));
13181316
}
13191317
_ => {
13201318
out.push(*op);

0 commit comments

Comments
 (0)