Skip to content

perf: pool HMM (kofam/sulfur) via Z-independent bit-score prefilter (-T)#11

Merged
tpall merged 3 commits into
perf/search-bundlingfrom
perf/hmm-pool-bitscore
Jun 28, 2026
Merged

perf: pool HMM (kofam/sulfur) via Z-independent bit-score prefilter (-T)#11
tpall merged 3 commits into
perf/search-bundlingfrom
perf/hmm-pool-bitscore

Conversation

@tpall

@tpall tpall commented Jun 28, 2026

Copy link
Copy Markdown
Owner

Summary

Stacked on #10 (base perf/search-bundling; retargets to dev once #10 merges). Adds HMM (kofam/sulfur) to --pool_searches by removing the only thing that blocked it.

mmseqs pooling (#10) is byte-identical because mmseqs filters on bit score (independent of search-space size). HMM couldn't be pooled byte-identically because hmmsearch's -E prefilter — and hmm_parser already filters on per-profile bit-score thresholds, so the -E prefilter is the only Z-dependent step. This PR replaces it with a Z-independent bit-score prefilter:

hmmsearch -T 10 --domT 10   (was: -E 1e-5)

10 sits below kofam's lowest profile threshold (15.07 of 24,405), so no hit a real threshold would keep is pre-cut. Bit score is identical whether a gene is searched alone or in a 134k-gene pool, so pooled HMM == per-genome HMM. kofam/sulfur pooling + pooled-then-chunked kofam (search_chunk_size) are enabled on top.

Validation (extraves, 56 bins)

per-genome(-T) vs pooled-chunked(-T), all 5 DBs:

rows: 141270 == 141270
merops/viral/methyl/kofam/sulfur: IDENTICAL
RESULT: IDENTICAL

kofam fanned out to 8 chunks (vs 56 per-genome). With this PR the entire annotation path (mmseqs + HMM) pools byte-identically.

⚠️ Behavior change vs -E (why this is separate from #10)

-T recovers the bit-score-significant hits that -E 1e-5 silently dropped: +63 kofam calls (~0.08%) on extraves. Bit score is the intended KOfam filter, so this is arguably a latent-bug fix — but it does change kofam/sulfur output vs the -E pipeline. #10 has zero behavior change; this PR is a deliberate, pipeline-wide switch and should be adopted for a fresh campaign (everything -T from the start), not mixed with already-finished -E cohorts.

Output size is unchanged (final annotations 34M == 34M; only the transient domtblout grows).

Notes

  • -Z/--domZ does not work here: one pooled -Z can only match one genome's size, but a pool has differently-sized genomes.
  • Full record + the rejected alternatives: docs/dev/search-bundling.md.
  • nextflow lint: no errors.

🤖 Generated with Claude Code

tpall and others added 3 commits June 28, 2026 09:36
On branch perf/hmm-pool-bitscore (experiment, NOT for PR #10). Re-enables
kofam/sulfur pooling + chunking (un-reverts 3457a80) and switches hmmsearch from
the e-value prefilter (-E, scales with search-space size Z) to a bit-score
prefilter (-T 10 --domT 10). Bit scores are Z-independent, so pooled multi-genome
hmmsearch reports the SAME hits as per-genome; hmm_parser still applies per-profile
bit-score thresholds. Floor 10 < lowest kofam threshold (15.07), so no real hit is
pre-cut.

Goal: validate per-genome(-T) == pooled(-T) on extraves (proves -T removes the
Z-dependence that made -E pooling churn ~5% of kofam calls). NB changes results vs
-E, so a future pipeline-wide decision, not mid-campaign.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…validated)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant