Synteny from MCScan anchors (grape, peach)
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.
Grape and peach keep long runs of genes in the same order, though the genomes have diverged too far to align base by base. We:
- produce the gene BEDs and anchor files with jcvi MCScan
- load the assemblies, gene tracks, and the
.anchorsand.anchors.simpletracks - open a linear synteny view, with a ribbon for each gene pair and a bar for each block (a run of gene pairs in conserved order), and color by syntenic depth
- open the same pairs in a dotplot, and convert an MCScanX run the same way
Prerequisites
- jcvi with the LAST aligner
- Or, in place of jcvi, an existing MCScanX run: converting one needs only python3
- the NCBI
datasetsCLI - gffread
samtools- A running JBrowse instance (the web quickstart or the desktop quickstart)
# Debian/Ubuntu
sudo apt install samtools gffread last-align
# or conda, which has every tool above
conda install -c bioconda -c conda-forge samtools gffread ncbi-datasets-cli \
last
# or Linux x86_64 binaries for the tools apt lacks
wget -P ~/.local/bin \
https://ftp.ncbi.nlm.nih.gov/pub/datasets/command-line/v2/linux-amd64/datasets \
https://ftp.ncbi.nlm.nih.gov/pub/datasets/command-line/v2/linux-amd64/dataformat
chmod +x ~/.local/bin/datasets ~/.local/bin/dataformat
# any platform
pip install jcviThe data
Grape (Jaillon et al. 2007) and peach
RefSeq assemblies and annotations, each fetched by accession with the datasets
CLI: the same two genomes Synteny from an ortholog table (grape, peach, cacao)
stacks with cacao.
The tracks below read hosted copies of the files the build script writes from these, so you don't need these files to follow the page; run Producing the BEDs and anchor files with jcvi on a GFF3 and a genome FASTA per genome of your own.
| What it is | File |
|---|---|
| Grape | GCF_030704535.1_ASM3070453v1/ |
| Peach | GCF_000346465.2_Prunus_persica_NCBIv2/ |
What .anchors and .anchors.simple hold
The run writes two files that JBrowse loads as separate synteny tracks.
.anchors, via MCScanAnchorsAdapter, is the gene-pair level: each line is one
orthologous pair and its alignment score, with ### separating synteny blocks.
Each id is an NCBI mRNA, grape first:
###
rna-XM_019221872.2 rna-XM_007222072.2 1120
rna-XM_010651756.3 rna-XM_020568908.1 526
rna-XM_010651744.3 rna-XM_007225432.2 2020.anchors.simple, via MCScanSimpleAnchorsAdapter, is the same run reduced to
one line per block: the first and last gene of the block on each side, a score,
and the block's orientation:
rna-XM_019221872.2 rna-XM_010651102.3 rna-XM_007225348.2 rna-XM_007222072.2 86 -
rna-XM_002279913.5 rna-XM_002285264.5 rna-XM_007227461.2 rna-XM_007222578.2 370 +
rna-XM_002281938.5 rna-XM_010652331.3 rna-XM_007222787.2 rna-XM_020562574.1 39 +.anchors.simple draws one ribbon per block where .anchors draws one per gene
pair. The BED files supply the coordinates for both.
BED files mapping gene ids to coordinates
One BED per genome, prepared from its GFF3 before the ortholog run. The adapters read the first six columns, and column 4 must match the anchor gene ids byte for byte:
NC_081805.1 37288 41411 rna-XM_019221872.2 0 +
NC_081805.1 53914 63050 rna-XM_010651756.3 0 +Column 1 must name a sequence the JBrowse assembly knows, directly or through
its alias table: the hub assemblies below resolve NC_081805.1 to grape chr1.
A gene id in the anchors file that no BED names breaks the join, and some such
mismatches load with no error; the
synteny track guide
lists which. The mismatch that matters here is jcvi stripping isoform suffixes
from the ids unless run with --no_strip_names, which the command in the next
section passes.
Producing the BEDs and anchor files with jcvi
gffread extracts each genome's CDS from its GFF3 and FASTA, and jcvi writes the BED with the same ids:
gffread grape.gff3 -g grape.fa -x grape.cds.fa
# --key=ID writes each mRNA's GFF3 ID into BED column 4, the name gffread gave
# its CDS; --primary_only keeps one transcript per gene
python -m jcvi.formats.gff bed --type=mRNA --key=ID --primary_only \
grape.gff3 -o grape.bed
python -m jcvi.formats.fasta format grape.cds.fa grape.cdsPeach goes through the same three commands. One ortholog run then writes the
gene pairs, and screen --simple reduces them to blocks:
# --no_strip_names keeps the ids matching the BEDs; --no_dotplot skips jcvi's
# own PDF, which needs LaTeX
python -m jcvi.compara.catalog ortholog --no_strip_names --no_dotplot grape peach
# --simple writes grape.peach.anchors.simple; --minspan=30 keeps blocks of 30
# genes or more
python -m jcvi.compara.synteny screen --minspan=30 --simple \
grape.peach.anchors grape.peach.anchors.newThe adapters read anchors and BED files plain or gzipped. The configs below name
gzipped copies, which gzip -k makes of each of the four files; drop .gz from
a uri to read the plain file.
Setting up the grape and peach assemblies
Grape and peach are each a genome hub on
genomes.jbrowse.org under the RefSeq accession
the BEDs were built from, and the build takes each assembly entry and NCBI
RefSeq gene track from there, as
the three-genome page
shows. Each entry carries the short name as an alias, so a session can still say
grape.
A genome of your own loads from its FASTA, with a .fai from samtools faidx
beside it:
Goes in the assemblies array of config.json. See Assemblies.
{ "name": "myGenome", "uri": "myGenome.fa" }jbrowse add-assembly myGenome.fa \
--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
myGenome.fa.faiJBrowse reads the format off the file name. Then fill in:
- Genome name:
myGenome
myGenome.fa is relative to a config.json. Replace it with its URL or its path on this computer.
Each genome also gets a gene track, which the
close-up below turns to Show only
genes. Swap the uri for your own GFF3, bgzipped and tabix-indexed
(prep):
Goes in the tracks array of config.json. See Tracks.
{
"type": "FeatureTrack",
"trackId": "myGenome_genes",
"name": "myGenome genes",
"assemblyNames": ["myGenome"],
"adapter": {
"type": "Gff3TabixAdapter",
"uri": "myGenome.sorted.gff3.gz"
}
}jbrowse add-track myGenome.sorted.gff3.gz \
--trackId myGenome_genes \
--name "myGenome genes" \
--assemblyNames myGenome \
--load copyIn JBrowse Desktop, or in any running JBrowse Web session, open a view on this track’s assembly, then File → Open track... and, in Add a track from file or URL, enter:
- Main file:
myGenome.sorted.gff3.gz
Click Next. JBrowse reads the adapter and track type off the file name. Then fill in:
- Track name:
myGenome genes - Assembly:
myGenome
Click Add.
myGenome.sorted.gff3.gz is relative to a config.json. Replace it with its URL or its path on this computer.
Loading the .anchors and .anchors.simple tracks
Each adapter takes the anchor file plus the two BEDs, and assemblyNames lists
the genomes in the order the anchor columns are in (column 1's genome first,
grape here):
Goes in the tracks array of config.json. See Tracks.
{
"type": "SyntenyTrack",
"trackId": "grape_peach_anchors",
"name": "Grape peach synteny (MCScan, anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanAnchorsAdapter",
"uri": "grape.peach.anchors.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
}
}jbrowse add-track grape.peach.anchors.gz \
--trackId grape_peach_anchors \
--name "Grape peach synteny (MCScan, anchors)" \
--assemblyNames GCF_030704535.1,GCF_000346465.2 \
--bed1 grape.bed.gz \
--bed2 peach.bed.gz \
--load copyIn 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": "grape_peach_anchors",
"name": "Grape peach synteny (MCScan, anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanAnchorsAdapter",
"uri": "grape.peach.anchors.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
}
}grape.peach.anchors.gz is relative to a config.json. Replace it with its URL or its path on this computer.
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.
The .anchors.simple track takes the same shape with the adapter type and file
swapped:
Goes in the tracks array of config.json. See Tracks.
{
"type": "SyntenyTrack",
"trackId": "grape_peach_anchors_simple",
"name": "Grape peach synteny (MCScan, simple anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanSimpleAnchorsAdapter",
"uri": "grape.peach.anchors.simple.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
}
}jbrowse add-track grape.peach.anchors.simple.gz \
--trackId grape_peach_anchors_simple \
--name "Grape peach synteny (MCScan, simple anchors)" \
--assemblyNames GCF_030704535.1,GCF_000346465.2 \
--bed1 grape.bed.gz \
--bed2 peach.bed.gz \
--load copyIn 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": "grape_peach_anchors_simple",
"name": "Grape peach synteny (MCScan, simple anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanSimpleAnchorsAdapter",
"uri": "grape.peach.anchors.simple.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
}
}grape.peach.anchors.simple.gz is relative to a config.json. Replace it with its URL or its path on this computer.
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.
MCScanAnchorsAdapter and MCScanSimpleAnchorsAdapter read the whole file into
memory, which MCScan output is small enough for.
Viewing gene pairs and blocks in one synteny view
We'll start with Add → Linear synteny view and pick peach and grape. Then:
- Turn on both MCScan tracks in the band between them.
- Turn on the simple-anchors track in each panel's track selector, where it draws as a row of bars.
The bars in each panel come from the block track's LGVSyntenyDisplay, which
draws synteny as features in an ordinary linear genome view row. Selecting it by
name needs the full displays array:
Goes in the tracks array of config.json. See Tracks.
{
"type": "SyntenyTrack",
"trackId": "grape_peach_anchors_simple",
"name": "Grape peach synteny (MCScan, simple anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanSimpleAnchorsAdapter",
"uri": "grape.peach.anchors.simple.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
},
"displays": [
{
"type": "LGVSyntenyDisplay",
"height": 60
}
]
}jbrowse add-track-json '{
"type": "SyntenyTrack",
"trackId": "grape_peach_anchors_simple",
"name": "Grape peach synteny (MCScan, simple anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanSimpleAnchorsAdapter",
"uri": "grape.peach.anchors.simple.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
},
"displays": [
{
"type": "LGVSyntenyDisplay",
"height": 60
}
]
}'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": "grape_peach_anchors_simple",
"name": "Grape peach synteny (MCScan, simple anchors)",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"],
"adapter": {
"type": "MCScanSimpleAnchorsAdapter",
"uri": "grape.peach.anchors.simple.gz",
"bed1": "grape.bed.gz",
"bed2": "peach.bed.gz",
"assemblyNames": ["GCF_030704535.1", "GCF_000346465.2"]
},
"displays": [
{
"type": "LGVSyntenyDisplay",
"height": 60
}
]
}grape.peach.anchors.simple.gz is relative to a config.json. Replace it with its URL or its path on this computer.
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.
A single gene pair up close
Zoom to one block with both gene tracks on and set to Filter by... → Genes → Only genes.
MCScan anchors only the pairs it could call confidently, so most genes have no ribbon.
Copies sharing one ortholog
Pick Color by value → Syntenic depth on the palette button in the view
header. A ribbon stays grey where its two genes pair only with each other, and
turns orange where several genes share one ortholog. The count covers the whole
.anchors file, so a gene whose other copies are off screen still takes color.
Viewing the gene pairs as a dotplot
The anchors track and the simple anchors track also load in a dotplot, where a gene pair is one point and a block a run of them; Add → Dotplot view opens one. The axes start in index order; Re-order chromosomes, in the overflow menu of the dotplot header, sorts the vertical axis to follow the horizontal one.
Re-order chromosomes puts each peach chromosome's strongest grape partner on the diagonal, and its other partners stay off it.
Converting an MCScanX run
MCScanX is a different program from jcvi's
MCScan. It writes one .collinearity holding every block, self-synteny and
cross-species together, and tells genomes apart by a two-letter tag on each
chromosome name.
mcscanx_to_anchors.py
splits a run into the four files jcvi writes, in place of the
jcvi step:
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/mcscanx_to_anchors.py
python3 mcscanx_to_anchors.py --gff xyz.gff --collinearity xyz.collinearity \
--species vv=grape --species pp=peach --strand-gff3 peach=peach.gff3.gzThe track configs above load the converted files
unchanged. --species order is the anchors column order, so it has to match the
track's assemblyNames. Two options decide whether the result draws:
--chr-prefix peach=chrGprepends to the refNames, and--keep-chr-tagkeeps MCScanX's tag, stripped by default (vv1becomes1)--strand-gff3 peach=peach.gff3.gzrecovers strand from the annotation, so an inverted.anchorspair draws as inverted
--fai peach=peach.fa.fai checks the refNames against the assembly; an unknown
name draws empty. An anchors score becomes -log10 of MCScanX's e-value.
The number of --species names sets what the run writes:
- A third species writes an ortholog table instead, since one
.collinearitycovers every pair. See ortholog tables. - A single species keeps the blocks duplicated within that genome, which Synteny visualization (a polyploid against itself) draws as a dotplot of one assembly on both axes.
Reproduce it end to end
build_grape_peach_anchors.sh
runs everything above and writes a config.json with both assemblies, gene
tracks, both MCScan tracks and a default session opening them together:
- Download the grape and peach RefSeq genomes and annotations by accession, dropping organelle genes, which gffread rejects.
- Write a BED and a CDS file per genome keyed on the mRNA ID, and run jcvi with
--no_strip_namesso the anchor ids match the BEDs. - Screen the gene pairs into blocks for
.anchors.simple. - Write the config with both hub assemblies and gene tracks, both MCScan tracks and a session.
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_grape_peach_anchors.sh
bash build_grape_peach_anchors.sh
npx --yes serve grape_peach_anchors_build # then open config.json thereSee also
- Tutorial: Synteny visualization (pairwise minimap2)
- Tutorial: Synteny from an ortholog table (grape, peach, cacao)
- User guide: Linear synteny view
- Config guide: Synteny track
- Reference: MCScanAnchorsAdapter
- Reference: MCScanSimpleAnchorsAdapter
Citations
- Tang et al. (2008). Unraveling ancient hexaploidy through multiply-aligned angiosperm gene maps, the MCScan method jcvi implements
- Jaillon et al. (2007). The grapevine genome sequence suggests ancestral hexaploidization in major angiosperm phyla
Feedback on this tutorial is welcome: contact us.