Structural variants (Cancer GIAB)
TL;DR: the Cancer Genome in a Bottle project publishes HG008, a matched tumor/normal PDAC cell line, as PacBio HiFi reads, a draft SV and CNV benchmark, and a telomere-to-telomere assembly of the tumor. Load them as tracks and read each benchmark call against the alignments and the copy number under it. The tumor is hypodiploid, so arm-level loss is the backdrop to every call.
Prerequisites
The walkthroughs at the end need none of this: they run on the finished site, hosted at the C-GIAB demo. Building your own instance needs:
- A machine with HTTP access, either a public URL or
http://localhost - ~1 TB of free disk to build the tracks from the raw reads, or ~1.5 TB for the full pipeline below; the BAMs and CRAMs are most of it
- At least 32 GB of RAM for the minimap2 alignment step. Only data preparation needs it; a 2 GB instance hosts the finished site.
- The command-line tools below, with the versions tested in parentheses:
Where the data comes from
HG008, the C-GIAB matched tumor/normal pair, under NCBI BioProject PRJNA200694 on the C-GIAB FTP, one dated directory per group that ran an analysis on it, with the assemblies in NIST's S3 bucket and the per-clone CNV calls rehosted here.
The reference and the reads:
- the C-GIAB reference build (GRCh38 with decoys and masked regions): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/release/references/GRCh38/GRCh38_GIABv3_no_alt_analysis_set_maskedGRC_decoys_MAP2K3_KMT2C_KCNJ18.fasta.gz
- the tumor/normal PacBio HiFi reads (Revio run, 116x tumor, 35x normal): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/PacBio_Revio_20240125/
The somatic call sets, one per group that published one:
- the V0.5 draft benchmark SV and CNV calls: https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIST_HG008-T_somatic-stvar-CNV_DraftBenchmark_V0.5-20260318/
- Severus somatic SVs (HiFi): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH_HiFi_Severus-SV_20240308/somatic_SVs/severus_somatic.vcf.gz
- the minda ensemble SVs (HiFi, ONT and Illumina callers): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH-NCI_minda-ensemble_20240710/HG008_minda_ensemble.vcf
- DRAGEN's somatic SV and CNV calls (Illumina): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/DRAGEN-v4.2.4_ILMN-WGS_20240312/standard/
- NYGC's somatic SVs, annotated CNV segments and BIC-seq2 log2 ratio (Illumina): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NYGC-somatic-pipeline_20240412/GRCh38-GIABv3/
- Wakhan's haplotype-specific copy number and LOH segments (HiFi phased with Hi-C): https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH_HiFi-HiC_Wakhan-CNA_20240424/bed_output/
- the earlier Wakhan run's Clair3 tumor small-variant calls, which HiFiCNV reads for its own MAF track: https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH_HiFi_Wakhan-CNA_20240308/vcf_inputs/merge_output_tumor.vcf.gz
- the normal's germline calls, which the BAF track piles the tumor reads up against: https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/PacBio_Revio_20240125/pacbio-wgs-wdl_germline_20240206/HG008-N-P.GRCh38.deepvariant.phased.vcf.gz
The assemblies:
- the T2T tumor assembly, v3.2: https://nist-giab.s3.us-east-1.amazonaws.com/giab_tumor-normal/analysis/HG008/NIST_asm_dev/HG008T_v3.2/HG008T_v3.2.fasta.gz
- the matched normal assembly, v6.3: https://nist-giab.s3.us-east-1.amazonaws.com/giab_tumor-normal/analysis/HG008/NIST_asm_dev/HG008N_v6.3/HG008N_v6.3.fasta.gz
The single-cell-derived clone panel:
- short-read WGS, one run per clone: https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/NIST/HG008-T_clones/
- the per-clone CNVkit calls, rehosted merged into one multi-row BED: https://jbrowse.org/demos/cgiab/HG008T-clones.cnv.multirow.bed.gz
The C-GIAB dataset
Cancer Genome in a Bottle (C-GIAB) publishes HG008 as a matched pair from one pancreatic ductal adenocarcinoma (PDAC) donor: the tumor (HG008-T) and normal pancreatic tissue (HG008-N-P).
HG008-T is hypodiploid: its assembly recapitulates 35 tumor chromosomes, down from 46, with widespread arm-level loss and 16 truncal interchromosomal rearrangements (Wagner et al. 2026). Arm-level loss is the backdrop for every copy-number figure below, so the benchmark CNV BED, which reports absolute copy number per interval, is what every other track gets read against.
The SV visualization guide and the SV inspector guide cover the concepts; this page is the data-loading workflow and a few worked examples. For the rest of the call sets, the auxiliary assays and the methods, see the NIST C-GIAB page and McDaniel et al. 2025.
Setting up
The instance itself is the web quickstart unchanged. Two of the prerequisites install from release binaries:
wget https://github.com/ChristopherWilks/megadepth/releases/download/1.2.0/megadepth
chmod +x megadepth && sudo mv megadepth /usr/local/bin/
curl -L https://github.com/PacificBiosciences/HiFiCNV/releases/download/v1.0.1/hificnv-v1.0.1-x86_64-unknown-linux-gnu.tar.gz \
| tar xz --strip-components=1 -C /usr/local/bin --wildcards '*/hificnv'
Load the C-GIAB build of GRCh38 as the assembly: it carries decoys and several masked regions, and it is also the reference the CRAM conversion below writes against.
Reproduce it end to end fetches that reference and every file below in one script; the sections below give the track config for each file.
The benchmark SV and CNV calls
The V0.5 HG008-T draft benchmark is two files: the SV calls as an indexed VCF, the CNV calls as a BED. Both load straight from their FTP URL with nothing downloaded. The walkthroughs below open individual calls out of the SV track, so it goes in first.
{
"type": "VariantTrack",
"trackId": "hg008t_benchmark_sv",
"name": "HG008-T V0.5 draft benchmark somatic SVs",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "VcfTabixAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIST_HG008-T_somatic-stvar-CNV_DraftBenchmark_V0.5-20260318/GRCh38_HG008-T-V0.5_somatic-stvar_PASS.draftbenchmark.vcf.gz"
}
}
jbrowse add-track https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIST_HG008-T_somatic-stvar-CNV_DraftBenchmark_V0.5-20260318/GRCh38_HG008-T-V0.5_somatic-stvar_PASS.draftbenchmark.vcf.gz \
--trackId hg008t_benchmark_sv \
--name "HG008-T V0.5 draft benchmark somatic SVs" \
--assemblyNames GRCh38_GIABv3
The CNV BED ships without a header, so its columns beyond chrom/start/end load
unnamed. Name them on the adapter with the
columnNames slot:
{
"type": "FeatureTrack",
"trackId": "hg008t_somatic_cnv",
"name": "HG008-T somatic CNV",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIST_HG008-T_somatic-stvar-CNV_DraftBenchmark_V0.5-20260318/GRCh38_HG008-T-V0.5_somatic-CNV_PASS.draftbenchmark.calls.bed",
"columnNames": [
"chrom",
"start",
"end",
"total_copy_number",
"hap1_copy_number",
"hap2_copy_number",
"name"
]
}
}
jbrowse add-track-json '{
"type": "FeatureTrack",
"trackId": "hg008t_somatic_cnv",
"name": "HG008-T somatic CNV",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIST_HG008-T_somatic-stvar-CNV_DraftBenchmark_V0.5-20260318/GRCh38_HG008-T-V0.5_somatic-CNV_PASS.draftbenchmark.calls.bed",
"columnNames": [
"chrom",
"start",
"end",
"total_copy_number",
"hap1_copy_number",
"hap2_copy_number",
"name"
]
}
}'
The reads and their coverage
The tumor and normal BAMs at the C-GIAB FTP are large, slow to read remotely,
and carry no MD tags, which JBrowse uses to display mismatches without
re-fetching the reference. Pull each one through samtools view into a local
CRAM against the reference above, and write a whole-genome coverage bigWig
beside it:
# -T names the reference the CRAM is written against, and it has to be the same
# build the assembly was loaded from or every base reads as a mismatch
# --write-index saves a second samtools pass for the .crai
samtools view HG008-T.bam --write-index -o HG008-T.cram -T GRCh38.fa
# one whole-genome coverage bigWig per sample, written beside its CRAM
megadepth HG008-T.cram --bigwig
Structural variants from the published callsets
The benchmark is one of five somatic SV callsets on this pair, and C-GIAB publishes the rest as one URL each, loaded the way the benchmark was:
| Callset | Called from |
|---|---|
| NIST V0.5 draft benchmark | assembly comparison plus read support |
| Severus | PacBio HiFi |
| minda ensemble | eleven caller runs over HiFi, ONT and Illumina |
| DRAGEN | Illumina WGS |
| NYGC somatic pipeline (Manta and GRIDSS) | Illumina WGS |
The benchmark files the two chr3 breakends in that window under one EVENT,
cluster_3, while its CNV BED covers the whole window with a single segment
named noCNV. The CNV callset works at a coarser scale, so an event this size
is the SV lanes' to carry.
The second of those breakends is written two ways. The benchmark and minda place
a breakend there; Severus and DRAGEN write a symbolic inversion whose SVLEN
runs far down the arm, so those two lanes draw a span leaving the window where
the others draw a mark.
Severus and DRAGEN
Both are indexed VCFs with a record at each breakend, so they load with no display settings:
{
"type": "VariantTrack",
"trackId": "hg008t_severus_sv",
"name": "HG008-T Severus somatic SVs (HiFi)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "VcfTabixAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH_HiFi_Severus-SV_20240308/somatic_SVs/severus_somatic.vcf.gz"
}
}
jbrowse add-track https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH_HiFi_Severus-SV_20240308/somatic_SVs/severus_somatic.vcf.gz \
--trackId hg008t_severus_sv \
--name "HG008-T Severus somatic SVs (HiFi)" \
--assemblyNames GRCh38_GIABv3
{
"type": "VariantTrack",
"trackId": "hg008t_dragen_sv",
"name": "HG008-T DRAGEN somatic SVs (Illumina)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "VcfTabixAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/DRAGEN-v4.2.4_ILMN-WGS_20240312/standard/dragen_4.2.4_HG008-mosaic_tumor.sv.vcf.gz"
}
}
jbrowse add-track https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/DRAGEN-v4.2.4_ILMN-WGS_20240312/standard/dragen_4.2.4_HG008-mosaic_tumor.sv.vcf.gz \
--trackId hg008t_dragen_sv \
--name "HG008-T DRAGEN somatic SVs (Illumina)" \
--assemblyNames GRCh38_GIABv3
DRAGEN's record over the chr3-chr13 junction places the breakend where the
others do and carries MaxDepth in its own FILTER column, the depth cap a
caller applies where a pileup runs far above the genome average. Clicking the
record shows it.
minda: the caller runs behind each junction
The ensemble callset is a plain VCF, so VcfAdapter
loads it whole, with no index:
{
"type": "VariantTrack",
"trackId": "hg008t_minda_sv",
"name": "HG008-T minda ensemble SVs (HiFi, ONT, Illumina)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "VcfAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH-NCI_minda-ensemble_20240710/HG008_minda_ensemble.vcf"
}
}
jbrowse add-track-json '{
"type": "VariantTrack",
"trackId": "hg008t_minda_sv",
"name": "HG008-T minda ensemble SVs (HiFi, ONT, Illumina)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "VcfAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH-NCI_minda-ensemble_20240710/HG008_minda_ensemble.vcf"
}
}'
Clicking a junction shows its SUPP_VEC, which names every caller run that
supported it, each prefixed by the technology it ran on: PB_severus_BND1941_1,
ONT_Sniffles2.INV.30AM2, ILL_gridss63ff_2860h.
NYGC: a BEDPE drawn as arcs
BedpeAdapter reads a paired-end BED whole, with
no index, and serves it to a variant track. The # header names the columns, so
each record arrives with the pipeline's call, the strands, the CNV changepoints
it was linked to, and an evidence column holding each tool's split-read and
paired-end counts:
{
"type": "VariantTrack",
"trackId": "hg008t_nygc_sv",
"name": "HG008-T NYGC somatic SVs (Manta, GRIDSS)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedpeAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NYGC-somatic-pipeline_20240412/GRCh38-GIABv3/HG008-T--HG008-N.sv.annotated.v7.somatic.high_confidence.final.bedpe"
}
}
jbrowse add-track-json '{
"type": "VariantTrack",
"trackId": "hg008t_nygc_sv",
"name": "HG008-T NYGC somatic SVs (Manta, GRIDSS)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedpeAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NYGC-somatic-pipeline_20240412/GRCh38-GIABv3/HG008-T--HG008-N.sv.annotated.v7.somatic.high_confidence.final.bedpe"
}
}'
Each record holds both ends, so the whole callset reads as arcs at chromosome scale: Display types → Variant display arcs on the track menu draws one arc per record between its two breakends.
Copy number from the published callsets
Four groups have called copy number on this pair, and C-GIAB publishes each one's output. Every file is small and loads from its FTP URL, so they can share one view:
| Callset | Called from | Each segment carries |
|---|---|---|
| NIST V0.5 draft benchmark | assembly comparison plus read support | absolute total and per-haplotype copy number |
| Wakhan | PacBio HiFi, phased with Hi-C | copy number per parental haplotype, with LOH intervals in a second file |
| NYGC somatic pipeline, BIC-seq2 | Illumina WGS | log2 tumor-versus-normal copy ratio, and the genes the segment covers |
| DRAGEN | Illumina WGS | integer copy number, minor-haplotype copy number and minor allele frequency |
The benchmark CNV BED added above is the lane the others get read against, since its copy numbers are absolute: it states a diploid region explicitly as CN 2, and it leaves out segments whose breakpoints the project could not place on GRCh38, so a gap in that lane is a gap in the benchmark. Depth per bin is the one signal no group publishes; the end of this section computes it from the tumor reads.
DRAGEN: integer copy number from short reads
Each record in DRAGEN's somatic CNV VCF is one segment, and its ID names the
class the caller assigned: LOSS, GAIN, CNLOH for copy-neutral loss of
heterozygosity, and REF for a segment left at the reference state.
{
"type": "VariantTrack",
"trackId": "hg008t_dragen_cnv",
"name": "HG008-T DRAGEN somatic CNV (Illumina)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "VcfTabixAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/DRAGEN-v4.2.4_ILMN-WGS_20240312/standard/dragen_4.2.4_HG008-mosaic_tumor.cnv.vcf.gz"
}
}
jbrowse add-track https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/DRAGEN-v4.2.4_ILMN-WGS_20240312/standard/dragen_4.2.4_HG008-mosaic_tumor.cnv.vcf.gz \
--trackId hg008t_dragen_cnv \
--name "HG008-T DRAGEN somatic CNV (Illumina)" \
--assemblyNames GRCh38_GIABv3
The VCF header carries DRAGEN's purity and ploidy estimate for the sample, and its ploidy lands below two: the hypodiploidy the assembly reports, arrived at from short reads by another caller.
NYGC: a copy ratio, and the genes each segment covers
The New York Genome Center's somatic pipeline ran on the same pair, and C-GIAB
publishes its CNV output two ways. HG008-T--HG008-N.cnv.annotated.v7.final.bed
needs nothing done to it: its # header line is tab-separated, so the adapter
takes the column names from the file.
{
"type": "FeatureTrack",
"trackId": "hg008t_nygc_cnv",
"name": "HG008-T NYGC CNV calls, annotated (BIC-seq2)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NYGC-somatic-pipeline_20240412/GRCh38-GIABv3/HG008-T--HG008-N.cnv.annotated.v7.final.bed"
},
"displayDefaults": {
"color": "jexl:feature.type=='DEL'?'#2166ac':'#b2182b'",
"labels": { "name": "jexl:feature.type+' '+feature.cytoband" },
"displayMode": "compact",
"legend": [
{ "label": "Loss (DEL)", "color": "#2166ac" },
{ "label": "Gain (DUP)", "color": "#b2182b" }
]
}
}
jbrowse add-track-json '{
"type": "FeatureTrack",
"trackId": "hg008t_nygc_cnv",
"name": "HG008-T NYGC CNV calls, annotated (BIC-seq2)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NYGC-somatic-pipeline_20240412/GRCh38-GIABv3/HG008-T--HG008-N.cnv.annotated.v7.final.bed"
},
"displayDefaults": {
"color": "jexl:feature.type=='\''DEL'\''?'\''#2166ac'\'':'\''#b2182b'\''",
"labels": { "name": "jexl:feature.type+'\'' '\''+feature.cytoband" },
"displayMode": "compact",
"legend": [
{ "label": "Loss (DEL)", "color": "#2166ac" },
{ "label": "Gain (DUP)", "color": "#b2182b" }
]
}
}'
Clicking a segment then shows its call, its log2 ratio, its cytoband, the focal flag, and each Cancer Gene Census gene at its tier.
HG008-T--HG008-N.bicseq2.txt is the same segmentation in quantitative form,
one log2 ratio per segment, and one awk away from a bedGraph:
# column 9 is log2.copyRatio, and the file is 1-based where bedGraph is not
awk 'NR>1 {printf "%s\t%d\t%d\t%.4f\n", $1, $2-1, $3, $9}' \
HG008-T--HG008-N.bicseq2.txt > HG008-T_bicseq2_log2ratio.bedgraph
Plot it as a Line (step) over a fixed range, since a homozygous deletion carries no reads and so no finite ratio. The balanced baseline sits above zero because BIC-seq2 normalizes on total read counts and this genome is hypodiploid; read its steps against the benchmark's absolute copy numbers.
Wakhan: copy number per parental haplotype
A log2 ratio and a folded allele frequency both average the two parental alleles
together, so at whole-genome zoom an LOH block reads as balanced.
Wakhan phases the germline
heterozygous SNPs and reports copy number per haplotype, which keeps the LOH
signal at every zoom. C-GIAB publishes two Wakhan runs on this tumor, and the
later one phases the normal with Arima Hi-C alongside the HiFi reads:
HG008_HiFi_HiC_copynumbers_segments.bed and HG008_HiFi_HiC_loh_segments.bed,
both of them URL tracks.
The copy-number file is worth a few more lines of config than add-track
writes. It is long format, one row per haplotype, and its column-name line
carries no #:
chr start end copynumber_state coverage haplotype
chr1 0 23750000 2 106.025 1
chr1 23750001 119650000 0.72 58.025 1
so name the columns on the adapter with
columnNames. The header line
itself loads as a feature on a refName no assembly has, so nothing draws it.
Because a haplotype column already assigns each segment to a row, this is a
LinearMultiRowFeatureDisplay
track: set
partitionField
to haplotype and it paints one row per parental copy.
{
"type": "FeatureTrack",
"trackId": "hg008_wakhan_haplotype",
"name": "HG008-T Wakhan copy number per haplotype",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedAdapter",
"uri": "https://ftp-trace.ncbi.nlm.nih.gov/ReferenceSamples/giab/data_somatic/HG008/Liss_lab/analysis/NIH_HiFi-HiC_Wakhan-CNA_20240424/bed_output/HG008_HiFi_HiC_copynumbers_segments.bed",
"columnNames": [
"chrom",
"start",
"end",
"copynumber_state",
"coverage",
"haplotype"
]
},
"displays": [
{
"type": "LinearMultiRowFeatureDisplay",
"displayId": "hg008_wakhan_haplotype-LinearMultiRowFeatureDisplay",
"partitionField": "haplotype",
"color": "jexl:get(feature,'copynumber_state')<0.5?'#2166ac':get(feature,'copynumber_state')<1.5?'#bdbdbd':'#f4a582'",
"legend": [
{ "label": "Haplotype lost (0)", "color": "#2166ac" },
{ "label": "One copy", "color": "#bdbdbd" },
{ "label": "Two or more copies", "color": "#f4a582" }
]
}
]
}
copynumber_state counts one parental copy, so 1 is the expected state and a
0 row is the lost haplotype that makes an arm LOH. Wakhan emits fractional
states for segments that are not clonal, which is why the color buckets ranges.
coverage is Wakhan's median depth for the segment, so the per-copy depth scale
can be read straight off it.
Depth per bin, and B-allele frequency
The coverage bigWigs above are raw depth. Two more tracks, both built from the tumor reads, are what make copy number readable beside the callsets: binned depth, and B-allele frequency. HiFiCNV, PacBio's somatic CNV caller, writes the first:
# --maf holds the TUMOR's small-variant calls, the Clair3 tumor VCF published
# alongside C-GIAB's Wakhan run: HiFiCNV reads AD out of this VCF for its own
# allele-frequency output and never looks at --bam for it
hificnv --bam HG008-T.cram --ref GRCh38.fa --maf tumor_smallvariants.vcf.gz \
--output-prefix hificnv
HiFiCNV names each output for the sample it came from, so the depth bigWig
carries the --bam sample's name. Give it the Scatter plot type: depth is a
read count per bin, so a whole-chromosome view is a cloud hundreds of points
deep and a copy-number step is wherever its centre moves. The NYGC copy ratio
above is that same signal already segmented.
The allelic panel is B-allele frequency, unfolded. HiFiCNV's own maf.bw
folds to min(AF, 1-AF), so a region that has lost one parental copy collapses
onto a single band near 0. Unfolded BAF keeps the two apart: a balanced region
is one band at 0.5, a loss-of-heterozygosity region two bands at 0 and 1. Build
it by piling up the tumor reads at the sites the normal calls heterozygous
and taking the alt fraction:
# het sites from the NORMAL, which is the choice the whole track rests on: an LOH
# site is homozygous in the tumor, so a tumor-derived list drops exactly the
# sites the track exists to show
bcftools view -g het -Oz -o hets.vcf.gz normal.deepvariant.vcf.gz
tabix -p vcf hets.vcf.gz
cut -f1,2 GRCh38.fa.fai > GRCh38.chrom.sizes
# -q 1 drops multi-mapped reads, -Q 0 leaves HiFi base qualities alone
bcftools mpileup -f GRCh38.fa -T hets.vcf.gz -a AD -q 1 -Q 0 tumor.bam |
bcftools query -f '%CHROM\t%POS\t[%AD]\n' |
# unfolded alt fraction, so LOH separates into 0 and 1 instead of folding
# onto one band; the 10x floor keeps thin coverage from painting a fake 0/1
awk -F'[\t,]' '{d=$3+$4; if (d>=10) printf "%s\t%d\t%d\t%.4f\n",$1,$2-1,$2,$4/d}' |
LC_COLLATE=C sort -k1,1 -k2,2n > baf.bedgraph
bedGraphToBigWig baf.bedgraph GRCh38.chrom.sizes tumor_baf.bw
Plot it with Scatter over a fixed 0 to 1 range: the spread is the entire signal.
Keep the BAF track off bigWig summaries
A bigWig carries precomputed zoom levels, and each zoomed bin holds a minimum,
an average and a maximum. BAF is a distribution, so every bin over an LOH arm
comes back as minimum 0, maximum 1 and an average that wanders. The default
summaryScoreMode of
whiskers draws all three, which paints the arm as a solid full-height wash.
The fix goes on the adapter, with
resolutionMultiplier.
It scales the bases-per-bin the adapter asks for, and a small enough value keeps
the fetch on the raw per-site values at the zoom levels these figures use:
{
"type": "QuantitativeTrack",
"trackId": "HG008-T_baf",
"name": "HG008-T B-allele frequency (BAF)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BigWigAdapter",
"uri": "HG008-T_baf.bcftools.bw",
"resolutionMultiplier": 0.001
},
"displayDefaults": {
"defaultRendering": "scatter",
"scatterPointSize": 1,
"minScore": 0,
"maxScore": 1
}
}
Raw het sites are cheap here, because the track carries one value per germline heterozygous site rather than one per base. Whole-genome view still falls back to the summary, which is what Wakhan's segments above are for.
Resolution → Finer in the track menu is the same control interactively. Reach for it whenever a scatter track paints as a filled band.
Subclonal copy number
Every callset above averages over the cells it was sequenced from, so a change only part of the tumor carries reads as a muted, intermediate signal. HG008-T is such a mixture: karyotyping across passages finds the arm-level losses in nearly every cell, and finds the genome-doubled fraction of the culture growing between early and late passage (Wagner et al. 2026). The benchmark CNV BED reports copy number for the cells that have not doubled.
C-GIAB publishes short-read WGS for a panel of HG008-T single-cell-derived
clones under
HG008-T_clones/.
Each clone is a colony grown from one tumor cell, so each reports one subclone's
copy number. Called per clone and merged into one BED with a clone column,
they partition into rows the way the Wakhan haplotypes do, and a row that
departs from the rest is a CNV private to that subclone:
{
"type": "FeatureTrack",
"trackId": "hg008_subclonal_cnv",
"name": "HG008-T subclonal CNV (per-clone CNVkit)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedTabixAdapter",
"uri": "https://jbrowse.org/demos/cgiab/HG008T-clones.cnv.multirow.bed.gz"
},
"displays": [
{
"type": "LinearMultiRowFeatureDisplay",
"displayId": "hg008_subclonal_cnv-LinearMultiRowFeatureDisplay",
"partitionField": "clone",
"color": "jexl:get(feature,'cn')<1?'#2166ac':get(feature,'cn')<2?'#92c5de':get(feature,'cn')<3?'#e0e0e0':get(feature,'cn')<4?'#f4a582':'#b2182b'",
"legend": [
{ "label": "CN 0", "color": "#2166ac" },
{ "label": "CN 1", "color": "#92c5de" },
{ "label": "CN 2", "color": "#e0e0e0" },
{ "label": "CN 3", "color": "#f4a582" },
{ "label": "CN 4+", "color": "#b2182b" }
]
}
]
}
jbrowse add-track-json '{
"type": "FeatureTrack",
"trackId": "hg008_subclonal_cnv",
"name": "HG008-T subclonal CNV (per-clone CNVkit)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BedTabixAdapter",
"uri": "https://jbrowse.org/demos/cgiab/HG008T-clones.cnv.multirow.bed.gz"
},
"displays": [
{
"type": "LinearMultiRowFeatureDisplay",
"displayId": "hg008_subclonal_cnv-LinearMultiRowFeatureDisplay",
"partitionField": "clone",
"color": "jexl:get(feature,'\''cn'\'')<1?'\''#2166ac'\'':get(feature,'\''cn'\'')<2?'\''#92c5de'\'':get(feature,'\''cn'\'')<3?'\''#e0e0e0'\'':get(feature,'\''cn'\'')<4?'\''#f4a582'\'':'\''#b2182b'\''",
"legend": [
{ "label": "CN 0", "color": "#2166ac" },
{ "label": "CN 1", "color": "#92c5de" },
{ "label": "CN 2", "color": "#e0e0e0" },
{ "label": "CN 3", "color": "#f4a582" },
{ "label": "CN 4+", "color": "#b2182b" }
]
}
]
}'
Read those integers on the caller's own scale: CNVkit centers each sample's log2
on that sample's own median, so on a hypodiploid genome the balanced state is
not the row's CN 2. The benchmark CNV track in the same view is what anchors
them, its total_copy_number being absolute.
The p-arm of chr3 reads clearly for that reason: the benchmark calls one state across the whole arm, and the bulk depth holds one level under it.
Align the tumor assembly to GRCh38
The tumor assembly is haplotype-resolved into T2T scaffolds. Load it as a second JBrowse assembly and align it to GRCh38; the PAF that comes out is what the synteny and dotplot views draw:
# asm5 is the same-species preset; -c emits the base-level CIGAR the synteny
# view needs to draw a junction at base scale
minimap2 -cx asm5 GRCh38.fa HG008T_v3.2.fasta > HG008T_v3.2.paf
# -a is query,target, the REVERSE of the target query minimap2 just took: get it
# backwards and the view opens empty rather than erroring
jbrowse add-track HG008T_v3.2.paf -a HG008T_v3.2,GRCh38_GIABv3
The matched normal assembly (HG008N_v6.3.fasta.gz, same S3 path) loads the
same way. See the
synteny track config guide and the
linear synteny view guide.
Walkthroughs
The loaded data reads three complementary ways: the SV inspector for whole-genome triage, the linear genome view for read-level detail and copy number, and the dotplot and synteny views for chromosome-scale rearrangements in the assembly. Each walkthrough below runs on an instance built from the sections above, or on the hosted C-GIAB demo, which carries the benchmark calls, the reads and the copy-number tracks already loaded.
A chr3-chr13 translocation
Add → SV inspector, then Open from track to pick the C-GIAB benchmark VCF loaded earlier.
Click the chord joining chr3 and chr13, then open the tumor PacBio HiFi reads on each panel of the breakpoint split view it launches and set Read height → Compact.
That junction is one breakend of a larger event, and interchromosomal translocations in HG008 are frequently complex this way (Wagner et al. 2026). The next walkthrough reads this one three ways.
For the SV inspector workflow itself (filtering the table, search, configuring the circular overview), see the SV inspector guide.
The same junction three ways
The chord says where to look. Three things in this instance say what is there, and none of them is derived from the others.
The caller. SV_20 and SV_190 are one junction written twice, joining
chr3:139,976,414 to chr13:114,353,244. A BND record names one partner, so each
describes a translocation. The EVENT field groups them: the benchmark files
both under cluster_3 alongside two further breakends and tags them
EVENTTYPE=CHROMOPLEXY. A caller can group junctions into an event because it
sees the whole callset at once. It cannot say which molecule carries them.
The reads. Put both breakpoint loci on screen and, from the tumor PacBio HiFi track's menu, choose Launch → Reconstruct derivative allele.... The reads in the window are grouped by the route their split alignments describe, each offered with the number of reads that independently take it. The top route runs chr13 forward into the junction and then down chr3 inverted, the orientation the black splines above draw. The matched normal is the control and a track away: the tumor reads split at this position, the normal reads read through it.
The assembly. The synteny track loaded earlier says the same thing from no reads at all. The C-GIAB assembly resolves both loci onto a single tumor contig, and named that contig for the two chromosomes it fuses. Its chr13 arm ends at the chr13 breakend above and its chr3 arm begins at the chr3 one, abutting at a single base of contig coordinate, with the same orientation flip the reads describe. Open it in the synteny or dotplot view against GRCh38 and the junction is the point where one contig stops following chr13 and starts following chr3.
Back in the reconstruction, reading the list below the top route is the other half of the exercise. This window ends at the chr13 q-terminus, so most of what is offered under the real junction is reads mismapped into the terminal repeats of other chromosomes, each a confident-looking two-segment route with a real read count behind it. The read count ranks the routes. What picks this one out is that the caller and the assembly put its two ends in the same two places.
The reconstruction is bounded twice by what is loaded. It is assembled from the
reads in the displayed regions, which is why both sides of this junction are
open above. And the hosted demo slices the tumor reads to the loci these
walkthroughs visit, so the reads reach one of cluster_3's junctions where the
assembly contig carries both. Rebuilding from the full BAM with
the build script lifts that limit.
Which calls are drivers
Most somatic calls in a tumor genome are passengers: real events, carried along by the cell lineage, with no role in the cancer. A handful are drivers. In pancreatic ductal adenocarcinoma the recurrently altered genes are KRAS, CDKN2A, TP53 and SMAD4 (Waddell et al. 2015, Bailey et al. 2016), and the copy-number walkthroughs below visit all four in this genome. The deletion that comes first is a passenger, and reads exactly the same way.
The benchmark BED states copy number and haplotype; consequence comes from a driver catalogue, and the somatic ones (COSMIC's Cancer Gene Census among them) are licensed, so a public demo cannot carry one as a lane. The NYGC segments loaded above carry theirs inline, each one listing the census genes inside it. Every copy-number figure below also draws one MANE Select transcript under the lanes, so the event and the gene it covers are read off the same axis.
A small deletion in CUZD1
For small to medium SVs the linear genome view is usually enough. Use the
search (magnifying glass) button in the SV inspector to find a specific
call, for example SV_85, a heterozygous deletion that affects two exons of
CUZD1.
CUZD1 is a passenger here, a pancreatic acinar protein predicted to act in trypsinogen activation (NCBI Gene 50624). The call takes one of its two copies, and at ~1.8 kb over two exons it reads base by base in a pileup.
Whether anyone has submitted a CNV here is a lane of its own: ClinVar CNVs carries the submitted copy-number variants and their clinical significance. Add it from UCSC:
{
"type": "FeatureTrack",
"trackId": "hg38_clinvar_cnv_ucsc",
"name": "ClinVar CNVs (UCSC)",
"assemblyNames": ["GRCh38_GIABv3"],
"adapter": {
"type": "BigBedAdapter",
"uri": "https://hgdownload.soe.ucsc.edu/gbdb/hg38/bbi/clinvar/clinvarCnv.bb"
},
"displayDefaults": {
"jexlFilters": ["get(feature,'_varLen') < 50000"],
"displayMode": "compact"
}
}
jbrowse add-track https://hgdownload.soe.ucsc.edu/gbdb/hg38/bbi/clinvar/clinvarCnv.bb \
--trackId hg38_clinvar_cnv_ucsc \
--name "ClinVar CNVs (UCSC)" \
--assemblyNames GRCh38_GIABv3 \
--displayDefaults "{\"jexlFilters\":[\"get(feature,'_varLen') < 50000\"],\"displayMode\":\"compact\"}"
ClinVar holds chromosome-scale records alongside focal ones, so the size filter
keeps the lane at this event's scale; _varLen is the catalogue's own length
field. The lane comes back empty over this locus, no submitted CNV near this
deletion's size covering it.
Open the gene annotations and the tumor PacBio HiFi reads, set Read height → Compact and Sort by... → Base pair from the track menu, and center the deletion. Turning on the view menu's center line helps line the breakpoint up.
A tandem-repeat call, sized against the normal
Some benchmark records are sized against the donor's own germline allele:
EVENTTYPE=CNV:TR, a somatic size change inside a tandem repeat, taken from the
tumor assembly aligned to the normal assembly. Their SVLEN is a number GRCh38
does not carry.
SV_223 on chr5 is the benchmark's own worked example of one. Open it with both
samples' PacBio HiFi reads and sort each pileup at the call:
SVLEN here is the span between the two samples' alleles rather than either
one's distance from the reference. The record states itself in the normal
assembly's coordinates as well, in CHROM_HG8N6.3, POS_HG8N6.3, REF_HG8N6.3
and ALT_HG8N6.3, so clicking it shows the same variant on the yardstick it was
called against.
Two more fields under it are worth the click. SVVIZ_VAF_ALL is the variant
allele fraction svviz2 measured across the HG008-T datasets, and
SVVIZBYDATASET breaks it into the sequencing runs behind it, which are worth
reading against each other at a repeat. The field's own description in the VCF
header says the estimate is biased there, and the pileup shows one reason why:
reads crossing a repeat spread the same allele over several alignments of it.
Reading copy number
The quickest copy-number check is the tumor and normal coverage bigWigs as one multi-bigwig track, which is fast at any zoom:
- Show all regions in assembly on the linear genome view start screen opens every chromosome at once.
- Score → Set min/max score... in the track menu pins the axis, holding the scale off the centromere and repeat spikes.
- Plot type → Overlapping → Scatter draws the two samples as points in one band, tumor red and normal blue.
The two rows in the figures here come from
goleft indexcov, which
divides each sample by its own median. That normalization is what lets the rows
share an axis at all: the tumor and the normal were sequenced to different
depths, so raw coverage separates them before any copy number does, where
normalized rows put the normal flat at 1 and read every level the tumor holds as
a ratio against it. The pipeline above does not build those two files. They are
published beside the demo, as HG008-N_indexcov.bw and HG008-T_indexcov.bw
under https://jbrowse.org/demos/cgiab/, and load as a multi-wiggle track by URL.
Zoom to a region and open the benchmark CNV BED to check the coverage changes against the called intervals. Coverage says a level changed; the BAF track in the same window says what changed.
Four loci in HG008-T sit in four different copy-number states, and the depth, BAF and copy-number lanes built above tell them apart:
| Locus | State in HG008-T | Signature on the tracks |
|---|---|---|
| CDKN2A | Focal homozygous deletion (CN 0) | depth to 0, copy number 0 |
| TP53 | 17p loss + LOH (CN 1, 1+0) | depth halved, BAF splits to 0 and 1 |
| SMAD4 | 18q loss + LOH (CN 1, 0+1) | depth halved, BAF splits to 0 and 1 |
| KRAS | Tandem duplication (CN 3, 2+1) | depth raised, BAF to 1/3 and 2/3 |
All four carry clonal somatic variants in HG008 (Wagner et al. 2026).
Arm-level loss is widespread in this hypodiploid genome, so a single band at 0.5 is the exception. Where a whole chromosome is LOH end to end, as chr17 is below, the balanced band has to come from another chromosome.
CDKN2A: a homozygous deletion inside a single-copy loss
Navigate to CDKN2A on chr9, where the benchmark calls a focal ~20 kb
homozygous deletion over the gene (SV_75, total copy number 0). Both parental
copies are gone, so depth goes to ~0 under it. The deletion sits inside a larger
single-copy-loss arm (CNA_14, 0+1) where depth is already halved, so the focal
event removes the one copy the arm-level loss had left
(Wagner et al. 2026).
Load the tumor and matched normal per-base coverage as one multi-quantitative track, one row per sample, and set an explicit score range from the track menu so both rows are drawn on the same scale. HiFiCNV's depth is binned where these two are per base, and the PacBio HiFi read pileup below them is where the exact breakpoints are: the thin lines crossing the gap in that pileup are single reads carrying the deletion as one gap in their alignment.
The benchmark's total_copy_number is absolute, so CN 2 is a diploid segment.
The whole of 9p has lost a copy in this tumor, so CN 1 is the local background
here and the deletion is punched into it. Widen the view several hundred
kilobases to the right to reach the first CN 2 segment and read the CN 1 lane
against it.
chr17: loss with LOH, and copy-neutral LOH
Chromosome 17 carries a different LOH state on each arm. Open the whole chromosome with the depth track above the BAF:
- the p-arm (covering TP53) is a single-copy loss with LOH (
CNA_20, CN 1, 1+0): depth is halved and the BAF splits away from 0.5. - the q-arm is copy-neutral LOH (
CNA_21, CN 2, 2+0): one parental haplotype was lost and the other duplicated, so total copy number is still 2 and depth stays flat, yet the BAF still splits away from 0.5.
The copy-ratio lane in the figure fills from a pivot at zero, and on this hypodiploid genome the balanced level sits above zero, so the q-arm's copy-neutral state fills upward in the gain color. Read that lane for where its steps fall, not for which way they point.
The depth and BAF combinations read as a compact decision table:
| depth | BAF | Interpretation |
|---|---|---|
| flat (CN 2) | one band at 0.5 | balanced diploid |
| flat (CN 2) | split to 0, 1 | copy-neutral LOH |
| halved | split to 0, 1 | single-copy loss with LOH |
| raised | 1/3 and 2/3 | allelic gain |
The benchmark BED's per-haplotype columns (hap1_copy_number,
hap2_copy_number) encode this allelic state: any segment with a 0 haplotype
(e.g. 1+0, 2+0) has lost one parental allele and its BAF splits away from
0.5, regardless of its total copy number. Clicking a CNV feature shows both.
KRAS and SMAD4
The same reading covers the other two loci. KRAS on chr12 sits in a gain
(SV_101, CN 3, 2+1): the assembly resolves it as a 2 Mb tandem duplication
carrying the G12V-mutated copy, an event associated with advanced disease
(Wagner et al. 2026). The event is
a couple of megabases, so zoom to it: at whole-chromosome scale it is a handful
of pixels wide.
SMAD4 on 18q is lost with LOH (CNA_48, CN 1, 0+1), the mirror image of the
TP53 event. Two controls are in the same picture: the balanced p-arm, and the
matched normal on the same axis as the tumor.
Leave the display's bicolor mode on and give it a symmetric axis, so the lane fills from its zero pivot with a step down drawn the same size as a step up.
Synteny and dotplot views of the tumor assembly
Side by side with the reference, the tumor assembly draws a complex SV as a break in a diagonal. Add → Dotplot view, set the de novo assembly as one axis and GRCh38 as the other, and pick the matching synteny track.
HG008-T v3.2 is haplotype-resolved, so its scaffold names end in _hap1 or
_hap2 and one plot stacks both on the same axis, doubling every diagonal.
Restrict the y axis to one haplotype at a time and each plot reads as a plain
assembly-vs-reference diagonal.
Drag over a region and take Launch → Linear synteny view from the selection,
keeping HG008T v3.2 as the dialog's synteny dataset, then enter chr3 chr13
in the GRCh38 search box to focus on those chromosomes. Raising the minimum
alignment length (in the synteny view's menu) drops short, noisy anchors so
the large syntenic blocks read clearly, and zooming in on a breakpoint reads it
at base level.
The chr3/chr13 fusion is one of this genome's truncal interchromosomal rearrangements, many of which break in or near a centromere (Wagner et al. 2026). A scaffold named for two GRCh38 chromosomes is the cue, so the names on the dotplot's y axis are a worklist.
For more on these views, see the dotplot view guide and the linear synteny view guide.
Methylation on the tumor reads
The C-GIAB PacBio HiFi BAMs carry per-read 5mC calls in their MM/ML tags,
and JBrowse renders those with no extra files: open the tumor reads and set
Color by... → Modifications from the track menu. The tags survive the
conversion to CRAM above, so the reads loaded for the SV walkthroughs already
carry them.
Two modes sit under that item:
- One color per modification type marks the cytosines the basecaller called modified and leaves the rest blank, so an unmethylated stretch and a stretch with no CpGs in it look alike.
- One color per type, plus low-probability & unmodified in blue paints every CpG in context, which is what the figure below is set to.
Where the marks thin out to scattered ticks, that is CpG density: the fill draws a cytosine only where the reference puts one in context.
Most somatic LINE insertions in HG008 come from two hypomethylated non-reference germline LINE insertions, so the methylation state of a source element explains the insertion burden downstream of it (Wagner et al. 2026). See Modifications and methylation for the display modes, and the methylation tutorial for the aggregate and allele-specific views.
Where to go next
Swap the VCF, the CRAMs, the caller output and the assembly for your own, and the same tracks and walkthroughs apply. The SV visualization guide covers the display options the walkthroughs reach for: the color schemes (pair orientation, insert size), the read filters (discordant pairs, soft-clipped), and the display modes (pileup, read arcs, linked reads).
Within C-GIAB itself there is more on the same FTP than this tutorial loads:
- a somatic small-variant draft benchmark, published alongside the SV/CNV one used here, which loads as a variant track the same way
- the matched normal assembly (
HG008N), which loads as a second JBrowse assembly and serves as the synteny target. Comparing the tumor assembly to the donor's own normal separates somatic change from germline difference, and it is the approach the C-GIAB assembly paper is built on - HG009, a second matched pair (PDAC liver metastasis with matched CD4+ T cells) on the NIST C-GIAB page
Reproduce it end to end
build_sv_visualization_cgiab.sh
runs the whole data-preparation pipeline above in one shot:
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_sv_visualization_cgiab.sh
bash build_sv_visualization_cgiab.sh # builds ./cgiab_build/jbrowse2
npx --yes serve cgiab_build/jbrowse2
It downloads the C-GIAB GRCh38 build and the V0.5 benchmark calls, turns both
HiFi BAMs into CRAMs, computes megadepth coverage, calls copy number with
HiFiCNV, builds the BAF bigWig, aligns the T2T tumor assembly to GRCh38 with
minimap2, downloads JBrowse, and writes a config.json with all of it loaded
beside the published Wakhan segments.
The BAF and Wakhan tracks go in with add-track-json: the settings that make
them readable (resolutionMultiplier on one, partitionField on the other) are
track config, with no command-line flag.
It needs the tools listed under Prerequisites, plus bcftools
and bedGraphToBigWig. It pulls down more than 200 GB, wants roughly 1.5 TB of
free disk and 32 GB of RAM, and its alignment and copy-number steps take hours.
See also
- Synteny visualization (pairwise minimap2)
- Reviewing a whole SV callset
- Complex rearrangements and derivative alleles
- SV visualization
- SV inspector view
- Multi-quantitative track
References
- Bailey et al. (2016). Genomic analyses identify molecular subtypes of pancreatic cancer
- Diesh et al. (2023). JBrowse 2: A Modular Genome Browser with Views of Synteny and Structural Variation
- McDaniel et al. (2025). Development and Extensive Sequencing of a Broadly-Consented Genome in a Bottle Matched Tumor-Normal Pair
- Rautiainen et al. (2023). Verkko: telomere-to-telomere assembly of diploid chromosomes
- Waddell et al. (2015). Whole genomes redefine the mutational landscape of pancreatic cancer
- Wagner et al. (2026). A complete human pancreatic cancer genome
Feedback on this tutorial is welcome: contact us.