Repository navigation
alignMatesGapMax limits the gap between mates, not the fragment span - #373
Open
BenjaminDEMAILLE wants to merge 1 commit into
Open
BenjaminDEMAILLE wants to merge 1 commit into
BenjaminDEMAILLE wants to merge 1 commit into
Conversation
STAR rejects a pair only when mate B starts more than alignMatesGapMax after mate A's end (stitchAlignToTranscript.cpp:354). rustar compared the whole fragment span, so pairs with a small gap but a span above the limit were reported unmapped. The proper-pair flag no longer depends on alignMatesGapMax either: STAR's 0x2 test is geometric. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 (
--alignMatesGapMaxlimits the gap between mates;--outMultimapperOrder Randomchecked).Base:
perf/hotpaths. Merges cleanly with #367 (fix/half-mapped-multimap) and #368 (fix/end-to-end-pairs), in that order.Problem
try_pair_transcriptsrejected a pair when the fragment span (right.genome_end - left.genome_start) was above--alignMatesGapMax. STAR limits the gap between the mates. So under--alignMatesGapMax 300, a pair with 100-base mates and a 149-base gap (span 349) was reported unmapped "too short". STAR maps it:check_proper_pairalso used the span against--alignMatesGapMaxfor the 0x2 flag.What STAR does (2.7.11b source)
alignMatesGapMaxis institchAlignToTranscript.cpp:354: stitching mate B onto mate A fails whengBstart > end of mate A's last exon + alignMatesGapMax. That is the gap, not the span. It is skipped when the value is 0.Genome_genomeLoad.cpp:382-405:winBinNbits,winFlankNbins) and the old chimeric detection (ReadAlign_chimericDetectionOld.cpp:299). rustar already ports both (Parameters::redefine_window_params,chimeric/detect.rs); I checked them and changed nothing.ReadAlign_outputTranscriptSAM.cpp:79-83) is geometric: it fails only for mates that protrude past each other. With the default--alignEndsProtrude 0(the only value rustar takes) stitching already rejects those pairs, so every pair is proper.alignMatesGapMaxplays no part.Change
try_pair_transcripts(src/align/read_align.rs): reject whenright.genome_start > left.genome_end + alignMatesGapMax, as STAR's stitcher does. The stitcher's own check (stitch.rs, forward-gap check) was already right.check_proper_pairreturnstrue. I kept the function and its call sites so the branch merges cleanly with Half-mapped pairs go through the same selection and filters as pairs #367, which rewrites those call sites.--outMultimapperOrder Random: only DIVERGENCE.md §1.1, nothing changedSTAR's
multMapSelect(ReadAlign_multMapSelect.cpp:58-87) moves the best-scoring alignments to the top, shuffles them and the rest separately with the per-threadmt19937, and markstrMult[0]primary. rustar keeps the same candidates (same score range), puts the best-scoring ones first, shuffles them with a per-read seed, and marks the first one primary. The remaining difference is the random stream itself (§1.1), plus rustar leaves the non-best alignments sorted rather than shuffled. Both are order only.Evidence,
--outMultimapperOrder Random --runThreadN 1, yeast 10k, this branch:HIASalignment (STAR / rustar)ASalignment: same primaryOn the 4,000-pair simulation below with #367 and #368 merged, 551 reads differ under Random. Set the unmapped-mate records aside and 405 differ, all only in order and primary, with the same set of alignments; the primary is a best-
ASalignment in all 4,000 reads in both tools. The other differences are in the unmapped-mate record: with #367, a half-mapped multimapper writes the unmapped record for the mate opposite the primary, so a different random primary also changes that record. That is still the primary choice.Measured against STAR 2.7.11b
Each tool with its own index,
--runThreadN 1. "Reads differ" counts reads whose records (fields 2-9 and tags) are not all identical.Simulation: 4,000 pairs on a random 300 kb
chr1with two 2 kb repeats, 100-base mates, fragments 80-900, 1% mismatches. Options--alignMatesGapMax 300 --outFilterScoreMinOverLread 0.3 --outFilterMatchNminOverLread 0.3 --outSAMunmapped Within.--alignMatesGapMax 300perf/hotpathsperf/hotpaths+ #367 + #368The 700 left on this branch alone are half-mapped multimappers, which #367 fixes.
CONTRIBUTING.md check, yeast 10k, defaults: SE 9,724 records and PE 18,600 records identical to STAR,
SJ.out.tabidentical (test/compare_sam.py: 8,927/8,927 and 8,391/8,391).Tests
test_mates_gap_max_limits_gap_not_span(replacestest_check_proper_pair_too_far): mates at 1000-1100 and 1300-1400 (gap 200, span 400) pair under a limit of 300 and are proper; under 199 they do not pair. It fails with the old span check.cargo test --release,cargo clippy --all-targets -- -D warningsandcargo fmt --checkare clean on macOS.Not checked
parity_suite.sh(chr21, fusion, STARsolo): the defaultalignMatesGapMaxis 0 and both changed checks are skipped at 0.--outMultimapperOrder Randomwith--outSAMmultNmaxor--outSAMprimaryFlag AllBestScore.🤖 Generated with Claude Code