Graph genome view
The graph genome view plugin draws a pangenome graph as a graph, as a track of the linear genome view. The graph sits under the view's other tracks, on the view's coordinates, and moves when the view moves. The reference's path through the graph is the backbone, and every segment off that path is an alternate allele from another assembly. Most other pangenome tracks are projections, which flatten the graph onto one reference's coordinates as synteny, variants, alignment, or depth.
Prerequisites: the plugin (below), a graph in rGFA or GFA, and the contributing assemblies if you want to open a node on them.
The graph track comes from a separate plugin,
jbrowse-plugin-graphgenomeviewer,
not bundled in JBrowse Web, because its force-directed layout uses the
GPL-licensed Bandage engine (its
OGDF FMMM layout). The plugin is in beta, and the
plugin store lists it as GraphGenomeView. A
config names it with the entry below, where storePlugin picks the build for
the JBrowse reading the config and esmUrl is the fallback when the store
cannot be read (configuring plugins).
{
"plugins": [
{
"name": "GraphGenomeView",
"storePlugin": "GraphGenomeView",
"esmUrl": "https://jbrowse.org/plugins/jbrowse-plugin-graphgenomeviewer/latest/dist/jbrowse-plugin-graphgenomeviewer.esm.js"
}
]
}RgfaTabixAdapter and MinigraphBubbleAdapter ship in the same plugin. The
plugin needs a JBrowse 5 build (v5.0.0-beta.9 or later). A JBrowse 4 host does
not load it, and a config naming it opens with no graph track and neither
adapter.
Quick start
To index a graph, convert it once into a tabix-indexed BED file that JBrowse can
query by locus, .graph.bed.gz, which holds the segments and the links between
them. One command, gfa-to-tabix build, builds it and writes a track config for
it, as Pangenome (hosting your own graph) describes. Then Add track
with that config, whose adapter is RgfaTabixAdapter, and the track opens as
the graph. Route 1 builds the
index. Skip to Seven layouts if you just need to know what the
track menu's items do.
The graph opens in the Anchored layout, on the view's coordinates, so typing in the location box, a gene search, a click on the cytoband and a drag-zoom move it as they move every other track. When the view moves past the stretch the graph was cut from, the track cuts the new window.
A graph track can also name a coarse tier, the same graph with one node per bubble. Zoomed out past the handover the track names, the track cuts the tier, so a whole chromosome draws as a graph, and zoomed back in it cuts the segments again.
Two adapters cut a subgraph: RgfaTabixAdapter over the index, and
WalkTabixSyntenyAdapter over gfa-to-tabix --walks files, whose cut includes
the haplotypes' walks. A BedTabixAdapter over the RgfaTabixAdapter index
draws only as a lane. To skip indexing entirely, Route 2
opens a GFA as a file.
Segment coordinates by format
A graph is a set of segments and links, which is all force-directed layout needs. Drawing it as a track of a linear view also needs each segment's position on a reference, and the formats differ on where that position is stored.
| Format | Where positions live | Opening a locus |
|---|---|---|
| rGFA (minigraph, the minigraph stage of Minigraph-Cactus) | SN/SO/SR tags on every segment | direct, the file has them |
| plain GFA (pggb, odgi, base-level Minigraph-Cactus) | inside the P/W path lines | walk a path first, in the app or offline |
| assembly graph (SPAdes, Flye, Velvet) | nowhere, there is no reference | not possible |
rGFA and plain GFA both produce a segment track on the reference and a graph that lines up under it. Every feature below except the force layout reads those coordinates. An assembly graph therefore gets no locus cut, neither anchored layout, no hover sync and no graph track. Bandage, whose engine draws the force layout here, was built for assembly graphs, so use Bandage for one.
Route 1: a graph track, browsable by locus
Once indexed, the graph loads as a GraphTrack that draws whatever window is on
screen as a graph.
gfa-to-tabix build
2.0.0 or later builds the index by the route the input format requires, and
every step after that is the same. An rGFA's bubbles also need
gfatools on PATH:
# or a binary from https://github.com/GMOD/gfa-to-tabix/releases
cargo install gfa-to-tabix
# rGFA: the tags are already coordinates, so this is a projection
gfa-to-tabix build ecoli_minigraph.rgfa -o ecoli_minigraph
# plain GFA: walk the P (or W) lines to derive the same thing, with K12 as the
# backbone, and take the bubbles from the snarl VCF that pggb -V wrote
gfa=$(ls pggb/*.smooth.final.gfa)
vcf=$(ls pggb/*.smooth.final.K12.vcf)
gfa-to-tabix build "$gfa" -o ecoli_pggb --reference K12 --snarls "$vcf"The rGFA in these figures is a minigraph graph of five strains, built by the
pangenome tutorials. To build your own,
minigraph needs PanSN-named records. It takes its stable names from the input
FASTA headers, and the per-strain files call their contig chr in all five. Fed
those files, minigraph puts every segment on an ambiguous chr that no later
command can query by strain.
gfa-to-tabix makes four choices when it walks a plain GFA:
--referencenames an assembly, not a path. Every contig that assembly contributes is reference, and the command walks those contigs first, at rank 0. A genome with more than one contig has one reference path per contig. Anchoring on only one of those paths would leave the other contigs' segments to whichever donor path reaches them first. A bare sample (GRCh38) is enough where the reference is haploid. For a diploid reference, write the haplotype (HG002#1), or the command picks one and names it on stderr.- The walk also records which haplotypes visit each segment, as an
SB:H:bitmask in the index over the haplotypes its#samplesheader lists. rGFA has no field for them. On this route that value fillssamplesin the node popup. - When a path reaches a segment twice, the first visit wins, and the node draws as one tube at one x, and the repeat stays visible as depth.
- A segment the reference never visits is placed on the coordinates of the assembly it comes from. rGFA places such segments the same way, which is why a reference query reaches them through the link rows.
gfa-to-tabix build writes <prefix>.graph.bed.gz with its tabix index for an
rGFA or a plain GFA, and a second such file for the coarse tier, which is the
same graph with every variant under 10 kb folded into the reference. One adapter
reads both, and <prefix>.config.json holds the track:
Goes in the tracks array of config.json. See Tracks.
{
"type": "GraphTrack",
"trackId": "ecoli_minigraph_segments",
"name": "minigraph graph: rGFA segments",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "ecoli_minigraph",
"format": 2,
"coarse": {
"uri": "ecoli_minigraph.fold10000",
"format": 2,
"foldBelowBp": 10000
}
},
"displays": [
{
"type": "LinearGraphDisplay",
"displayId": "ecoli_minigraph_segments-LinearGraphDisplay"
},
{
"type": "LinearBasicDisplay",
"displayId": "ecoli_minigraph_segments-LinearBasicDisplay"
}
]
}jbrowse add-track-json '{
"type": "GraphTrack",
"trackId": "ecoli_minigraph_segments",
"name": "minigraph graph: rGFA segments",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "ecoli_minigraph",
"format": 2,
"coarse": {
"uri": "ecoli_minigraph.fold10000",
"format": 2,
"foldBelowBp": 10000
}
},
"displays": [
{
"type": "LinearGraphDisplay",
"displayId": "ecoli_minigraph_segments-LinearGraphDisplay"
},
{
"type": "LinearBasicDisplay",
"displayId": "ecoli_minigraph_segments-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_minigraph_segments",
"name": "minigraph graph: rGFA segments",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "ecoli_minigraph",
"format": 2,
"coarse": {
"uri": "ecoli_minigraph.fold10000",
"format": 2,
"foldBelowBp": 10000
}
},
"displays": [
{
"type": "LinearGraphDisplay",
"displayId": "ecoli_minigraph_segments-LinearGraphDisplay"
},
{
"type": "LinearBasicDisplay",
"displayId": "ecoli_minigraph_segments-LinearBasicDisplay"
}
]
}ecoli_minigraph, ecoli_minigraph.fold10000 are relative to a config.json. Replace each with its URL or its path on this computer.
The adapter takes three keys here:
uri, the shared prefix, from which the adapter resolves.graph.bed.gzand its.tbi"format": 2, which names that one-file layout, gfa-to-tabix's default since 2.0. Without it the adapter reads format 1, the.segs.bed.gzand.links.bed.gzpair that--format 1and earlier releases writecoarse, the tier's prefix, format and fold size,foldBelowBp. A tenth of that is the handover, the linear view's zoom in bp per pixel past which the graph track cuts the tier;aboveBpPerPxincoarsesets the handover directly
<prefix>.graph.json lists the same files and fold size, and Add pangenome
graph track reads it beside the graph file, so a track opened there gets the
tier with no config. The E. coli graph's stable names are PanSN (K12#1#chr),
and their sample prefix is already the assembly name, so the track needs no
assemblyNameToPanSN mapping.
HPRC's graph track
needs one, because that graph calls the reference GRCh38 while the assembly is
hg38.
The config lists the graph display first, so the track opens as the graph, and Track menu → Display types → Feature display draws the same segments as a lane instead, one block each. As the graph, the track cuts the window on screen out of the index with a window-width of margin on each side, and cuts again whenever the view leaves that stretch. A cut of segments spans at most 5 Mb; past that the track keeps its last cut and reports it. The track cuts on the graph's reference, which is the first assembly the track names.
The legible window width depends on the graph. A minigraph graph records structural variation and merges everything smaller, so a legible window is hundreds of kb. A pggb graph puts a node at every SNP, so a legible window is hundreds of bp.
The graph track draws only what the zoom can show: variants smaller than ten of
the linear view's pixels fold into the reference, the legend gives the size, and
zooming in restores them. A track whose adapter names coarse gives the graph a
second tier to cut, built by the same fold
(gfa-to-tabix fold).
Once the linear view is zoomed out past the handover, the graph track cuts the
tier and the size limit no longer applies; the drawing barely changes across the
handover, since the fine cut has folded the same variants by then. The segments
lane draws segments at every zoom, so load the tier's prefix as a separate track
too, because that lane draws a whole chromosome where the segments lane refuses.
Each line in the graph is one graph link. The track draws a link only when both endpoints are inside the cut, so an allele near the window's edge draws only the link that stays inside it.
Route 2: a GFA file
With no index, Add → Graph genome view opens a GFA by file or URL in a separate view and draws all of it, with pan and zoom in that view and the same layouts the track has. The file is the whole graph, with no index to cut another window from. Use this route for a window someone cut for you, and for a graph too large to index:
odgi extract -i graph.og -r K12#1#chr:1004500-1004900 -E -o - \
| odgi sort -i - -o - -O | odgi view -i - -g > window.gfa
# vg equivalent, for a Minigraph-Cactus graph
vg chunk -x graph.xg -p K12#1#chr:1004500-1004900 -c 20 > window.vgView menu → Graph settings... → Reference path picks the path to anchor on,
since a plain GFA has no reference. odgi extract writes the window into the
path name (K12#1#chr:1004500-1004961), and the view takes the offsets from
that name, and a whole-genome path starts at zero.
The paths also show which samples go through a node. The P and W lines list
every traversal, and Node details lists them under samples. A true rGFA
has no traversals to read. There samples is empty, and the panel reports
contributingAssembly, the one assembly SN gives for the segment.
Route 1 gives the same answer without the GFA file when the index came from a
plain GFA. On that route gfa-to-tabix build does the traversal walk offline
and writes each segment's haplotypes into the index as SB:H: bits. Only an
index built from a minigraph rGFA lacks them.
Sample rows draws a row per contributing assembly. Each node is drawn once,
on the row of the first path that reaches it, and the other haplotypes stay in
samples. A segment that several haplotypes share appears on only one of their
rows.
On JBrowse Desktop
JBrowse Desktop opens your own graph from files on
disk, with no server and no config file, by either route. Desktop reads a file
by its path, so a graph track finds the files gfa-to-tabix build wrote beside
the one you pick: the tabix index, the coarse tier and <prefix>.graph.json.
JBrowse Web's file picker hands over only the file picked, so there an indexed
graph opens by URL.
Install the plugin and open a genome first:
- Install the plugin once. Open Global plugins... in the start screen menu and click Install beside GraphGenomeView under Available plugins
- Open a genome. Desktop starts a session only by opening one. For a graph track, open the graph's reference, the assembly its backbone comes from (K12 in the figures above, hg38 for HPRC)
A GFA small enough for the view to draw whole opens in a separate view (Route 2):
- Add → Graph genome view, then Choose file. Any genome works, because the view lays out the GFA from its P/W lines
A graph indexed once on the command line opens as a track that cuts each window as you browse (Route 1):
- Index the graph with
gfa-to-tabix build, as Route 1 shows, and its haplotype walks withgfa-to-tabix --walks, as Pangenome (hosting your own graph) does. Keep the output files together in one folder - File → Open track..., then pick Add pangenome graph track from the dropdown at the top of the form
- Choose the file type, then Choose File for the one file it names:
- Indexed GFA (gfa-to-tabix .segs.bed.gz or .graph.bed.gz):
<prefix>.graph.bed.gz, for an rGFA or a plain GFA, or the<prefix>.segs.bed.gzof a format 1 pair. The form also reads<prefix>.graph.json, so the track gets the coarse tier - Haplotype walks (.walks.bed.gz):
<prefix>.<sample>.walks.bed.gz, fromgfa-to-tabix --walks - GBZ database (.gbz.db): the database, with the haplotype index from
gbz-haplotype-indexbeside it, and optionally reads aligned to the graph as GAF
- Indexed GFA (gfa-to-tabix .segs.bed.gz or .graph.bed.gz):
- Sample name in the graph: the graph's name for the open genome where the
two differ,
GRCh38for an HPRC graph opened on hg38. Leave it blank where they match - Submit, then type a locus. Zoomed out past what the track can cut, it asks you to zoom in, unless the graph has a coarse tier
The general Add a track from file or URL form opens the same three files as a graph track too, with no coarse tier and no sample name field.
Desktop autosaves the session, local paths included, so it reopens from the start screen with the graph as long as the files stay where they were.
Seven layouts
The track menu's Layout submenu draws the same subgraph seven ways, and the axes mean something different in each:
| Layout | x | y |
|---|---|---|
| Anchored | reference bp | one row per stable rank |
| Sample rows | reference bp | one row per assembly |
| Walk rows | per-walk bp | one bar per haplotype |
| Ordered | reference order | a lane per allele |
| Tube map | node order | a tube per path |
| Tube map on reference | reference bp | a tube per path |
| Force-directed | nothing (FMMM) | nothing |
Ordered keeps x monotone in reference order, ignoring bp. A SNP allele gets the same room as the kilobase segment beside it, and a bubble draws as a lens. Walk rows needs a graph with walks, and draws each haplotype's route as a bar. Tube map and Tube map on reference need P or W lines, and draw each path as a colored tube through boxed nodes.
The track opens in Anchored, whose x is the view's coordinate, so the graph lines up under the other tracks and pans and zooms with them. Ordered and Force-directed give x another meaning, so the track draws them in coordinates fitted to the track, the way a variant matrix does, and adds Zoom in, Zoom out and Zoom to fit to its menu; moving the view still cuts the new window.
A strip along the top of such a track draws each reference segment at its bp in the view, in the color its node has below, so under the Reference position scheme you can match a hue on the strip to its node in the drawing. A triangle at either end of the strip marks reference the graph draws past that edge of the window, and Reference strip at bp in the track menu turns the strip off. Use Force-directed when the structure of a locus matters: an anchored drawing flattens both routes through a locus onto the reference axis, and an allele then looks like a stub hanging under a line. A graph opened from a file starts in the force layout.
Anchored and Sample rows both need a backbone, from rGFA tags or from a reference path, and a graph with neither greys them out. Force-directed is then the only layout available, and it draws the Bandage picture with alternate alleles as bubbles. The MHC figure shows it under the lanes of the same window.
Rank is minigraph's SR tag, and it counts build order. Rank 0 is the first
assembly on the command line, rank 1 is sequence first added with the second,
and so on. A high-rank segment is sequence none of the earlier assemblies had.
Only rank 0 has reference coordinates, so rank 0 is the only rank that a lane on
the reference can show.
Rank comes from how the graph was built. At a dense locus one rank holds alleles from many haplotypes, so a rank row has no biological meaning. Sample rows groups rows by the assembly each allele came from. The backbone sits on top, and each strain's charcoal marks sit under it, tied by grey threads to where they attach, so a row shows what that strain does to the reference.
The assembly an allele "came from" depends on the format. On rGFA it is the
strain that first contributed the sequence, because SR is build order and
the file records only that assembly. A path GFA lists every path that visits a
segment, so a row shows which haplotypes have it and the node popup lists the
rest.
Anchored and Sample rows both draw an allele across the reference it replaces. An insertion replaces no reference, so it draws as a mark where it attaches, with its size in the tooltip.
Bubbles, genes and walks on the drawing
Show → Show bubble halos in the track menu draws the graph's bubbles on every node layout. Each bubble is a halo along the bubble's nodes, colored by its type, with a label naming the type, and the legend lists each color. The option starts off, because on a base-level cut every SNP's halo is a blob. The bubbles come from the bubble index beside an rGFA where there is one. Otherwise the track derives them from the drawing's layering, which covers a GBZ cut, a plain GFA and the inside of an opened bubble. Click a label to open that bubble alone inside the track, with a button back. The track derives the bubbles inside an opened bubble, so a superbubble opens level by level.
The graph draws the session's gene track onto the backbone. Exons are dark stretches along their reference nodes, and each gene's name is pinned under the backbone at the gene's midpoint. An allele has no reference coordinates and shows no exon. Show → Show genes on the backbone in the track menu turns the genes off, and Gene track in its Graph settings... picks the track when the assembly has more than one.
A graph with walks, such as a GBZ cut or a GFA with P or W lines, supports three more displays. Node width in the track menu's Graph settings... draws a node thicker the more walks visit it, scaled by the square root of its depth against the mean, which is Bandage's rule. Uniform turns that off.
In a bubble with a route over a kilobase, every route has a chip at the far point of its loop while the halos are on. The chip lists the walks that take the route and gives the route's length.
The track menu's Haplotypes submenu highlights one walk. Its nodes keep their color, its links draw dark, and everything else fades, on the reference strip too, so the stretches of reference the walk skips read at their bp. A readout beside the legend compares the walk's length with the reference walk's.
A gbz-base track draws one lane per haplotype, and Display types → Graph in
its track menu draws the same track as a graph of the haplotypes' walks. The
Haplotypes field in Graph settings... lists the haplotypes the cut holds
beside the reference, and with the field empty the track cuts every haplotype in
the graph. Past 5 Mb, or for a cut over the adapter's nodeLimit, the track
asks you to zoom in. A variant track over the graph's VCF covers a wider window.
Repeat lengths across HPRC haplotypes
reads a repeat array this way.
Bubble spread and graph context
Bubble spread in the track menu's Graph settings... sets how a node's bp becomes its drawn length in the force layout. The anchored layouts place a node from its coordinates, so the setting has no effect there. The engine comes from Bandage, whose graphs are assembled contigs of kb to Mb. It maps length linearly with a tiny floor, so a pangenome allele of a few bases clamps to a stub.
Two alternative settings fix that:
- Open bubbles and Wide bubbles raise the floor, so every allele gets a drawn length while everything above the floor stays proportional. Pick one of these when a long node has to stay long, such as when a path ribbon runs along it. The floor applies per node, so it also lengthens a graph's non-branching chain nodes, and the drawing grows with node count.
- Compress lengths pulls both ends towards the graph's mean, so a cut spanning kilobases and single bases fits one drawing at any node count. It uses Bandage's power law, moved onto the axis a pangenome needs it on. The cost is that a long node no longer looks long.
Proportional is the unmodified Bandage map. Keep it when a figure is about relative length.
Graph context, in the same Graph settings..., sets how far the cut
follows links past the region, and defaults to 1 hop. It is the in-app
counterpart of odgi extract -c N. An allele's interior segments are indexed
under the sequence of their haplotype, so a reference query never reaches them.
A detour that leaves the backbone before the window and rejoins after it
therefore draws as two stubs. A hop closes those stubs, at the cost of one query
per off-reference segment already reached. None shows what the region query
alone reaches.
The left and right halves of the figure below share the genes and segments lanes and color each node the same way, so a segment can be found in either. A hop is one step, so the right half still ends in a loose end. The hop expands only over off-reference segments, so it does not pull in the backbone on either side of the window.
A 2 hops setting handles a graph with alleles nested inside alleles. On this window 1 hop already closes the cut. The setting stops at two, because hops only grow a neighbourhood, and in HPRC's graph half of the off-reference segments sit three or more links from the backbone.
An exact cut comes from an index in the anchored layout, which
gfa-to-tabix writes by default and the
HPRC track reads. It files each allele under the reference interval its bubble
attaches to, so one query returns every bubble under the region whole, and
Graph context changes nothing there. The E. coli index in the figure above
is in the older layout, where each segment is filed under its coordinate.
Color schemes and matching a linear track
The track menu's Color submenu opens on Auto, which is Reference position on any graph with reference coordinates and Uniform on one with none. Three of its schemes are described here:
- Reference position ramps hue over the window the subgraph was cut from, red at its start to magenta at its end, with a key in the top right naming the interval. A segment off the backbone draws flat charcoal, outside the ramp, so a hue always marks a position on the reference. A linear track can reproduce only this scheme exactly, because it is a function of two numbers and a midpoint.
- Stable rank is the rank ladder above: rank 0 blue, then a ramp for the rest.
- Depth is how many paths walk each segment, which is core-versus-accessory at the segment level.
A segments lane shares the graph's hues when its track's encoding.color holds
the matching expression as its value. The encoding.color for Reference
position, over the 50 kb window from 4,050,000 that the figures above are cut
from, is:
Goes in the tracks array of config.json. See Tracks.
{
"type": "GraphTrack",
"trackId": "ecoli_minigraph_segments",
"name": "minigraph graph: rGFA segments",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "ecoli_minigraph",
"format": 2,
"coarse": {
"uri": "ecoli_minigraph.fold10000",
"format": 2,
"aboveBpPerPx": 1000
}
},
"displayDefaults": {
"encoding": {
"color": {
"value": "jexl:feature.rank>0 ? 'rgb(60,65,72)' : `hsl(${min(300, max(0, ((feature.start+feature.end)/2 - 4050000) / 50000 * 300))},70%,50%)`"
}
}
},
"displays": [
{
"type": "LinearGraphDisplay",
"displayId": "ecoli_minigraph_segments-LinearGraphDisplay"
},
{
"type": "LinearBasicDisplay",
"displayId": "ecoli_minigraph_segments-LinearBasicDisplay"
}
]
}jbrowse add-track-json '{
"type": "GraphTrack",
"trackId": "ecoli_minigraph_segments",
"name": "minigraph graph: rGFA segments",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "ecoli_minigraph",
"format": 2,
"coarse": {
"uri": "ecoli_minigraph.fold10000",
"format": 2,
"aboveBpPerPx": 1000
}
},
"displayDefaults": {
"encoding": {
"color": {
"value": "jexl:feature.rank>0 ? '\''rgb(60,65,72)'\'' : `hsl(${min(300, max(0, ((feature.start+feature.end)/2 - 4050000) / 50000 * 300))},70%,50%)`"
}
}
},
"displays": [
{
"type": "LinearGraphDisplay",
"displayId": "ecoli_minigraph_segments-LinearGraphDisplay"
},
{
"type": "LinearBasicDisplay",
"displayId": "ecoli_minigraph_segments-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_minigraph_segments",
"name": "minigraph graph: rGFA segments",
"assemblyNames": ["K12"],
"adapter": {
"type": "RgfaTabixAdapter",
"uri": "ecoli_minigraph",
"format": 2,
"coarse": {
"uri": "ecoli_minigraph.fold10000",
"format": 2,
"aboveBpPerPx": 1000
}
},
"displayDefaults": {
"encoding": {
"color": {
"value": "jexl:feature.rank>0 ? 'rgb(60,65,72)' : `hsl(${min(300, max(0, ((feature.start+feature.end)/2 - 4050000) / 50000 * 300))},70%,50%)`"
}
}
},
"displays": [
{
"type": "LinearGraphDisplay",
"displayId": "ecoli_minigraph_segments-LinearGraphDisplay"
},
{
"type": "LinearBasicDisplay",
"displayId": "ecoli_minigraph_segments-LinearBasicDisplay"
}
]
}ecoli_minigraph, ecoli_minigraph.fold10000 are relative to a config.json. Replace each with its URL or its path on this computer.
The rank branch matches the graph's charcoal for off-reference segments. It
applies only on a lane opened on a contributing assembly, where rank>0 segments
have coordinates.
Stable rank needs no window, so it is the only scheme a hosted config can use.
For the same track, set this encoding.color.value:
jexl:feature.rank==0 ? 'rgb(52,152,219)' : 'rgb(237,137,44)'Hover sync between the graph and the lanes
Hover a node, and the lanes above it highlight the reference interval the node occupies; above a force-directed or ordered drawing, the reference strip boxes the same interval and draws a line to the node. Hovering a bubble's label does the same for the bubble's span. This needs no configuration, and it is the only way to locate a rank>0 allele, because those alleles have no reference coordinates.
The reverse direction, a lane's pointer lighting the segment under it, is off by default, since every track's pointer crosses some segment. Show → Hover highlight → Everything turns it on, along with edge hover. It then works from any track, because a gene gives a coordinate, and rGFA segments do not overlap on a stable sequence, so one backbone segment covers the coordinate.
The alignment lane below shows CFT073's 65 kb insertion from the other side. CFT073 has no aligned bases across the band, and neither do IAI39 or Sakai, while NCTC86 aligns straight through it.
The lane is a projection onto K12's coordinates, with a column for each K12 base, so it cannot draw 65 kb that exists only in CFT073. The graph holds both, and the ringed node in the graph track is that 65 kb.
An alignment of the same insertion is independent evidence. The graph's insertion comes from the graph's index, and the alignment below comes from a whole-genome alignment made without the graph.
The all-vs-all tutorial puts the same kind of alignment beside a graph track.
A hover highlight disappears when the pointer moves, whereas Right-click a node → Highlight in <assembly> writes the same interval into the linear view's highlight list, where it stays. The label shows the assembly the item will mark, so it reads Highlight in hg38 on an HPRC session.
From a node back to a genome
Every segment has tags that give the sequence it came from and its offset in that sequence. With only the reference loaded, a node's right-click menu offers Open in the reference around the node, which moves the view the graph is drawn in. With the contributing assemblies loaded, the same menu offers Open in the strain that contributed the node, which opens a linear view of that strain framed on the segment in that strain's coordinates. A CFT073 allele opens CFT073 at the offset in its tags.
The view it opens shows the session's annotation for the assembly it opens on, so each strain opens with its genes. A graph opened as a separate view has a Launch menu in its view menu that does the same for the whole window: one linear view per contributing strain, and a synteny view of all of them, one panel per strain, which needs a synteny track in the session that aligns the strains. An alignment in a synteny track offers the same jump from its right-click menu, Open <strain> at the matching region, so either view opens a strain the same way.
On HPRC's graph the contributors are its 464 haplotypes, and the config the HPRC page on genomes.jbrowse.org opens declares every one as an assembly under its PanSN name, so a node there offers the haplotype that contributed it. Browsing the HPRC graph opens one this way.
The per-strain entries show each strain's sequence at the locus. K12's
asnW/asnU/asnV tRNA genes are integration sites for E. coli pathogenicity
islands, and in that window the graph gives CFT073 tens of kilobases that the
reference lacks. Clicking CFT073's entry opens that sequence on CFT073's
coordinates, where CFT073's gene track names it: clbA to clbS, the
colibactin island. The coordinates it opens on come from the segments' SN/SO
tags.
In the figure below, the graph on the left opens a linear view of a strain, and
on the right a linear view draws the graph, around segment s1277 of the
Route 1 track. The halves use
different colorings: stable rank shows whose sequence an arm is, and the
reference-position ramp shows where each segment sits.
Alleles from the rGFA alone
Someone else's rGFA usually comes without the assemblies it was built from. The
index still records every allele in the graph, because each L-line row records
both of its endpoints in full. A link between two backbone segments that leaves
a coordinate gap is a deletion. A link from the backbone into a rank>0 segment
enters an allele, and the allele's length is the total of the segments it walks
before rejoining.
gfa-to-tabix alleles
does that walk and needs only the index, built with --layout contig in either
format:
gfa-to-tabix alleles ecoli_minigraph # -> ecoli_minigraph.alleles.bed.gzEach row describes an allele against the reference it replaces, which makes the
row an alignment. The BED therefore has a CIGAR column (2062M63348I), and an
alignments track reads it directly:
Goes in the tracks array of config.json. See Tracks.
{
"type": "AlignmentsTrack",
"trackId": "ecoli_minigraph_alleles",
"name": "minigraph graph: allele inventory (from the rGFA alone)",
"assemblyNames": ["K12"],
"adapter": {
"type": "BedTabixAdapter",
"uri": "ecoli_minigraph.alleles.bed.gz"
}
}jbrowse add-track ecoli_minigraph.alleles.bed.gz \
--trackId ecoli_minigraph_alleles \
--name "minigraph graph: allele inventory (from the rGFA alone)" \
--assemblyNames K12 \
--trackType AlignmentsTrack \
--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": "AlignmentsTrack",
"trackId": "ecoli_minigraph_alleles",
"name": "minigraph graph: allele inventory (from the rGFA alone)",
"assemblyNames": ["K12"],
"adapter": {
"type": "BedTabixAdapter",
"uri": "ecoli_minigraph.alleles.bed.gz"
}
}ecoli_minigraph.alleles.bed.gz is relative to a config.json. Replace it with its URL or its path on this computer.
An AlignmentsTrack works over a BED because the display draws any feature that
has a CIGAR. The alleles pack into rows, and each draws the same insertion
marker and deletion bar a read does, at its real size. Without the CIGAR, a 63
kb allele draws as a 1 bp feature with the size shown only in its label.
The allele size is measured, and the position inside the anchor span is a convention, because a bubble records only the span and the CIGAR puts the indel at the end. Over a 2 kb anchor the offset is invisible, and over a 100 kb anchor the position is approximate.
The popup shows altLen, nested, discoveryRank and the traversed
segments. Two filters are useful, and both are set from Edit filters on
the same file loaded as a FeatureTrack, whose default display has that menu
item:
jexl:abs(feature.delta)>10000makes this lane workable for HPRC's two hundred thousand alleles. Filter onabs, sincedeltais negative for a deletion.jexl:feature.nested==0before reading lengths in bulk.nestedmarks a row whose walk passed a branch point, so itsdeltais one of several routes through a nested bubble.
The rGFA alone gives only the first assembly to contribute a segment, in
discoveryRank and firstSeenIn, because minigraph merges shared sequence. An
allele that four strains share is credited to whichever strain was added first.
Rank records build order, so a high rank does not mean the earlier assemblies
lacked the sequence. With the assemblies,
per-strain presence in
the E. coli tutorial shows which strains have each stretch of a graph.
See also
- Tutorial: Pangenome (hosting your own graph)
- Tutorial: Pangenome (pggb)
- Tutorial: Pangenome (HPRC) part 1: the graph's alleles and the haplotypes that have them
- Tutorial: Pangenome (HPRC) part 2: haplotypes against each other
- Tutorial: Pangenome (mouse)
- Tutorial: Pangenome (Minigraph-Cactus)
- User guide: Linear synteny view
- User guide: Dotplot view
- User guide: Alignments track
- Config guide: Configuring plugins
- PANGENOME_GRAPHS.md — the coordinates and haplotype membership that rGFA and plain GFA record, the one-node-per-bubble level of detail, and the decisions here that look like bugs