Variants and vaccines¶
The website lists the patient's tumor variants, which pipelines found them, how many reads support them in each BAM, and which went into the cancer vaccines. The examples open your most recent snapshot; see Get started.
Select variants¶
from osteosarc import Dataset
data = Dataset.open()
site = data.variants()
dynein = site.select(gene="DYNC1H1", status="ready")
for variant in dynein:
print(variant.id, variant.allele)
data.variants() gives every variant on the website's variants page.
data.variants("vaccine") gives the ones in at least one vaccine, and
data.variants("all") adds entries found only in the site's read-count table.
Select by gene, vaccine, pipeline or status.
From a terminal:
osteosarc variants --gene DYNC1H1 --status ready
osteosarc variants --vaccine mRNA
osteosarc variants DYNC1H1-chr14-101980529
The last shows one variant with its allele, effect, vaccines, corrections and the site's read counts.
Alleles¶
variant = site["DYNC1H1-chr14-101980529"]
print(variant.allele) # (chromosome, one-based position, REF, ALT)
print(variant.region(padding=100)) # zero-based, half-open
Pass variants straight to read extraction to get the reads around them.
Variant status¶
A variant's status says whether it has one usable allele. It says nothing about samples or read support.
| Status | Meaning |
|---|---|
| ready | One allele, written in DNA bases |
| missing_literal_allele | No allele given |
| non_literal_allele | REF or ALT is a placeholder, such as dup or not_reported |
| ambiguous_literal_allele | More than one allele given |
| conflicting_coordinates | The site's pages disagree on the position or allele |
| malformed_source_row | A read-count row is broken; the other entries are unaffected |
Only ready variants have an allele and a region. Ready doesn't mean the variant is
somatic, expressed or changes the protein. Corrections, on by
default, fix some alleles and statuses; open the snapshot with
corrections=False to see the published ones.
Read counts¶
counts = data.vafs.select(variant_id=variant.id)
print(counts.rows[:2])
Counts are kept as published, one row per variant and BAM. A missing count isn't zero: counts measured at the wrong allele or position are cleared by a correction, so they read as not measured.
Vaccines¶
for row in data.vaccine_peptides("mRNA"):
print(row["variant_id"], row["sequence"])
for row in data.vaccines.select(gene="SMC5"):
print(row["vaccines"], row["elispot_status"])
The vaccines table has one row per vaccine target: which vaccines include it, and
its ELISPOT result. An ELISPOT that wasn't run, or has no recorded response, isn't
a negative result. osteosarc vaccines prints the same table.
Which vaccines contain a variant comes from the site's vaccine-overlap file. Its
variant data file flags vaccines separately, and the two can disagree; select
with vaccine_source="source_variants" to use the flags.
Reviewed alleles¶
Five entries needed their alleles reviewed (issue #5); each variant's annotations hold the outcome and evidence:
fam157a = site["FAM157A-p_W70_Q71ins_14"]
print(fam157a.allele)
print(fam157a.annotations["allele_resolution"]["summary"])
| Entry | Outcome |
|---|---|
| FAM157A | A 42-base insertion at chr3:198153259, from a public Tempus call. NCBI withdrew the protein model, so it isn't known to make a neoantigen. |
| COL3A1 | A 737-base deletion at chr2:189010889 that removes intron 50, as the catalogue's cDNA says. |
| MUC3A | A GRCh37 duplication whose GRCh38 position can't be settled: it sits in a repeat that differs between builds. |
| OTUD4 | No public call gives its allele. |
| USH2A-chr1-215560752 | A typo of USH2A-chr1-215650752. The site has since merged the two. |
VCFs and your own parsing¶
The bucket's VCFs are ordinary files: find them with
data.files.select(kind="variants"), download one with data.download(file) and
open it with pysam. For Varcode variants, see
OpenVax libraries. To parse the site's variant files yourself,
use osteosarc.parsing.parse_variants.