Summary
The 2.17.0 mRNA output works end-to-end but reads worse than the peptide path. Fix as a batch in a follow-up PR.
Reproduce:
vaxrank --input-lens HugoLo_IPRES_2016-Pt02-ad-839+ar-280+nd-840.lens-v1.9-dev.report.tsv \\
--output-dir vaxrank-output \\
--vaccine-type mrna \\
--ensembl-release 114
Output today (real Pt02 LENS, 2153 epitope predictions):
>seq_001 antigens=SIAH2_3_150742446_A_.,TAOK1_17_29502684_T_.,R3HDM1_2_135710074_C_T,CPSF7_11_61416340_G_A,KMT2B_19_35722658_G_A length=1203
ACATTTGCTTCTGACACAACTGTGTTCACTAGCAACCTCAAACAGACACCATGCTG...
$ ls vaxrank-output/
cds.fasta full.fasta layers.csv manifest.json no_polyA.fasta
Concrete issues
1. Cryptic antigen names
`SIAH2_3_150742446_A_.` carries gene + chrom + position + ref + alt-or-placeholder. Useful for traceability, illegible at a glance. Need either:
- a short human-readable token (`SIAH2_p.K23N` style — protein-change notation), with the long form available in the manifest, or
- a configurable name template (`{gene}{protein_change}`, `{gene}{chrom}:{pos}`, …).
2. FASTA `antigens=` separator is comma
The current `antigens=A,B,C` field uses commas; many FASTA-parsing pipelines split the description on commas (`>seq.split(',')`), so today's format silently produces N+1 garbage tokens. Switch to `;` (the GenBank convention for compound description fields) and treat `,` as forbidden inside an antigen name.
3. `seq_NNN` is the wrong namespace
Construct IDs should announce what they are: `mrna_001` (or `mrna_seq_001`), not bare `seq_001`. Same construct goes through cds.fasta / no_polyA.fasta / full.fasta — the ID needs to be modality-stamped because users will mix outputs from peptide + mRNA runs in the same downstream tool. Mirror the peptide-side scheme (which uses `peptide_NNN`).
4. Surprising antigen count (5 antigens out of 384)
`--mrna-max-constructs=1` (default) + `--mrna-antigens-per-construct=5` (FixVac canonical) packs only 5 of the 384 ranked variants into the mRNA. We log:
Reached --mrna-max-constructs (1); dropping remaining antigens including MIB2_1_1624824_C_T.
The default is correct (FixVac uses 5/construct); but the WARNING line names one dropped antigen — the user can't tell from the log whether they lost 1 antigen or 379. Need:
- summary count in the warning (`dropped 379 / 384 ranked antigens past the construct cap`),
- and a doc note in the CLI help that mRNA defaults to 1 construct × 5 antigens (so the user knows to bump `--mrna-max-constructs` if they want more coverage).
5. No mRNA ranking report
Peptide path produces an ASCII / HTML / PDF report showing ranked vaccine peptides + manufacturability + processing scores. mRNA path emits FASTAs + manifest.json + layers.csv only. Same ranking decisions feed both paths — surface them in a report on the mRNA side too:
- which 5 antigens were chosen and why (ranks, combined score, expression / mutant epitope score),
- which were dropped past the cap (and how many),
- per-junction linker selection (the optimizer's chosen linker per junction + the second-best alternative, since today the run logs "falling back to shared linker at every junction" but the user can't tell which junctions optimization would have changed).
This is partly a ranking-decisions report (modality-agnostic, both modalities want it) and partly construct-assembly notes (modality-specific). First pass: add a section to the existing ASCII report when mRNA is active.
6. `layers.csv` is poorly named
A user sees `layers.csv` next to `cds.fasta` / `full.fasta` and has to open it to learn it's a per-element decomposition. Rename to `mrna-sequence-parts.csv` (or `mrna-elements.csv`); the contents map 1:1 to the BioNTech FixVac diagram nomenclature so "parts" reads better than "layers".
Proposed scope for the follow-up PR
Fix all six points in one PR. They share one writer (`vaxrank/mrna.py` + `vaxrank/cli/entry_point.py::_emit_mrna_constructs`) and one report-template insertion point (`vaxrank/templates/template.txt`). Tests: extend `tests/test_mrna.py` to assert the new naming / separator / construct-id pattern; new test verifying the ranking-decisions section renders in the ASCII report when mRNA is active.
cc @iskandr — found while running 2.17.0 against Pt02.
Summary
The 2.17.0 mRNA output works end-to-end but reads worse than the peptide path. Fix as a batch in a follow-up PR.
Reproduce:
Output today (real Pt02 LENS, 2153 epitope predictions):
Concrete issues
1. Cryptic antigen names
`SIAH2_3_150742446_A_.` carries gene + chrom + position + ref + alt-or-placeholder. Useful for traceability, illegible at a glance. Need either:
2. FASTA `antigens=` separator is comma
The current `antigens=A,B,C` field uses commas; many FASTA-parsing pipelines split the description on commas (`>seq.split(',')`), so today's format silently produces N+1 garbage tokens. Switch to `;` (the GenBank convention for compound description fields) and treat `,` as forbidden inside an antigen name.
3. `seq_NNN` is the wrong namespace
Construct IDs should announce what they are: `mrna_001` (or `mrna_seq_001`), not bare `seq_001`. Same construct goes through cds.fasta / no_polyA.fasta / full.fasta — the ID needs to be modality-stamped because users will mix outputs from peptide + mRNA runs in the same downstream tool. Mirror the peptide-side scheme (which uses `peptide_NNN`).
4. Surprising antigen count (5 antigens out of 384)
`--mrna-max-constructs=1` (default) + `--mrna-antigens-per-construct=5` (FixVac canonical) packs only 5 of the 384 ranked variants into the mRNA. We log:
The default is correct (FixVac uses 5/construct); but the WARNING line names one dropped antigen — the user can't tell from the log whether they lost 1 antigen or 379. Need:
5. No mRNA ranking report
Peptide path produces an ASCII / HTML / PDF report showing ranked vaccine peptides + manufacturability + processing scores. mRNA path emits FASTAs + manifest.json + layers.csv only. Same ranking decisions feed both paths — surface them in a report on the mRNA side too:
This is partly a ranking-decisions report (modality-agnostic, both modalities want it) and partly construct-assembly notes (modality-specific). First pass: add a section to the existing ASCII report when mRNA is active.
6. `layers.csv` is poorly named
A user sees `layers.csv` next to `cds.fasta` / `full.fasta` and has to open it to learn it's a per-element decomposition. Rename to `mrna-sequence-parts.csv` (or `mrna-elements.csv`); the contents map 1:1 to the BioNTech FixVac diagram nomenclature so "parts" reads better than "layers".
Proposed scope for the follow-up PR
Fix all six points in one PR. They share one writer (`vaxrank/mrna.py` + `vaxrank/cli/entry_point.py::_emit_mrna_constructs`) and one report-template insertion point (`vaxrank/templates/template.txt`). Tests: extend `tests/test_mrna.py` to assert the new naming / separator / construct-id pattern; new test verifying the ranking-decisions section renders in the ASCII report when mRNA is active.
cc @iskandr — found while running 2.17.0 against Pt02.