Skip to content

mRNA output ergonomics: naming, separators, ranking-report (#270) - #271

Merged
iskandr merged 4 commits into
mainfrom
mrna-output-quality
May 5, 2026
Merged

mRNA output ergonomics: naming, separators, ranking-report (#270)#271
iskandr merged 4 commits into
mainfrom
mrna-output-quality

Conversation

@iskandr

@iskandr iskandr commented May 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Addresses #270 (mRNA output ergonomics). First batch lands in commit 1; the broader items (mRNA ranking-decisions report, configurable antigen-name template, signal-peptide / start-codon polish) ride in follow-up commits on this branch before merge.

Commit 1 — naming, separators, dropped-count

  • Construct names: seq_NNNmrna_NNN. Modality-stamped namespace mirrors the peptide writer's peptide_NNN scheme so mixed peptide+mRNA outputs in the same downstream pipeline don't collide on bare seq_001.
  • FASTA antigens= separator: ,;. Comma is a token boundary in many FASTA-parsing tools' description-line handlers; ; is the GenBank convention.
  • layers.csvmrna-sequence-parts.csv. Next to cds.fasta / full.fasta, the legacy name was too cryptic — the new name spells out the per-element decomposition.
  • --mrna-max-constructs cap warning now reports dropped count: dropping 379 / 384 ranked antigen(s) past the cap instead of naming only one antigen as including X. Operators can tell whether they lost 1 or 379.

Coming on this branch (TODO)

  • mRNA ranking-decisions report section (parity with peptide-side ASCII / HTML / PDF reports — which 5 antigens, why; which dropped past the cap).
  • Configurable antigen-name template ({gene}_{protein_change} style; long form retained in manifest).
  • default.yaml header rewrite (drop pre-mRNA "frozen config groups" / EpitopeConfig / VaccineConfig language; commit d2a51bd).

Default.yaml header

Already in commit 0 on this branch. The PR also rewrites the header to match the post-2.17 layout (drops outdated class-name mappings, adds the resolution-order line at the top instead of repeating it per section).

Test plan

  • ./test.sh — 714 passed, 0 failures
  • New regression tests: FASTA ;-separator, dropped-count warning shape, cross-modality mrna|peptide_NNN pattern
  • CI green on this branch
  • End-to-end smoke on Pt02 LENS to confirm the new file names + warning ergonomics
  • Add the mRNA ranking-decisions report (next commit)

Bumps version to 2.18.0.

iskandr added 2 commits May 5, 2026 12:54
The header still mixed pre-mRNA language ("frozen config groups",
``EpitopeConfig`` / ``VaccineConfig`` class names) with post-mRNA
content. Section is now described in user terms:

- modality-agnostic vs peptide-only is called out per section,
- ``manufacturability``'s actual role (tie-break + report
  auto-skip) is documented instead of an outdated
  ``-> VaccineConfig`` mapping that no longer holds,
- the resolution order (CLI > per-modality > cross-modality >
  built-in default) is named once at the top so the per-section
  text doesn't have to re-state it.
First batch of fixes from the issue. Touches the mRNA writer + CLI
plumbing; the broader items (mRNA ranking-decisions report,
configurable antigen-name template) ride in follow-up commits on
this branch.

- Construct names: ``seq_NNN`` -> ``mrna_NNN``. Mixed peptide+mRNA
  outputs in the same downstream pipeline collide on a bare
  ``seq_001``; modality-stamped names mirror the peptide writer's
  ``peptide_NNN`` scheme.
- FASTA ``antigens=`` field now uses ``;`` instead of ``,``. Comma
  is a token boundary in many FASTA-parsing tools' description-line
  handlers; ``;`` is the GenBank convention for compound description
  fields.
- ``layers.csv`` -> ``mrna-sequence-parts.csv``. ``layers`` next to
  ``cds.fasta`` / ``full.fasta`` is too cryptic; the new name spells
  out what each row describes.
- ``--mrna-max-constructs`` cap warning now reports the dropped
  count: ``dropping 379 / 384 ranked antigen(s) past the cap``
  rather than the legacy single-name ``including X``. Operators
  can tell whether they lost 1 or 379.

Tests pin the FASTA ``;``-separator format, the dropped-count
warning shape, and the cross-modality construct-name pattern
(``mrna|peptide_NNN``).

Bump version to 2.18.0.
iskandr added 2 commits May 5, 2026 14:37
Continuation of #270 ergonomics. Real-LENS-run feedback drove these:

- mrna assembly cap is **top-k selection**, not an error. Log at
  INFO instead of WARNING; drop "spill" / "drop" panic language.
  Names selected count, total ranked, and the next-best
  not-selected antigen for traceability.
- ``--mrna-max-constructs`` default: 1 -> **2** (BioNTech FixVac
  canonical = 2x pentatope, 10 antigens at 5/construct,
  Sahin 2017). Bare default now produces a credible vaccine
  out of the box on a real LENS file.
- ``_resolve_mhc_for_linker_optimizer``: thread MHC alleles
  inferred from LENS / pVACseq through to the per-junction
  optimizer (was failing on the LENS path because the external
  arg parser doesn't carry --mhc-alleles). Targeted hint when
  alleles are inferred but --mhc-predictor is missing instead
  of one generic "set both" warning.
- ``_log_args_summary``: replace the flat ``Namespace(...)`` dump
  (100+ keys, no grouping) with grouped sections — Inputs / MHC /
  Vaccine design / Peptide / mRNA / Processing / Outputs / Reports /
  Config — and hide values that match parser defaults unless
  ``--verbose``. Auto-inferred state (LENS-derived alleles, …)
  surfaces under a separate ``[auto-inferred]`` block.
- LENS antigen_source breakdown logged BEFORE filter messages so
  the operator sees the input composition before the per-filter
  drop counts.
- LENS rows lacking ``rna_reads_covering_genomic_origin`` now log
  at INFO with the antigen_source breakdown — ERV / SPLICE /
  FUSION rows are *expected* not to carry that column. Only
  flags SNV / INDEL gaps as a WARNING (those should always have
  it).
- Pepsickle "peptide not in pep_context" warning: drop the
  "File upstream if this rate is non-trivial" tail.
- "report_df has N duplicate (peptide, allele) rows" demoted
  from INFO to DEBUG. Multi-source duplicates are by design,
  not actionable; logging them at INFO every run was noise.

Filed as follow-ups (not in this PR):

- #272 — Pepsickle Predictions vs EpitopePredictions split
- #273 — Config flatten: drop vaccine_constructs wrapper, move
  manufacturability under peptide
Five housekeeping fixes from the post-review punch list, plus the
test debt:

- Move ``_MISSING_SENTINEL = object()`` above ``_log_args_summary``
  so it's defined before the function that reads it.
- Replace ``__import__('logging').DEBUG`` with ``logging.DEBUG``
  in epitope_io.py — the module imports ``logging`` at the top.
- Cache ``_ARG_GROUPS_BY_NAME = dict(_ARG_GROUPS)`` at module level
  so the per-call ``dict(_ARG_GROUPS).get(...)`` reconstruction
  goes away.
- Drop the misleading "OR is a non-empty string" claim from
  ``_log_args_summary``'s docstring — only the
  differs-from-default check controls visibility.
- Narrow the bare ``except Exception`` in
  ``_resolve_mhc_for_linker_optimizer`` to
  ``(AttributeError, ValueError, KeyError)``. A genuine model-load
  error (e.g. missing weights) inside mhctools must propagate, not
  be swallowed into "linker optimizer disabled".
- ``LENS_PROVENANCE_MARKER`` constant in
  ``vaxrank.external_input`` shared between producer (the LENS
  PatientInfo synth) and consumer (the entry-point alleles
  filter), so the string can't drift between the two.

Test debt added (tests/test_entry_point_helpers.py):

- Branch tests for ``_resolve_mhc_for_linker_optimizer``: alleles
  inferred but predictor missing, both missing, real model-load
  failure propagates.
- Smoke + ``--verbose`` + auto-inferred-section tests for
  ``_log_args_summary`` (with parser_defaults snapshot captured
  *before* overrides, mirroring the real arg-parser snapshot).
- caplog-style ordering test for the up-front LENS antigen-source
  breakdown — must log before the per-filter "skipped X rows"
  lines, and SNV / INDEL must precede other kinds with
  ``(missing)`` last.

Tests use a local capture handler attached directly to the target
logger, not pytest's ``caplog``: importing
``vaxrank.cli.entry_point`` transitively triggers isovar's
``logging.config.fileConfig`` which wipes pytest's caplog handlers
from the root logger. Pre-existing project quirk; documented in
the test module.
@iskandr
iskandr merged commit 461d5ed into main May 5, 2026
10 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