Corrections

Osteosarc fixes 35 known problems in the website's data, by default. Each time a snapshot is opened, every fix is checked against the data. You can see what changed, turn the fixes off, or add your own.

osteosarc corrections                               # every fix and its status
osteosarc corrections allele-MAP2-chr2-209694768    # one fix, with its evidence
osteosarc --no-corrections variants --gene MAP2     # the website's values

Compare corrected and published values

from osteosarc import Dataset

data = Dataset.open()
raw = Dataset.open(corrections=False)
map2 = data.variants()["MAP2-chr2-209694768"]
print("Corrected:", map2.allele)
print("Published:", raw.variants()[map2.id].allele)
print(map2.annotations["corrections"])

A fix that changes a variant's allele usually clears its read counts, since they were measured for a different allele or position; MAP2 is the exception (see below). Variant IDs are the snapshot's own, and newer snapshots may rename them. The MAP2 example checks a correction against the reads.

See every correction

for row in data.corrections:
    print(row["id"], row["status"], row["summary"])

Every record a fix touches names it: a variant in its annotations (under corrections, or count_corrections when only some of its read counts changed), a file in its metadata, and a sample, timeline event, or row of counts, vaccines or measurements in its own corrections field.

When the website changes

Each fix records what the data should look like before it's applied, so it notices when the website changes. Its status says what it found:

Status Meaning
applied The problem is still there, and the fix was applied
fixed_upstream The website now has the right value, or has removed the bad record
stale The data changed unexpectedly; the fix was skipped, with a warning
unavailable The snapshot doesn't have the data the fix needs
disabled Corrections are turned off

A fix applies completely or not at all. Some also check a record they don't change, to confirm the problem is still there; tempus-grch37-counts, for example, checks PDZRN4's published 7/7 before clearing counts. When the website reorganizes records, a fix can list each layout it accepts; exactly one must match, or the fix is stale.

osteosarc corrections --strict

This exits with an error if a fix is stale or the data uses a label osteosarc doesn't know. It checks the snapshot you have; run osteosarc sync --refresh first to check the live website, and look at the new data before changing or removing a fix.

Labels are tidied separately, without counting as corrections: Boston Gene becomes BostonGene, and CITE becomes cite-seq. The original labels are kept.

Add your own correction

from osteosarc import CORRECTIONS, Change, Correction, glob

mine = Correction(
    "my-lab-note", "Flag CITE-seq BAMs for QC review.",
    (Change("bucket", {"key": glob("kamil/blood/output/*CITE*/outs/*.bam")}),),
    evidence=("internal QC log 2026-09",), verified="2026-09-18",
)
data = Dataset.open(corrections=[*CORRECTIONS, mine])

A change picks records by exact field values or glob patterns (dotted names reach nested fields). Without new values to set, it only flags the records. To turn off some built-in fixes, pass a shorter list. A correction can accept other record layouts, and a change can require that no record matches; pair such a check with one on a record that should still be there, since a record disappearing doesn't prove a fix.

The corrections

Checked against the website on 2026-09-24: 30 fixes apply and 5 are already fixed on the site; a snapshot from 2026-09-18 uses all 35. Each fix's evidence is in data.corrections and the source. None only rewrites a value in an equivalent form: each fixes a wrong value, fills in a missing one, or flags something to be careful with.

Variants and read counts

