Multi-way synteny track
TL;DR: we read one grape locus across seven plant genomes without leaving
grape's own view. Each genome gets a lane under the gene track, drawn in that
genome's own coordinates, and grey ribbons carry every ortholog from one lane
down to the next. The lane stack is one ordinary track display, a
MultiWaySyntenyDisplay, so it pans with the tracks above it.
Prerequisites
- nothing to install to read along: every session below opens from a hosted demo config, and each figure links the session it was captured in
- to build the same track on your own genomes, an ortholog table with a column per genome (jcvi MCScan blocks, OrthoFinder orthogroups) or an all-vs-all PAF
- one BED per genome, placing the gene ids the table names
- every genome loaded as an assembly in the same session
- a GFF3 feature track per assembly, or that genome's lane outlines the table's
gene spans and says
no annotation - Synteny from an ortholog table builds the grape table this page opens, end to end
Where the data comes from
Five hosted demo configs, each carrying an ortholog table or an alignment that serves a mate per genome.
- grape, peach, cacao and four more plant genomes, from a jcvi MCScan
.blockstable: https://jbrowse.org/demos/grape_peach_cacao/config.json - five grasses, from an OrthoFinder run: https://jbrowse.org/demos/orthofinder_grasses/config.json
- five vertebrates, from the same pipeline: https://jbrowse.org/demos/orthofinder_vertebrates/config.json
- HPRC release 2 haplotypes, joined on their CAT gene names: https://jbrowse.org/demos/hprc/config.json
- five E. coli strains, from an all-vs-all PAF: https://jbrowse.org/demos/ecoli_pangenome/config.json
Opening the track
We'll start on the hosted grape/peach/cacao demo, whose one
MCScanBlocksAdapter track carries an ortholog column for seven plant genomes:
- Open a linear genome view on grape and navigate to
11:778,000-866,000. - Turn on the grape gene track, and the ortholog track Grape vs peach, cacao, arabidopsis, poplar, tomato, citrus (MCScan blocks).
- In its track menu, choose Display types → Multi-way synteny display.
The same thing as a defaultSession, which the live link below opens directly:
{
"defaultSession": {
"name": "Grape multi-way synteny track",
"views": [
{
"type": "LinearGenomeView",
"init": {
"assembly": "grape",
"loc": "11:778,000-866,000",
"tracks": [
{
"trackId": "grape_genes",
"type": "LinearBasicDisplay",
"showOnlyGenes": true,
"displayMode": "compact"
},
{
"trackId": "grape_peach_cacao_blocks",
"type": "MultiWaySyntenyDisplay",
"rowOrder": [
"peach",
"cacao",
"poplar",
"citrus",
"arabidopsis",
"tomato"
],
"height": 340
}
]
}
}
]
}
}
jbrowse set-default-session --session - << 'EOF'
{
"name": "Grape multi-way synteny track",
"views": [
{
"type": "LinearGenomeView",
"init": {
"assembly": "grape",
"loc": "11:778,000-866,000",
"tracks": [
{
"trackId": "grape_genes",
"type": "LinearBasicDisplay",
"showOnlyGenes": true,
"displayMode": "compact"
},
{
"trackId": "grape_peach_cacao_blocks",
"type": "MultiWaySyntenyDisplay",
"rowOrder": [
"peach",
"cacao",
"poplar",
"citrus",
"arabidopsis",
"tomato"
],
"height": 340
}
]
}
}
]
}
EOF
Reading a lane's scale
Each lane has its own scale, so each lane states it:
- Left: where the lane starts, with
[rev]where its gene order runs against the anchor's. - Right: the lane's span, and the multiple of the anchor's span where that is not one.
- Ticks fall at one interval shared by every mate lane, so two lanes at the same spacing are at the same bp-per-pixel. A lane zoomed far enough out that its ticks would read as hatching draws none, and its multiple is the scale statement instead.
- The view's own gridlines stop at the anchor lane, the only lane they are true for.
Ordering the lanes
rowOrderpins the lanes it names to the top; the rest follow densest-first over the whole fetched table, so the order holds still across a pan.- A ribbon joins adjacent lanes, bridging past a lane that places nothing for the group. Turn Bridge lanes that place nothing off and a sparse lane mid-stack cuts every chain running through it, which is what densest-first guards against.
Zooming to genes
Cut the window to a few genes and each ribbon connects one gene to one ortholog:
- A lone ortholog draws at gene size, centered in its lane, since the shortest rung on the ladder of lane spans is the anchor's own.
- Hovering a ribbon names its ortholog group and highlights it down every lane that kept the gene; clicking a glyph opens the feature detail panel.
From lanes to a full stack
- Launch stacked synteny view (visible region) in the track menu opens the multi-panel dialog, cut from this track's dataset over the visible window.
- Every genome aligning there is offered a full row of its own.
The five-grass OrthoFinder table behind Synteny from OrthoFinder orthogroups reads both ways: as lanes under rice's own genes, and as a stack where every grass gets a row to drive.
The same track on other sources
The display draws whatever pairs the track serves for the visible window, so any
adapter whose features carry a mate per other assembly works. It keys an
ortholog group by gene name, falling back to the adapter's syntenyId.
A pangenome's own annotations
HPRC release 2 annotates every haplotype assembly with CAT, which projects the
GENCODE gene set onto each assembly's own contigs under the same gene names, so
joining the annotations by name is the whole pipeline.
build_hprc_cfhr_synteny.sh
does that for the CFHR3/CFHR1 deletion:
# one plain BED per genome, from the gene rows of its own annotation
gzip -dc hprc_cfhr_HG00099.1.genes.gff3.gz \
| awk -F'\t' -v OFS='\t' '$3=="gene" {
match($9, /Name=[^;]*/)
print $1, $4 - 1, $5, substr($9, RSTART+5, RLENGTH-5), 0, $7
}' > hprc_cfhr_HG00099.1.bed
An all-vs-all alignment
An alignment file names no genes, so each record is its own ribbon. The track also fetches each adjacent pair's own records from the same file, so the gutters carry the direct alignments the file holds for that pair.
{
"defaultSession": {
"name": "E. coli all-vs-all multi-way track",
"views": [
{
"type": "LinearGenomeView",
"init": {
"assembly": "K12",
"loc": "chr:1,443,000-1,466,000",
"tracks": [
{ "trackId": "ecoli_pggb_depth", "height": 60 },
{
"trackId": "ecoli_ava",
"type": "MultiWaySyntenyDisplay",
"rowOrder": ["NCTC86", "CFT073", "Sakai", "IAI39"],
"height": 340
}
]
}
}
]
}
}
jbrowse set-default-session --session - << 'EOF'
{
"name": "E. coli all-vs-all multi-way track",
"views": [
{
"type": "LinearGenomeView",
"init": {
"assembly": "K12",
"loc": "chr:1,443,000-1,466,000",
"tracks": [
{ "trackId": "ecoli_pggb_depth", "height": 60 },
{
"trackId": "ecoli_ava",
"type": "MultiWaySyntenyDisplay",
"rowOrder": ["NCTC86", "CFT073", "Sakai", "IAI39"],
"height": 340
}
]
}
}
]
}
EOF
Deep-time orthologs
The lanes hold up past the range whole-genome alignment reaches: the five-vertebrate OrthoFinder table draws the human HOXD cluster with a lane per genome.
Two more orthogroup sets read as lanes beside their stacked views:
- five Drosophila genomes, where the block survives out to D. virilis and its orientation does not.
- five nightshade genomes, where the same genes span a different amount of DNA in each genome and every lane's header says how much.