Synteny from liftOver chains (hg38 and eight vertebrates)
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.20. Desktop beta builds for Linux and
macOS are on the releases page;
the Windows build waits on code signing.
We look at one human locus across eight other mammals at once, from alignments that already exist. UCSC publishes a liftOver chain from hg38 to each genome it hosts, and jbrowse.org keeps each chain as an indexed alignment file. The same config works for any set of pairwise chains that share one genome. We look at TP53, where the genomes keep one gene order, and at the PMP22 segmental duplications, where they break into many blocks. We:
- index a chain as PIF, and compose the chains into one multi-way synteny track, each lane drawing the RefSeq gene models from that genome's UCSC hub
- open the track in a linear genome view at TP53, with the lanes in tree order
- pin and flip lanes from the lane header menu near PMP22
Prerequisites
- htslib (
tabix), to read a hosted index without downloading the alignment - A running JBrowse instance (the web quickstart or the desktop quickstart)
- for a chain of your own,
chain2paf and the
JBrowse CLI, for
jbrowse make-pif
# Debian/Ubuntu
sudo apt install tabix
# or conda, which has every tool above
conda install -c bioconda -c conda-forge htslib
# any platform
npm install -g @jbrowse/cli@nextThe data
UCSC's pairwise liftOver chains from hg38 (Kent et al. 2003), each converted to an indexed PAF and rehosted beside the hub configs genomes.jbrowse.org serves, and eight UCSC genome hubs, whose assembly entry and NCBI RefSeq gene track each lane takes verbatim.
You don't need these files to follow the page: the track config below reads the
hosted indexed copies. To index a chain of your own, convert it with chain2paf
and make-pif, as LiftOver chains as one indexed alignment per genome shows.
| What it is | File |
|---|---|
UCSC's liftOver folder for hg38, one hg38To<Genome>.over.chain.gz per genome | liftOver/ |
The liftOver chains as indexed alignments (no download needed)
| What it is | File |
|---|---|
| Chimpanzee, panTro6 | hg38ToPanTro6.over.pif.gz |
| Gorilla, gorGor6 | hg38ToGorGor6.over.pif.gz |
| Orangutan, ponAbe3 | hg38ToPonAbe3.over.pif.gz |
| Rhesus macaque, rheMac10 | hg38ToRheMac10.over.pif.gz |
| Marmoset, calJac4 | hg38ToCalJac4.over.pif.gz |
| Mouse, mm39 | hg38ToMm39.over.pif.gz |
| Dog, canFam6 | hg38ToCanFam6.over.pif.gz |
| Cow, bosTau9 | hg38ToBosTau9.over.pif.gz |
LiftOver chains as one indexed alignment per genome
A liftOver chain maps each stretch of one genome to a position in another, whether or not a gene lies there, so the track draws each lane from the chain alone. Each UCSC chain aligns hg38 to one other genome, so no file aligns chimpanzee to mouse, and every ribbon joins a lane to hg38, whichever lane sits above it.
Each hosted file is a chain converted to PAF and indexed with
jbrowse make-pif. To index a chain of your own, convert it to PAF with
chain2paf, which reads an
uncompressed chain, then run make-pif:
gzip -dc genomeA.genomeB.over.chain.gz > genomeA_genomeB.chain
chain2paf -i genomeA_genomeB.chain > genomeA_genomeB.paf
# --csi writes the .csi index that "csi": true in the track below reads
jbrowse make-pif genomeA_genomeB.paf --csimake-pif can write a coarser tier beside the per-base one, for
whole-chromosome zooms. Coarse-tier sequence names are upper-case, so tabix
lists a file's tiers from its index without downloading the alignment:
# the #pif header, if the file was built recently enough to have one
tabix -H https://jbrowse.org/ucsc/hg38/liftOver/hg38ToPanTro6.over.pif.gz | awk 'NR==1'
# how many coarse-tier sequences the index holds; zero means one tier
tabix -l https://jbrowse.org/ucsc/hg38/liftOver/hg38ToPanTro6.over.pif.gz | grep -c '^[TQ]'Composing the chains into one track
One SyntenyTrack names hg38 and every genome it stacks. Its adapter, a
MultiPairwiseSyntenyAdapter, holds one PairwiseIndexedPAFAdapter per chain:
- Each child names its two assemblies as
query,target, with the genome the chain lifts to first. The anchor is the one assembly every chain names. - The config below is cut to a few genomes for the page, and the hosted config has all of them. genomes.jbrowse.org serves the same kind of track over every hg38 chain, which Stacking many genomes under hg38 turns on.
- The assemblies and their gene tracks come from the hub configs unchanged, and each lane finds its gene models through the session, so this track is the only addition to the hub entries.
A genome of your own loads from its FASTA instead:
Goes in the assemblies array of config.json. See Assemblies.
{
"name": "myGenome",
"uri": "myGenome.fa.gz"
}jbrowse add-assembly myGenome.fa.gz \
--name myGenome \
--load copyIn 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:
myGenome.fa.gz
myGenome.fa.gz.fai
myGenome.fa.gz.gziJBrowse reads the format off the file name. Then fill in:
- Genome name:
myGenome
myGenome.fa.gz is relative to a config.json. Replace it with its URL or its path on this computer.
Goes in the tracks array of config.json. See Tracks.
{
"type": "SyntenyTrack",
"trackId": "hg38_liftover_multiway",
"name": "hg38 vs 8 UCSC genomes (liftOver chains)",
"assemblyNames": ["hg38", "panTro6", "rheMac10", "mm39"],
"adapter": {
"type": "MultiPairwiseSyntenyAdapter",
"adapters": [
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToPanTro6.over.pif.gz",
"csi": true,
"assemblyNames": ["panTro6", "hg38"]
},
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToRheMac10.over.pif.gz",
"csi": true,
"assemblyNames": ["rheMac10", "hg38"]
},
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToMm39.over.pif.gz",
"csi": true,
"assemblyNames": ["mm39", "hg38"]
}
]
},
"displays": [
{
"type": "MultiWaySyntenyDisplay",
"height": 600
}
]
}jbrowse add-track-json '{
"type": "SyntenyTrack",
"trackId": "hg38_liftover_multiway",
"name": "hg38 vs 8 UCSC genomes (liftOver chains)",
"assemblyNames": ["hg38", "panTro6", "rheMac10", "mm39"],
"adapter": {
"type": "MultiPairwiseSyntenyAdapter",
"adapters": [
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToPanTro6.over.pif.gz",
"csi": true,
"assemblyNames": ["panTro6", "hg38"]
},
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToRheMac10.over.pif.gz",
"csi": true,
"assemblyNames": ["rheMac10", "hg38"]
},
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToMm39.over.pif.gz",
"csi": true,
"assemblyNames": ["mm39", "hg38"]
}
]
},
"displays": [
{
"type": "MultiWaySyntenyDisplay",
"height": 600
}
]
}'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:
{
"type": "SyntenyTrack",
"trackId": "hg38_liftover_multiway",
"name": "hg38 vs 8 UCSC genomes (liftOver chains)",
"assemblyNames": ["hg38", "panTro6", "rheMac10", "mm39"],
"adapter": {
"type": "MultiPairwiseSyntenyAdapter",
"adapters": [
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToPanTro6.over.pif.gz",
"csi": true,
"assemblyNames": ["panTro6", "hg38"]
},
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToRheMac10.over.pif.gz",
"csi": true,
"assemblyNames": ["rheMac10", "hg38"]
},
{
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToMm39.over.pif.gz",
"csi": true,
"assemblyNames": ["mm39", "hg38"]
}
]
},
"displays": [
{
"type": "MultiWaySyntenyDisplay",
"height": 600
}
]
}That shows it in the linear view. For the synteny view, open Add → Linear synteny view, pick the track under Quick start, and click Launch.
Level of detail in the track menu picks which stored tier a zoom reads, as
on a pairwise synteny track. The menu offers it once every child has a coarse
tier, which the tabix -l line above checks on each file.
Stacking the genomes at TP53 and at PMP22
We'll open the track on hg38 around TP53. It draws a lane per genome under the
human axis, each fitted to wherever its chain places the window, and each lane
header names the chromosome and the span the lane shows, with [rev] where that
chromosome runs the other way relative to hg38. In the session, rows.sort
stacks the lanes down the tree from human, the apes first and the cow last.
Goes at the top level of config.json, replacing any defaultSession there. See Default session.
{
"defaultSession": {
"name": "TP53 neighbourhood across nine vertebrates",
"views": [
{
"type": "LinearGenomeView",
"assembly": "hg38",
"loc": "chr17:7,400,000-7,700,000",
"tracks": [
"hg38-ncbiRefSeq",
{
"trackId": "hg38_liftover_multiway",
"type": "MultiWaySyntenyDisplay",
"ribbons": { "encoding": { "color": "strand" } },
"rows": {
"sort": [
"panTro6",
"gorGor6",
"ponAbe3",
"rheMac10",
"calJac4",
"mm39",
"canFam6",
"bosTau9"
]
},
"height": 600
}
]
}
]
}
}jbrowse set-default-session --session - << 'EOF'
{
"name": "TP53 neighbourhood across nine vertebrates",
"views": [
{
"type": "LinearGenomeView",
"assembly": "hg38",
"loc": "chr17:7,400,000-7,700,000",
"tracks": [
"hg38-ncbiRefSeq",
{
"trackId": "hg38_liftover_multiway",
"type": "MultiWaySyntenyDisplay",
"ribbons": { "encoding": { "color": "strand" } },
"rows": {
"sort": [
"panTro6",
"gorGor6",
"ponAbe3",
"rheMac10",
"calJac4",
"mm39",
"canFam6",
"bosTau9"
]
},
"height": 600
}
]
}
]
}
EOFThe ribbons color by strand, the default ribbons.encoding.color (Color by →
Strand, under Ribbons in the track menu). Each ribbon takes the strand of
the chain record that placed it, red where the lane runs the same way as hg38
and blue where it runs reversed.
Around TP53 every lane but gorilla places the whole window from one chain, with the same genes in the same order:
- The gorilla ribbons stop after FXR2, because gorGor6 holds the TP53 end of the window on an unplaced contig.
- The mouse, cow and dog lanes break into many ribbons, because the track cuts a chain record at every long indel and draws each gap-free run as one ribbon, with a gap wherever the lane has sequence hg38 lacks.
- The ape lanes have only short gaps, so their ribbons look continuous.
- The mouse lane shows
[rev]because its chain runs the other way against hg38 here, so its ribbons are blue.
Navigate to chr17:15,200,000-16,400,000, toward the centromere, near PMP22.
The region is a hotspot of segmental duplications (long repeated copies of
sequence): every genome places it as several blocks, and many of those blocks
run the other way against their neighbours. Three rules decide how a lane draws
them:
- A lane whose blocks mostly run backwards along hg38 draws flipped, so its ribbons run straight on screen while the strand color still marks each of them as an inversion.
- Inside a lane, a ribbon crosses where one block runs against its neighbour, as in the dog and cow lanes.
- A lane draws one stretch of its chromosome at a time. Where the window
aligns to two stretches a window or more apart, the lane draws the one holding
more of the window, and its header names the other after
also at. The marmoset lane draws the reversed block that places the right of the window, and names the forward chain that places the left.
The gorilla lane header names chr17 beside chr5, the chromosome the lane drew. Part of the window aligns to chr17, the homologous chromosome, so the chr5 frame misses some of what the alignment places. The lane header menu sets the frame:
- Show chr17 in this lane pins the lane onto chr17.
- Show ⟨stretch⟩ in this lane, on the marmoset lane, pins it onto the
stretch its header names after
also at. - Flip lane turns the lane the other way on the same contig, for a lane whose blocks split about evenly between the two orientations.
- Let the lane choose its orientation hands the choice back.
Reproduce it end to end
The script writes one config, with nothing to build or upload, in three steps:
- Probe which of the listed genomes have both a hub config and an indexed chain
with its
.csion jbrowse.org, and drop the rest. - Report the tiers each chain file holds, since Level of detail needs a coarse tier in every child.
- Write each kept genome's hub entry and gene track, and one composed track with a child per chain.
GENOMES, a space-separated list of UCSC genome names, stacks a different set:
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_hg38_liftover_multiway.sh
bash build_hg38_liftover_multiway.sh # writes ./hg38_vertebrates_build/config.json
GENOMES="panTro6 mm39" bash build_hg38_liftover_multiway.sh my_stack/config.jsonSee also
- Tutorial: Pangenome (HPRC) part 2: haplotypes against each other
- Tutorial: Synteny from gene symbols (primates and E. coli)
- Tutorial: Synteny from a Cactus alignment (T2T apes)
- Tutorial: Synteny on genomes.jbrowse.org
- Tutorial: Synteny visualization (all-vs-all minimap2)
- Tutorial: Synteny on a circle (human and mouse)
- User guide: Multi-way synteny display
External links
- UCSC Genome Browser downloads: https://hgdownload.soe.ucsc.edu/downloads.html
Citations
- Kent et al. (2003). Evolution's cauldron: duplication, deletion, and rearrangement in the mouse and human genomes
Feedback on this tutorial is welcome: contact us.