ID Does What
tempus-grch37-counts edit Clears counts measured in a GRCh37 Tempus exome BAM at GRCh38 positions, which describe unrelated places. Newer snapshots drop those rows.
allele-CABLES1-chr18-23135500 edit Gives the Tempus allele, chr18:23135764 T>TGGCGGC; the site had it 264 bp away as a dup placeholder.
allele-CCDC40-chr17-80058951 edit Gives the Tempus allele at chr17:80090148; the site had it 31 kb away, not reported.
allele-DCHS2-chr4-154322488 edit Gives the Tempus allele (a complex change) at chr4:154323273; the site had it 785 bp away with a wrong REF.
allele-GAPVD1-chr9-125299105 edit Gives the Tempus allele, chr9:125301980 TAGTGC>ATTGG; the site had it 2.9 kb away with a wrong REF.
allele-GOLGA6L2-chr15-23441121 edit Gives the Tempus allele, a 120-base insertion at chr15:23440197; the site had it 924 bp away as a dup.
allele-MAP2-chr2-209694768 edit The vaccine target's 22-bp deletion isn't what's in the tumor. Tempus calls one complex change (c.2599_2630delinsAGGG), CeGaT the same as three records, and the catalogue's protein and the reads match it. Its counts are kept: the site counts any large deletion there, which in the T0 exome is always this one.
allele-FAM157A-p_W70_Q71ins_14 edit Fills in the missing allele: a 42-base insertion at chr3:198153259, from a public Tempus call.
allele-COL3A1-Splice edit Fills in the missing allele: a 737-base deletion at chr2:189010889 that removes exactly intron 50, from a public Tempus call.
map2-split-representations flag Two other MAP2 entries are pieces of the same change; don't count them separately.
muc3a-grch38-placement note The Tempus call is on GRCh37, in a repeat that differs between builds, so its GRCh38 position stays unresolved.
ush2a-transposed-duplicate note USH2A-chr1-215560752 is a typo of USH2A-chr1-215650752. The site has merged them; the kept entry's location label and sequence context are fixed.
fam157a-withdrawn-protein flag NCBI withdrew the protein model behind FAM157A's insertion; the site now says so too.
natera-alleles-unavailable flag COL3A1 and OTUD4 come from a Natera report that isn't public; a Tempus call now gives COL3A1's allele.
otud4-source-unavailable note No public call gives OTUD4's allele, so the entry has none.
transcript-DCHS2 edit NM_1142552 is missing two zeros: NM_001142552, which the site now uses.
transcript-COL4A2 edit NM_001846. has a stray dot.
transcript-GTF3C5 edit NM_00112283 is missing a digit: NM_001122823.
gene-symbol-TRMO edit TMRO is a typo for TRMO.

The five moved alleles and MAP2's come from the Tempus TL-24-ALMY2X4KMV calls in the bucket, converted from GRCh37 to GRCh38 with Ensembl. Each REF matches GRCh38, and no equivalent way of writing an allele reaches its old position. These fixes make the catalogue match what Tempus called; several calls have few reads or sit in repeats, so they don't prove a variant is real. FAM157A and COL3A1 were also checked with UCSC's liftover and NCBI's reference sequence.

The GRCh37 counts were wrong because the site's pileup script looked up GRCh38 positions in a BAM aligned to GRCh37; MT-ND5's 0/0 has the same cause. These counts are cleared rather than read as zero.

Samples, pipelines and files

ID Does What
viewer-label-BG009368 edit This reprocessed RNA is T1 2024-06, not T0 2022-12, by its FASTQ and allele fractions. The site now agrees.
viewer-label-SARC0277 edit Likewise, it's T2 UCLA 2025-01, not T0 BostonGene. The site now agrees.
provider-IPISRC044-T1-rna edit The oncoanalyser T1 RNA BAM was built from BostonGene's FASTQs, not UCLA's.
pvac-2025-detection edit CDC40, PIP5K1A, SMC5 and TECPR1 are in the 2025-04-27 pVACtools runs, which the site's detection flag misses.
pvac-header-only-filtered-reports flag Seven filtered pVACseq reports are empty, which doesn't mean no epitope passed.
pvac-rna-fields-na flag RNA depth, VAF and expression are NA in every pVACseq report: RNA was never given to pVACseq.
pvac-extended-run-no-class-i flag The "MHCI.extended" run has only Class II reports.

Timeline and samples

ID Does What
specimen-T1-site edit T1 was a UCLA biopsy, not a UCSF resection; it spans two UCLA biopsies, on 2024-06-06 and 2024-06-11.
specimen-T2-date-site edit T2 was a UCLA biopsy on 2025-01-28, not UCSF on 2025-01-06.
specimen-T3-site edit T3 was an MSKCC resection, not a UCSF biopsy.
pbmc-capture-dates flag Four blood samples are dated by cell capture; the blood was drawn two to four days earlier.
events-duplicate-rows flag SQ3370 and Trabectedin each appear twice.
tempus-timepoint flag The timeline dates the Tempus tests to T0 (2022), which the data supports, but the files are labeled T1 (2024-06).
tempus-file-labels flag The Tempus files are labeled T1, but carry all three variants seen only at T0 and none of the 35 seen only at T1. The labels are left as published.
apheresis-date flag The apheresis is 2024-05-14 on the timeline and 2024-05-15 in the ELISPOT records.
reyagel-end-date flag ReyaGel's end date is 7/14, with no year, so it shows as one day; the only broken date of the sheet's 371.

Other things to know

  • Some DRAGEN BAMs, mostly blood normals and organoid runs, aren't linked to a sample; osteosarc files --prefix kamil/basespace/results/ lists them. The four 2026 blood samples have only FASTQs so far.
  • An ELISPOT experiment's date is that of the earliest blood sample it used.
  • The site's older treatment timeline file is out of date, and isn't used.
  • The site lists LENS pipeline detections, but has no LENS files to download.