Skip to content

review D: LOESS boundaries, experiment provenance, audit q unit, transfer basis in TSVs (docs/29 findings 10, 15, 16, 19) - #65

Merged
RobbinBouwmeester merged 4 commits into
review/c-desktopfrom
review/d-provenance
Sep 8, 2026
Merged

review D: LOESS boundaries, experiment provenance, audit q unit, transfer basis in TSVs (docs/29 findings 10, 15, 16, 19)#65
RobbinBouwmeester merged 4 commits into
review/c-desktopfrom
review/d-provenance

Conversation

@RobbinBouwmeester

@RobbinBouwmeester RobbinBouwmeester commented Sep 7, 2026

Copy link
Copy Markdown
Member

Last of the four stacked code-review PRs (docs/29_code_review_2026-09-07.md, work package D). Base is review/c-desktop (#64); merge A, B, C, then this.

What changes

#10, LOESS boundaries. Loess::predict continues the boundary local fit (its value at the boundary grid point and the slope of the local line there) outside the anchor range instead of switching to the global least-squares line. Continuous at both ends; the global line is now only the degenerate fallback (fewer than four anchors, or a local window without spread). Test: the review's reproduction (y = 200 + 10x^2, span 0.3), endpoint continuity within 1e-3, extrapolation follows the local slope, linear far from the data.

HYE B01 before/after (merge check for #10). doxy, LFQ_Orbitrap_AIF_Condition_B_Sample_Alpha_01, identical DIA-NN library, native_tda, 32 threads per arm, C-branch binary (#64 head) against this branch; two RT sources. Unit: peptides.tsv rows selected on the stripped-peptide peptide_q_value at 1% (one row per stripped sequence here); PSM counts on the pooled q_value.

imported DIA-NN iRT, before after DeepLC 4.1.1 re-predicted iRT, before after
w_rt (identical cal.json per pair) 691 s 691 s 414 s 414 s
stripped peptides at peptide_q_value 1% 45,946 45,957 48,533 48,533
PSM-q 1% targets 50,332 50,335 53,124 53,127
PSM-q 1% decoy fraction 0.010 0.010 0.010 0.010
protein groups at pg_q_value 1% 6,410 6,410 6,519 6,519
extract accepted rows 2,183,445 2,183,899 1,961,773 1,961,800
candidates with a different window 208,130 (1.9%) 22,779 (0.2%)
wall (32 threads) 34:14 37:30 26:06 25:46

Neutral on both RT sources, as a boundary correction should be. The mechanism is visible in the first pair: 194,698 of the moved candidates have iRT above the anchor range (170); the old global line placed them at 10,625 to 11,946 s in a 9,000 s run, so they could never be extracted, and the continued local fit places them at 8,578 to 9,100 s, from which 454 produced an accepted extraction row.

#15, experiment manifest. experiment_manifest.json adds config_json (the resolved configuration, next to its hash), model_identities (RT source, fragment predictor, classifier that actually ran from the rescore report, feature schema id, MBR strategy), experiment.quant_q_filter.{configured,effective}, experiment.rescorer, and hashes the inputs at the start of the run (inputs_hashed_at: start). Relocatable references and the shared/per-run artifact inventory stay deferred, as agreed.

#16, audit. passed_precursor_fdr / FAILED_PRECURSOR_FDR read precursor_q; PSM q_value only on a table without it, with q_unit in the metrics JSON. A scored table with more than one source is refused. NO_PEAK_GROUP renamed to DID_NOT_SURVIVE_EXTRACTION (RejectionReason::DidNotSurviveExtraction), docs updated where the code appears. Tests: PSM and precursor q on opposite sides of the threshold; pooled table refused.

#19, report TSVs. is_transferred and transfer_q columns on both TSVs from both writers; the MBR worker writes transfer_q into the augmented scored table (NaN on non-transfers). The acceptance rule is unchanged and documented (docs/12, docs/15): a tighter threshold does not revoke a transfer; a transfer is not protein-group confidence. Tests: transfer basis exported, tighter threshold keeps the transfer, protein rows carry the columns; Python test checks transfer_q is finite on exactly the flagged rows and equals the accepted q. ci/check_smoke.py expects the two new trailing columns.

Guide. CLAUDE.md: retain_top_peaks alternatives do reach features/compete/rescore (peak_rank, selected_peak_rank); the rescore matrix is flat f32 with the ceiling checked before allocation; the top-K contract exists and awaits entrapment validation. Desktop comments no longer claim run-experiment writes no report. docs/29 gains an implementation-status section for A to D with both before/after pairs.

Local checks

Engine cargo fmt --check, clippy -D warnings, cargo test --workspace (258 tests); desktop clippy + cargo test --lib (78); pytest tests/python/test_mbr_worker.py (18); python -m compileall scripts; ci/gen_config_reference.py --check; ci/check_doc_refs.py; ci/check_desktop_ui.py.

🤖 Generated with Claude Code

RobbinBouwmeester and others added 4 commits September 7, 2026 20:00
…precursor-q audit, transfer basis in TSVs, replayable experiment manifest

Code review D (docs/29 findings 10, 15, 16, 19) plus stale guide statements.

LOESS (#10). Outside the anchor range the smoother switched from the boundary
local fit to the global least-squares line, and the two need not agree: on
y = 200 + 10x^2 (span 0.3) the prediction jumped from 193.4 at x = 1e-6 to 38.3
at x = 0 and from 1173.5 to 1018.4 at the top, about 155 s discontinuities for
gradient-edge peptides against a narrow extraction window. The map now continues
the boundary local fit (value and slope) and is continuous at both ends; the
global line remains the degenerate fallback only. Endpoint continuity and the
local-slope extrapolation are tested on the review's reproduction.

Experiment manifest (#15). Records config_json next to config_hash, the model
identities that produced the artifacts (RT source, fragment predictor, the
classifier that actually ran from the rescore report, feature schema id, MBR
strategy), the configured and effective quant.q_filter, and hashes the inputs at
the start of the run rather than after it.

Audit (#16). The passed_precursor_fdr gate and FAILED_PRECURSOR_FDR reason read
precursor_q, the unit the label names, falling back to the PSM q_value only on a
table without it and recording q_unit in the metrics JSON. A pooled scored table
is refused, since the audit keys on candidate_id. The coarse extraction bucket
NO_PEAK_GROUP is DID_NOT_SURVIVE_EXTRACTION: extract does not write the table
that would separate presence, matched-fraction and gate failures, so the old
name claimed a cause the audit cannot see.

Report (#19). peptides.tsv and proteins.tsv, single-run and experiment-wide,
carry is_transferred and transfer_q so the acceptance basis of a match-between-
runs row is visible next to its untouched grouped q; the MBR worker's augmented
scored table gains transfer_q. The rule is unchanged and now documented: a
tighter report threshold does not revoke a transfer, and a transfer is not
protein-group confidence.

Guide corrections: retain_top_peaks alternatives do reach features, compete and
rescore (peak_rank, selected_peak_rank); the rescore matrix is flat f32; the
desktop comments no longer say run-experiment writes no report.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@RobbinBouwmeester
RobbinBouwmeester merged commit 7d84c15 into review/c-desktop Sep 8, 2026
12 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