Synteny on a circle (human and mouse)
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.17. Desktop beta builds are coming soon.
We lay the human and mouse chromosomes around one circle and draw UCSC's hg38-to-mm39 liftOver chain as ribbons between them, so one picture shows where the autosomes have been shuffled and where the X has not. We:
- declare both assemblies and load the chain as an indexed alignment track
- open both on a circular view and order the mouse arc to follow the human one
- color the ribbons by strand
- add a gene density ring over both genomes
- hover a ribbon for its span in each genome
Prerequisites
- a JBrowse to open the files in (Web or Desktop)
- to build the density ring for another pair of genomes, htslib (
bgzip,tabix),bedGraphToBigWigfrom the UCSC utilities, andnodefor the JBrowse CLI
# Debian/Ubuntu
sudo apt install tabix nodejs
# or conda, which has every tool above
conda install -c bioconda -c conda-forge htslib nodejs ucsc-bedgraphtobigwig
# or Linux x86_64 binaries for the tools apt lacks
wget -P ~/.local/bin \
https://hgdownload.soe.ucsc.edu/admin/exe/linux.x86_64/bedGraphToBigWig
chmod +x ~/.local/bin/bedGraphToBigWig
# any platform
npm install -g @jbrowse/cliThe data
UCSC's hg38-to-mm39 liftOver chain (Kent et al. 2003), the RefSeq curated gene sets of both genomes from genomes.jbrowse.org's copies of the UCSC hubs, and the density bigWig the build script makes of them.
You don't need these files to follow the page: the track configs below read the hosted results. The build script fetches them to rebuild those results. The last section, Your own pair of genomes, lists what a pair of your own needs.
| What it is | File |
|---|---|
| RefSeq curated genes, hg38 | ncbiRefSeqCurated.gff.gz |
| RefSeq curated genes, mm39 | ncbiRefSeqCurated.gff.gz |
Read by URL (no download needed)
| What it is | File |
|---|---|
| The chain | hg38ToMm39.over.chain.gz |
Declaring the human and mouse assemblies
The ribbons name chromosomes, so the circle needs both genomes declared. Each
alias table is the hub's with the build's genome-prefixed names added, so a
track naming 1, chr1 or hg38.chr1 finds chr1:
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://jbrowse.org/demos/circular_synteny/hg38.chromAlias.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://jbrowse.org/demos/circular_synteny/hg38.chromAlias.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://jbrowse.org/demos/circular_synteny/hg38.chromAlias.txt - cytobands (under More options):
https://jbrowse.org/genomes/GRCh38/cytoBand.txt
Goes in the assemblies array of config.json. See Assemblies.
{
"name": "mm39",
"uri": "https://hgdownload.soe.ucsc.edu/goldenPath/mm39/bigZips/mm39.2bit",
"refNameAliases": {
"uri": "https://jbrowse.org/demos/circular_synteny/mm39.chromAlias.txt"
}
}jbrowse add-assembly https://hgdownload.soe.ucsc.edu/goldenPath/mm39/bigZips/mm39.2bit \
--name mm39 \
--refNameAliases https://jbrowse.org/demos/circular_synteny/mm39.chromAlias.txtmm39 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:
https://hgdownload.soe.ucsc.edu/goldenPath/mm39/bigZips/mm39.2bitJBrowse reads the format off the file name. Then fill in:
- Genome name:
mm39 - refName aliases (under More options):
https://jbrowse.org/demos/circular_synteny/mm39.chromAlias.txt
The chain as an indexed alignment
jbrowse.org keeps every liftOver chain UCSC publishes as an indexed PAF, one row per chain, the same files the vertebrates tutorial stacks under a locus. The track names that file and its two assemblies, query first. A chain's query is the genome it lifts to, so for hg38ToMm39 that is mouse:
Goes in the tracks array of config.json. See Tracks.
{
"type": "SyntenyTrack",
"trackId": "hg38ToMm39_liftover",
"name": "hg38 to mm39 liftOver chain",
"assemblyNames": ["mm39", "hg38"],
"adapter": {
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToMm39.over.pif.gz",
"csi": true,
"assemblyNames": ["mm39", "hg38"]
}
}jbrowse add-track-json '{
"type": "SyntenyTrack",
"trackId": "hg38ToMm39_liftover",
"name": "hg38 to mm39 liftOver chain",
"assemblyNames": ["mm39", "hg38"],
"adapter": {
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToMm39.over.pif.gz",
"csi": true,
"assemblyNames": ["mm39", "hg38"]
}
}'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": "hg38ToMm39_liftover",
"name": "hg38 to mm39 liftOver chain",
"assemblyNames": ["mm39", "hg38"],
"adapter": {
"type": "PairwiseIndexedPAFAdapter",
"uri": "https://jbrowse.org/ucsc/hg38/liftOver/hg38ToMm39.over.pif.gz",
"csi": true,
"assemblyNames": ["mm39", "hg38"]
}
}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.
For your own pair, convert the alignment to a PIF, JBrowse's indexed PAF. A
chain goes through chain2paf,
which reads it uncompressed; a PAF from minimap2 or wfmash goes straight in.
Then add the track with assemblyNames as query,target:
gzip -dc pair.over.chain.gz > pair.over.chain
chain2paf -i pair.over.chain > pair.paf
jbrowse make-pif pair.paf
jbrowse add-track pair.pif.gz -a query,target --load copyA liftOver chain set holds long chains that cover the genome and many short
ones, mostly repeats and gene copies. Min length in the view's menu drops
the short ones, and the sessions below set it to 100 kb with a length
predicate in filter.
Opening both genomes on one circle
The circular view's assembly takes a list, and each assembly lays out its
chromosomes in turn: hg38 takes the first arc of the circle, mm39 the next, and
ribbons cross between them. displayedRegionNames matches against each assembly
separately, so one list of chromosome names keeps both genomes' unplaced contigs
off the circle. Add → Circular view opens the import form, whose Quick start
builds the same circle once you pick the chain track. As a session:
Goes at the top level of config.json, replacing any defaultSession there. See Default session.
{
"defaultSession": {
"name": "hg38 and mm39 on one circle",
"views": [
{
"type": "CircularView",
"assembly": ["hg38", "mm39"],
"filter": [{ "field": "length", "gte": 100000 }],
"displayedRegionNames": [
"chr1",
"chr2",
"chr3",
"chr4",
"chr5",
"chr6",
"chr7",
"chr8",
"chr9",
"chr10",
"chr11",
"chr12",
"chr13",
"chr14",
"chr15",
"chr16",
"chr17",
"chr18",
"chr19",
"chrX"
],
"height": 780,
"tracks": ["hg38ToMm39_liftover"]
}
]
}
}jbrowse set-default-session --session - << 'EOF'
{
"name": "hg38 and mm39 on one circle",
"views": [
{
"type": "CircularView",
"assembly": ["hg38", "mm39"],
"filter": [{ "field": "length", "gte": 100000 }],
"displayedRegionNames": [
"chr1",
"chr2",
"chr3",
"chr4",
"chr5",
"chr6",
"chr7",
"chr8",
"chr9",
"chr10",
"chr11",
"chr12",
"chr13",
"chr14",
"chr15",
"chr16",
"chr17",
"chr18",
"chr19",
"chrX"
],
"height": 780,
"tracks": ["hg38ToMm39_liftover"]
}
]
}
EOFThe human and mouse assemblies name their chromosomes alike, so the arcs have the same labels. To read the circle:
- Human chromosomes run clockwise from the top and mouse chromosomes follow; the title bar names the two in that order.
- Each ribbon takes the ideogram color of the human chromosome it leaves, so a human chromosome's pieces can be followed to every mouse chromosome that holds one.
- A reverse alignment twists between its two ends.
- A row narrower than a pixel draws at the share of the pixel it covers, as in the linear synteny view, so large blocks dominate and short rows stay faint.
Ordering the mouse arc to follow human
In native contig order, a mouse chromosome sits wherever its number falls, so ribbons cross the middle of the circle to reach their human partners. On open, the circle reorders the mouse arc as the linear synteny view and the dotplot do, placing each mouse chromosome next to the human chromosome it shares the most aligned bases with.
- The circle draws the mouse arc mirrored, so a mouse chromosome running the same way as its human partner faces it and their ribbons run straight across.
- A mouse chromosome running antiparallel is flipped whole, so a twist left in the figure is an inversion inside a chromosome.
- Re-order chromosomes in the view's menu reruns the reorder, and
"autoDiagonalize": falseon the view keeps each genome in its native contig order.
The mouse genome in human chromosomes
Each stretch of a mouse chromosome's ideogram is painted the color of the human chromosome aligned to it, and grey where nothing is. A mouse chromosome carved from one human chromosome is one color, and one assembled from several is striped with them.
Hover the mouse chr11 band on the circle opened above to dim every ribbon that misses it. The tooltip lists each human chromosome aligned to it with the share it covers.
Coloring the ribbons by strand
The chromosome colors show where each piece went, and strand shows which way
round it lies. In grammar-of-graphics terms,
the view's encoding.color is a color scale, a field mapped to colors. The
circle opens on "field": "query", which colors by the first genome's
chromosomes, human here. To color by strand instead:
- Color by... → Strand in the view's menu paints the reverse alignments a second color, and Show legend names the two.
- In a session, set
"encoding": { "color": "strand" }on the view.
The X chromosome as the control
The X chromosome has stayed whole across the two lineages, so no ribbon at the
100 kb cut should join it to an autosome. Open the first session above with
displayedRegionNames cut to ["chr1", "chr2", "chrX"] to read the control.
The figure also has the gene density ring that
Gene density as a ring builds.
Chain rows under the 100 kb Min length cut do join the X to autosomes: the PIF holds short rows between human chrX and mouse autosomes, each a repeat or retrocopy a few hundred bases long, and lowering Min length brings them back.
Gene density as a ring
A track that draws in the linear genome view also draws on the circle, as a ring
inside the ideogram, so asking whether the conserved blocks are the gene-rich
stretches takes one more track. jbrowse make-density counts a GFF3's top-level
features per bin into a bigWig, so a gene is one count however many transcripts
it has.
For one genome, make-density takes the GFF3 and its chrom.sizes directly:
jbrowse make-density genes.gff.gz --chrom-sizes genome.chrom.sizes --bin 100000A ring on a two-genome circle comes from one track naming both assemblies, so both genomes' densities go into one bigWig.
# one chrom.sizes and one GFF3 for the pair, every contig prefixed by genome
for g in hg38 mm39; do
awk -v g="$g" -F'\t' -v OFS='\t' '{print g "." $1, $2}' "$g.chrom.sizes" >> hg38ToMm39.chrom.sizes
gzip -dc "$g.genes.gff.gz" | awk -v g="$g" -F'\t' -v OFS='\t' '/^#/ {next} {$1 = g "." $1; print}' >> hg38ToMm39.genes.gff
# the hub's alias table, plus the prefixed name as one more alias per row
awk -v g="$g" -F'\t' -v OFS='\t' '/^#/ {print; next} {print $0, g "." $1}' "$g.hub.chromAlias.txt" > "$g.chromAlias.txt"
done
bgzip -f hg38ToMm39.genes.gff
# a whole-genome ring is megabases per pixel, so the bin is 100 kb
jbrowse make-density hg38ToMm39.genes.gff.gz --chrom-sizes hg38ToMm39.chrom.sizes --bin 100000The track names both assemblies. Its display defaults draw a heatmap strip whose
color is the average over each pixel's bins. mark is the shape drawn, and
encoding.color is a linear color scale mapping the score across a
scale.range from white at the fewest genes in view to orange at the most:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "hg38ToMm39_gene_density",
"name": "Genes per 100 kb",
"uri": "https://jbrowse.org/demos/circular_synteny/hg38ToMm39.genes.gff.density.bw",
"assemblyNames": ["hg38", "mm39"],
"displayDefaults": {
"mark": "span",
"encoding": {
"color": {
"scale": { "type": "linear", "range": ["#ffffff", "#d95f02"] }
}
},
"height": 40
}
}jbrowse add-track https://jbrowse.org/demos/circular_synteny/hg38ToMm39.genes.gff.density.bw \
--trackId hg38ToMm39_gene_density \
--name "Genes per 100 kb" \
--assemblyNames hg38,mm39 \
--displayDefaults '{"mark":"span","encoding":{"color":{"scale":{"type":"linear","range":["#ffffff","#d95f02"]}}},"height":40}'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": "hg38ToMm39_gene_density",
"name": "Genes per 100 kb",
"uri": "https://jbrowse.org/demos/circular_synteny/hg38ToMm39.genes.gff.density.bw",
"assemblyNames": ["hg38", "mm39"],
"displayDefaults": {
"mark": "span",
"encoding": {
"color": {
"scale": { "type": "linear", "range": ["#ffffff", "#d95f02"] }
}
},
"height": 40
}
}Edit colors/arrangement... → Edit plot... in the track menu changes the ramp's colors.
Rings stack inward from the ideogram in the order the view's tracks lists
them, and the ribbons draw inside the innermost ring, so the density entry goes
before the synteny track:
Goes at the top level of config.json, replacing any defaultSession there. See Default session.
{
"defaultSession": {
"name": "hg38 and mm39 with a gene density ring",
"views": [
{
"type": "CircularView",
"assembly": ["hg38", "mm39"],
"filter": [{ "field": "length", "gte": 100000 }],
"displayedRegionNames": [
"chr1",
"chr2",
"chr3",
"chr4",
"chr5",
"chr6",
"chr7",
"chr8",
"chr9",
"chr10",
"chr11",
"chr12",
"chr13",
"chr14",
"chr15",
"chr16",
"chr17",
"chr18",
"chr19",
"chrX"
],
"height": 780,
"tracks": [
{
"trackId": "hg38ToMm39_gene_density",
"type": "LinearWiggleDisplay",
"mark": "span",
"encoding": {
"color": {
"scale": { "type": "linear", "range": ["#ffffff", "#d95f02"] }
}
},
"height": 40
},
"hg38ToMm39_liftover"
]
}
]
}
}jbrowse set-default-session --session - << 'EOF'
{
"name": "hg38 and mm39 with a gene density ring",
"views": [
{
"type": "CircularView",
"assembly": ["hg38", "mm39"],
"filter": [{ "field": "length", "gte": 100000 }],
"displayedRegionNames": [
"chr1",
"chr2",
"chr3",
"chr4",
"chr5",
"chr6",
"chr7",
"chr8",
"chr9",
"chr10",
"chr11",
"chr12",
"chr13",
"chr14",
"chr15",
"chr16",
"chr17",
"chr18",
"chr19",
"chrX"
],
"height": 780,
"tracks": [
{
"trackId": "hg38ToMm39_gene_density",
"type": "LinearWiggleDisplay",
"mark": "span",
"encoding": {
"color": {
"scale": { "type": "linear", "range": ["#ffffff", "#d95f02"] }
}
},
"height": 40
},
"hg38ToMm39_liftover"
]
}
]
}
EOFHovering a ribbon
Cut the ring session's displayedRegionNames to ["chr1", "chr2", "chrX"] and
hover the widest ribbon, the X block that runs reverse between the two genomes
and so twists. A tooltip gives its span in each genome and its strand.
Your own pair of genomes
The script takes any UCSC pair by name. A pair with no hosted chain goes through
the make-pif commands under
The chain as an indexed alignment, and
each ring takes one bigWig per assembly, or one bigWig with prefixed contigs and
an alias per assembly as in Gene density as a ring.
Reproduce it end to end
The script works in four steps:
- Fetch the hg38 and mm39 hub configs, chromosome sizes and alias tables, and both RefSeq curated gene sets.
- Prefix every contig with its genome and add the prefixed name to each alias table, so one bigWig can hold both genomes' counts.
- Count genes per 100 kb into that bigWig with
jbrowse make-density, one count per gene however many transcripts it has. - Write the config with the chain track pointing at jbrowse.org's indexed copy, which the ribbons and the reorder both read.
The script reads four settings, and the tools it runs are in Prerequisites:
TARGETandQUERYpick another UCSC pair.PIFpoints the track at a chain indexed elsewhere.MIN_LENGTHmoves the cut.BASE_URLis the prefix the finished files will be served under.
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_circular_synteny.sh
bash build_circular_synteny.shSee also
- Tutorial: Synteny from liftOver chains (hg38 and eight vertebrates)
- Tutorial: Synteny visualization (pairwise minimap2)
- Tutorial: Gene density and transposon density along a chromosome
- Tutorial: A map of the human mitochondrial genome
- User guide: Circular genome view
- Config guide: Synteny track
Citations
- Kent et al. (2003). Evolution's cauldron: duplication, deletion, and rearrangement in the mouse and human genomes
- Ohno (1967). Sex Chromosomes and Sex-Linked Genes, the argument that the mammalian X chromosome's gene content is conserved across species.
- Krzywinski et al. (2009). Circos: an information aesthetic for comparative genomics
Feedback on this tutorial is welcome: contact us.