Reviewing a whole SV callset
The tutorials target the JBrowse v5 beta, and the v4.3.0 release
on the download page lacks some of what they show. To install the
beta of JBrowse Web, run npm install -g @jbrowse/cli@next, then
jbrowse create jbrowse2 --branch v5.0.0-beta.8. Desktop beta builds are coming soon.
jb2export batch renders every junction in a somatic callset as a breakpoint
split view, so triage becomes a directory of images. The matched normal,
rendered the same way, is the control.
Prerequisites
@jbrowse/img, which putsjb2exporton your PATH- nothing to download: the callset, the tumor reads and the matched normal are all hosted
- a JBrowse, for the last section only (Web or Desktop); the renders above need none
npm install -g @jbrowse/img
Where the data comes from
COLO829's somatic SV callset is the ONT open-data release's own
wf-somatic-variation run
(Valle-Inclán et al. 2022),
rehosted alongside the cancer SV demo.
- the callset these commands fetch directly: https://jbrowse.org/demos/cancer_sv/COLO829.somatic-sv.vcf.gz
- the config the batch renders read tracks from: https://jbrowse.org/demos/cancer_sv/config.json
- the tumor reads the config's
COLO829_tumor_onttrack streams, Oxford Nanopore R10 from the ONT open-data release: https://ont-open-data.s3.amazonaws.com/colo829_2024.03/wf_somatic_variation/sup/COLO829_tumor.ht.cram - the matched normal the config's
COLO829BL_normal_onttrack streams: https://ont-open-data.s3.amazonaws.com/colo829_2024.03/basecalls/colo829bl/sup/PAU59807.d052sup4305mCG_5hmCGvHg38.bam
COLO829 and its matched normal
COLO829 is a melanoma cell line with a matched normal, COLO829BL, and a community reference for somatic structural-variant calling. The multi-hop tutorial follows one event in this callset all the way down; this page renders every junction at a glance.
The contact sheet
A junction joins two loci, which are the two panels of a breakpoint split view, so a callset renders straight into a review queue:
curl -fO https://jbrowse.org/demos/cancer_sv/COLO829.somatic-sv.vcf.gz
jb2export batch --vcf COLO829.somatic-sv.vcf.gz \
--config https://jbrowse.org/demos/cancer_sv/config.json --assembly hg38 \
--track COLO829_tumor_ont height:240 \
--outDir tumor --flank 600 --width 1100
Warning: skipped 35 record(s), e.g. line 271: names no second locus (INS)
[########################] 100% 100/100
wrote 100/100 images to tumor
Insertions name one locus, so there is no second panel and the warning counts
them out. Each breakend pair is written twice and collapses to one. The result
is the same 100 junctions, in the same order, that sv_multihop.py chains
reports in the
multi-hop tutorial, because
neither parses the ALT bracket by hand, which goes wrong four ways, none of them
raising an error:
- the replacement string may carry inserted sequence either side of the bracket
(
GTGATGGATTCA[CHR12:72273112[) - callers upper-case the mate contig, and
CHR12is not a region hg38 has END=matches insideCIEND=, and the first hit wins- the two records of one breakend pair name the same translocation twice
One image per row, named 1_chr1_33053494-chr6_2919922_gridss12o.png: index
first so the directory sorts in callset order, coordinates next, the caller's ID
last. A file with no ID column falls back to junction_<n>.
--flank frames the panel, since a breakend is one base. --dryRun prints the
file and loci of every row and renders nothing, and --limit 20 renders the
first few, to check the framing before the whole callset.
For a long run:
--resumeskips a row whose image is already in--outDir--manifestwritesmanifest.tsvbeside the images: one row per junction with its file, both loci, its name, and whether it rendered--passOnlydrops records the caller filtered out.--limittakes the first N in file order, so on an unfiltered callset the two go together
The reads stream from the hosted CRAM, the module graph loads once for the whole
callset, and a --config URL or --hub is fetched once. A row that cannot be
rendered is reported and the run continues.
A connector drawn dashed means the read has a segment at a locus the frame does
not show. These reads also visit chr10, so this junction wants a third panel,
and the control belongs beside it: one render per sample, the same --loc list
and --width.
featureHeight:super-compact draws reads at 1 px apiece, which keeps six
pileups on one screen.
A curve marks two loci as joined; a contig shows the order and orientation. The
multi-hop tutorial builds that contig from these
reads, and rendering it is another jb2export run with a different
--assembly.
The same export over the normal
One directory per track:
jb2export batch --vcf COLO829.somatic-sv.vcf.gz \
--config https://jbrowse.org/demos/cancer_sv/config.json --assembly hg38 \
--track COLO829BL_normal_ont height:240 \
--outDir normal --flank 600 --width 1100
Side by side, the somatic calls are the ones with curves in tumor/ and none in
normal/.
Reading the sheet
What each picture shows:
- a fan of curves at both breakends is the junction as the reads describe it
- nothing connecting the panels means the reads do not support the caller's
coordinates, which is either a false call or a breakpoint placed far enough
off that
--flankmissed it. Re-render that row wider - curves in the normal too means germline, not somatic
- a dense fan in a region of ragged coverage is usually a repeat. The connectors are drawn from what the aligner reported, so a read mismapped into a repeat contributes a confident-looking curve
Opening a call in the browser
Take the coordinates from an image's filename, open the SV inspector on the same VCF, and click through to the breakpoint split view, with the gene track and read details attached.
For a junction that is one hop of something larger, the alignments track menu's Reconstruct derivative allele... groups the reads in view by the route their split alignments describe. COLO829's der(3) is three junctions across three chromosomes, and the multi-hop tutorial follows it the rest of the way.
Other callers
Anything that writes breakends or symbolic SVs to a VCF goes through the same two commands:
- cuteSV, Sniffles, pbsv, Delly, Manta, GRIDSS all write a VCF that
sv_multihop.py bedpereads directly - LINX publishes clusters and chained links as TSVs. Convert the junction
columns to the six BEDPE columns with
awk; one--outDirper cluster gives a chromothripsis event as a contact sheet - PURPLE copy-number segments are not junctions. Convert the segment TSV to
a bedGraph,
bedGraphToBigWigit, and add it as a--bigwigso every image carries the copy number under the reads
Ordering breakends into a derivative chromosome needs allele-specific copy number and a centromere constraint. LINX derives both from PURPLE's purity and ploidy.
Reproduce it end to end
Everything on this page is the commands above against hosted files. The figure
is three jb2export invocations: two breakpoint renders with one --loc per
panel, one per sample, and a plain render of the derivative assembly, which are
the sv_review_tumor, sv_review_normal and sv_review_derivative specs in
website/scripts/specs/jbrowse-img.ts.
See also
- Complex rearrangements and derivative alleles
- Structural variants (Cancer GIAB)
- Low-mappability regions (SMN)
- Static image export (@jbrowse/img)
- SV inspector view
- SV visualization
References
- Valle-Inclán JE, et al. A multi-platform reference for somatic structural variation detection. Cell Genomics (2022). https://doi.org/10.1016/j.xgen.2022.100139
- Shale C, et al. Unscrambling cancer genomes via integrated analysis of structural variation and copy number. Cell Genomics (2022). https://doi.org/10.1016/j.xgen.2022.100112
Feedback on this tutorial is welcome: contact us.