openvax / openvax/varcode

VariantCollection builds joint haplotype effects outside the selected annotator

Open
#437 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
87
Forks
28
Avg merge
3h 27m
Merged PRs (30d)
27

Description

Problem

VariantCollection.effects() uses the selected annotator for per-variant
effects, but then unconditionally calls build_haplotype_effects() whenever a
phase resolver is supplied. That builder applies variants to a transcript and
constructs HaplotypeEffect directly, without consulting the annotator.

Consequently:

  • Selecting experimental transcript_model does not give that model control
    over combined cis predictions through the collection API.
  • Even an annotator returning NotImplemented for every input can have joint
    predictions appended by the outer collection layer.
  • The collection reports the selected annotator's name, although these joint
    predictions were constructed by another path.

This is active functionality to relocate, not dead code to delete.

Reproducer (Ensembl 81 cached)

from pyensembl import cached_release
from varcode import Variant, VariantCollection
from varcode.effects.effect_classes import HaplotypeEffect, Unresolved

class Declining:
    name = "declining"
    def annotate_on_transcript(self, variant, transcript):
        return NotImplemented

class Cis:
    phase_source = "test_cis"
    def in_cis(self, left, right, transcript=None):
        return True

genome = cached_release(81)
variants = VariantCollection([
    Variant("7", 117531100, "T", "A", genome),
    Variant("7", 117531114, "G", "T", genome),
])
effects = variants.effects(annotator=Declining(), phase_resolver=Cis())
assert effects.annotator == "declining"
assert any(isinstance(e, Unresolved) for e in effects)
# Unexpected: a plugin that declined every input still gets joint predictions.
assert any(isinstance(e, HaplotypeEffect) for e in effects)

Relevant code

At main 9113af081b59978d9fa74832ad7f5d8053eff9ff:

Proposed scope / acceptance criteria

  • Let the selected annotator own combined prediction, with the default retaining
    today's working point-edit haplotype behavior.
  • Let transcript_model invoke its joint modeling implementation through the
    normal collection API; keep it experimental.
  • Define a return-based unsupported-group contract, without capability lists,
    silent fallback to another annotator, or silently dropping unresolved groups.
  • Preserve phase evidence, observed RNA transcript handling, patient germline
    context, and truthful provenance.
  • Regression-test default, experimental, and declining third-party annotators;
    known cis/trans/unknown groups; conflicting edits; SV/splice combinations; and
    coexistence of individual and joint results.

Related: #421 (composing uncertainty) and #423 (unified transcript-model design).
Explicitly deferred from the structural-helper/default-annotator cleanup PR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in varcode/variant_collection.py at the outer VariantCollection.effects call, then read the joint builder in varcode/phasing.py and the annotator behavior described in the issue. Trace how default, transcript_model, and declining annotators should handle grouped variants. Done means regression coverage for the listed annotators, group types, conflicting edits, SV/splice combinations, individual and joint results, phase evidence, context, and provenance.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
bioinformatics
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.