Germline-aware annotation¶
By default, Varcode compares each variant with the reference genome. Pass the patient's germline calls to classify somatic variants against the patient's own sequence instead. This matters when an inherited variant sits nearby: if it already changed a codon, a somatic mutation in that codon can produce a different amino acid than the reference codon would suggest.
Basic usage¶
from varcode import GermlineContext, load_vcf
somatic_variants = load_vcf("tumor.vcf", genome=81)
germline_ctx = GermlineContext.from_germline_vcf("normal.vcf", genome=81)
effects = somatic_variants.effects(germline=germline_ctx)
Use matching genome builds. normal.vcf should be a germline call set, not a
sparse normal column from a somatic caller; see
constructing a context for that distinction.
Unknown relative phase can produce several candidate effects. See two variants in one codon for a worked example, or phased VCF input to supply evidence. With many unphased germline variants nearby, the result is unresolved instead; see the phase enumeration limit. No annotator selection is needed.
The default lookup covers the full transcript span, including introns that a
splice hypothesis may retain. effect.baseline_transcript and
effect.mutant_transcript retain the actual products compared. The baseline
includes inherited alleles assigned in cis by each hypothesis. The same
germline=, phase_resolver= and rna_resolver= inputs compose through the
shared transcript pipeline.
Constructing a GermlineContext¶
Choose the source that matches your input:
from varcode import Completeness, GermlineContext
# Route 1: full germline call set from a real germline caller.
ctx = GermlineContext.from_germline_vcf("normal.vcf", genome=81)
# Route 2: multi-sample VCF, extract one column.
ctx = GermlineContext.from_multi_sample_vcf(
"tumor_normal.vcf",
sample="NORMAL", genome=81,
completeness=Completeness.SPARSE, # required, no default
)
# Route 3: explicit no-germline fallback (== germline=None).
ctx = GermlineContext.empty()
# Route 4: direct construction from an existing collection of germline variants.
ctx = GermlineContext.from_variants(germline_variants, reference_name="GRCh38")
completeness= distinguishes "no call here = ref/ref" (a real
germline caller's output) from "no call here = unknown" (the
NORMAL column of a somatic VCF, which only reports rows the
somatic caller looked at). Forcing the caller to declare prevents
silently mis-treating sparse data as complete.
| Completeness | Pipeline | Absence at a position |
|---|---|---|
COMPLETE |
DeepVariant, HaplotypeCaller, Strelka2 germline | ⇒ ref/ref |
SPARSE |
Mutect2 NORMAL, Strelka2 somatic |
⇒ unknown |
HOTSPOTS_ONLY |
Panel-of-normals, ClinVar | ⇒ unknown |
EMPTY |
Explicit no-data | n/a |
When the context is sparse, Varcode flags effect.germline_unknown =
True rather than silently assuming ref/ref.
Cross-VCF build mismatch¶
Use a VariantCollection for collection-level build validation. It raises
GenomeBuildMismatchError when its somatic variants and germline context have
different reference builds:
from varcode import GenomeBuildMismatchError
try:
effects = somatic_variants.effects(germline=germline_ctx)
except GenomeBuildMismatchError as error:
print(error.somatic_reference, error.germline_reference)
raise # correct the input builds before retrying
The one-variant API does not provide the same collection-level preflight.
validate_reference=False is an option on VariantCollection.effects(),
not Variant.effects(); it suppresses that check and does not convert
coordinates. Prefer correcting mismatched inputs.
How germline changes predictions¶
Supplied germline variants can change baseline codons or splice signals used to classify a somatic variant. This is a transcript comparison, not a complete patient-genome reconstruction; see limitations.
Phase-set tags describe phase within their source VCF. Do not equate tags from independently produced tumor and normal files. Use a resolver backed by a jointly phased VCF or molecular evidence. Short- and long-read data can both leave phase unknown; coverage and linked alleles determine whether a particular pair is resolved.
Phase enumeration limit¶
Each germline variant of unknown phase doubles the number of cis/trans combinations. Homozygous germline variants are always cis, and variants phased to each other (for example in one VCF phase set) count once, so both reduce the count.
When the combinations exceed the cap (default eight, so more than three
independent unphased germline variants across the transcript), Varcode does not guess a phase. It
returns a HypothesisLimit effect, a kind of Unresolved:
- Its
phaserecords which germline variants are known cis, known trans, or unphased. - Its
reference_effectis the effect without germline context. TheHypothesisLimitis ranked like that effect.
To raise the cap, set it on the context:
When a patient comparison cannot be built¶
Each candidate retains its baseline and mutant products. Missing intronic
sequence, conflicting edits and unsupported rearrangements remain explicit
unresolved results rather than reference-relative substitutes. Unknown phase
and splice choices stay in the same candidate.outcomes records; inspect
outcome.hypothesis.phase, baseline_splice_plan, and splice_plan.
A germline-disrupted site retains all compatible baseline mechanisms. An unchanged active site uses the same mechanism on both sides of the comparison; a site deleted or changed in the tumor does not force one guessed baseline. RNA support can select a matching predicted product without inventing phase.
When all inherited edits are in trans, the affected haplotype has the reference baseline. Missing germline information cannot establish that the patient has that baseline. For unavailable fields, see sequence availability.
The explicit annotator="fast" compatibility path retains local germline
lookup, PhaseCandidateSet results, and Unresolved with
mechanism="germline_composition" for combinations it cannot compose. Its
reference_effect is a diagnostic without germline context, not a patient
consequence. Existing serialized results remain readable.
Loss of heterozygosity (LOH)¶
When a reported somatic allele matches the supplied germline, Varcode returns
GermlineAlleleOverlap with is_germline_overlap=True, is_loh=None, and
loh_status="not_assessed". It does not apply the inherited allele a second
time or claim a new somatic protein sequence. The allele may still have a
functional effect relative to the genome reference.
LOH requires evidence about loss of an allele previously present in the normal sample (NCI definition). Varcode's sequence annotation does not perform that tumor/normal allelic-state analysis. An allele match, including unchanged heterozygous or inherited homozygous calls, cannot establish LOH. Integrate a dedicated LOH caller's evidence separately.
for effect in effects:
if getattr(effect, "is_germline_overlap", False):
print("Germline-overlap flag:", effect.short_description)
Here effects is the collection annotated with germline context above.
The check requires germline=; annotation without that context cannot attach
the flag.
Use detect_germline_overlap for an allele-match query. The deprecated
detect_loh now returns None (not assessed) and warns, rather than making a
zygosity claim.
The default transcript model composes known-cis groups that mix inherited and somatic alleles, applying each inherited allele once; see mixed inherited and somatic haplotypes.
Limitations¶
- Splice predictions remain hypotheses. Sequence changes do not establish which transcript is expressed or automatically reduce splice severity.
- Subclonal somatic and CNV dosage are not modeled. Every somatic variant is treated as 100% present.
- Hypothesis cap of 8 by default when phase is unknown across
multiple germline variants across the transcript; above it the effect is
unresolved. Change it with
GermlineContext.max_phase_hypotheses. - Normalization mismatch between germline and somatic VCFs (left-alignment, MNV split) causes apparent position mismatches. Normalize both with the same tool first.
- Population-frequency germline (gnomAD/ExAC as a substitute for patient germline) is not supported.
Lower-level helpers¶
The high-level effects(germline=...) path uses the shared transcript model.
predict_transcript_model_effect accepts an explicit known-cis group and
supplied germline variants. The existing predict_germline_aware_effect and
apply_germline_to_transcript helpers remain available for compatibility and
custom small-edit annotators; they retain their local/cDNA-edit contracts.