Structural variants from Hi-C
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.13. Desktop beta builds are coming soon.
Two chromosomes joined by a translocation touch along the join, so Hi-C reads linking them run far above background. We look for the Philadelphia chromosome, the BCR-ABL1 fusion, in the Hi-C of the K562 leukemia line against GM12878's normal karyotype. JBrowse fetches a Hi-C matrix for every pair of regions on screen, so a chr9 window and a chr22 window in one linear view draw the contacts between the two. Over the same matrices, we then compare the two lines' compartment calls at EBF1, a gene B cells depend on for their identity.
Prerequisites
- a JBrowse to paste the tracks into (Web or Desktop)
java, whichjuicer_toolsneeds for the scan script; the script downloadsjuicer_toolsitselfcurl, for the same scan script
Where the data comes from
Deep in situ Hi-C for GM12878 and K562 from ENCODE, plus ENCODE's domain, loop and compartment calls over the same two matrices.
Nothing to download: the track configs and the scan script below read these files by URL.
The files
- GM12878 in situ Hi-C (ENCSR410MDC): https://encode-public.s3.amazonaws.com/2021/10/28/6f0cc163-86c7-4a68-baac-65af90f5a90d/ENCFF053VBX.hic
- K562 in situ Hi-C (ENCSR545YBD): https://encode-public.s3.amazonaws.com/2021/10/28/4d332729-3463-4782-b33c-76e4fa8ff72a/ENCFF080DPJ.hic
- GM12878 contact domains (Arrowhead): https://encode-public.s3.amazonaws.com/2021/10/28/467750ae-7aab-47b0-a304-dc5f8dff89f7/ENCFF301CUL.bedpe.gz
- GM12878 loops (HiCCUPS): https://encode-public.s3.amazonaws.com/2021/10/28/70e6944c-1212-45f9-855c-dbc74e9a21f5/ENCFF712NKX.bedpe.gz
- GM12878 compartment eigenvector: https://encode-public.s3.amazonaws.com/2021/10/28/5b488af0-df49-4b9b-9feb-8ad671b7eaef/ENCFF661LPK.bigWig
- K562 compartment eigenvector: https://encode-public.s3.amazonaws.com/2021/10/28/1180b7b2-99fd-429a-bfe1-f76cc8aa751a/ENCFF699RSL.bigWig
Reading a Hi-C contact map: the triangle, domains and loops
Hi-C counts how often two stretches of the genome touch in the nucleus. JBrowse draws the result as a triangle: the diagonal runs along the top edge, and depth below it is genomic separation. Two features of that picture have names, and ENCODE publishes both as annotation files derived from the matrix:
- Contact domains (also called topologically associating domains, TADs) are the square blocks sitting on the diagonal. Inside one, everything contacts everything; across a boundary, contact drops sharply. ENCODE calls them with Arrowhead and ships a BEDPE.
- Loops are individual bright dots off the diagonal: two specific points contacting each other far more than their separation predicts, usually a pair of convergent CTCF sites. ENCODE calls them with HiCCUPS, also a BEDPE.
Over a wide window the triangle can render as red speckle. If a Hi-C track looks
like noise, change
resolutionBias first,
which steps to coarser bins
(adjusting resolution).
Loading the GRCh38 assembly
ENCODE aligned both Hi-C libraries to GRCh38, so we load that assembly before adding any track.
Goes in the assemblies array of config.json. See Assemblies.
{
"name": "hg38",
"uri": "https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz",
"refNameAliases": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt"
},
"cytobands": "https://jbrowse.org/genomes/GRCh38/cytoBand.txt"
}jbrowse add-assembly https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz \
--name hg38 \
--refNameAliases https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt \
--config '{"cytobands":"https://jbrowse.org/genomes/GRCh38/cytoBand.txt"}'hg38 is one of the genomes JBrowse Desktop hosts, with gene tracks already set up: on the start screen click Show all available genomes and pick it. To load the files of this config instead:
In JBrowse Desktop, Open new genome on the start screen (or File → Open genome... in a session), then Open from a URL and paste, one per line:
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.fai
https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.gziJBrowse reads the format off the file name. Then fill in:
- Genome name:
hg38 - refName aliases (under More options):
https://s3.amazonaws.com/jbrowse.org/genomes/GRCh38/hg38_aliases.txt - cytobands (under More options):
https://jbrowse.org/genomes/GRCh38/cytoBand.txt
Adding the Hi-C and contact-domain tracks
The .hic files are 20 GB and 55 GB, and JBrowse requests only the bins on
screen.
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "hic_k562_insitu",
"name": "K562 in situ Hi-C (ENCODE ENCSR545YBD)",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/4d332729-3463-4782-b33c-76e4fa8ff72a/ENCFF080DPJ.hic",
"assemblyNames": ["hg38"],
"displayDefaults": {
"selectedNormalization": "NONE"
}
}jbrowse add-track https://encode-public.s3.amazonaws.com/2021/10/28/4d332729-3463-4782-b33c-76e4fa8ff72a/ENCFF080DPJ.hic \
--trackId hic_k562_insitu \
--name "K562 in situ Hi-C (ENCODE ENCSR545YBD)" \
--assemblyNames hg38 \
--displayDefaults '{"selectedNormalization":"NONE"}'In JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"trackId": "hic_k562_insitu",
"name": "K562 in situ Hi-C (ENCODE ENCSR545YBD)",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/4d332729-3463-4782-b33c-76e4fa8ff72a/ENCFF080DPJ.hic",
"assemblyNames": ["hg38"],
"displayDefaults": {
"selectedNormalization": "NONE"
}
}Goes in the tracks array of config.json. See Tracks.
{
"trackId": "hic_gm12878_insitu",
"name": "GM12878 in situ Hi-C, deep (ENCODE ENCSR410MDC)",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/6f0cc163-86c7-4a68-baac-65af90f5a90d/ENCFF053VBX.hic",
"assemblyNames": ["hg38"],
"displayDefaults": {
"selectedNormalization": "NONE"
}
}jbrowse add-track https://encode-public.s3.amazonaws.com/2021/10/28/6f0cc163-86c7-4a68-baac-65af90f5a90d/ENCFF053VBX.hic \
--trackId hic_gm12878_insitu \
--name "GM12878 in situ Hi-C, deep (ENCODE ENCSR410MDC)" \
--assemblyNames hg38 \
--displayDefaults '{"selectedNormalization":"NONE"}'In JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"trackId": "hic_gm12878_insitu",
"name": "GM12878 in situ Hi-C, deep (ENCODE ENCSR410MDC)",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/6f0cc163-86c7-4a68-baac-65af90f5a90d/ENCFF053VBX.hic",
"assemblyNames": ["hg38"],
"displayDefaults": {
"selectedNormalization": "NONE"
}
}Use ENCODE's direct S3 URLs. hic-straw's range reader cannot follow the
cross-origin redirect the portal's @@download links return, and the .hic
comes back as a 403. The S3 URL for any ENCODE file is in its metadata under
cloud_metadata.url.
The domain BEDPE needs one extra slot, "type": "FeatureTrack":
Goes in the tracks array of config.json. See Tracks.
{
"type": "FeatureTrack",
"trackId": "hic_gm12878_domains",
"name": "GM12878 contact domains (Arrowhead)",
"assemblyNames": ["hg38"],
"adapter": {
"type": "BedpeAdapter",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/467750ae-7aab-47b0-a304-dc5f8dff89f7/ENCFF301CUL.bedpe.gz"
}
}jbrowse add-track https://encode-public.s3.amazonaws.com/2021/10/28/467750ae-7aab-47b0-a304-dc5f8dff89f7/ENCFF301CUL.bedpe.gz \
--trackId hic_gm12878_domains \
--name "GM12878 contact domains (Arrowhead)" \
--assemblyNames hg38 \
--trackType FeatureTrackIn JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"type": "FeatureTrack",
"trackId": "hic_gm12878_domains",
"name": "GM12878 contact domains (Arrowhead)",
"assemblyNames": ["hg38"],
"adapter": {
"type": "BedpeAdapter",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/467750ae-7aab-47b0-a304-dc5f8dff89f7/ENCFF301CUL.bedpe.gz"
}
}Arrowhead writes each domain with both BEDPE ends set to the same interval, so
as a FeatureTrack the file gives one box per domain, nested domains stacking
into rows. Loops, whose mates differ, are the paired-arc case in the
Hi-C track config guide;
the whole GM12878 loops track is hic_gm12878_loops in
https://jbrowse.org/code/jb2/main/test_data/config_demo.json.
To color or filter either track by a column, set
columnNames
explicitly.1
Opening chr9 and chr22 in one view to look for the translocation
Type both locations into the location box, separated by a space:
chr9:129,730,000-131,730,000 chr22:22,285,000-24,285,000.
Two regions on separate chromosomes touch at background rate. If they are fused, they contact each other constantly.
K562 has the Philadelphia chromosome, t(9;22)(q34;q11) (Rowley 1973), joining BCR on chr22 to ABL1 on chr9.
The domain boundaries inside each window line up between the two lines, so chr9 and chr22 each fold normally in K562.
Choosing the control and normalization for the translocation scan
Control depth. The scan script below compares a case .hic against a
control, ENCODE's deep GM12878 in situ file ENCSR410MDC by default. The script
leaves the much shallower GM12878 "supernatant" fraction, ENCSR730CER,
commented out, because a wedge empty for want of reads looks the same as one
empty for want of a translocation. With the deep file, the scan finds GM12878
with more contact than K562 across the whole chr9-chr22 block except the
junction bin, where the order inverts.
Normalization. Matrix balancing divides out per-bin coverage differences,
and an amplified fusion is such a difference, so balancing hides it. Re-run the
scan with NORM=INTER_SCALE and ABL1×BCR drops off the top of the table.
Balanced matrices suit domains and loops and raw counts suit rearrangements, so
both Hi-C tracks here set
selectedNormalization
to NONE.
The scan prints a ranked list for the control below the one for the case. The top bin in the control list is hot in both GM12878 and K562, so it is a reproducible mapping artifact and not a rearrangement.
Ranking chr9-chr22 contact bins with juicer_tools
Finding the translocation takes one dump per .hic file and a sort. Dump the
raw contact counts between the two chromosomes:
# NONE: raw counts, for the reason above
# BP 250000: 250 kb base-pair bins
# -Xmx4g: a whole chromosome pair needs more than the default heap
java -Xmx4g -jar juicer_tools.jar dump observed NONE \
case.hic chr9 chr22 BP 250000 case.txtAn empty output file means the .hic stores nothing at that resolution, or has
no vector for the normalization you asked for (a file may store those only at
coarser bins). The file has three columns: bin1 start, bin2 start and contact
count. Rank the bins by count:
# awk in place of head, which would kill sort with SIGPIPE under pipefail
sort -k3,3 -rn case.txt | awk 'NR <= 10'scan_hic_translocation.sh
dumps the case and the control, ranks the case bins and prints the control count
beside each:
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/scan_hic_translocation.sh
bash scan_hic_translocation.shOverride CASE, CTRL, CHR1, CHR2, RES and NORM to scan any two .hic
files that hold inter-chromosomal blocks. Reading the output:
- The top row pairs ABL1 intron 1 with the 5' end of BCR.
RES=10000lands on the junction itself, ABL1 intron 1 against the BCR major breakpoint cluster region. The K562 fusions tutorial places the DNA break of the same fusion in that intron.- A second chr9-chr22 bin further down also sits well clear of the control, so treat the ranking as a list of candidates to open.
Purpose-built callers scan the whole genome: EagleC, hic_breakfinder and HiNT. Each writes BEDPE, which loads here as a paired-arc track next to the matrix it was called from.
A and B compartments at EBF1 in GM12878 and K562
The genome sorts into two interleaved sets of regions, the gene-rich, active A compartment and the inactive B compartment, and each region contacts regions in the same set most. ENCODE publishes that call for every experiment as a compartment eigenvector and a set of subcompartment classes.
We load each line's eigenvector, a score per bin whose sign marks the
compartment, as a bigWig. Both tracks pin scales.y, the y scale, to one
symmetric range, so they compare directly and 0, where the compartment flips,
sits in the middle of each:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "hic_gm12878_compartments",
"name": "GM12878 compartment eigenvector (ENCFF661LPK)",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/5b488af0-df49-4b9b-9feb-8ad671b7eaef/ENCFF661LPK.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"scales": { "y": { "domainMin": -0.012, "domainMax": 0.012 } }
}
}jbrowse add-track https://encode-public.s3.amazonaws.com/2021/10/28/5b488af0-df49-4b9b-9feb-8ad671b7eaef/ENCFF661LPK.bigWig \
--trackId hic_gm12878_compartments \
--name "GM12878 compartment eigenvector (ENCFF661LPK)" \
--assemblyNames hg38 \
--displayDefaults '{"scales":{"y":{"domainMin":-0.012,"domainMax":0.012}}}'In JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track..., choose Add track from pasted JSON, and paste:
{
"trackId": "hic_gm12878_compartments",
"name": "GM12878 compartment eigenvector (ENCFF661LPK)",
"uri": "https://encode-public.s3.amazonaws.com/2021/10/28/5b488af0-df49-4b9b-9feb-8ad671b7eaef/ENCFF661LPK.bigWig",
"assemblyNames": ["hg38"],
"displayDefaults": {
"scales": { "y": { "domainMin": -0.012, "domainMax": 0.012 } }
}
}The K562 track uses
https://encode-public.s3.amazonaws.com/2021/10/28/1180b7b2-99fd-429a-bfe1-f76cc8aa751a/ENCFF699RSL.bigWig.
On an eigenvector track already open, Y axis... → Range writes the same two
ends. Open both eigenvector tracks over EBF1 on chr5:
The band over EBF1 is in the A compartment in GM12878, a B-lymphoblastoid line, and the B compartment in K562, an erythroleukemia, while the sequence either side of it agrees. The sign of an eigenvector is arbitrary, so use the gene track to tell which sign is A, the gene-rich compartment.
See also
- Tutorial: ChromHMM chromatin states
- Tutorial: Complex rearrangements and derivative alleles
- Tutorial: Gene fusion calls and the DNA behind them
- User guide: Hi-C track
- User guide: SV visualization
- Config guide: Hi-C track
External links
Notes
-
Juicer writes a version banner after the header line, so column names read from the header come out
undefinedpast the tenth column, and a jexl expression on one of them matches nothing and reports no error. HiCCUPS writes 24 columns and Arrowhead 16, and both leavenameandscoreat.and put what they rank by further along:observedfor HiCCUPS, a second column calledscorefor Arrowhead. Values past the tenth column arrive as strings, so compare with>and<, which coerce. ↩
Feedback on this tutorial is welcome: contact us.