Pangenome (Minigraph-Cactus)
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.
We build a pangenome graph of five E. coli strains with Minigraph-Cactus and
turn its outputs into JBrowse tracks on the K12 genome. One cactus-pangenome
run writes the graph, a VCF, an odgi file, a HAL alignment and short-read
indexes, and we:
- load synteny, variants, a whole-genome alignment (MAF), depth and per-strain presence as tracks
- map the reads of an isolate outside the graph through it
- index the graph and draw it as a track
The graph view is a beta plugin. We welcome your feedback.
Prerequisites
dockerorsingularity, for the cactus image, which includes odgi, halSynteny, hal2maf,vgandsamtools- htslib (
bgzip,tabix) andpython3 node, for the JBrowse CLI- the GraphGenomeView plugin, for drawing the graph as a graph. In your own JBrowse, install it from the plugin store
gfa-to-tabix0.12.0 or later andgfatools, for indexing the graph- for the whole build: the NCBI
datasetsCLI,bedGraphToBigWig(UCSC kentUtils),samtools,unzipandwget
On Debian/Ubuntu, apt install samtools tabix unzip wget python3 covers five of
those; cargo install gfa-to-tabix installs gfa-to-tabix, bioconda packages
gfatools, and datasets and bedGraphToBigWig are each a
single-binary download.
Where the data comes from
The five E. coli RefSeq assemblies come from the NCBI datasets CLI by
accession. K12 is the --reference backbone the other four align onto.
The build script takes these files from their URLs, so there is nothing to download by hand.
- K12: ftp.ncbi.nlm.nih.gov/…/GCF_000005845.2_ASM584v2https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/000/005/845/GCF_000005845.2_ASM584v2/
- Sakai: ftp.ncbi.nlm.nih.gov/…/GCF_000008865.2_ASM886v2https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/000/008/865/GCF_000008865.2_ASM886v2/
- CFT073: ftp.ncbi.nlm.nih.gov/…/GCF_000007445.1_ASM744v1https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/000/007/445/GCF_000007445.1_ASM744v1/
- NCTC86: ftp.ncbi.nlm.nih.gov/…/GCF_002007705.1_ASM200770v1https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/002/007/705/GCF_002007705.1_ASM200770v1/
- IAI39: ftp.ncbi.nlm.nih.gov/…/GCF_000026345.1_ASM2634v1https://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/000/026/345/GCF_000026345.1_ASM2634v1/
- KTa004 short reads mapped through the finished graph, forward mate: ftp.sra.ebi.ac.uk/…/DRR063408_1.fastq.gzhttps://ftp.sra.ebi.ac.uk/vol1/fastq/DRR063/DRR063408/DRR063408_1.fastq.gz
- KTa004 short reads, reverse mate: ftp.sra.ebi.ac.uk/…/DRR063408_2.fastq.gzhttps://ftp.sra.ebi.ac.uk/vol1/fastq/DRR063/DRR063408/DRR063408_2.fastq.gz
Read by URL (no download needed)
- the graph's segments, tabix-indexed, which the graph track below reads: jbrowse.org/…/ecoli_cactus.segs.bed.gzhttps://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus.segs.bed.gz
- the graph's links: jbrowse.org/…/ecoli_cactus.links.bed.gzhttps://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus.links.bed.gz
Building the graph with cactus-pangenome
Minigraph-Cactus
(cactus-pangenome) builds a pangenome graph reference-first.
minigraph lays down a backbone from the
reference you pick, and Cactus aligns every other sample onto it and normalizes
the result into a graph. It takes a seqFile: one name<TAB>path line per
sample.
cat > seqfile.txt <<'EOF'
K12 K12.fa
Sakai Sakai.fa
CFT073 CFT073.fa
NCTC86 NCTC86.fa
IAI39 IAI39.fa
EOFContigs keep their plain names here (chr). Cactus applies
PanSN sample#haplotype#contig
naming to the graph internally.
Every step runs in the same cactus image (Cactus also ships a
binary release
for a machine with no container runtime), so wrap the docker run once:
in_cactus() {
docker run --rm -u "$(id -u):$(id -g)" -w /data -v "$PWD":/data \
quay.io/comparative-genomics-toolkit/cactus:v3.2.1 "$@"
}Under singularity,
singularity exec --bind "$PWD":/data --pwd /data docker://<image> replaces the
wrapper body. The build script picks the runtime off
PATH.
--reference K12 makes K12 the minigraph backbone and the path every output is
decomposed against:
in_cactus cactus-pangenome /data/js /data/seqfile.txt \
--outDir /data/mc --outName ecoli --reference K12 \
--vcf --gfa --gbz --odgi --viz --draw --giraffe --consCores 8/data/jsis the Toil job store, and must not already exist on a fresh run.--outName ecoliprefixes every output file.--vcfdeconstructs the graph into the variants track's input.--odgiwrites the.ogthat the depth and presence tracks read.--vizwrites the odgi raster shown at the end.--giraffewrites the indexes the read-mapping section needs (mc/ecoli.d2.gbzand its.dist/.min/.zipcodes), built over the graph filtered to sequence at least two haplotypes have.
Load the genomes
Every projection is a track on a strain's assembly, and each strain's FASTA
holds one sequence named chr. We'll add K12, the reference the projections
land on, from a bgzip-compressed, indexed FASTA:
Goes in the assemblies array of config.json. See Assemblies.
{
"name": "K12",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/K12.fa.gz"
}jbrowse add-assembly https://jbrowse.org/demos/ecoli_pangenome/K12.fa.gz \
--name K12In 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/demos/ecoli_pangenome/K12.fa.gz
https://jbrowse.org/demos/ecoli_pangenome/K12.fa.gz.fai
https://jbrowse.org/demos/ecoli_pangenome/K12.fa.gz.gziJBrowse reads the format off the file name. Then fill in:
- Genome name:
K12
Sakai, CFT073, NCTC86 and IAI39 load the same way, one assembly per strain,
named as in the assemblyNames of the tracks below.
Synteny between all five strains (halSynteny)
halSynteny reads the
HAL's base-level alignment and emits synteny blocks per genome pair as PSL with
no sample tag in its sequence names, so the
build script runs it for all ten pairs and converts
each to PAF with PanSN sample#0#chr names.
Index the combined PAF so a range query fetches only the region in view:
jbrowse make-pif ecoli_cactus_ava.paf # -> ecoli_cactus_ava.pif.gz (+ .tbi)Load it with an
MultiGenomeIndexedPAFAdapter,
whose PanSN sample# prefix on every record is how it maps a record to its
strain:
Goes in the tracks array of config.json. See Tracks.
{
"type": "SyntenyTrack",
"trackId": "ecoli_cactus_ava",
"name": "MC graph: all-vs-all synteny (halSynteny)",
"assemblyNames": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"],
"adapter": {
"type": "MultiGenomeIndexedPAFAdapter",
"uri": "ecoli_cactus_ava.pif.gz",
"assemblyNames": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"]
}
}jbrowse add-track ecoli_cactus_ava.pif.gz \
--trackId ecoli_cactus_ava \
--name "MC graph: all-vs-all synteny (halSynteny)" \
--assemblyNames K12,Sakai,CFT073,NCTC86,IAI39 \
--adapterType MultiGenomeIndexedPAFAdapter \
--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": "ecoli_cactus_ava",
"name": "MC graph: all-vs-all synteny (halSynteny)",
"assemblyNames": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"],
"adapter": {
"type": "MultiGenomeIndexedPAFAdapter",
"uri": "ecoli_cactus_ava.pif.gz",
"assemblyNames": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"]
}
}ecoli_cactus_ava.pif.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.
To stack the five strains, a linear synteny view takes one panel per strain and
names the track once in tracks, which puts it on every band. Put this in the
session's views, or use Add → Linear synteny view, whose Quick start fills
in a row per assembly the track lists.
{
"type": "LinearSyntenyView",
"views": [
{ "assembly": "K12" },
{ "assembly": "Sakai" },
{ "assembly": "CFT073" },
{ "assembly": "NCTC86" },
{ "assembly": "IAI39" }
],
"tracks": ["ecoli_cactus_ava"],
"minAlignmentLength": 10000,
"levelHeights": [110, 110, 110, 110],
"color": { "field": "strand" }
}In grammar-of-graphics terms, color is a color scale that maps each ribbon's
strand to red where the two strains run the same way and blue where one is
inverted against the other.
Variants against K12 (vg deconstruct)
--vcf decomposes the graph against K12 with
vg deconstruct, genotyped across the other
four strains. Its CHROM is already chr, so the .gz and .tbi Cactus wrote
load unchanged as a VariantTrack with the
matrix display, one column per variant and one row per sample:
Goes in the tracks array of config.json. See Tracks.
{
"type": "VariantTrack",
"trackId": "ecoli_cactus_variants",
"name": "MC graph: pangenome variants (vs K12)",
"uri": "mc/ecoli.vcf.gz",
"assemblyNames": ["K12"],
"displays": [
{
"type": "LinearMultiSampleVariantDisplay",
"variantLayout": "columns",
"unit": "haplotype"
}
]
}jbrowse add-track-json '{
"type": "VariantTrack",
"trackId": "ecoli_cactus_variants",
"name": "MC graph: pangenome variants (vs K12)",
"uri": "mc/ecoli.vcf.gz",
"assemblyNames": ["K12"],
"displays": [
{
"type": "LinearMultiSampleVariantDisplay",
"variantLayout": "columns",
"unit": "haplotype"
}
]
}'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": "VariantTrack",
"trackId": "ecoli_cactus_variants",
"name": "MC graph: pangenome variants (vs K12)",
"uri": "mc/ecoli.vcf.gz",
"assemblyNames": ["K12"],
"displays": [
{
"type": "LinearMultiSampleVariantDisplay",
"variantLayout": "columns",
"unit": "haplotype"
}
]
}mc/ecoli.vcf.gz is relative to a config.json. Replace it with its URL or its path on this computer.
Each strain is one haplotype, so unit: "haplotype" draws one row per strain,
colored by that strain's allele. The
multi-sample variant track guide covers
columns versus genomic positions, the genotype colors, and clustering samples by
genotype.
vg deconstruct writes a record per snarl (vg's word for a bubble) at every
nesting level, so wide records paint over finer ones. cactus-pangenome prunes
that tree with vcfbub by default;
--vcfbub 0 turns that off, and --vcfwave realigns the remaining records into
primitive variants.
Whole-genome alignment onto K12 (MAF)
The MAF comes out of mc/ecoli.full.hal. hal2maf --refGenome K12 roots every
block on K12, and the rows come out as K12.chr, Sakai.chr, and so on, the
sample.contig naming the MAF display splits species on:
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/maf_to_bed.py
in_cactus hal2maf --refGenome K12 --noAncestors /data/mc/ecoli.full.hal /data/ecoli_cactus.maf
python3 maf_to_bed.py ecoli_cactus.maf ecoli_cactus.maf.bed
bgzip ecoli_cactus.maf.bed
tabix -p bed ecoli_cactus.maf.bed.gzmaf_to_bed.py
writes one line per block, which a
MafTabixAdapter reads. The streaming
maf2bed converts this MAF too; see
producing the tabix BED.
Goes in the tracks array of config.json. See Tracks.
{
"type": "MafTrack",
"trackId": "ecoli_cactus_maf",
"name": "MC graph: whole-genome alignment (MAF, vs K12)",
"assemblyNames": ["K12"],
"adapter": {
"type": "MafTabixAdapter",
"samples": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"],
"uri": "ecoli_cactus.maf.bed.gz"
}
}jbrowse add-track-json '{
"type": "MafTrack",
"trackId": "ecoli_cactus_maf",
"name": "MC graph: whole-genome alignment (MAF, vs K12)",
"assemblyNames": ["K12"],
"adapter": {
"type": "MafTabixAdapter",
"samples": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"],
"uri": "ecoli_cactus.maf.bed.gz"
}
}'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": "MafTrack",
"trackId": "ecoli_cactus_maf",
"name": "MC graph: whole-genome alignment (MAF, vs K12)",
"assemblyNames": ["K12"],
"adapter": {
"type": "MafTabixAdapter",
"samples": ["K12", "Sakai", "CFT073", "NCTC86", "IAI39"],
"uri": "ecoli_cactus.maf.bed.gz"
}
}ecoli_cactus.maf.bed.gz is relative to a config.json. Replace it with its URL or its path on this computer.
A row with no colored columns shares its sequence with K12, and a row that stops has no alignment to K12 there. The coverage band tells the two apart.
samples names the rows and fixes their order. To order them by shared graph
content instead, build a tree from
odgi similarity
and point nhLocation at it, as the
pggb tutorial's MAF track
does:
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/odgi_similarity_to_newick.py
# -D '#' -p 1: group the paths by sample, the first field of each PanSN name
in_cactus odgi similarity -i /data/mc/ecoli.full.og -D '#' -p 1 > ecoli_cactus_similarity.tsv
python3 odgi_similarity_to_newick.py ecoli_cactus_similarity.tsv ecoli_cactus.nhPangenome depth and per-strain presence
odgi depth
counts how many paths traverse the graph under each K12 base, and
odgi pav
splits that per strain. Both run over mc/ecoli.full.og in 500 bp windows of
K12's path, which Cactus names K12#0#chr:
# the windows, and the reference length bedGraphToBigWig needs
reflen=$(awk '!/^>/ { c += length($0) } END { print c }' K12.fa)
printf 'chr\t%s\n' "$reflen" > chrom.sizes
awk -v p="K12#0#chr" -v len="$reflen" -v w=500 \
'BEGIN { for (s = 0; s < len; s += w) { e = s + w; if (e > len) e = len
print p "\t" s "\t" e } }' > depth_windows.bed
in_cactus odgi depth -i /data/mc/ecoli.full.og -b /data/depth_windows.bed |
awk -v p="K12#0#chr" -v OFS='\t' '$1 == p && $4 + 0 == $4 { print "chr", $2, $3, $4 }' |
sort -k1,1 -k2,2n > ecoli_cactus_depth.bedgraph
bedGraphToBigWig ecoli_cactus_depth.bedgraph chrom.sizes ecoli_cactus_depth.bwEach other strain's path name ends in a subpath tag (Sakai#0#chr#0), so the
per-strain filter matches the sample prefix:
in_cactus odgi pav -i /data/mc/ecoli.full.og -b /data/depth_windows.bed > pav.tsv
for strain in Sakai CFT073 NCTC86 IAI39; do
awk -F'\t' -v OFS='\t' -v s="$strain" \
'$5 ~ "^" s "#" && $6 + 0 == $6 { print "chr", $2, $3, $6 }' pav.tsv |
sort -k1,1 -k2,2n > "pav_${strain}.bedgraph"
bedGraphToBigWig "pav_${strain}.bedgraph" chrom.sizes "ecoli_cactus_pav_${strain}.bw"
doneEach strain's presence bigWig loads as one row of a
MultiQuantitativeTrack,
the
pggb page's presence track
with ecoli_cactus_pav_ in each uri.
Depth counts path steps, so a repeat the graph folded onto one run of nodes reads above the strain count. seqwish, pggb's graph builder, folds the rRNA copies together; the reference-first graph keeps them apart.
To compare the two builders, load both depth curves as rows of one track on a
fixed axis, and type chr:3,935,000-3,955,000, the rrnC operon (a ribosomal RNA
gene copy):
Goes in the tracks array of config.json. See Tracks.
{
"type": "MultiQuantitativeTrack",
"trackId": "ecoli_depth_by_builder",
"name": "Pangenome depth over K12, by builder (odgi depth)",
"assemblyNames": ["K12"],
"adapter": {
"type": "MultiWiggleAdapter",
"subadapters": [
{
"type": "BigWigAdapter",
"name": "pggb",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_pggb_depth.bw"
},
{
"type": "BigWigAdapter",
"name": "Minigraph-Cactus",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus_depth.bw"
}
]
},
"displayDefaults": { "scales": { "y": { "domainMin": 0, "domainMax": 10 } } }
}jbrowse add-track-json '{
"type": "MultiQuantitativeTrack",
"trackId": "ecoli_depth_by_builder",
"name": "Pangenome depth over K12, by builder (odgi depth)",
"assemblyNames": ["K12"],
"adapter": {
"type": "MultiWiggleAdapter",
"subadapters": [
{
"type": "BigWigAdapter",
"name": "pggb",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_pggb_depth.bw"
},
{
"type": "BigWigAdapter",
"name": "Minigraph-Cactus",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus_depth.bw"
}
]
},
"displayDefaults": { "scales": { "y": { "domainMin": 0, "domainMax": 10 } } }
}'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": "MultiQuantitativeTrack",
"trackId": "ecoli_depth_by_builder",
"name": "Pangenome depth over K12, by builder (odgi depth)",
"assemblyNames": ["K12"],
"adapter": {
"type": "MultiWiggleAdapter",
"subadapters": [
{
"type": "BigWigAdapter",
"name": "pggb",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_pggb_depth.bw"
},
{
"type": "BigWigAdapter",
"name": "Minigraph-Cactus",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus_depth.bw"
}
]
},
"displayDefaults": { "scales": { "y": { "domainMin": 0, "domainMax": 10 } } }
}Mapping a new isolate through the graph
We'll map the short reads of a sample outside the graph through the whole pangenome and project the result onto K12. A read that follows another strain's path through a variable region has no mismatches or soft clips and lands at that region's K12 coordinates. A read over sequence K12 lacks has no K12 coordinate and stays unmapped.
--giraffe wrote the indexes during the build. vg giraffe emits a GAM, and
vg surject projects it onto one path as a BAM. The reads are E. coli KTa004
(ENA DRR063408, Illumina
MiSeq), a strain the graph has never seen:
# -Z/-d/-m/-z are the graph and the three indexes --giraffe built; -f takes
# the paired FASTQs, one flag per mate; -p shows progress
in_cactus vg giraffe -p \
-Z /data/mc/ecoli.d2.gbz -d /data/mc/ecoli.d2.dist \
-m /data/mc/ecoli.d2.shortread.withzip.min -z /data/mc/ecoli.d2.shortread.zipcodes \
-f /data/reads/sub_1.fastq.gz -f /data/reads/sub_2.fastq.gz > mapped.gam
# -x is the graph the GAM was mapped against; -b writes BAM instead of GAM;
# -p is the path to surject onto, so the BAM's one reference sequence is that
# PanSN name; -N/-R set the sample name and read group on every read
in_cactus vg surject -x /data/mc/ecoli.d2.gbz -b -p K12#0#chr \
-N KTa004 -R KTa004 /data/mapped.gam > mapped.raw.bamThe BAM's one reference sequence is the PanSN path name, which matches no
assembly. Rename it to the assembly's refName (chr) in the header, drop the
unmapped reads, then sort and index:
samtools view -H mapped.raw.bam | sed 's|SN:K12#0#chr|SN:chr|' > reads_hdr.sam
samtools reheader reads_hdr.sam mapped.raw.bam > reads_reheader.bam
samtools view -b -F 4 reads_reheader.bam > reads_mapped.bam
samtools sort -o ecoli_cactus_reads.bam reads_mapped.bam
samtools index ecoli_cactus_reads.bamThe build script also subsamples the reads. The result loads as an ordinary alignments track:
Goes in the tracks array of config.json. See Tracks.
{
"trackId": "ecoli_cactus_reads",
"name": "KTa004 reads mapped through the graph (vs K12)",
"uri": "ecoli_cactus_reads.bam",
"assemblyNames": ["K12"]
}jbrowse add-track ecoli_cactus_reads.bam \
--trackId ecoli_cactus_reads \
--name "KTa004 reads mapped through the graph (vs K12)" \
--assemblyNames K12 \
--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:
ecoli_cactus_reads.bam
Click Next. JBrowse reads the adapter and track type off the file name. Then fill in:
- Track name:
KTa004 reads mapped through the graph (vs K12) - Assembly:
K12
Click Add.
ecoli_cactus_reads.bam is relative to a config.json. Replace it with its URL or its path on this computer.
vg giraffe rewrites ecoli.d2.dist as it runs, leaving it newer than the
.min and .zipcodes built from it, so a second run refuses to start. touch
the two derived files before re-mapping.
Drawing the graph as a graph
The graph genome view plugin draws the graph as a track of the linear view. Pangenome (hosting your own graph) covers installing the plugin and the one command that indexes a graph for it.
Indexing the graph
cactus-pangenome also wrote mc/ecoli.sv.gfa.gz, the graph its minigraph
stage built. This rGFA of the structural variation states each segment's place
on a genome in SN/SO/SR tags, so
gfa-to-tabix build indexes it
with no further arguments:
# gfa-to-tabix build runs gfatools for the bubbles, so it has to be on PATH
gfa-to-tabix build mc/ecoli.sv.gfa.gz -o ecoli_cactus_svThe command writes the segments and links, the bubbles, a coarse tier (one node
per bubble), the allele inventory (one row per alternative path),
ecoli_cactus_sv.config.json, whose graph track names the tier under coarse,
and ecoli_cactus_sv.graph.json, from which Add pangenome graph track picks up
the tier.
The figures below draw the base-level graph, where every SNP is a bubble. That
GFA has no rGFA tags, so --reference makes the command place segments by
following the reference's path lines:
gfa-to-tabix build mc/ecoli.gfa.gz -o ecoli_cactus --reference K12Without --snarls the command writes no bubble file. Our hosted copy of the
index loads as one GraphTrack at the shared prefix:
Goes in the tracks array of config.json. See Tracks.
{
"type": "GraphTrack",
"trackId": "ecoli_cactus_segments",
"name": "MC graph: segments (whole graph, by locus)",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus"
},
"displayDefaults": { "showLabels": "none" },
"displays": [
{ "type": "LinearGraphDisplay" },
{ "type": "LinearBasicDisplay" }
]
}jbrowse add-track-json '{
"type": "GraphTrack",
"trackId": "ecoli_cactus_segments",
"name": "MC graph: segments (whole graph, by locus)",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus"
},
"displayDefaults": { "showLabels": "none" },
"displays": [
{ "type": "LinearGraphDisplay" },
{ "type": "LinearBasicDisplay" }
]
}'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": "GraphTrack",
"trackId": "ecoli_cactus_segments",
"name": "MC graph: segments (whole graph, by locus)",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "https://jbrowse.org/demos/ecoli_pangenome/ecoli_cactus"
},
"displayDefaults": { "showLabels": "none" },
"displays": [
{ "type": "LinearGraphDisplay" },
{ "type": "LinearBasicDisplay" }
]
}Turned on, the track draws the window as a graph on K12's coordinates. In its track menu, Display types → Feature display draws the same segments as a row of blocks instead.
Past the flagellar operon, K12 has an IS1 element (a short insertion sequence) the other four skip. To see it:
- Type
chr:1,978,100-1,979,700. - Pick Force-directed under the Layout row of the graph track's menu.
- Add a second copy of the segments track, colored by how many strains the
SM:Z:tag lists for each segment (config on the pggb page). - Show the MAF track above the graph: the strains-per-segment track counts the strains, and the MAF's rows name them.
In the track menu, Show... → Show deletion edges hides the dashed link the graph draws for the other four strains' route, which is labelled with the length of the node it skips.
Comparing odgi viz's node-order axis with K12's coordinates
Open mc/ecoli.viz/chr.full.viz.png, the
odgi viz
raster --viz wrote, with one row per strain and graph node order on the
horizontal axis.
The odgi pav track contains the same paths. Drawn on K12's coordinates, in the
raster's row order and colors, they differ only on the horizontal axis. The gold
band marks chr:1,000,000-1,100,000 in both.
The graph axis counts pangenome bases, so a locus where other strains have sequence K12 lacks takes up more of it. The band contains Sakai's stx2 prophage and a second Sakai-only stretch.
Reproduce it end to end
build_ecoli_pangenome_cactus.sh
runs everything above in one shot. It:
- downloads the five RefSeq genomes, keeping only each one's chromosome, and
runs
cactus-pangenome - converts the HAL, VCF,
odgi depthandodgi pavinto the projections above, and maps the KTa004 reads - indexes the base-level graph by following the reference's paths, as the graph-hosting tutorial describes
- writes a
config.jsonwith the five assemblies, per-strain gene tracks, the projection and segments tracks, the plugin declaration and a default session
curl -fO https://raw.githubusercontent.com/GMOD/jbrowse-components/main/scripts/build_ecoli_pangenome_cactus.sh
bash build_ecoli_pangenome_cactus.sh # builds ./ecoli_cactus_build/jbrowse2
npx --yes serve ecoli_cactus_build/jbrowse2The script needs the tools under Prerequisites; force a
container runtime with CONTAINER=singularity.
See also
- Tutorial: Pangenome (pggb)
- Tutorial: Pangenome (HPRC) part 1: the graph's alleles and the haplotypes that have them
- Tutorial: Synteny visualization (all-vs-all minimap2)
- User guide: Graph genome view
- User guide: MAF track
External links
Feedback on this tutorial is welcome: contact us.