You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The published-paper analysis layer — the multi-tool accuracy benchmark, the significance testing, the headline figures, and the supplemental tables (Tables S1/S2/S6/S7, Data S1–S6) — currently exists only as a stack of one-off Jupyter notebooks (the 2023-retraining set) that never landed in the repo. Those notebooks are TF1/Keras-era, depend on hardcoded cluster paths (/home/odonnt02/..., /data/mhcflurry-evaluation/), pull inputs from Springer/Dropbox URLs, use unseeded RNG, and reference three different download versions. They will not run against the current PyTorch 2.3 tree and are not something we should port line-for-line.
Meanwhile the in-repo reproducible pipeline stops at scored prediction tables (downloads-generation/data_evaluation) and a 2-way new-vs-public release-regression evaluator (mhcflurry compare-models / plot-model-comparison). There is no reproducible in-tree path that answers the paper's actual question — "does MHCflurry beat the field (netMHCpan, MixMHCpred), and is the difference significant?" — nor one that regenerates the figures/tables.
This issue proposes rebuilding that whole layer clean-room as first-class mhcflurry subcommands plus one orchestration script, reusing the existing metric core and CLI conventions, and carrying none of the historical Keras/TF baggage.
Design principles (the "no baggage" contract)
Clean-room, current-era inputs only. Consume only current artifacts: the data_evaluation scored benchmark, data_predictions (external-tool scores via mhctools, already produced upstream — never re-invoke netMHCpan/MixMHCpred inline the way the notebooks do), analysis_predictor_info, data_mass_spec_annotated, data_curated, data_references (FM-index for peptide→protein mapping instead of pyensembl), and current PyTorch model bundles. No keras/tensorflow imports anywhere.
No hidden state, no hardcoded paths. Every input is a CLI flag with a mhcflurry-downloads-resolvable default. Datasets the notebooks hardcoded as sibling files (expression_groups.xlsx, the immunogenicity screening set, Wolf-Levy S2) become explicit --dataset/--input args or documented download items.
Deterministic. All decoy resampling and bootstrap steps take --seed; default seeded. Golden-CSV tests become possible.
Follow the established metric/plot split. Metric subcommands write CSV/JSON only (torch/pandas/sklearn, no matplotlib) exactly like compare-models; plot subcommands read those artifacts and render, with matplotlib/logomaker lazy-imported, exactly like plot-model-comparison.
One metric implementation. Refactor the shared scoring core (ROC-AUC / PR-AUC / PPV@N, per-allele/per-sample/per-length aggregation) out of mhcflurry/cli/compare_models.py into a library (mhcflurry/benchmarks/) and have both compare-models and the new paper commands call it, so the release-regression numbers and the paper numbers can never silently diverge.
Register through the existing lazy dispatcher. Add each new subcommand to _SUBCOMMANDS + _HELP_GROUPS in mhcflurry/cli/main.py (new group: "Paper benchmarks"), each exposing run_argv(argv); add matching mhcflurry-* console-script shims in setup.py for parity. Builds directly on Unify mhcflurry CLI under a single mhcflurry parent command #291.
Proposed shared library: mhcflurry/benchmarks/
Pure-python, matplotlib-free, importable by both the regression and paper commands:
metrics.py — roc_auc, pr_auc, ppv_at_n, per-{allele,sample,length} aggregation. (Lifted from compare_models.py; compare-models switches to importing it.)
predictor_registry.py + predictor_info.csv — replaces notebook 0 aesthetics: a versioned data file mapping predictor id → display name, plot color, sort order, primary flag. Single source of truth for every plot command (kills the runtime color-hacking in the old aesthetics cell).
benchmark-score detail (the scientific core): per-sample × per-length × per-predictor ROC-AUC / PR-AUC / PPV@N over all predictors including external tools; percent-change vs configurable baseline predictors; seeded bootstrap CIs; paired significance (ttest_rel + binomial win-count) for each predictor against each baseline; optional cysteine-removed variant (--exclude-residues C). This is the N-way, statistics-bearing generalization of what compare-models' affinity/presentation components do 2-way — hence the shared metrics.py.
Supplemental assembly is release-specific and file-shuffling-heavy, so it stays a script rather than a general tool:
scripts/release/make_supplemental.sh — replaces 1 training datasets copy, 3 make additional files, 5 make supplemental data: assembles Tables S1/S2/S6/S7 + Data S1–S6 with publication column renaming from the eval outputs + training-data copies. No ln -s symlink deliverables (the notebooks' approach); real file copies.
Then wire a --paper-eval phase into retrain_evaluate_deploy.sh that simply invokes this script after the existing compare-models/plot-model-comparison step, so a release run can optionally produce the full paper bundle from the same entry point.
Explicitly out of scope (the baggage we are not carrying)
No line-for-line port of the Keras/TF notebooks; the notebooks are reference only.
No inline re-invocation of external predictor binaries — external scores come from data_predictions.
No hardcoded machine paths, sibling-dir inputs, or Dropbox/Springer URL fetches.
pyensembl + Ensembl-release dependency dropped in favor of the data_references FM-index already in the pipeline. logomaker/statannot become optional plotting extras, not hard deps of the metric path.
Suggested phasing
Extract mhcflurry/benchmarks/ (metrics/stats/assembly/registry); refactor compare-models onto it (no behavior change; golden-CSV regression test).
benchmark-assemble + benchmark-score + plot-benchmark — the headline mono/multi benchmark. This alone reproduces the main figures.
benchmark-processing + plot-processing; then benchmark-novel-alleles, benchmark-immunogenicity.
make_supplemental.sh + paper_eval.sh; wire --paper-eval into retrain_evaluate_deploy.sh.
Testing
Tiny fixtures under test/data/, golden CSVs for each metric command, and a --limit-samples/--limit-files fast path (as compare-models already has --limit-files) so the whole chain runs in CI on a handful of samples.
Source for the notebook→subcommand mapping: audit of the untracked notebooks/2023-retraining/ set against downloads-generation/, scripts/, and mhcflurry/cli/.
Summary
The published-paper analysis layer — the multi-tool accuracy benchmark, the significance testing, the headline figures, and the supplemental tables (Tables S1/S2/S6/S7, Data S1–S6) — currently exists only as a stack of one-off Jupyter notebooks (the
2023-retrainingset) that never landed in the repo. Those notebooks are TF1/Keras-era, depend on hardcoded cluster paths (/home/odonnt02/...,/data/mhcflurry-evaluation/), pull inputs from Springer/Dropbox URLs, use unseeded RNG, and reference three different download versions. They will not run against the current PyTorch 2.3 tree and are not something we should port line-for-line.Meanwhile the in-repo reproducible pipeline stops at scored prediction tables (
downloads-generation/data_evaluation) and a 2-way new-vs-public release-regression evaluator (mhcflurry compare-models/plot-model-comparison). There is no reproducible in-tree path that answers the paper's actual question — "does MHCflurry beat the field (netMHCpan, MixMHCpred), and is the difference significant?" — nor one that regenerates the figures/tables.This issue proposes rebuilding that whole layer clean-room as first-class
mhcflurrysubcommands plus one orchestration script, reusing the existing metric core and CLI conventions, and carrying none of the historical Keras/TF baggage.Design principles (the "no baggage" contract)
data_evaluationscored benchmark,data_predictions(external-tool scores viamhctools, already produced upstream — never re-invoke netMHCpan/MixMHCpred inline the way the notebooks do),analysis_predictor_info,data_mass_spec_annotated,data_curated,data_references(FM-index for peptide→protein mapping instead ofpyensembl), and current PyTorch model bundles. Nokeras/tensorflowimports anywhere.mhcflurry-downloads-resolvable default. Datasets the notebooks hardcoded as sibling files (expression_groups.xlsx, the immunogenicity screening set, Wolf-Levy S2) become explicit--dataset/--inputargs or documented download items.--seed; default seeded. Golden-CSV tests become possible.compare-models; plot subcommands read those artifacts and render, with matplotlib/logomaker lazy-imported, exactly likeplot-model-comparison.mhcflurry/cli/compare_models.pyinto a library (mhcflurry/benchmarks/) and have bothcompare-modelsand the new paper commands call it, so the release-regression numbers and the paper numbers can never silently diverge._SUBCOMMANDS+_HELP_GROUPSinmhcflurry/cli/main.py(new group: "Paper benchmarks"), each exposingrun_argv(argv); add matchingmhcflurry-*console-script shims insetup.pyfor parity. Builds directly on Unify mhcflurry CLI under a singlemhcflurryparent command #291.Proposed shared library:
mhcflurry/benchmarks/Pure-python, matplotlib-free, importable by both the regression and paper commands:
metrics.py—roc_auc,pr_auc,ppv_at_n, per-{allele,sample,length} aggregation. (Lifted fromcompare_models.py;compare-modelsswitches to importing it.)stats.py— seeded bootstrap CIs, pairedttest_rel, binomial win-counts, percent-change-vs-baseline normalization.assembly.py— benchmark table assembly: predictor-column merge, train-leak assertion, seeded per-sample decoy resampling, sample-group tagging, external-tool masking.predictor_registry.py+predictor_info.csv— replaces notebook0 aesthetics: a versioned data file mapping predictor id → display name, plot color, sort order,primaryflag. Single source of truth for every plot command (kills the runtime color-hacking in the old aesthetics cell).Proposed subcommands
Metric / eval (matplotlib-free → CSV/JSON)
benchmark-assemble1 prepare benchmark dataset - {mono,multi}allelicdata_evaluation,data_mass_spec_annotatedbenchmark.{mono,multi}allelic.parquet,manifest.jsonbenchmark-score2 multiallelic accuracy,2 monoallelic accuracy plotsaccuracy_scores.{mono,multi}.csv,significance.csv,summary.jsonbenchmark-novel-alleles2 monoallelic analysis of novel allelesmodels_class1_pan_variantsnovel_alleles.csvbenchmark-immunogenicityimmunogenicity experiments--dataset(screening set),data_predictionsimmunogenicity_scores.csvbenchmark-processing1 proteasome mass spec,2 processing predictor motifs--dataset(Wolf-Levy S2),data_referencesFM-index, presentation predictorprocessing_proteasome.csv,processing_correlation.parquet,processing_motifs.parquetmodel-selection-accuracy1 model selection predictor accuracy(retires the…UNUSED, NOW WE PRECOMPUTE THISnotebook)analysis_predictor_infomodel_selection_accuracy.csvsample-table2 sample table,4 supplemental sample table with accuraciesdata_mass_spec_annotated, assembled benchmark,--expression-groupssample_table.csv,sample_table_with_accuracies.csvbenchmark-scoredetail (the scientific core): per-sample × per-length × per-predictor ROC-AUC / PR-AUC / PPV@N over all predictors including external tools; percent-change vs configurable baseline predictors; seeded bootstrap CIs; paired significance (ttest_rel+ binomial win-count) for each predictor against each baseline; optional cysteine-removed variant (--exclude-residues C). This is the N-way, statistics-bearing generalization of whatcompare-models'affinity/presentationcomponents do 2-way — hence the sharedmetrics.py.Plot (matplotlib/logomaker isolated → figures)
plot-benchmark3 scores plots - {mono,multi}allelic--panelsselects subsetsplot-processing4 processing predictor plots(+ its "redo post resubmission" dupe)(Novel-allele and immunogenicity panels fold into
plot-benchmark --panelsrather than getting their own commands.)Bespoke release packaging → sub-scripts (not core subcommands)
Supplemental assembly is release-specific and file-shuffling-heavy, so it stays a script rather than a general tool:
scripts/release/make_supplemental.sh— replaces1 training datasets copy,3 make additional files,5 make supplemental data: assembles Tables S1/S2/S6/S7 + Data S1–S6 with publication column renaming from the eval outputs + training-data copies. Noln -ssymlink deliverables (the notebooks' approach); real file copies.Tie-it-together orchestration
scripts/release/paper_eval.sh, mirroring the existingscripts/release/retrain_evaluate_deploy.shconventions (set -euo pipefail,run_cmdcommand-echo,--dry-run, phase--skip-*flags):Flow:
mhcflurry-downloads fetch …→benchmark-assemble→benchmark-score→ (novel-alleles,immunogenicity,processing,model-selection-accuracy,sample-table) →plot-benchmark+plot-processing→make_supplemental.sh.Then wire a
--paper-evalphase intoretrain_evaluate_deploy.shthat simply invokes this script after the existingcompare-models/plot-model-comparisonstep, so a release run can optionally produce the full paper bundle from the same entry point.Explicitly out of scope (the baggage we are not carrying)
data_predictions.pyensembl+ Ensembl-release dependency dropped in favor of thedata_referencesFM-index already in the pipeline.logomaker/statannotbecome optional plotting extras, not hard deps of the metric path.Suggested phasing
mhcflurry/benchmarks/(metrics/stats/assembly/registry); refactorcompare-modelsonto it (no behavior change; golden-CSV regression test).benchmark-assemble+benchmark-score+plot-benchmark— the headline mono/multi benchmark. This alone reproduces the main figures.sample-table+model-selection-accuracy(Table S1/S2 substrate).benchmark-processing+plot-processing; thenbenchmark-novel-alleles,benchmark-immunogenicity.make_supplemental.sh+paper_eval.sh; wire--paper-evalintoretrain_evaluate_deploy.sh.Testing
Tiny fixtures under
test/data/, golden CSVs for each metric command, and a--limit-samples/--limit-filesfast path (ascompare-modelsalready has--limit-files) so the whole chain runs in CI on a handful of samples.Related
mhcflurryparent command #291 (unify CLI under a singlemhcflurryparent) — this builds on that dispatcher.model-selection-accuracyconsumes that pipeline's output.Source for the notebook→subcommand mapping: audit of the untracked
notebooks/2023-retraining/set againstdownloads-generation/,scripts/, andmhcflurry/cli/.