Skip to content

Commit e0a10fe

Browse files
authored
chore: enable pedantic lints (#56)
1 parent 2ab4a3c commit e0a10fe

20 files changed

Lines changed: 282 additions & 280 deletions

src/align/read_align.rs

Lines changed: 119 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ pub fn align_paired_read(
749749
combined_seeds.extend(m2_seeds);
750750
// mate_id: positions 0..len1 → mate1(0); positions len1+1.. → RC(mate2)(1).
751751
for s in &mut combined_seeds {
752-
s.mate_id = if s.read_pos < len1 { 0 } else { 1 };
752+
s.mate_id = u8::from(s.read_pos >= len1);
753753
}
754754

755755
// Cluster combined seeds using the combined read length
@@ -831,135 +831,132 @@ pub fn align_paired_read(
831831
for wt in &wts {
832832
let split_result =
833833
split_combined_wt(wt, len1, len2, stitch_is_reverse, scorer.align_intron_min);
834-
match split_result {
835-
Some((m1_wt, m2_wt)) => {
836-
let (m1_read_slice, m1_orig_rev, m2_read_slice, m2_orig_rev) =
837-
if stitch_is_reverse {
838-
// stitch_read = [mate2(0..len2) | SPACER | RC(mate1)(len2+1..)]
839-
(
840-
&stitch_read[len2 + 1..], // RC(mate1_seq)
841-
true, // mate1 5' at right in RC
842-
&stitch_read[..len2], // mate2_seq
843-
false, // mate2 5' at left
844-
)
845-
} else {
846-
// stitch_read = [mate1(0..len1) | SPACER | RC(mate2)(len1+1..)]
847-
(
848-
&stitch_read[..len1], // mate1_seq
849-
false, // mate1 5' at left
850-
&stitch_read[len1 + 1..], // RC(mate2_seq)
851-
true, // mate2 5' at right in RC
852-
)
853-
};
854-
855-
// Suppress inner-side extensions for each mate.
856-
// Inner = 3' end: right for forward (orig_is_rev=false), left for reverse.
857-
let Some(mut t1) = finalize_transcript(
858-
&m1_wt,
859-
m1_read_slice,
834+
if let Some((m1_wt, m2_wt)) = split_result {
835+
let (m1_read_slice, m1_orig_rev, m2_read_slice, m2_orig_rev) = if stitch_is_reverse
836+
{
837+
// stitch_read = [mate2(0..len2) | SPACER | RC(mate1)(len2+1..)]
838+
(
839+
&stitch_read[len2 + 1..], // RC(mate1_seq)
840+
true, // mate1 5' at right in RC
841+
&stitch_read[..len2], // mate2_seq
842+
false, // mate2 5' at left
843+
)
844+
} else {
845+
// stitch_read = [mate1(0..len1) | SPACER | RC(mate2)(len1+1..)]
846+
(
847+
&stitch_read[..len1], // mate1_seq
848+
false, // mate1 5' at left
849+
&stitch_read[len1 + 1..], // RC(mate2_seq)
850+
true, // mate2 5' at right in RC
851+
)
852+
};
853+
854+
// Suppress inner-side extensions for each mate.
855+
// Inner = 3' end: right for forward (orig_is_rev=false), left for reverse.
856+
let Some(mut t1) = finalize_transcript(
857+
&m1_wt,
858+
m1_read_slice,
859+
index,
860+
&scorer,
861+
&stitch_cluster,
862+
m1_orig_rev,
863+
m1_orig_rev, // no_left_ext = inner for reverse (orig_is_rev=true)
864+
!m1_orig_rev, // no_right_ext = inner for forward (orig_is_rev=false)
865+
) else {
866+
continue;
867+
};
868+
let Some(mut t2) = finalize_transcript(
869+
&m2_wt,
870+
m2_read_slice,
871+
index,
872+
&scorer,
873+
&stitch_cluster,
874+
m2_orig_rev,
875+
m2_orig_rev, // no_left_ext = inner for reverse (orig_is_rev=true)
876+
!m2_orig_rev, // no_right_ext = inner for forward (orig_is_rev=false)
877+
) else {
878+
continue;
879+
};
880+
881+
if stitch_is_reverse {
882+
t1.is_reverse = true;
883+
t2.is_reverse = false;
884+
} else {
885+
t1.is_reverse = false;
886+
t2.is_reverse = true;
887+
}
888+
t1.read_seq = mate1_seq.to_vec();
889+
t2.read_seq = mate2_seq.to_vec();
890+
891+
if params.chim_segment_min > 0 {
892+
all_m1_transcripts.push(t1.clone());
893+
all_m2_transcripts.push(t2.clone());
894+
}
895+
896+
let combined_span =
897+
t1.genome_end.max(t2.genome_end) - t1.genome_start.min(t2.genome_start);
898+
let combined_wt_score = wt.score + scorer.genomic_length_penalty(combined_span);
899+
900+
if let Some(pair) = try_pair_transcripts(
901+
&t1,
902+
&t2,
903+
len1,
904+
len2,
905+
params,
906+
combined_score_threshold,
907+
combined_wt_score,
908+
) {
909+
joint_pairs.push(pair);
910+
}
911+
} else {
912+
// Single-mate WT: save for half-mapped fallback
913+
let all_m1 = wt.exons.iter().all(|e| e.mate_id == 0);
914+
let all_m2 = wt.exons.iter().all(|e| e.mate_id == 1);
915+
if all_m1 {
916+
let (read_slice, orig_rev) = if stitch_is_reverse {
917+
(&stitch_read[len2 + 1..], true)
918+
} else {
919+
(&stitch_read[..len1], false)
920+
};
921+
if let Some(mut t) = finalize_transcript(
922+
wt,
923+
read_slice,
860924
index,
861925
&scorer,
862926
&stitch_cluster,
863-
m1_orig_rev,
864-
m1_orig_rev, // no_left_ext = inner for reverse (orig_is_rev=true)
865-
!m1_orig_rev, // no_right_ext = inner for forward (orig_is_rev=false)
866-
) else {
867-
continue;
927+
orig_rev,
928+
false,
929+
false,
930+
) {
931+
t.is_reverse = stitch_is_reverse;
932+
t.read_seq = mate1_seq.to_vec();
933+
if params.chim_segment_min > 0 {
934+
all_m1_transcripts.push(t.clone());
935+
}
936+
single_mate1_transcripts.push(t);
937+
}
938+
} else if all_m2 {
939+
let (read_slice, orig_rev) = if stitch_is_reverse {
940+
(&stitch_read[..len2], false)
941+
} else {
942+
(&stitch_read[len1 + 1..], true)
868943
};
869-
let Some(mut t2) = finalize_transcript(
870-
&m2_wt,
871-
m2_read_slice,
944+
if let Some(mut t) = finalize_transcript(
945+
wt,
946+
read_slice,
872947
index,
873948
&scorer,
874949
&stitch_cluster,
875-
m2_orig_rev,
876-
m2_orig_rev, // no_left_ext = inner for reverse (orig_is_rev=true)
877-
!m2_orig_rev, // no_right_ext = inner for forward (orig_is_rev=false)
878-
) else {
879-
continue;
880-
};
881-
882-
if stitch_is_reverse {
883-
t1.is_reverse = true;
884-
t2.is_reverse = false;
885-
} else {
886-
t1.is_reverse = false;
887-
t2.is_reverse = true;
888-
}
889-
t1.read_seq = mate1_seq.to_vec();
890-
t2.read_seq = mate2_seq.to_vec();
891-
892-
if params.chim_segment_min > 0 {
893-
all_m1_transcripts.push(t1.clone());
894-
all_m2_transcripts.push(t2.clone());
895-
}
896-
897-
let combined_span =
898-
t1.genome_end.max(t2.genome_end) - t1.genome_start.min(t2.genome_start);
899-
let combined_wt_score = wt.score + scorer.genomic_length_penalty(combined_span);
900-
901-
if let Some(pair) = try_pair_transcripts(
902-
&t1,
903-
&t2,
904-
len1,
905-
len2,
906-
params,
907-
combined_score_threshold,
908-
combined_wt_score,
950+
orig_rev,
951+
false,
952+
false,
909953
) {
910-
joint_pairs.push(pair);
911-
}
912-
}
913-
None => {
914-
// Single-mate WT: save for half-mapped fallback
915-
let all_m1 = wt.exons.iter().all(|e| e.mate_id == 0);
916-
let all_m2 = wt.exons.iter().all(|e| e.mate_id == 1);
917-
if all_m1 {
918-
let (read_slice, orig_rev) = if stitch_is_reverse {
919-
(&stitch_read[len2 + 1..], true)
920-
} else {
921-
(&stitch_read[..len1], false)
922-
};
923-
if let Some(mut t) = finalize_transcript(
924-
wt,
925-
read_slice,
926-
index,
927-
&scorer,
928-
&stitch_cluster,
929-
orig_rev,
930-
false,
931-
false,
932-
) {
933-
t.is_reverse = stitch_is_reverse;
934-
t.read_seq = mate1_seq.to_vec();
935-
if params.chim_segment_min > 0 {
936-
all_m1_transcripts.push(t.clone());
937-
}
938-
single_mate1_transcripts.push(t);
939-
}
940-
} else if all_m2 {
941-
let (read_slice, orig_rev) = if stitch_is_reverse {
942-
(&stitch_read[..len2], false)
943-
} else {
944-
(&stitch_read[len1 + 1..], true)
945-
};
946-
if let Some(mut t) = finalize_transcript(
947-
wt,
948-
read_slice,
949-
index,
950-
&scorer,
951-
&stitch_cluster,
952-
orig_rev,
953-
false,
954-
false,
955-
) {
956-
t.is_reverse = !stitch_is_reverse;
957-
t.read_seq = mate2_seq.to_vec();
958-
if params.chim_segment_min > 0 {
959-
all_m2_transcripts.push(t.clone());
960-
}
961-
single_mate2_transcripts.push(t);
954+
t.is_reverse = !stitch_is_reverse;
955+
t.read_seq = mate2_seq.to_vec();
956+
if params.chim_segment_min > 0 {
957+
all_m2_transcripts.push(t.clone());
962958
}
959+
single_mate2_transcripts.push(t);
963960
}
964961
}
965962
}
@@ -2144,7 +2141,7 @@ mod tests {
21442141
assert_eq!(items[4], (40, 4));
21452142
// Tied prefix contains the original three items in some order.
21462143
let mut top: Vec<u32> = items[..3].iter().map(|t| t.1).collect();
2147-
top.sort();
2144+
top.sort_unstable();
21482145
assert_eq!(top, vec![0, 1, 2]);
21492146
}
21502147

src/align/score.rs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -224,35 +224,39 @@ impl AlignmentScorer {
224224
// Score the net indel portion
225225
(gg, rg) if gg > 0 && rg > 0 => {
226226
let excess = gg - rg;
227-
if excess > 0 {
228-
let del_len = excess as u32;
229-
if del_len >= self.align_intron_min && del_len <= self.align_intron_max {
230-
let rc_donor = genome_pos + rg as u64;
231-
let donor = if is_reverse {
232-
n_genome - rc_donor - del_len as u64
227+
match excess {
228+
1.. => {
229+
let del_len = excess as u32;
230+
if del_len >= self.align_intron_min && del_len <= self.align_intron_max {
231+
let rc_donor = genome_pos + rg as u64;
232+
let donor = if is_reverse {
233+
n_genome - rc_donor - del_len as u64
234+
} else {
235+
rc_donor
236+
};
237+
let motif = self.detect_splice_motif(donor, del_len, genome);
238+
let score = self.score_splice_junction(&motif);
239+
(
240+
score,
241+
GapType::SpliceJunction {
242+
intron_len: del_len,
243+
motif,
244+
},
245+
)
233246
} else {
234-
rc_donor
235-
};
236-
let motif = self.detect_splice_motif(donor, del_len, genome);
237-
let score = self.score_splice_junction(&motif);
238-
(
239-
score,
240-
GapType::SpliceJunction {
241-
intron_len: del_len,
242-
motif,
243-
},
244-
)
245-
} else {
246-
let score = self.score_del_open + self.score_del_base * del_len as i32;
247-
(score, GapType::Deletion(del_len))
247+
let score = self.score_del_open + self.score_del_base * del_len as i32;
248+
(score, GapType::Deletion(del_len))
249+
}
250+
}
251+
..=-1 => {
252+
let ins_len = (-excess) as u32;
253+
let score = self.score_ins_open + self.score_ins_base * ins_len as i32;
254+
(score, GapType::Insertion(ins_len))
255+
}
256+
0 => {
257+
// Equal gaps: no net indel
258+
(0, GapType::Deletion(0))
248259
}
249-
} else if excess < 0 {
250-
let ins_len = (-excess) as u32;
251-
let score = self.score_ins_open + self.score_ins_base * ins_len as i32;
252-
(score, GapType::Insertion(ins_len))
253-
} else {
254-
// Equal gaps: no net indel
255-
(0, GapType::Deletion(0))
256260
}
257261
}
258262
// Other cases (negative gaps, etc.)

src/align/seed.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -366,14 +366,11 @@ fn find_seed_at_position(
366366
.sa_index
367367
.hierarchical_lookup(kmer_idx, actual_len as u32, n_sa);
368368

369-
let (sa_start, sa_end, matched_level, bounds_tight) = match result {
370-
Some(r) => r,
371-
None => {
372-
return Ok(MmpResult {
373-
seed: None,
374-
advance: 1,
375-
});
376-
}
369+
let Some((sa_start, sa_end, matched_level, bounds_tight)) = result else {
370+
return Ok(MmpResult {
371+
seed: None,
372+
advance: 1,
373+
});
377374
};
378375

379376
if sa_start >= sa_end {
@@ -440,7 +437,7 @@ fn find_seed_at_position(
440437
/// Overflow-safe median of two unsigned integers.
441438
/// Equivalent to STAR's medianUint2: a/2 + b/2 + (a%2 + b%2)/2
442439
fn median_uint2(a: usize, b: usize) -> usize {
443-
a / 2 + b / 2 + (a % 2 + b % 2) / 2
440+
a / 2 + b / 2 + usize::midpoint(a % 2, b % 2)
444441
}
445442

446443
/// Compare read to genome at a specific SA position, starting from offset l_start.

0 commit comments

Comments
 (0)