Annotation pipeline and compatibility¶
Since Varcode 11, the default transcript_model annotator uses one path for
reference edits, patient germline baselines, known-cis groups and splice
alternatives: realize the baseline and mutant transcripts, then classify their
sequence difference. Read collection, alignment and RNA assembly remain in
upstream tools such as Isovar. Varcode consumes their supplied models.
Supported inputs¶
| Selection | Method | Inputs |
|---|---|---|
Default, or annotator="transcript_model" |
Composes phase/splice hypotheses and compares each product with its patient baseline | Small variants and local DEL/DUP; sequence insertions need alt_assembly. Reuses existing structural builders for junctions, inversions and supplied assemblies. |
annotator="fast" |
Compatibility implementation from Varcode 10 | Small variants and SVs; local germline lookup; limited joint composition. |
annotator="protein_diff" |
Alternative protein-difference implementation | Small variants; shares legacy splice, location and germline helpers; no SV support. |
Typed junctions, BNDs, inversions, nonlocal rearrangements and supplied transcript assemblies reuse the existing structural builders. Combining these with germline or other cis edits requires mapped patient-baseline coordinates and remains unresolved. CNVs retain dosage uncertainty. See limitations.
Comparing annotators¶
Given a variant and one of its transcript objects, selection is explicit:
effect = variant.effect_on_transcript(transcript) # ordinary use
comparison = variant.effect_on_transcript(transcript, annotator="protein_diff")
legacy = variant.effect_on_transcript(transcript, annotator="fast")
The transcript model can use germline= and phase_resolver= context. Canonical
and exon-skip paths need only transcript annotation; a genome with reference
FASTA additionally supplies sequence for intron retention and cryptic splice
sites. Without a calibrated scorer, mechanism preference is an ordering rule,
not a probability. No implementation resolves every structural or combined input.
Use the same entry point as more evidence becomes available:
effects = variant.effects(
germline=germline_ctx, # or None when unavailable
phase_resolver=phaser, # or None when phase is unknown
rna_resolver=rna_evidence, # or None when no RNA models are available
)
The germline lookup covers the whole transcript span, including introns that
a splice hypothesis may retain. This can expose more phase uncertainty than
the legacy annotator's local lookup. Sparse/hotspot contexts retain
germline_unknown=True even when some inherited alleles are supplied.
Through effects(germline=...), the transcript model uses the context phase cap (GermlineContext.max_phase_hypotheses, default 8). It
also caps the combined phase × baseline-splice × mutant-splice outcomes at max_hypotheses=64, which is
the phase cap too when predict_transcript_model_effect is called directly.
Exceeding either returns a HypothesisLimit
rather than a partial set of candidates.
Mixed inherited and somatic haplotypes¶
predict_transcript_model_effect(variants, transcript, germline_variants=...)
and annotate_haplotype take a known-cis group. Members matching the supplied
germline are included once in the patient baseline. Only novel alleles are
applied to that baseline to obtain the mutant; effect.variant is the first
novel member and effect.variants retains the supplied group. Matching uses
reference assembly, contig, normalized position, REF and ALT. A group with no
novel allele returns GermlineAlleleOverlap, without inferring LOH.
The group itself supplies cis constraints. Phase can propagate from any member
to other germline alleles; unlinked alleles still produce separate hypotheses.
Homozygous alleles are on both haplotypes and do not bridge their phase.
As with other phase constraints, conflicting resolver answers are logged and
ignored. Each hypothesis retains its germline cis/trans assignments, phase
state, resolver source and novel somatic_variants in its evidence.
VariantCollection.effects constructs these groups only when the resolver
supports cis. Unknown or trans relationships retain individual predictions;
listing alleles in a collection alone does not assert that they are in cis.
Transcript-model results¶
Use effect.baseline_transcript and effect.mutant_transcript for the products
used in classification, and the usual original_protein_sequence and
mutant_protein_sequence properties for proteins. Candidate effects use these
same accessors. See sequence availability.
The shared pipeline and legacy candidate wrappers expose different details:
| Candidate type | Shared access | Additional information |
|---|---|---|
EffectCandidate (legacy splice/SV sets and imported RNA) |
candidate.effect |
source, evidence; sequences are on the effect or its optional mutant_transcript |
RealizedEffectCandidate (transcript-model hypothesis pipeline) |
candidate.effect |
outcomes, hypotheses, probability, ordinal_key; each outcome has baseline and mutant products with cdna_sequence, protein_sequence and evidence |
The default returns an ordinary top effect with candidates attached, not
necessarily a MultiOutcomeEffect. Its structural builders use ordinary candidates;
early noncoding, incomplete or unresolved results may have no candidates at all.
Inspect the returned shape rather than assuming it from the annotator name:
from varcode import EffectCandidate
from varcode.effect_hypotheses import RealizedEffectCandidate
print(effect.short_description)
for candidate in getattr(effect, "candidates", ()):
print(candidate.effect.short_description)
if isinstance(candidate, RealizedEffectCandidate):
# A merged candidate can retain several hypotheses and their products.
for outcome in candidate.outcomes:
print(outcome.baseline.protein_sequence, outcome.mutant.protein_sequence)
print(outcome.mutant.cdna_sequence, outcome.hypothesis.evidence)
elif isinstance(candidate, EffectCandidate):
print(candidate.source, candidate.evidence)
print(candidate.effect.mutant_protein_sequence)
Baseline splice uncertainty¶
Each hypothesis records baseline_splice_plan and splice_plan. Unchanged
active sites share a mechanism between baseline and mutant. If the site changes
or disappears on one side, all compatible baseline choices remain; Varcode does
not select an arbitrary patient splice product. Both plans are graph-valid.
Unchanged annotated noncanonical sites are not called variant-induced loss.
Migrating from Varcode 10¶
Ordinary calls now return a classified effect such as Deletion, Substitution
or Unresolved, with alternatives in candidates. Code requiring
SpliceOutcomeSet, LargeDeletion, PhaseCandidateSet or HaplotypeEffect
results can explicitly select annotator="fast". Existing classes, imports and
serialized results remain supported. A candidate rank is not a probability.
The shared default builds full baseline/mutant products and retains uncertainty;
this costs more CPU and memory than the legacy local classifier, especially
across large call sets or many transcripts. For workflows requiring the older
throughput and result contract, select annotator="fast" explicitly.
Collection filtering and effect priority consider every candidate, so a
preferred silent comparison cannot hide a protein-changing alternative. The
selected effect's own sequence properties describe that comparison; use
highest_priority_candidate.effect when you need the most severe alternative.
Known limitations¶
RNA evidence refines the existing hypothesis candidates. An exact match to a
full predicted cDNA adds rna_support to that product's evidence and ranks
supported comparisons first. All compatible phase baselines remain, and
unobserved alternatives are retained. Read counts do not become probabilities,
and RNA sequence agreement does not prove translation.
Partial or unmatched RNA models retain their actual supplied sequence as an
Unresolved candidate with an unavailable baseline. No reference sequence is
appended, and no phase or CDS mapping is inferred. Such observations follow the
DNA candidates in ordering. The same behavior applies to RNA models supplied
by a phase resolver for a known-cis group; no separate observation list is
needed on this path. Legacy delegated BND/assembly results keep their existing
contracts. Read-based transcript reconstruction belongs upstream; broader mapped
rearrangement consequence support is tracked in
#466.
Models containing assumed reference completion do not count as full observed
RNA support, even when their completed cDNA matches a prediction.
- Combined variants: the selected annotator makes known-cis joint predictions
through
VariantCollection.effects(phase_resolver=...). The default composes germline, splice and local structural edits.fastandprotein_diffretain their legacy point-edit haplotype behavior. Unsupported groups remain explicit unresolved results. See the joint contract. - Rearrangements beyond the layout: existing structural builders retain their fusion candidates and supplied transcript sequences. A clipped DUP/INV cannot establish an unchanged protein or a complete rearranged transcript (#449); unavailable sequence and unmapped CDS/translation remain uncertain. Local symbolic DEL/DUP events use the shared genomic layout.
Unresolved results report None, not False, for sequence-change flags.
drop_silent_and_noncoding() retains them by default; see
SV filtering.
Previous names¶
realized, RealizedEffectAnnotator, and predict_realized_effect are aliases
for the transcript-model implementation. Use the transcript_model names in
new code. The RealizedEffectCandidate wrapper still has a different interface
from ordinary EffectCandidate, as shown above.
To implement your own, see Writing an annotator.