Skip to content

fix(variants): read UniProt-native deletions (empty <variation>)#1095

Open
trishorts wants to merge 3 commits into
smith-chem-wisc:masterfrom
trishorts:variant-corpus-deletions
Open

fix(variants): read UniProt-native deletions (empty <variation>)#1095
trishorts wants to merge 3 commits into
smith-chem-wisc:masterfrom
trishorts:variant-corpus-deletions

Conversation

@trishorts

Copy link
Copy Markdown
Contributor

What

Fixes the ProteinXmlEntry reader so it reads UniProt-native deletions, which UniProt encodes as an empty <variation/> (e.g. <original>P</original><variation/>). The reader previously admitted a sequence variant feature only when <variation> was non-empty, so every UniProt-native deletion was silently dropped — no SequenceVariation was ever created. This is not something we can push onto the encoding: it is how UniProt writes a deletion.

The guard now admits any feature that encodes a real change (not both <original> and <variation> empty), so deletions are read alongside substitutions and insertions. SequenceVariation, the writer, and the round-trip already support an empty VariantSequence, so no other production change is needed.

Corpus (L1 deletions — executable spec, oracle derived from the domain model, red-before-fix)

New nodes in Test/DatabaseTests/VariantCorpus:

  • D00–D01 — single- and multi-base deletion, unmodified
  • D02–D04 — deletion before / on / after a PTM residue (phospho re-anchors ↓ / drops / stays)
  • D05–D06 — deletion out of range / straddling the C-terminus → pruned
  • D07–D08 — the VCF depth cutoff (minAlleleDepth), same deletion passing at cutoff 5 (2 forms) / filtered at 7 (1 form)
  • MD00–MD02pairs of separate deletions (unmodified, flanking a PTM, one-on-the-PTM), capped at 2 to stay under the combination cap

D00–D04 fail on master (reproducing the reader gap) and go green with the fix. The harness gains BEGIN/END, empty-VAR (deletion), SRC=vcf (GT/AD/DP) support, and a per-case MinAlleleDepth.

Buggy fixture the drop was masking

Admitting the deletions surfaced a latent error in seqvartests.xml: the YPSE deletion declared begin=960, but YPSE sits at 961–964 (the base is NYPSE at 960–964), violating SeqVarXmlTest's own invariant that OriginalSequence equals the residues at [begin,end]. It never ran because the variant was being dropped. Corrected begin 960→961.

Verification

  • 34/34 VariantCorpus (incl. ProteinDbWriter round-trip + run-twice determinism)
  • 666/666 DatabaseTests + Transcriptomics

🤖 Generated with Claude Code

The ProteinXmlEntry reader admitted a sequence-variant feature only when
<variation> was non-empty, so it silently dropped every UniProt-native
deletion (encoded as <original>X</original><variation/>, which is how
UniProt writes a deletion and is not ours to change). Admit any feature
that encodes a real change -- not both <original> and <variation> empty --
so deletions become SequenceVariations alongside substitutions/insertions.

Corpus (L1 deletions, bible-derived oracle, red-before-fix): add nodes
D00-D08 and MD00-MD02 -- single/multi-base deletions, deletions before/on/
after a PTM residue (phospho re-anchors/drops/stays), out-of-range and
straddle-end pruning, the VCF depth cutoff (minAlleleDepth) pass/fail, and
pairs of separate deletions (capped at 2). Harness gains BEGIN/END, empty
VAR (deletion), SRC=vcf (GT/AD/DP), and a per-case MinAlleleDepth.

Fix a latent fixture error the drop had masked: in seqvartests.xml the
YPSE deletion declared begin=960, but YPSE sits at 961-964 (base is NYPSE
at 960-964), violating SeqVarXmlTest's invariant that OriginalSequence
equals the residues at [begin,end]. Corrected begin 960->961.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GbKQ6fMLGsmiPAHPN3W6gz
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.46%. Comparing base (77fb7db) to head (ca57af0).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1095   +/-   ##
=======================================
  Coverage   91.46%   91.46%           
=======================================
  Files         427      427           
  Lines       52777    52777           
  Branches     6325     6325           
=======================================
  Hits        48273    48273           
  Misses       3268     3268           
  Partials     1236     1236           
Files with missing lines Coverage Δ
mzLib/UsefulProteomicsDatabases/ProteinXmlEntry.cs 98.94% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@trishorts trishorts added Performance Maintenance The user isn't impacted by it, it's purely behind the scenes ready for review stability labels Jul 10, 2026
…variants; isolate D06 end>len

Corpus_Node_RoundTrip previously asserted only the digested proteoform set,
which for consensus-only nodes equals the base sequence whether or not the
writer preserved the SequenceVariation. Add AssertConsensusVariationsRoundTrip
comparing the consensus SequenceVariations (position + original + variant)
before write vs after re-read, so a writer that drops a read-but-unapplied
variant now fails the round-trip (real teeth on D08, the depth-filtered node
whose variant is retained on the consensus). Out-of-range nodes (D05/D06) are
pruned from the consensus at load, so both sides are legitimately empty.

Retune D06 to OP=E BEGIN=7 END=8 so end>len is the sole reason for pruning
(the original now matches residues[begin,end] in range), cleanly isolating the
PruneOutOfRangeSequenceVariants end-beyond-length branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@trishorts

trishorts commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Manual unit-test review

All 14 unit test(s) added by this PR were reviewed individually by the author (not only by automated/AI-generated checks): 13 approved as written, 1 edited, 0 flagged.

This satisfies the author's standing AI-use policy that AI-assisted tests receive human review before relying on them. Recorded 2026-07-11 06:54.

…inal YPSE deletion

SeqVarXmlTest only asserts that P40467's UniProt-native YPSE deletion (empty
<variation/> at 961-964, admitted by the smith-chem-wisc#1095 reader fix) is READ with the
right coordinates. Add SeqVar_NativeCTerminalDeletion_YPSE_AppliesAndShortensProtein
to assert it is APPLIED correctly: taking the deletion exactly as read from the
fixture and applying it in isolation yields a proteoform that ends ...YLPLN
(length - 4), not ...YLPLNYPSE, with the applied variation carrying original
"YPSE", empty variant, and post-collapse coordinates 961..960. A bug that read
the native deletion yet failed to apply it would pass SeqVarXmlTest and fail here.

Scoped to the deletions tranche; P40467's substitutions/insertions are left for
their own tranches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Maintenance The user isn't impacted by it, it's purely behind the scenes Performance ready for review stability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant