Skip to content

seqtree 1.0.0 — TextIndex, nanobind bindings, first stable release

Latest

Choose a tag to compare

@mikessh mikessh released this 06 Sep 12:17
· 2 commits to master since this release

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 mmap paths, exercised by CI on all three platforms.
  • Audit pass: one parallel_for replaces 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; psutil is out of the [bench] extra.
  • Docs: two claims that no longer matched the code are corrected — engine="auto" never routed to seqtrie, and the first BLOSUM62 example used gap_open=8 against the library's own 2 * 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