Skip to main content

minimizer-stream

CI Coverage Types Mutation Python License

A dependency-free Python library and command-line program that streams canonical minimizer sketches from FASTA and four-line FASTQ. Output includes record, zero-based position, stable 64-bit FNV-1a hash, canonical strand, and canonical k-mer.

Install

python -m pip install minimizer-stream

For development and verification:

python -m pip install -e '.[test]'
ruff check .
pytest --cov=minimizer_stream --cov-branch --cov-fail-under=100

Quickstart

minimizer-stream reads.fasta -k 21 -w 10 > sketch.tsv
minimizer-stream reads.fastq -k 21 -w 10 --format jsonl --deduplicate
cat reads.fasta | minimizer-stream - -k 15 -w 5

TSV has no header and its columns are record, position, hash, strand, kmer. JSONL uses the same field names. The Python API is lazy:

from minimizer_stream import minimizers, naive_minimizers

for item in minimizers("ACGTTGCA", k=3, w=2, deduplicate=True):
    print(item.position, item.hash, item.strand, item.kmer)

assert list(minimizers("ACGTTGCA", 3, 2)) == list(naive_minimizers("ACGTTGCA", 3, 2))

Algorithm

flowchart LR; R[FASTA/FASTQ] --> K[canonical k-mers]; K --> H[FNV-1a 64-bit]; H --> D[monotonic deque, window w]; D --> M[leftmost minimum]; M --> U{deduplicate?}; U --> O[record, position, hash, strand, kmer]

Each k-mer is compared lexicographically with its reverse complement; the smaller representation is canonical, with palindromes assigned to the forward strand. Canonical strings are hashed with deterministic 64-bit FNV-1a, never Python's process-randomized hash. A monotonic deque retains possible minima for each window, removing expired entries from the front and strictly larger hashes from the back. Keeping equal hashes preserves deterministic leftmost tie-breaking.

Constructing, reverse-complementing, and hashing each canonical k-mer costs $O(k)$ in this pure-Python implementation. The monotonic-deque path is therefore $O(nk)$ total with $O(w+k)$ working memory, versus $O(n(k+w))$ for naive_minimizers, which additionally scans each minimizer window. Non-ACGT characters reset both k-mer construction and the minimizer window, so no output spans an invalid base.

Reproducible capability evidence

The deterministic benchmark seeds its input and first requires both implementations to produce exactly identical objects:

python benchmarks/benchmark.py --length 50000 --k 21 --w 50 --repeats 3

On an Apple M3 Max with Python 3.11.12, that command produced 49,931 identical selections and median times of 0.130359 seconds for the deque implementation and 0.195500 seconds for the oracle, a 1.50x speedup. Timing depends on hardware and Python version; the durable claim is removing the extra $O(nw)$ window scan through amortized $O(n)$ deque maintenance, while shared k-mer construction remains $O(nk)$. The exhaustive deterministic randomized test also compares both APIs across lengths 0–39 and all combinations of k and w from 1–5.

Verification

CI runs Ruff, strict mypy, and the full property-based and deterministic test suites on Linux and macOS with Python 3.11–3.13. Its exact coverage command is:

pytest --cov=minimizer_stream --cov-branch --cov-fail-under=100

Tests include reverse complements, palindromes, ties, invalid-base resets, short and lowercase sequences, FASTA, FASTQ, malformed records, invalid parameters, subprocess execution from a clean temporary directory, TSV, JSONL, standard input, and deduplication.

Mutation testing

From the repository root, reproduce the mutation run with:

source .venv/bin/activate
mutmut run
mutmut results

Mutation testing generated 392 mutants and killed 388 (98.98%). The remaining 4 survivors were reviewed as behavior-equivalent, not missed mutants; the run had zero suspicious mutants and zero timeouts.

Behavior-equivalent rationale Count
ASCII codec alias 1
Initial None versus empty value, compared only to Minimizer instances 2
typing.cast is an identity operation at runtime 1

Limitations

  • FASTQ must use the conventional four-line form; wrapped sequence or quality lines are rejected.
  • FASTA permits wrapped sequence lines but rejects blank lines and empty records.
  • Record names containing control characters or beginning with =, +, -, or @ are rejected so default TSV output keeps five columns and is safe from spreadsheet formula interpretation.
  • Input is decoded as ASCII; compressed files must be decompressed before use.
  • Record sequences are retained one at a time. The parser does not load the full file, but an individual record must fit in memory.
  • w counts consecutive valid k-mers, not bases. A valid window therefore spans k + w - 1 bases.
  • Hash collisions are possible for any 64-bit sketch; the canonical k-mer is emitted so callers can distinguish them when needed.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

minimizer_stream-1.0.0.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

minimizer_stream-1.0.0-py3-none-any.whl (10.3 kB view details)

Uploaded Python 3

File details

Details for the file minimizer_stream-1.0.0.tar.gz.

File metadata

  • Download URL: minimizer_stream-1.0.0.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for minimizer_stream-1.0.0.tar.gz
Algorithm Hash digest
SHA256 aa6ddc849381828f3687d568b90c724becbed86834de40b2f3b625013582bafc
MD5 07ebdedd7513580dcef0a122715c68ec
BLAKE2b-256 acc8096eb3c1321e218263646ca0df4fc58e32ef52cd5ae5157bdfeb6932e8d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for minimizer_stream-1.0.0.tar.gz:

Publisher: publish.yml on bmouler/minimizer-stream

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file minimizer_stream-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for minimizer_stream-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9ebd165e39091ab4f076d87bf3913fa194ae18c547bbfd9fc86f480fe04907c8
MD5 2c95862bbb4583ae6f77ca4412a65a53
BLAKE2b-256 3908d993d58da129549e79d99e3cfc71839700f7cac75e88cbf1b59372f7e152

See more details on using hashes here.

Provenance

The following attestation bundles were made for minimizer_stream-1.0.0-py3-none-any.whl:

Publisher: publish.yml on bmouler/minimizer-stream

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page