Skip to content

feat(kdist-calibrate): --from-dada post-inference mode#61

Merged
cjfields merged 1 commit into
mainfrom
feat/kdist-from-dada
Jun 22, 2026
Merged

feat(kdist-calibrate): --from-dada post-inference mode#61
cjfields merged 1 commit into
mainfrom
feat/kdist-from-dada

Conversation

@cjfields

Copy link
Copy Markdown
Member

Summary

Adds a third mode to the hidden kdist-calibrate diagnostic — --from-dada — that operates on dada output instead of derep input, so every pairwise comparison is labelled by what inference actually decided rather than by what the screen saw beforehand.

Each dada output JSON is paired with its derep input (via --derep-dir, matched by sample name so indices line up with dada's map), and every input unique is classified and aligned against the relevant cluster center:

class aligned against meaning
member its own center a real error copy denoising corrected
failed nearest center shed by the abundance test (map == null), unassigned
center_pair another center two ASVs that both survived (resolution floor)

Each row carries the partner center's birth_type/birth_pval, so prior-born ASVs (pseudo-pool) and births near OMEGA_A are visible in the same table.

Why

  • Labels come from dada's actual abundance-p-value partition, not the nearest-more-abundant proxy of --nearest-parent — this is the ground-truth version of the headroom question, and the failed class is a population the proxy can't see at all.
  • Prior tracing: run dada-pseudo, filter on birth_type == Prior to see which ASVs exist only because a cross-sample prior rescued them past OMEGA_P, and how close each sits to the nearest abundance-born survivor.
  • Borderline ASVs: birth_pval sorts every ASV by how confident its split was.

failed ≠ distant noise

Verbose output splits the failed class by abundance. Failed singletons (which can never seed an ASV under the default ≥2 reads rule, toggled by --detect-singletons) are reported separately from genuinely distant uniques, with the within/beyond-cutoff split:

[kdist] sam1F : 59 failed | singletons 59 (14 within cutoff) | multi-read 0 (0 within cutoff) — failed singletons are the --detect-singletons tradeoff, not distance

On the test sample all 59 failed uniques are singletons — so "didn't survive" is the read-count tradeoff, not screen distance. The within-cutoff singletons are plausible error copies / real low-abundance variants that just lacked a second read.

Testing

Ran end-to-end on real data (dada and dada-pseudo, single- and multi-sample). Builds, cargo clippy, and cargo fmt all clean; pre-commit hooks pass.

Docs

docs/diagnostics.md documents the mode, CSV columns, the prior-tracing recipe, the verbose failed-class breakdown, and the failed != distant noise caveat pointing at --detect-singletons.

🤖 Generated with Claude Code

Adds a third mode to the hidden `kdist-calibrate` subcommand that operates
on `dada` output instead of derep input, so every pairwise comparison is
labelled by what inference actually decided. Pairs each dada output JSON
with its derep input (via --derep-dir, matched by sample name so indices
line up with dada's `map`) and classifies each input unique:

  - member      -> its own center  (a real error copy denoising corrected)
  - failed      -> nearest center  (shed by the abundance test, unassigned)
  - center_pair -> another center  (two surviving ASVs; resolution floor)

Each row carries the partner center's birth_type/birth_pval, so prior-born
ASVs (pseudo-pool) and births near OMEGA_A are visible in the same table.
Because labels come from dada's actual abundance-p-value partition (not the
nearest-more-abundant proxy of --nearest-parent), this is the ground-truth
version of the headroom question, and the failed class is a population the
proxy can't see.

Verbose output breaks the failed class down by abundance: failed singletons
(which can never seed an ASV under the default >=2-read rule, toggled by
--detect-singletons) are reported separately from genuinely distant uniques,
with the within/beyond-cutoff split.

Documents the mode, columns, prior-tracing recipe, and the
`failed != distant noise` caveat in docs/diagnostics.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cjfields cjfields merged commit fb859eb into main Jun 22, 2026
7 checks passed
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