Repository navigation
--alignEndsType on pairs: extend a mate's two ends while stitching (100M, AS:182 as STAR) - #368
Open
BenjaminDEMAILLE wants to merge 2 commits into
Open
BenjaminDEMAILLE wants to merge 2 commits into
BenjaminDEMAILLE wants to merge 2 commits into
Conversation
Both ends of a mate are now extended in the stitcher, with ext[iFrag][iEnd] applied at the mate boundary and at the transcript's outer ends. The extension's mismatches count in the pair's score and limits. finalize_transcript worked on one mate's slice after the pair was already chosen, so inner ends stayed clipped and a mate that cannot reach its end could be clipped into a pair. Transcript scores are not floored at 0 before the window's score gate, so a negative end-to-end transcript loses to an existing one. Part of #354 (finding 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
STAR's extendAlign checks the chromosome boundary first and the fragment spacer second, so a mate whose 3' end sits on a chromosome edge is killed under EndToEnd / Extend3pOfRead1 instead of stopping at the spacer. With mate 1 the last 100 bases of the chromosome and mate 2 its reverse complement, STAR reports mate 2 alone (153 100M AS:98); this branch reported a pair with AS:198. It now matches STAR, and with an unrelated mate 2 both leave the read unmapped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 3, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #354 (finding 3).
Moved from BenjaminDEMAILLE#2. The base,
perf/hotpaths, is a copy of #346's branch ataeba641, pushed here so this PR can target it. If #346 gets new commits, the copy needs them too. Once #346 merges, retarget this PR tomainand deleteperf/hotpaths.Stacked on #346 (
perf/hotpaths, tipaeba641). Only the one commit is this PR. It merges without a conflict with the PR for finding 2, so neither is stacked on the other. Pairs only reach zero differences with both, see the tables.Problem
--alignEndsType EndToEndleft the inner ends of a pair's mates soft-clipped. With 4 mismatches at the 3' end of each mate:100M/100Mperf/hotpaths96M4S/4S96M100M/100MThe end-to-end decision was made in
finalize_transcript, on one mate's slice, after the pair had been chosen and scored. Its mismatches never counted in the pair's score or limits, and a mate that could not reach its end could still be clipped into a pair.Extend5pOfRead1,Extend5pOfReads12andExtend3pOfRead1went through the same code.What STAR does
Observed output of Homebrew STAR 2.7.11b; source not read.
100M/100M,AS:182,nM:8.Extend3pOfRead1extends only read 1's 3' end:100Mand4S96M,AS:186,nM:4.100M,AS:98).Change
All in
src/align/stitch.rs, plus the removed argument at four calls insrc/align/read_align.rs.ext[iFrag][iEnd].ext_fragmaps a seed'smate_idto that fragment; single-end seeds carrymate_id2 and use fragment 0.return falseat the boundary,break 'leafat the leaf.finalize_transcriptloses itsimateparameter and no longer forces any end. Its check for that case moved with it.wt_final_scoreis not floored at 0 any more. An end-to-end extension can take a transcript below zero, and the window's score gate has to see that.In
Localmode every extension flag stays false, as before. Removing the floor does reachLocal, for a transcript whose genomic-length penalty takes it below zero; the numbers below show no change there, on these reads.Measured against STAR
Fields 1-11 plus
NH,HI,AS,nM.Crafted reads (reads with mismatches at the ends, with both mate orders, and reads that cannot reach an end), this branch:
Log.final.outcountse1.fq/e2.fqEndToEndEndToEnd,--outSAMunmapped WithinExtend5pOfRead1Extend5pOfReads12Extend3pOfRead1LocalEndToEndExtend5pOfRead1Extend3pOfRead1EndToEnd, no mismatch limitEndToEnd, filters 0.3On
perf/hotpathsthe audit fixture differs, pairs underEndToEndhave 16 records against 12, andExtend3pOfRead1has 20 against 18.Fuzz: 4000 repeat-rich pairs, and their first mates for single-end. Reads differing from STAR:
perf/hotpathsEndToEndEndToEnd, filters 0.3Extend5pOfRead1Extend5pOfReads12Extend3pOfRead1LocalEndToEndLocalSo this branch alone does not bring pairs to zero. The differences left are the half-mapped reads of finding 2, which is why
Local, which this PR does not touch, stays at 523. The merge'sLog.final.outcounts are identical to STAR's for every row but single-endEndToEnd, below.The merge also passes
cargo test --release(831 passed).Not the same as STAR
On the single-end
EndToEndfuzz, the alignments are identical but 7 of the 335 unmapped junk reads carry another label:I do not know why. I tried treating a negative score as no alignment: that gave 121 / 214, and three crafted reads scoring 0, -1 and -2 said STAR calls those "too short", so the idea was wrong and I removed it. The crafted fixtures and the audit's reads do not show it. On
perf/hotpaths, a read past the chromosome start was "too short" where STAR says "other"; that case is fixed and tested.Deliberate divergences
None, so no
DIVERGENCE.mdentry and no sign-off needed.Tests
tests/end_to_end_pairs.rs, all five failing on the oldsrc/, with expected values from STAR's output on the same fixture:inner_ends_are_extended_and_chargedouter_ends_are_charged_to_the_paira_mate_past_the_chromosome_start_cannot_be_clipped_into_a_pairone_sided_modes_extend_only_their_inner_endsingle_end_read_past_the_chromosome_start_has_no_alignmentcargo test --release(824 passed),cargo clippy --all-targetsandcargo fmt --checkare clean on macOS.Not checked
test/parity_suite.shwas not run.EndToEndnow extends during stitching, on every leaf, rather than once at the end. Local mode takes the same path with the flag off.--peOverlapNbasesMinwas not run together with--alignEndsType.--alignEndsType.Second commit, after review
An independent review fuzzed 4000 pairs against STAR 2.7.11b under 17 option sets. With this PR and #367 merged, every set had 0 differing reads except three EndToEnd sets with 1 or 3. The single read came from the order of two checks in the end-to-end extension: STAR's
extendAlign.cpp:24-31checks the chromosome edge before the mate spacer, this code the other way round, so a mate whose 3' end sits on a chromosome edge was extended into a pair.f7da8eeswaps them.f7da8eeEndToEndorExtend3pOfRead1153 100M AS:98AS:198153 100M AS:98EndToEnd73 100M AS:98Extend3pOfRead173S6M21SFilters at 0.3 in all rows. Locked by
a_mate_ending_on_the_chromosome_end_cannot_be_extended_into_a_pair, which fails without the change. Without #367 this branch also writes the unmapped mate's record (flag 101), which STAR omits; #367 handles that.The same review timed 200k pairs at
--runThreadN 1: 12.0-12.2 s of user CPU on the base and on this branch, Local and EndToEnd alike, so no measurable cost. Remaining:EndToEndwith--peOverlapNbasesMin 10leaves 2 reads with mates at a chromosome end unmapped where STAR maps them with2S/1S.🤖 Generated with Claude Code