First stable release. From 1.0.0 the project follows semantic versioning: breaking changes need a major bump.
TextIndex — exact k-mismatch search over a long text
Index is a trie over reference strings, so asking a text question with it means enumerating every length-L window as its own string — and again for every distinct query length. The human proteome has 68,389,335 nine-mer windows; a query set spanning 45 distinct lengths costs 45 multi-gigabyte builds. That is what ran over 2 h without finishing and filled 225 GB of index cache downstream.
TextIndex keys on a k-mer seed table over the flat text, so k belongs to the index, not the query: one build answers every length and every max_subs.
ix = seqtree.TextIndex.build(records, alphabet="aa", k=4, group_ids=gene_id_per_record)
res = ix.search_batch(peptides, max_subs=2, best_only=True, group_by=True, threads=0)Exact, not heuristic, by one search scheme: split the query into b = min(m+1, L//k) disjoint blocks and probe block j's leading k-mer at radius c_j. It is lossless exactly when Σ c_j ≥ m − b + 1. Completeness is pinned by brute-force set equality over L 6–30 × max_subs 0–3 × k ∈ {3,4,5}, and by the answer being identical across k.
On the human proteome (147,506 records, 69,578,135 residues), one thread:
| query length | max_subs |
ms/query |
|---|---|---|
| 9 | 2 | 1.28 |
| 12 | 3 | 0.39 (k=5) |
| 15 | 3 | 0.14 (k=5) |
Results come back as flat CSR arrays with zero-copy numpy views, mismatches as (pos, query_aa, text_aa) pairs, an optional fold onto caller-supplied group ids that makes a tie explicit, and a cap that is always reported.
nanobind bindings
The bindings moved from pybind11 to nanobind: smaller module, lower per-call overhead, and generated type stubs. The package has shipped py.typed since the beginning while providing no stubs at all, so every C++ symbol resolved to Any; _core.pyi now ships in the wheel. Externally visible behaviour is unchanged, including ScoreMatrix's buffer protocol and the exception mapping pinned by message text.
Also in this release
- Windows portability for the
mmappaths, exercised by CI on all three platforms. - Audit pass: one
parallel_forreplaces seven hand-rolled thread-pool copies (one of which had no exception plumbing at all); 59 previously undocumented members of the C++ binding surface are documented and gated by a test;psutilis out of the[bench]extra. - Docs: two claims that no longer matched the code are corrected —
engine="auto"never routed toseqtrie, and the first BLOSUM62 example usedgap_open=8against the library's own2 * scale()= 28 rule.
Zero runtime dependencies. Wheels for CPython 3.10–3.13 on Linux x86-64, macOS arm64, and Windows x86-64.
Full detail in CHANGELOG.md · docs at antigenomics.github.io/seqtree