Introduces a comprehensive documentation set covering theoretical foundations, CLI usage, installation, and system architecture. Adds MkDocs configuration and Makefile targets to generate, serve with live reload, and clean the documentation site. Includes citation styles and bibliography files for academic references.
2.9 KiB
Minimizer selection
Definition
A minimizer of a kmer window is the m-mer (m < k) that is smallest, among all k - m + 1 overlapping m-mers in the window, under a chosen ordering. The minimizer is always taken in canonical form (lexicographic minimum of forward and reverse complement) so that selection is strand-independent.
The minimizer partitions a sequence into super-kmers: maximal runs of overlapping kmers that share the same minimizer (see Kmers and super-kmers).
Hash-based ("random") minimizer
obikmer selects minimizers by hash order rather than plain lexicographic order. Ordering m-mers lexicographically on their 2-bit encoding systematically favors AT-rich m-mers (an all-A m-mer always encodes to 0), which causes low-complexity regions to dominate as minimizers and produces unbalanced partitions.
Instead, a well-distributed hash function H is applied to the canonical (lexicographically minimal) form of each m-mer, and the m-mer with the smallest H value wins. Because H is a bijection with good avalanche properties, every distinct m-mer in a window has an equal chance of holding the minimum hash value, independent of its nucleotide composition.
The canonical form used as input to H is still the lexicographic minimum of forward/reverse-complement — hashing is applied on top of it, not used to redefine it. Defining canonicity by hash value instead would bias the distribution of hash values themselves toward small values (the minimum of two independent hashes is not uniformly distributed), reintroducing a bias one layer down.
Hash function
The hash function is a 64-bit mixing function (splitmix64-style finalizer) applied to the m-mer XORed with a fixed non-zero seed:
H(x) = \text{mix64}(x \oplus s), \quad s = \lfloor 2^{64}/\varphi \rfloor = \texttt{0x9e3779b97f4a7c15}
H(x):
x ← x ⊕ 0x9e3779b97f4a7c15
x ← x ⊕ (x >> 30)
x ← x × 0xbf58476d1ce4e5b9
x ← x ⊕ (x >> 27)
x ← x × 0x94d049bb133111eb
return x ⊕ (x >> 31)
The XOR seed avoids the finalizer's fixed point at 0 (\text{mix64}(0) = 0), which would otherwise make an all-A m-mer (canonical value 0) win every window comparison.
Partition routing is independent of minimizer selection
The hash used to select a minimizer within a window (the minimum of several hash values) and the hash used to route a super-kmer to a storage partition are computed separately:
- Selection uses
Happlied to every candidate m-mer in the window, keeping the minimum. - Partition routing recomputes
Hon the single selected minimizer only, once its position is fixed. This is a hash of one specific value, not the minimum of several, so it is uniformly distributed and safe to use directly for routing.
See Partitioning and indexing architecture for how the routing value is turned into a partition index.