Repository navigation
fix(bitkmer): correct reverse complement window size and length tag in minimizer - #121
Merged
audy merged 2 commits intoOct 6, 2026
Conversation
audy
requested changes
Oct 2, 2026
| /// Find the lexicographically lowest substring of a given length in the `BitKmer` | ||
| pub fn minimizer(kmer: BitKmer, minmer_size: u8) -> BitKmer { | ||
| if minmer_size == 0 || minmer_size > kmer.1 { | ||
| return (0, minmer_size); |
Contributor
There was a problem hiding this comment.
this should probably just be an error. @IgnatiusPang can you change this to an assert + add a test
Contributor
Author
|
Thanks @audy! Updated to an This also matches (PR performed with assistance of AI) |
audy
approved these changes
Oct 6, 2026
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.
Which issue does this PR close?
Fixes an algorithmic defect where
bitkmer::minimizermiscalculated reverse complement values of candidate minimizers and returned an incorrect length tag, causing algorithmic divergence fromsequence::minimizer.Rationale for this change
1. Reverse Complement Window Size Mismatch
In
bitkmer::minimizer:bitmask & new_kmerextracts a window of lengthminmer_size. However, the tuple passed toreverse_complementwas(bitmask & new_kmer, kmer.1), passing the parent k-mer lengthkmer.1(e.g., 31) instead ofminmer_size(e.g., 15).Because
reverse_complementshifts right by2 * (32 - len), passingkmer.1causes the reversed bits to be shifted by2 * (32 - kmer.1)instead of2 * (32 - minmer_size). This misaligns the reverse complement by2 * (kmer.1 - minmer_size)bits and leaves bit-inverted junk in the lowest bits:"AGT"((0b00_1011, 3)) withminmer_size = 2:"GT"(0b1011= 11) has reverse complement"AC"(0b0001= 1).k=3shifted by 58 instead of 60 bits, computingcur_rev = 0b111(7) instead of 1.bitkmer::minimizerfailed to find the true minimizer"AC"(1) and erroneously selected"AG"(2).bitkmer::minimizerto disagree withsequence::minimizeron the exact same input (sequence::minimizer(b"AGT", 2)correctly returned"AC").2. Return Value Length Tag
minimizerreturned(lowest, kmer.1). A minimizer of lengthminmer_sizemust carryminmer_sizeas its length tag. Returningkmer.1caused downstream functions likebitmer_to_bytesto readkmer.1bases from the top, decoding prepended phantom'A'bases (e.g. decoding a 2-mer within a 3-mer as"AAC"instead of"AC").What changes are included in this PR?
src/bitkmer.rs:minmer_sizeinstead ofkmer.1intoreverse_complement.(lowest, minmer_size)as the function result and on early-exit bounds.minmer_size == 0 || minmer_size > kmer.1andminmer_size >= 32exponentiation.test_minimizerassertion for"AGT"to expect canonical minimizer(0b0001, 2)("AC").test_minimizer_matches_sequence_minimizer, verifying exhaustive parity betweenbitkmer::minimizerandsequence::minimizeracross all window lengths.Are these changes tested?
Yes:
cargo test --lib: 42 passed (0 failed).