Skip to content

Saving and reloading results

Save results as CSV for a table you can inspect or share, as JSON to archive supported objects, or write variants back to VCF. Whichever you choose, keep the original inputs and evidence too: a summary table does not preserve every alternative outcome, sequence, or annotation context.

For predicted protein FASTA with baseline comparisons, alternatives and omitted outcomes in a shared offline manifest, use protein collections.

Writing

from varcode import load_vcf

vc = load_vcf("variants.vcf", genome="GRCh38")
vc.to_csv("variants.csv")

effects = vc.effects()
effects.to_csv("effects.csv")

Splice rows list every current candidate description in effect, retain effect_type=SpliceOutcomeSet, and name the affected signal in splice_signal. The descriptions include unresolved candidates; they do not archive each candidate's sequences or evidence.

When a collection includes extra ORFs, to_csv() adds an effect_json column to every row. This archives the complete effects alongside the readable summaries. from_csv() restores those saved graphs, including ORF source identity, reference RNA, evidence, failures and alternative products, without reannotation or catalogue downloads. Keep the archive column intact: missing payloads or summary identities that disagree with them raise an error. to_dataframe() remains a compact summary; use to_dataframe(include_archive=True) to include the archives.

By default, both writers prepend #-prefixed provenance lines so the file is self-describing:

# varcode_version=10.2.1
# reference_name=GRCh38
chr,start,ref,alt,gene_name,gene_id
17,43082575,C,T,BRCA1,ENSG00000012048
...

Pass include_header=False for fast consumers that can't tolerate comment lines:

vc.to_csv("plain.csv", include_header=False)

Reading

The examples here apply to ordinary point-variant tables. Structural-variant CSV summaries without effect_json cannot be restored: from_csv rejects them rather than reconstructing incomplete SVs. See structural exports.

When the header is present, from_csv recovers the reference genome automatically:

from varcode import VariantCollection, EffectCollection

vc = VariantCollection.from_csv("variants.csv")
effects = EffectCollection.from_csv("effects.csv")

For summary files without effect_json, EffectCollection.from_csv re-runs annotation. It does not recover the original germline/phase/RNA evidence, candidate sets, or historical predictions. A reference-name header also does not pin the original annotation dataset; pass the same explicit genome when that matters.

When the CSV has no header (written by an older varcode or with include_header=False), pass genome explicitly:

vc = VariantCollection.from_csv("plain.csv", genome="GRCh38")

Missing both the header and an explicit genome produces a clear error:

ValueError: from_csv needs a reference genome: pass the `genome`
argument explicitly, or write the CSV with
`to_csv(include_header=True)` so `# reference_name=...` is recorded
in the header. Neither was found at plain.csv.

Column-name flexibility

VariantCollection historically writes a chr column while EffectCollection writes contig. Both readers accept either spelling for that column. This does not make their full schemas interchangeable: effect tables also need effect/transcript fields.

Version drift

For summary files without effect_json, EffectCollection.from_csv re-runs annotation, so loading under another version can produce different effects. Archived rows restore their saved predictions. from_csv emits a UserWarning when the header's varcode_version differs in major version from the currently-installed version. Minor and patch drift is silent, but bug fixes or a different annotation dataset can still change predictions; API compatibility is not a guarantee of identical scientific output.

CSV vs JSON

CSV JSON
Intended use Inspect or share a table Serialize supported objects
Reloading effects Summary rows re-annotate; effect_json rows restore saved graphs Restores serialized state where supported
Structural variants Summary import rejected; archived rows restore graphs Restore effect/candidate graphs and mutant transcript models
Carries annotator version header Yes (via the serialized object)
Preserves all effect-specific fields With effect_json, subject to graph support Depends on the effect type and serialization support

JSON (to_json / from_json) avoids CSV's re-annotation for supported objects. Deserialization restores recorded predictions without recomputing them, and collection annotator provenance is preserved.

Structural results use a versioned effect graph, which older Varcode versions cannot read. These survive a round trip:

  • Self candidates and shared effect links.
  • Primary, cryptic, splice, and external candidates, with their source/evidence fields.
  • Fusion partners and affected exons.
  • Attached mutant transcript sequences and segments.

This remains an object archive with Python class and reference-dataset dependencies. Arbitrary extra attributes and third-party sequence providers need their own serialization support. Test the round-trip for the actual result types you use, and retain source variants, reference release, and original RNA/phase/germline evidence independently.

Extra-ORF graphs snapshot their full reference RNA and use ORFdata's public record constructors to restore the bound coding model. Reading these ORF graphs needs ORFdata but no installed catalogue or reference database. The snapshot supplies archived transcript properties; it is not a reference genome for annotating new variants. See ORF annotations.

VCF export

varcode.vcf_output.variants_to_vcf writes small variants back to VCF:

from varcode import load_vcf
from varcode.vcf_parsing import VCFHeader
from varcode.vcf_output import variants_to_vcf

variants = load_vcf("input.vcf", genome=81)
header = VCFHeader.from_path("input.vcf")
with open("export.vcf", "w") as out:
    variants_to_vcf(variants, variants.metadata, out=out, header=header)

What is preserved:

  • Sample identities. Each value is looked up by sample name and FORMAT key, so values can't shift between sample columns. Sample order is deterministic, GT comes first, missing values are written as ., and samples present in only some records are kept.
  • Multi-allelic records. load_vcf remembers each record's original ALT list and indexes, so export rebuilds the complete record in its original order, with GT and allele-indexed values intact.
  • INFO/FORMAT declarations, when you pass the original VCFHeader as above. Without it, standard FORMAT definitions and the observed value types determine new declarations; custom descriptions and cardinalities can't be recovered from values alone.
  • Ordering. Positions sort numerically within each contig.

What is refused or not kept:

  • A subset that drops one of a record's original ALT alleles is rejected before any output is written. Keep all alleles, or explicitly remap the genotype and allele-indexed fields first. This includes invalid multiallelic input whose reference-identical ALT was skipped by load_vcf; correct that source record before exporting it.
  • Records are not merged just because their IDs match.
  • Hand-constructed records without an ALT index are treated as biallelic; their GT and standard allele-depth/likelihood fields must agree with that.
  • Metadata saved by older Varcode versions lacks the full ALT list; reload it from the source VCF.
  • Header lines other than INFO/FORMAT declarations are not archived, conflicting source records are not resolved, and StructuralVariant objects are not exported.

Keep the original VCF as the source of record.

Annotation provenance

Annotated effect collections record annotator, annotator_version, and annotated_at (an ISO-8601 UTC timestamp). Filtering and grouping preserve these fields. CSV export writes them into the metadata header, and loading recovers the original values.

A mismatch between the recorded annotator and the current default raises a warning on load. Selecting the recorded implementation does not restore the original predictions: CSV loading still re-annotates. Keep the original reference release and evidence separately; see CSV vs JSON.

Custom header fields

read_metadata_header is available in varcode.csv_helpers for tools that want to add their own metadata lines:

from varcode.csv_helpers import read_metadata_header, write_metadata_header

meta = read_metadata_header("variants.csv")
# OrderedDict([('varcode_version', '10.2.1'), ('reference_name', 'GRCh38')])

Annotator provenance fields (annotator, annotator_version) use the same # key=value convention.