Skip to main content

JBrowse 2 combined guide

This document is a collection of all our documentation. It includes our quick start guide, user guide, configuration guide, CLI guide, developer guide, and FAQ. You can browse the other documents individually, but this page is to help simple ctrl+f searching and easy browsing. You can also download a pdf version of these same docs located at https://jbrowse.org/jb2/jbrowse2.pdf

Super-quick start guide for JBrowse web#

This is a quick overview to get started running JBrowse 2 from scratch using the command line. It is helpful if you have some familiarity with the command line, and with some bioinformatics tools like samtools in general to follow these steps. This guide also assumes you have:

  • a webserver that reads files from /var/www/html/ e.g. Apache or nginx (not strictly necessary for jbrowse to run, see footnote)
  • node 10+ installed
  • genometools installed e.g. sudo apt install genometools or brew install brewsci/bio/genometools, used for sorting GFF3 for creating tabix GFF
  • samtools installed e.g. sudo apt install samtools or brew install samtools, used for creating FASTA index and BAM/CRAM processing
  • tabix installed e.g. sudo apt install tabix or brew install htslib, used for created tabix indexes for BED/VCF/GFF files

Super-quick overview for CLI#

### Install JBrowse 2 CLI tools, note: if you want to use the jbrowse command
### under the sudo user, change this to `sudo npm install -g @jbrowse/cli`, but
### sometimes it is better to work under the principle of least priviledge and
### operate under a normal user so this guide does not use this
npm install -g @jbrowse/cli
### Use the `jbrowse create` command to download the latest release, and put it
### in a web server directory
jbrowse create /var/www/html/jbrowse2
### Alternatively, you may download to a directory, and then move it to the web
### directory
jbrowse create ~/mylocaljbrowse
mv ~/mylocaljbrowse /var/www/html/jbrowse2
### Create indexed FASTA file and load it using the add-assembly command
### Add your genome assembly to the config at /var/www/html/jbrowse2/config.json
### Also copies the files to this directory
samtools faidx genome.fa
jbrowse add-assembly genome.fa --out /var/www/html/jbrowse2 --load copy
### Copies file.bam and file.bam.bai to /var/www/html/jbrowse2 and adds track to
### the config at /var/www/html/jbrowse2/config.json. Assumes that file.bam and
### file.bam.bai exist
samtools index file.bam
jbrowse add-track file.bam --out /var/www/html/jbrowse2/ --load copy
### Adds a url entry for a bam file to the config.json, the URL is stored in the
### config instead of downloading files, so no --load flag is needed
jbrowse add-track http://website.com/myfile.bam --out /var/www/html/jbrowse2
### If your BAM index (bai) is not filename+'.bai' then you can manually specify
### the --index flag. The --index flag also works with loading tabix tracks too
jbrowse add-track myfile.bam --index myfile.bai --out /var/www/html/jbrowse2 --load copy
### Outputting to a specific config file instead of a config directory
### Alternative loading syntax where I specify a config file, and then this can
### be loaded via http://localhost/jbrowse2/?config=alt_config.json
jbrowse add-assembly mygenome.fa --out /var/www/html/jbrowse2/alt_config.json --load copy
### load gene annotations from a GFF, using "GenomeTools" (gt) to sort the gff
### and tabix to index the GFF3
gt gff3 -sortlines -tidy -retainids myfile.gff > myfile.sorted.gff
bgzip myfile.sorted.gff
tabix myfile.sorted.gff.gz
jbrowse add-track myfile.sorted.gff.gz --out /var/www/html/jbrowse2 --load copy
### Example of using --subDir to organize your data directory:
### copies myfile.bam and myfile.bam.bai to /var/www/html/jbrowse2/my_bams
### folder, which helps organize your data folder
jbrowse add-track myfile.bam --subDir my_bams --out /var/www/html/jbrowse2 --load copy
### Example without using the --out parameter:
### If you are in a directory with a config.json file, you can omit the --out parameter
cd /var/www/html/jbrowse2
jbrowse add-track /path/to/my/file.bam --load copy
### Demo for loading synteny data, both assemblies are outputted to a single
### config.json in /var/www/html/jbrowse2/config.json
minimap2 grape.fa peach.fa > peach_vs_grape.paf
jbrowse add-assembly grape.fa --load copy --out /var/www/html/jbrowse2/ -n grape
jbrowse add-assembly peach.fa --load copy --out /var/www/html/jbrowse2/ -n peach
### Use gt gff3 to make sorted tabixed gffs for each assembly, and then load to
### their respective ## assembly
jbrowse add-track grape.sorted.gff.gz -a grape --load copy --out /var/www/html/jbrowse2
jbrowse add-track peach.sorted.gff.gz -a peach --load copy --out /var/www/html/jbrowse2
### Load the synteny "track" from a PAF file. Note the order matters here for
### the --assemblyNames parameter. If minimap2 is run like `minimap2 grape.fa
### peach.fa` then you load --assemblyNames peach,grape
jbrowse add-track peach_vs_grape.paf --assemblyNames peach,grape --out load copy
### After you've had jbrowse for awhile, you can upgrade to our latest release
jbrowse upgrade /var/www/html/jbrowse2

Conclusion#

You can now visit http://localhost/jbrowse2 and your genome should be ready!

This guide is meant to be a super-quick conceptual overview for getting jbrowse 2 setup, but if you are new to the command line or to jbrowse in general, you might want to start with the slightly-longer quick-start guide here.

Footnote#

JBrowse doesn't strictly need Apache or nginx, it is "static site compatible" meaning it uses no server side code and can run on any static website hosting. For example, you can upload the jbrowse folder that we prepared here in /var/www/html/jbrowse2 to Amazon S3, and it will work there too. See the FAQ for what webserver do I need for more info.

JBrowse web quick start#

In this guide, we'll get an instance of JBrowse running on your computer.

Pre-requisites#

  • Ability to run commands on the command line
  • Node.js 10.4+
caution

If you are using apt as your package manager, we recommend not using it to install Node.js. Good alternatives include NodeSource or NVM.

Download#

You can download JBrowse 2 by using the JBrowse CLI or by downloading and unpacking it manually. We recommend using the JBrowse CLI since it also includes utilities to help you configure JBrowse 2 once it is set up.

Downloading using the JBrowse CLI#

The JBrowse CLI can help perform many tasks to help you manage JBrowse 2, such as:

  • create a new instance of JBrowse 2 automatically
  • update an existing instance of JBrowse 2 with the latest released version
  • configure your JBrowse 2 instance
Installing the CLI tools#

To install the JBrowse CLI, run

npm install -g @jbrowse/cli

After running this command you can then test the installation with

jbrowse --version

This will output the current version of the JBrowse CLI.

note

If you can't or don't want to globally install the JBrowse CLI, you can also use the npx command, which is included with Node.js, to run JBrowse CLI without installing it. Simply replace jbrowse with npx @jbrowse/cli in any command, e.g.

npx @jbrowse/cli --version
Using jbrowse create to download JBrowse 2#

In the directory where you would like to download JBrowse 2, run this command

jbrowse create jbrowse2

Downloading manually#

You can also download JBrowse 2 manually. Go to the releases page of the JBrowse 2 GitHub repository and find the latest release that is tagged @jbrowse/web. Download the ZIP file from that release. Make sure it is the ZIP file that starts with jbrowse-web- and not the "Source code" ZIP file. Once you have downloaded the ZIP file, extract it to the location you would like to have JBrowse 2.

Checking the download#

Whether you used the JBrowse CLI or downloaded manually, the directory where you downloaded JBrowse should look something like this:

jbrowse2/
├── a586bb28a5bad4a3aba2.worker.js
├── a586bb28a5bad4a3aba2.worker.js.LICENSE.txt
├── a586bb28a5bad4a3aba2.worker.js.map
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.52c8ba3337cf7ae812b37d874b2de030.js
├── robots.txt
├── service-worker.js
├── static/
└── test_data/

Running JBrowse 2#

JBrowse 2 requires a web server to run. It won't work if you try to directly open the index.html in your web browser. We can use a simple server to check that JBrowse 2 has been downloaded properly. Run

cd jbrowse2/
npx serve .

This will start a web server in our JBrowse 2 directory. Navigate to the location specified in the tool's output. It will look something like http://localhost:5000. Once at that page, you should see a page that says that the configuration is not found. That is expected, since we haven't configured JBrowse 2 yet. It will look something like this:

JBrowse 2 screen showing no configuration found
Figure: JBrowse 2 screen showing no configuration found

Go ahead an click on the sample config to see a JBrowse 2 running with a demo configuration. It should look like this:

JBrowse 2 screen with a sample configuration
Figure: JBrowse 2 screen with a sample configuration

Congratulations! You're running JBrowse 2.

Next steps#

Now that JBrowse 2 is set up, you can configure it with your own genomes and tracks. There are two ways you can configure JBrowse 2: with the JBrowse CLI (guide here) or with JBrowse 2's built-in graphical configuration editing (guide here).

Config editing quick start — command-line interface#

In order to display your data, JBrowse 2 needs to know about the reference genome for your organism of interest and needs to have tracks created that reference your data sources. This guide will show you how to set those up using the JBrowse CLI.

note

You can also do this configuration with graphical configuration editing interface built into JBrowse 2. See that guide here.

Pre-requisites#

Adding a genome assembly#

info

For this step we configure JBrowse to use files being hosted at a URL. For an example of how to use files located on your computer, see the adding a track step.

First we will configure an assembly, or reference genome, for for JBrowse 2. This usually means providing a file that describes the reference sequence for the organism, such as a FASTA or 2BIT file.

You will want to use your own data for your organism, but for this example we provide a small example reference sequence for a simulated organism, volvox mythicus, that you can use.

## Make sure you are in the directory where you have downloaded JBrowse 2
jbrowse add-assembly http://jbrowse.org.s3.amazonaws.com/genomes/volvox/volvox.fa
caution

A FASTA must have an index to work in JBrowse 2. This command assumes that the index file is the same as the FASTA but with .fai appended to the file name.

This command will generate a config file if one does not exist yet and add an assembly called "volvox" to the config file with the URLs of the FASTA and FASTA index files. The name of the assembly was guessed from the file name, but you can customize that and many other things with various flags passed to the command. You can run jbrowse add-assembly --help to get a list of all the options.

JBrowse 2 also supports other assembly file formats, such as bgzip-compressed indexed FASTA (e.g. .fa.gz, .fa.gz.fai, and .fa.gz.gzi files) and 2BIT files. See configuring assemblies for more info on formats supported for the sequence file.

note

If your FASTA is not indexed, you can use the samtools tool to index it.

samtools faidx volvox.fa
## generates volvox.fa.fai

Or if you want to compress your FASTA, you can use bgzip as well.

bgzip volvox.fa
samtools faidx volvox.fa.gz
## compresses volvox.fa to volvox.fa.gz and generates volvox.fa.gz.fai and volvox.fa.gz.gzi

For more info about bgzip and samtools, see https://www.htslib.org/.

If you have your JBrowse 2 running as described in the JBrowse web quickstart, you can refresh the page and an add a linear genome view. You will now see your config in the Assembly dropdown.

JBrowse 2 linear genome view setup with volvox in assembly dropdown
Figure: JBrowse 2 linear genome view setup with volvox in assembly dropdown

Adding a track#

Now we will show you how to add an alignments track and a variant track to JBrowse 2.

info

For this step we configure JBrowse to use files located on your computer. For an example of how to use files hosted at a URL, see the adding a genome assembly step.

Adding an alignments track#

For this example we will use a BAM file to add an alignments track. Again, for this example we provide a small example BAM, but for your data you will replace the file name with the names of your data files.

For this track we will assume the data is on your computer at the locations /data/volvox.bam and /data/volvox.bam.bai. You can download these file here if you want to run this example: BAM and BAM index.

To add the track, run

## Replace with the location of your BAM file
jbrowse add-track /data/volvox.bam --load copy

This will copy the BAM and BAM index into the JBrowse 2 directory and add a track pointing at those files to the config file. To see more options adding the track, such as specifying a name, run jbrowse add-track --help.

If you don't want to copy your BAM file, you can use --move to move the file into the JBrowse 2 directory or --symlink to add a symlink to the file to the JBrowse 2 directory. If you want more control over the location, you can use inPlace to point the track at the file where it is, but be careful with this option because on a traditional server you will need to ensure that the file is in a place where the web server is serving it.

note

If your BAM is not indexed, you can use the samtools tool to index it.

samtools index volvox.bam
## generates volvox.bam.bai

For more info about samtools, see https://www.htslib.org/.

If you have your JBrowse 2 running as described in the JBrowse web quickstart, you can refresh the page and an add a linear genome view of the volvox assembly. Then open track selector, and you will see the alignments track.

JBrowse 2 linear genome view with alignments track
Figure: JBrowse 2 linear genome view with alignments track

Adding a variant track#

Adding a variant track is similar to adding an alignments track. For this example, we will use a VCF file for the track. JBrowse 2 expects VCFs to be compressed with bgzip and indexed. Similar to the above example, we will assume the files are at /data/volvox.vcf.gz and /data/volvox.vcf.gz.tbi. You can download these file here: VCF and VCF index.

To add the track, run

jbrowse add-track /data/volvox.vcf.gz --load copy
note

If your VCF is not indexed, you can use the bgzip and tabix tools to compress index it.

bgzip yourfile.vcf
tabix yourfile.vcf.gz

Alternatively, you can do the same thing with the bcftools tool.

bcftools view volvox.vcf --output-type z > volvox.vcf.gz
rm volvox.vcf
bcftools index --tbi volvox.vcf.gz

Note if you get errors about your VCF file not being sorted when using tabix, you can use bcftools to sort your VCF.

bcftools sort file.vcf > file.sorted.vcf
bgzip file.sorted.vcf
tabix file.sorted.vcf.gz

For more info about bgzip, tabix, and bcftools, see https://www.htslib.org/.

If you have your JBrowse 2 running as described in the JBrowse web quickstart, you can refresh the page and an add a linear genome view of the volvox assembly. Then open track selector, and you will see the variant track.

JBrowse 2 linear genome view with variant track
Figure: JBrowse 2 linear genome view with variant track

Adding a BigWig/BigBed track#

Probably one of the most simple track types to load is a BigWig/BigBed file since it does not have any external index file, it is just a single file

An example file is here http://jbrowse.org.s3.amazonaws.com/genomes/volvox/volvox-sorted.bam.coverage.bw

### Download bigwig or bigbed file
jbrowse add-track volvox-sorted.bam.coverage.bw --load copy

Adding a GFF3 file with GFF3Tabix#

To load a GFF3 file, we can sort and index it with tabix

Sorting a GFF3 can be done with GenomeTools (to install can use sudo apt install genometools)

gt gff3 -sortlines -tidy -retainids yourfile.gff > yourfile.sorted.gff
bgzip yourfile.sorted.gff
tabix yourfile.sorted.gff.gz
jbrowse add-track yourfile.sorted.gff.gz --load copy

Conclusion#

Now that you have JBrowse configured with an assembly and a couple of tracks, you can start customizing it further. Check out the rest of the docs for more information, especially the JBrowse CLI docs for more details on some of the steps shown here.

Config editing quick start — graphical interface#

In order to display your data, JBrowse 2 needs to know about the reference genome for your organism of interest and needs to have tracks created that reference your data sources. This guide will show you how to set those up using the JBrowse 2's graphical configuration editing.

note

You can also do this configuration with JBrowse CLI. See that guide here.

Pre-requisites#

This tutorial requires having the following software installed

Starting JBrowse 2 admin server#

The JBrowse CLI contains a tool called admin-server. This will act as a web server for JBrowse 2 and will write any changes made in JBrowse 2 to a config file. The admin-server is meant to be run only temporarily to help you set up your config, it is not used for serving your jbrowse instance in production.

The admin-server launches an instance of JBrowse 2 in "admin mode", which then lets you

  • Add and edit assemblies with the "Assembly manager"
  • Add tracks and edit tracks
  • Add and edit connections

All of these changes will be written by the server to the JBrowse config file (usually config.json) located in the JBrowse instance. This is something that can only be done while the admin-server is running, which again, is only meant to be temporary!

To start the admin-server, navigate into your JBrowse 2 directory and run

### Start the admin-server
jbrowse admin-server

This will then generate a link that you can visit in your web browser

JBrowse CLI admin-server output, which provides a link that can be used. Note: we do not recommend using admin-server in production, and should be used for temporary configuration
Figure: JBrowse CLI admin-server output, which provides a link that can be used. Note: we do not recommend using admin-server in production, and should be used for temporary configuration
warning

Note: the admin-server is meant to be used temporarily for configuration, not in production

Adding a genome assembly#

A key first step in configuring a genome browser is adding an assembly to view. In order to do this, use the navigation bar to open up the Assembly Manager (Admin > Open Assembly Manager).

This opens up a table which can be used to create, edit, and delete assemblies in your application

Screenshot showing the assembly manager, with no assemblies loaded yet
Figure: Screenshot showing the assembly manager, with no assemblies loaded yet

Let's add the hg38 human reference genome to our JBrowse 2 application.

Press the "Add New Assembly" button, and enter the necessary information in the form:

  • name: hg38
  • type: BgzipFastaAdapter
  • fasta: https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz
  • fasta index: https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.fai
  • gzi: https://jbrowse.org/genomes/GRCh38/fasta/hg38.prefix.fa.gz.gzi
Assembly manager page for adding a new assembly
Figure: Assembly manager page for adding a new assembly

Click on "Create New Assembly". Great, we've added an assembly! We can see that we have successfully added the hg38 assembly.

The assembly manager dialog box with human assemblies available
Figure: The assembly manager dialog box with human assemblies available

The assembly can be edited or deleted, but for now we will return to the application.

Editing a genome assembly#

After you've added a genome assembly, you can use the pencil icon button in the Assembly manager to edit that assembly. You can also delete assemblies from the assembly manager.

Adding a track#

To add a new track or connection, you can use the menu bar in the app to open the form for adding a track File > Open Track:

JBrowse 2 file menu with the 'Add track' form
Figure: JBrowse 2 file menu with the 'Add track' form

Alternatively, you can use the action button (circular "+") inside the track selector to access the "Add track" form.

The 'Add track' form can be launched from the circular '+' button in the bottom righthand corner
Figure: The 'Add track' form can be launched from the circular '+' button in the bottom righthand corner

In the "Add track" form, you can provide a URL to a file to load. Opening files from your local machine is not supported currently in the JBrowse 2 web app (JBrowse desktop does allow this, though, and this functionality may be added in some form in the future)

Paste a URL to a file and optionally provide an index file URL too. The following file formats are supported

  • tabix-indexed VCF
  • tabix-indexed BED
  • tabix-indexed GFF
  • indexed BAM
  • indexed CRAM
  • BigWig
  • BigBed
  • Hi-C (Juicebox)

For tabix files, TBI or CSI indexes are allowed. CSI or BAI is allowed for BAM. Only CRAI is allowed for CRAM. The index will be inferred for BAI or TBI files as e.g. filename+'.bai'. If it is different from this, make sure to specify the index file explicitly.

Editing a track#

First we will open a Linear Genome View using the navigation bar (File > Add > Linear Genome View), and click on the "Select Tracks" button.

The configuration settings are accessible by clicking on the ellipses by each track.

The configuration editor, which will persist settings to the config file if editing using the admin-server
Figure: The configuration editor, which will persist settings to the config file if editing using the admin-server

Open the configuration editor for the track by clicking on the "Settings" button shown above. You can use the configuration editor to live-edit any configurable value for a given track.

Setting a default session#

It is also possible to use the graphical admin server to set the default session of your JBrowse 2 instance. This is the session that will appear when JBrowse 2 is first visited. To do so, open the form to set the default session (Admin > Set default session):

The 'Set default session' will persist your current session into the config file so any subsequent visitors to the app will see this session
Figure: The 'Set default session' will persist your current session into the config file so any subsequent visitors to the app will see this session

You can use the form to clear your default session, select the currently open session, or any of your previously saved sessions.

Additional resources#

There are a number of additional features for configuring JBrowse 2. Make sure to refer to the config guide for topics such as adding tracks or adding an assembly with the CLI

Conclusion#

This quickstart showed how to launch the admin-server in the JBrowse CLI to perform graphical configuration of your application. Specifically, we looked at how to access and use the assembly manager, as well as how to access the configuration editor for tracks. Importantly, all tracks have different configuration options available in the configuration editor.

Make sure to take a look at any tracks you add to JBrowse 2 that you might want to further configure!

Quick start for JBrowse desktop#

Important note on JBrowse desktop

We do not have downloads of JBrowse 2 Desktop yet, it is expecting a release in late 2020

Installing JBrowse desktop#

This guide will walk you through installing jbrowse 2 on the desktop

JBrowse 2 desktop does not require any pre-requisites for your installation, so we can jump right in

Installing on Linux#

Visit http://github.com/gmod/jbrowse-components/releases/latest

Download the latest release artifact with linux in the name

Unzip the file, open the directory, and run the file named "JBrowse 2" in the terminal with

./JBrowse\ 2
Installing on MacOS#

Visit http://github.com/gmod/jbrowse-components/releases/latest and find the latest MacOS release artifact in our latest builds

You can then unzip this download and the "JBrowse 2" app will be unzipped to this folder. You can then run JBrowse 2 from clicking this file.

Screenshot of the Finder window showing the downloaded zip file and unzipped contents
Figure: Screenshot of the Finder window showing the downloaded zip file and unzipped contents

To run JBrowse 2, you can launch the unzipped app, however if you double click on the file it may give you a warning about running a program from an unauthorized developer since JBrowse 2 isn't registered with Mac's app store

In order to properly launch JBrowse 2

  1. Right-click or hold control and click "JBrowse 2" app in the Finder
  2. Select "Open" from the context menu
  3. The warning will pop up again but with the option to run icon

Reference https://support.apple.com/guide/mac-help/open-a-mac-app-from-an-unidentified-developer-mh40616/mac

Screenshot of the 'open app from unauthorized developer' after right-clicking and selecting 'open'
Figure: Screenshot of the 'open app from unauthorized developer' after right-clicking and selecting 'open'
Installing on Windows#

Visit http://github.com/gmod/jbrowse-components/releases/latest

You can then unzip this file and run the file that comes from unzipping it. Moving this file to the Applications folder is also equivalent to "installing" JBrowse 2

Unzip the zip archive
Figure: Unzip the zip archive
You can then double click the exe application in the unzipped archive
Figure: You can then double click the exe application in the unzipped archive

Then open up the Windows Explorer in the unzipped directory and run "JBrowse 2.exe". This may give a "Windows protected your PC" warning, but select "More info..." and then "Run anyway"

You can skip windows protection to run the app by clicking the 'More info...' link
Figure: You can skip windows protection to run the app by clicking the 'More info...' link
After clicking 'More info...' the button to run is revealed
Figure: After clicking 'More info...' the button to run is revealed

User guide#

Navigating the UI#

Linear genome view usage#

To start a linear genome view, use the menu bar

File->Add->Linear genome view

Using the location search box#
  • Use the search box in the LGV
  • Enter syntax chr1:1-100 or chr1:1..100
  • You can also specify an assembly name with the locstring {hg19}chr1:1-100

Note: searching by gene name is not yet available but will be added soon!

Scrolling#

Mouse wheel can scroll side to side, as well as click and drag. The pan buttons also exist in the header of the linear genome view

Zooming#

The zoom buttons exist in the header of the linear genome view, and there is also a slider bar to zoom in and out.

Note: You can also hold the "Ctrl" key and use your mousewheel or trackpad to scroll and this will zoom in and out

Re-ordering tracks#

There is a drag handle on the track labels indicating by the six dots, clicking and dragging on this part of the track label can reorder tracks

Adding tracks#

To add a new track or connection, you can use the menu bar in the app to open the form for adding a track:

File->Open Track

After opening the menu item for 'Open new track' a drawer widget for the 'Add track form' will appear
Figure: After opening the menu item for 'Open new track' a drawer widget for the 'Add track form' will appear

Note: There is also a circular "+" button inside the track selector menu that can also be used to access the "Add track" form.

The orange plus icon in the bottom right of a tracklist can also be used to launch the 'Add track form'
Figure: The orange plus icon in the bottom right of a tracklist can also be used to launch the 'Add track form'

In the "Add track" form, you can provide a URL to a file to load. Opening files from your local machine is not supported currently in the jbrowse-web app (jbrowse-desktop does allow this though, and may be added to jbrowse-web in the future)

Paste a URL to a file and optionally provide an index file URL too. The following file formats are supported

  • Tabixed VCF
  • Tabixed BED
  • Tabixed GFF
  • BAM
  • CRAM
  • BigWig
  • BigBed
  • .hic file (Juicebox)

For tabix files, TBI or CSI indexes are allowed. CSI or BAI is allowed for BAM. Only CRAI is allowed for CRAM. The index will be inferred for BAI or TBI files as filename+'.bai' for example, but if it is different than this, make sure to specify the index file explicitly.

Note: If you are an administrator, you can add tracks with the command line or with the admin server add-track or admin-server guide

Sharing sessions#

The main menu bar has a "Share" button to enable users to share their sessions with other people. The share button generates a URL that can be sent to other users. It is not possible to copy your URL bar and send this to another user currently, because sessions can become too large for the address bar in many cases.

Note that you can copy and paste URLs between different tabs in your local browser though

The session share dialog, which gives you a short URL to share your session with other users. It is important to use these URLs generated here rather than simply copying and pasting your URL to other users
Figure: The session share dialog, which gives you a short URL to share your session with other users. It is important to use these URLs generated here rather than simply copying and pasting your URL to other users

The session URL will contain

  • what views are on the screen, and settings for the views (e.g. track labels overlapping or offset)
  • what tracks are in the view
  • extra tracks that you added with the "Add track workflow"
  • for the alignments track, the show soft clipping and sort settings on the pileup
  • etc

All this stuff gets included in the session

This means you can share links with your custom tracks with other users, without being a JBrowse admin!

Editing track configs#

Currently, in order to edit a track config, you have to make a copy of the track

Screenshot showing how to copy a track. In order to edit detailed configuration of a track, we require that you first make a copy of it, which can be done via the track menu
Figure: Screenshot showing how to copy a track. In order to edit detailed configuration of a track, we require that you first make a copy of it, which can be done via the track menu

After you have copied the track, you can edit the track settings

After copying a track, which puts it in your 'session tracks', you can then edit the track settings, and you have full control over your session tracks
Figure: After copying a track, which puts it in your 'session tracks', you can then edit the track settings, and you have full control over your session tracks

Your new track is a "session track" and can be shared with other users with the "Share" button

Rubberband selection#

The scale bars accept a click and drag action to select a region

Rubberband selection can be performed on both the region and overview scale bars
Figure: Rubberband selection can be performed on both the region and overview scale bars
Track label positioning#

Track labels can be positioned on their own row or overlapping the data to save vertical screen space. They can also be hidden. This is done by clicking on the hamburger menu for a specific view.

Example of using the overlap and offset track label positioning options
Figure: Example of using the overlap and offset track label positioning options
Horizontally flip#

The view can be horizontally flipped, or reverse complemented, to make the coordinates go from right to left instead of left to right

We use triangles pointing in the direction of the orientation in the overview bar to help indicate whether the app is horizontally flipped or not

Here is an example of before and after horizontally flipping the view

Before and after horizontally flipping
Figure: Before and after horizontally flipping

Sequence track#

The sequence track shows the reference sequence and a three-frame translation. If the view is horizontally flipped, the sequence is "reverse complemented" so the bottom three translation frames go to the top, and the top frames go to the bottom.

The sequence track, with a positive strand gene for context, shows the start codon on the first exon in the top-three rows of the translation frame. The bottom panel shows the same view but with the view horizontally flipped, and the gene is now shown reversed and the start codon is in the bottom translation frames.
Figure: The sequence track, with a positive strand gene for context, shows the start codon on the first exon in the top-three rows of the translation frame. The bottom panel shows the same view but with the view horizontally flipped, and the gene is now shown reversed and the start codon is in the bottom translation frames.

Alignments tracks#

Visualizing alignments is an important aspect of genome browsers. This guide will go over the main features of the "Alignments track"

The alignments track is a combination of a pileup and a coverage visualization

Pileup visualization#

The pileup is the lower part of the alignments track and shows each of the reads as boxes positioned on the genome.

By default the reads are colored red if they aligned to the forward strand of the reference genome, or blue if they aligned to the reverse strand.

Coverage visualization#

The coverage visualization shows the depth-of-coverage of the reads at each position on the genome, and also draws using colored boxes any occurrence of mismatches between the read and the reference genome, so if 50% of the reads had a T instead of the reference A, half the height of the coverage histogram would contain a 'red' box

Screenshot showing the alignments track, which contains both a coverage view at the top and a pileup view at the bottom
Figure: Screenshot showing the alignments track, which contains both a coverage view at the top and a pileup view at the bottom

Show soft clipping#

If a read contains bases that do not map the the genome properly, they can either be removed from the alignment (hard clipping) or can be included, and not shown by default (soft clipping)

JBrowse 2 also contains an option to "show the soft clipping" that has occurred. This can be valuable to show the signal around a region that contains structural variation or difficult mappability

Shows what turning on soft-clipping enables for a simulated long-read dataset. There is a simulated structural variant, a deletion, at this position, so the read has bases that map to the other side of the deletion being revealed by this.
Figure: Shows what turning on soft-clipping enables for a simulated long-read dataset. There is a simulated structural variant, a deletion, at this position, so the read has bases that map to the other side of the deletion being revealed by this.

Sort by options#

The alignments tracks can also be configured to "sort by" a specific attribute for reads that span the center line.

By default the center line is not shown, but by showing it (Go to the view's hamburger menu->Select "Show center line") then you will obtain a better idea of what the "sort by" option is doing

Showing the center line#

Here is how to turn on the center line

  1. Open the hamburger menu in the top left of the linear genome view
  2. Select "Show center line"
Illustrates before and after turning on the center line. The center line is an indicator that shows what base pair underlies the center of the view. Note that this is used in the 'Sort by' option discussed below; the sort is performed using properties of the feature or even exact base pair underlying the center line
Figure: Illustrates before and after turning on the center line. The center line is an indicator that shows what base pair underlies the center of the view. Note that this is used in the 'Sort by' option discussed below; the sort is performed using properties of the feature or even exact base pair underlying the center line

Sorting by base#

Sorting by base will re-arrange the pileup so that the reads that have a specific base-pair mutation at the position crossing the center line (which is 1bp wide) will be arranged in a sorted manner. To enable Sort by base

  1. Open the track menu for the specific track using the vertical '...' in the track label
  2. Select 'Sort by'->'Base pair'
Illustrating the pileup re-ordering that happens when turning on the 'Sort by'->'Base pair'. The sorting is done by specifically what letter of each read underlies the current center line position (the center line is 1bp wide, so sorted by that exact letter)
Figure: Illustrating the pileup re-ordering that happens when turning on the 'Sort by'->'Base pair'. The sorting is done by specifically what letter of each read underlies the current center line position (the center line is 1bp wide, so sorted by that exact letter)

Sort, color and filter by tag#

We can now also do things like

  • Sort by tag
  • Filter by tag
  • Color by tag

With these features, we can create very expressive views of alignments tracks

Step-by-step guide showing how to sort and color by haplotype with the HP tag
Figure: Step-by-step guide showing how to sort and color by haplotype with the HP tag

Color by orientation#

JBrowse uses the same color scheme as IGV for coloring by pair orientation. These pair orientations can be used to reveal complex patterns of structural variation

See https://software.broadinstitute.org/software/igv/interpreting_pair_orientations for a good guide on interpreting these pair orientations

This shows an inverted duplication, the tandem duplication can produce green arrows which have reads pointing in opposite directions e.g. <-- and -->, while blue arrows which can indicate an inversion point in the same direction e.g. --> and -->
Figure: This shows an inverted duplication, the tandem duplication can produce green arrows which have reads pointing in opposite directions e.g. <-- and -->, while blue arrows which can indicate an inversion point in the same direction e.g. --> and -->

BigWig tracks#

Visualizing genome signals, whether it is read depth-of-coverage or other signal, can often be done by using BigWig files

A simple wiggle track with the XY plot renderer
Figure: A simple wiggle track with the XY plot renderer

Viewing whole-genome coverage for profiling CNV#

The latest jbrowse also allows refining the resolution of BigWig tracks, and viewing whole genome coverage. This allows us to get detailed global views of CNV for example from whole-genome coverage profiling

Here is a short picture guide to setup a whole-genome view of a BigWig for CNV coverage visualization

  1. Open your BigWig track
  2. Go to the view menu and select "Show all assembly regions"
  3. Adjust the "Autoscale type" to your liking, the new options for "Local +/- 3sd" allows the autoscaling to avoid outliers
  4. Go to the track menu and select "Turn off histogram fill", which then shows only a dot for each point on the graph
  5. Go to the track menu and select "Resolution->Finer resolution" a couple times until resolution looks nice

Also note: all tracks have a drag handle on the bottom of it which you can drag down to make the track taller

A step-by-step guide to view a whole-genome CNV profile of coverage from a BigWig file
Figure: A step-by-step guide to view a whole-genome CNV profile of coverage from a BigWig file

Variant tracks#

Visualizing variant tracks from the VCF format alongside the original alignment evidence track is a common workflow for validating your results. In JBrowse 2 we can open a variant track and an alignments track as shown below

Variant track indicating a SNP alongside the alignment track evidence
Figure: Variant track indicating a SNP alongside the alignment track evidence

Variant widget#

The variant features have a specialized widget that contains a table indicating all the calls that were made in a multi-sample VCF. Some VCF files, like the 1000 genomes VCF, can contain thousands of samples in a single file. This table can display the details

Screenshot showing the variant feature sidebar with a filtered by genotype (with alternative allele '1'). Users can also filter by sample name or other attributes
Figure: Screenshot showing the variant feature sidebar with a filtered by genotype (with alternative allele '1'). Users can also filter by sample name or other attributes

Linear synteny and dotplot views#

The dotplot view is a 2D comparative view that can display alignments between different genome assemblies, or even compare a long-read or NGS short-read versus the genome

Opening a dotplot view#

Currently the workflow for launching a dotplot is done by navigating in the header bar to the File->Add->Dotplot view

This will let you select the genome assemblies of interest

Then you can also provide a synteny file in the form of PAF via the Add track workflow

Then currently you must configuration edit the PAFAdapter to indicate the two assemblies in the PAFAdapter

Adding a new dotplot or synteny view via the menubar
Figure: Adding a new dotplot or synteny view via the menubar
Example of the import form for a dotplot or synteny view. Allows you to select two different assemblies and a PAF file can be supplied via a URL
Figure: Example of the import form for a dotplot or synteny view. Allows you to select two different assemblies and a PAF file can be supplied via a URL
Example of a dotplot visualization of the grape vs the peach genome
Figure: Example of a dotplot visualization of the grape vs the peach genome

See the dotplot configuration for more detailed descriptions

Opening a linear synteny view#

Use the main menu bar to select

File->Add->Linear synteny view

Example of the import form for a synteny view allowing you to select two different assemblies and optionally adding a PAF file via a URL
Figure: Example of the import form for a synteny view allowing you to select two different assemblies and optionally adding a PAF file via a URL
Example screenshot showing the linear synteny view for grape vs peach
Figure: Example screenshot showing the linear synteny view for grape vs peach

See the linear synteny configuration for more details on manually configuring the synteny view

Opening a synteny view from a dotplot view#

We have designed JBrowse 2 to be able to open up a synteny view from a dotplot view. This is enabled by "display modes" so that the same track can be displayed in different contexts.

Here is a short demo that shows opening a synteny view from a dotplot view selection

Screenshow showing the 'click and drag' selection over the dotplot view prompts you to open up a linear synteny view from the selected region
Figure: Screenshow showing the 'click and drag' selection over the dotplot view prompts you to open up a linear synteny view from the selected region

Long read vs reference plots#

One can also launch a dotplot view that compares a long read to the reference genome by

  • Right clicking an alignment
  • Select "Dotplot read vs ref" or "Linear read vs ref" in the context menu
Example of a dotplot of a long read vs the reference genome
Figure: Example of a dotplot of a long read vs the reference genome
Example of a 'synteny' view of a long read vs the reference genome
Figure: Example of a 'synteny' view of a long read vs the reference genome

Hi-C tracks#

Visualizing Hi-C data can be performed with .hic files which are generated by the Juicebox software suite. It uses the hic-straw module developed by the juicebox/igv.js team to visualize it in jbrowse.

Currently configuration options are basic for Hi-C tracks, see configuration for info about configuring Hi-C tracks

Screenshot of a Hi-C track
Figure: Screenshot of a Hi-C track

SV inspector#

The SV inspector is a "workflow" that is designed to help users inspect structural variant calls

Opening the SV inspector#

We can start the SV inspector by launching it from the App level menu bar

The SV inspector can be launched from the main menu bar
Figure: The SV inspector can be launched from the main menu bar

This will bring up an "import form" that asks you for your SV evidence. This can be provided opening a file locally or using a URL for files in the following formats:

  • VCF or VCF.gz (plain text VCF, or (b)gzipped VCF)
  • BEDPE
  • STAR-fusion result file
The import form for getting started with the SV inspector
Figure: The import form for getting started with the SV inspector

Example SV inspector workflow#

We can start the SV inspector workflow by opening up this file containing translocation events called from a breast cancer cell line SKBR3, based on these published data http://schatz-lab.org/publications/SKBR3/

## Example VCF for use in the SV inspector
https://jbrowse.org/genomes/hg19/skbr3/reads_lr_skbr3.fa_ngmlr-0.2.3_mapped.bam.sniffles1kb_auto_l8_s5_noalt.new.vcf

Copy this URL and paste it into the import form and select hg19

The SV inspector with the import form and URL pasted
Figure: The SV inspector with the import form and URL pasted

SV inspector results#

After loading the user's requested file, you will have a tabular view with each row representing a row of the file you opened, along with a whole-genome overview of the SVs on the right

The SV inspector with loaded results
Figure: The SV inspector with loaded results

Now here is where things can become interesting

We can search and filter the table, with filtering and searching being reflected in the circular view as well.

The SV inspector with filter applied
Figure: The SV inspector with filter applied

Launching breakpoint split view#

By clicking on the features in the circular view, or clicking on the triangle drop-down on the leftmost column of the table, we can dynamically launch a new view of the data that is called the "split view" or the "breakpoint split view"

This allows us to inspect the breakpoints of the structural variant, and compare each side to the alignments.

Screenshot of the 'breakpoint split view' which examines the breakpoints of a structural variant, e.g. an interchromosomal translocation, and connects supporting reads (black splines) and the variant call itself (green thicker line, with feet indicating directionality)
Figure: Screenshot of the 'breakpoint split view' which examines the breakpoints of a structural variant, e.g. an interchromosomal translocation, and connects supporting reads (black splines) and the variant call itself (green thicker line, with feet indicating directionality)

Config guide#

Intro to the config.json#

A JBrowse 2 configuration file, a config.json, is structured as follows

{
"configuration": {
/* global configs here */
},
"assemblies": [
/* list of assembly configurations, e.g. the genomes being viewed */
],
"tracks": [
/* array of tracks being loaded, contain reference to which assembl(y/ies)
they belong to */
],
"defaultSession": {
/* optional default session */
}
}

The most important thing to configure are your assemblies and your tracks

Configuring assemblies#

An assembly configuration includes the "name" of your assembly, any "aliases" that might be associated with that assembly e.g. GRCh37 is sometimes seen as an alias for hg19, and then a "sequence" configuration containing a reference sequence track config. This is provides a special "track" that is outside the normal track config

Here is a complete config.json file containing only a hg19

{
"assemblies": [
{
"name": "hg19",
"aliases": ["GRCh37"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "hg19_config",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi"
}
},
"rendering": {
"type": "DivSequenceRenderer"
}
},
"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt"
}
}
}
}
]
}

Configuring reference name aliasing#

Reference name aliasing is a process to make chromosomes that are named slightly differently but which refer to the same thing render properly

The refNameAliases in the above config provides this functionality

"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt"
}
}
}

The hg19_aliases then is a tab delimited file that looks like this

The first column should be the names that are in your FASTA sequence, and the rest of the columns are aliases

1 chr1
2 chr2
3 chr3
4 chr4
5 chr5
6 chr6
7 chr7
8 chr8
9 chr9
10 chr10
11 chr11
12 chr12
13 chr13
14 chr14
15 chr15
16 chr16
17 chr17
18 chr18
19 chr19
20 chr20
21 chr21
22 chr22
X chrX
Y chrY
M chrM MT

Adding an assembly with the CLI#

Generally we add a new assembly with the CLI using something like

## use samtools to make a fasta index for your reference genome
samtools faidx myfile.fa
## install the jbrowse CLI
npm install -g @jbrowse/cli
## add the assembly using the jbrowse CLI, this will automatically copy the
myfile.fa and myfile.fa.fai to your data folder at /var/www/html/jbrowse2
jbrowse add-assembly myfile.fa --load copy --out /var/www/html/jbrowse2

See our CLI docs for the add-assembly for more details here -- add-assembly

Note: assemblies can also be added graphically using the assembly manager when you are using the admin-server. See the quickstart guide for more details.

Assembly config#

Because JBrowse 2 can potentially have multiple assemblies loaded at once, it needs to make sure each track is associated with an assembly.

To do this, we make assemblies a special part of the config, and make sure each track refers to which genome assembly it uses

Example config with hg19 genome assembly loaded#

Here is a complete config.json that has the hg19 genome loaded

{
"assemblies": [
{
"name": "hg19",
"aliases": ["GRCh37"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "refseq_track",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi"
}
},
"rendering": {
"type": "DivSequenceRenderer"
}
},
"refNameAliases": {
"adapter": {
"type": "RefNameAliasAdapter",
"location": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/hg19/hg19_aliases.txt"
}
}
}
}
]
}

The top level config is an array of assemblies

Each assembly contains

  • name - a name to refer to the assembly by. each track that is related to this assembly references this name
  • aliases - sometimes genome assemblies have aliases like hg19, GRCh37, b37p5, etc. while there may be small differences between these different sequences, they often largely have the same coordinates, so you might want to be able to associate tracks from these different assemblies together. The assembly aliases are most helpful when loading from a UCSC trackHub which specifies the genome assembly names it uses, so you can connect to a UCSC trackHub if your assembly name or aliases match.
  • sequence - this is a complete "track" definition for your genome assembly. we specify that it is a track of type ReferenceSequenceTrack, give it a trackId, and an adapter configuration. an adapter configuration can specify IndexedFastaAdapter (fasta.fa and fasta.fai), BgzipFastaAdapter (fasta.fa.gz, fasta.fa.gz.fai, fasta.gz.gzi), ChromSizesAdapter (which fetches no sequences, just chromosome names)

ReferenceSequenceTrack#

Example ReferenceSequenceTrack config, which as above, is specified as the child of the assembly section of the config

{
"type": "ReferenceSequenceTrack",
"trackId": "refseq_track",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi"
}
},
"rendering": {
"type": "DivSequenceRenderer"
}
}

BgzipFastaAdapter#

A bgzip FASTA format file is generated by

bgzip -i sequence.fa
samtools faidx sequence.fa.gz
### above commands generates the following three files
sequence.fa.gz
sequence.fa.gz.gzi
sequence.fa.gz.fai

These are loaded into a BgzipFastaAdapter as follows

{
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi"
}
}

IndexedFastaAdapter#

An indexed FASTA file is similar to the above, but the sequence is not compressed

samtools faidx sequence.fa
### above commands generate the .fa and .fai files
sequence.fa
sequence.fa.fai

These are loaded into a IndexedFastaAdapter as follows

{
"type": "IndexedFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.fai"
}
}

TwoBitAdapter#

The UCSC twoBit adapter is also supported. Note however that the 2bit format has a longer startup time than other adapters because there is a larger upfront parsing time.

{
"type": "TwoBitAdapter",
"twoBitLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.2bit"
}
}

Track configurations#

All tracks can contain

  • trackId - internal track ID, must be unique
  • name - displayed track name
  • assemblyNames - an array of assembly names a track is associated with, often just a single assemblyName
  • category - (optional) array of categories to display in a hierarchical track selector

Example config.json containing a track config

{
"assemblies": [
{
"name": "hg19",
"aliases": ["GRCh37"],
"sequence": {
"type": "ReferenceSequenceTrack",
"trackId": "Pd8Wh30ei9R",
"adapter": {
"type": "BgzipFastaAdapter",
"fastaLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz"
},
"faiLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.fai"
},
"gziLocation": {
"uri": "https://jbrowse.org/genomes/hg19/fasta/hg19.fa.gz.gzi"
}
}
}
}
],
"tracks": [
{
"type": "FeatureTrack",
"trackId": "repeats_hg19",
"name": "Repeats",
"assemblyNames": ["hg19"],
"category": ["Annotation"],
"adapter": {
"type": "BigBedAdapter",
"bigBedLocation": {
"uri": "https://jbrowse.org/genomes/hg19/repeats.bb"
}
}
}
]
}

AlignmentsTrack config#

Example AlignmentsTrack config

{
"trackId": "my_alignments_track",
"name": "My Alignments",
"assemblyNames": ["hg19"],
"type": "AlignmentsTrack",
"adapter": {
"type": "BamAdapter",
"bamLocation": { "uri": "http://yourhost/file.bam" },
"index": { "location": { "uri": "http://yourhost/file.bam.bai" } }
}
}
BamAdapter configuration options#
  • bamLocation - a 'file location' for the BAM
  • index: a subconfiguration schema containing
    • indexType: options BAI or CSI. default: BAI
    • location: a 'file location' of the index

Example BamAdapter config

{
"type": "BamAdapter",
"bamLocation": { "uri": "http://yourhost/file.bam" },
"index": { "location": { "uri": "http://yourhost/file.bam.bai" } }
}
CramAdapter configuration options#
  • cramLocation - a 'file location' for the CRAM
  • craiLocation - a 'file location' for the CRAI

Example CramAdapter config

{
"type": "CramAdapter",
"cramLocation": { "uri": "http://yourhost/file.cram" },
"craiLocation": { "uri": "http://yourhost/file.cram.crai" }
}

HicTrack config#

Example Hi-C track config

{
"type": "HicTrack",
"trackId": "hic",
"name": "Hic Track",
"assemblyNames": ["hg19"],
"adapter": {
"type": "HicAdapter",
"hicLocation": {
"uri": "https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic"
}
}
}
HicAdapter config#

We just simply supply a hicLocation currently for the HicAdapter

{
"type": "HicAdapter",
"hicLocation": {
"uri": "https://s3.amazonaws.com/igv.broadinstitute.org/data/hic/intra_nofrag_30.hic"
}
}
HicRenderer config#
  • baseColor - the default baseColor of the Hi-C plot is red #f00, you can change it to blue so then the shading will be done in blue with #00f
  • color - this is a color callback that adapts the current Hi-C contact feature with the baseColor to generate a shaded block. The default color callback function is jexl:baseColor.alpha(Math.min(1,count/(maxScore/20))).hsl().string() where it receives the count for a particular block, the maxScore over the region, and the baseColor from the baseColor config

VariantTrack config#

  • defaultRendering - options: 'pileup' or 'svg'. default 'svg'
  • adapter - a variant type adapter config e.g. a VcfTabixAdapter

Example config

{
"type": "VariantTrack",
"trackId": "my track",
"name": "My Variants",
"assemblyNames": ["hg19"],
"adapter": {
"type": "VcfTabixAdapter",
"vcfGzLocation": { "uri": "http://yourhost/file.vcf.gz" },
"index": { "location": { "uri": "http://yourhost/file.vcf.gz.tbi" } }
}
}
VcfTabixAdapter configuration options#
  • vcfGzLocation - a 'file location' for the BigWig
  • index: a subconfiguration schema containing
    • indexType: options TBI or CSI. default TBI
    • location: the location of the index

Example VcfTabixAdapter adapter config

{
"type": "VcfTabixAdapter",
"vcfGzLocation": { "uri": "http://yourhost/file.vcf.gz" },
"index": { "location": { "uri": "http://yourhost/file.vcf.gz.tbi" } }
}

QuantitativeTrack config#

Example QuantitativeTrack config

{
"trackId": "my_wiggle_track",
"name": "My Wiggle Track",
"assemblyNames": ["hg19"],
"type": "QuantitativeTrack",
"adapter": {
"type": "BigWig",
"bigWigLocation": { "uri": "http://yourhost/file.bw" }
}
}
General QuantitativeTrack options#
  • scaleType - options: linear, log, to display the coverage data. default: linear
  • adapter - an adapter that returns numeric signal data, e.g. feature.get('score')
Autoscale options for QuantitativeTrack#

Options for autoscale

  • local - min/max values of what is visible on the screen
  • global - min/max values in the entire dataset
  • localsd - mean value +- N stddevs of what is visible on screen
  • globalsd - mean value +/- N stddevs of everything in the dataset
Score min/max for QuantitativeTrack#

These options overrides the autoscale options and provides a minimum or maximum value for the autoscale bar

  • minScore
  • maxScore
QuantitativeTrack drawing options#
  • inverted - draws upside down
  • defaultRendering - can be density, xyplot, or line
  • summaryScoreMode - options: min, max, whiskers
QuantitativeTrack renderer options#
  • filled - fills in the XYPlot histogram
  • bicolorPivot - options: numeric, mean, none. default: numeric
  • bicolorPivotValue - number at which the color switches from posColor to negColor. default: 0
  • color - color or color callback for drawing the values. overrides posColor/negColor. default: none
  • posColor - color to draw "positive" values. default: red
  • negColor - color to draw "negative" values. default: blue
  • clipColor - color to draw "clip" indicator. default: red
BigWigAdapter options#
  • bigWigLocation - a 'file location' for the bigwig

Example BigWig adapter config

{
"type": "BigWig",
"bigWigLocation": { "uri": "http://yourhost/file.bw" }
}

SyntenyTrack config#

Example SyntenyTrack config

{
"type": "SyntenyTrack",
"trackId": "dotplot_track",
"assemblyNames": ["YJM1447", "R64"],
"name": "dotplot",
"adapter": {
"type": "PAFAdapter",
"pafLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/yeast/YJM1447_vs_R64.paf"
},
"assemblyNames": ["YJM1447", "R64"]
}
}

We can add a SyntenyTrack from PAF with the CLI e.g. with

jbrowse add-track myfile.paf --type SyntenyTrack --assemblyNames \
grape,peach --load copy --out /var/www/html/jbrowse2

Advanced adapters#

There are two useful adapter types that can be used for more advanced use cases, such as generating configuration for data returned by an API. These are the FromConfigAdapter and FromConfigSequenceAdapter. They can be used as the adapter value for any track type.

FromConfigAdapter#

This adapter can be used to generate features directly from values stored in the configuration.

Example FromConfigAdapter

{
"type": "FromConfigAdapter",
"features": [
{
"refName": "ctgA",
"uniqueId": "alias1",
"aliases": ["A", "contigA"]
},
{
"refName": "ctgB",
"uniqueId": "alias2",
"aliases": ["B", "contigB"]
}
]
}
FromConfigSequenceAdapter#

Similar behavior to FromConfigAdapter, with a specific emphasis on performance when the features are sequences.

Example FromConfigSequenceAdapter

{
"type": "FromConfigSequenceAdapter",
"features": [
{
"refName": "SEQUENCE_1",
"uniqueId": "firstId",
"start": 0,
"end": 33,
"seq": "CCAAGATCTAAGATGTCAACACCTATCTGCTCA"
},
{
"refName": "SEQUENCE_2",
"uniqueId": "secondId",
"start": 0,
"end": 44,
"seq": "CCGAACCACAGGCCTATGTTACCATTGGAAAGCTCACCTTCCCG"
}
]
}

DotplotView config#

The configuration of a view is technically a configuration of the "state of the view" but it can be added to the defaultSession

An example of a dotplot config can help explain. This is relatively advanced so let's look at an example

{
"assemblies": [
{
"name": "grape",
"sequence": {
"trackId": "grape_seq",
"type": "ReferenceSequenceTrack",
"adapter": {
"type": "ChromSizesAdapter",
"chromSizesLocation": {
"uri": "grape.chrom.sizes"
}
}
}
},
{
"name": "peach",
"sequence": {
"trackId": "peach_seq",
"type": "ReferenceSequenceTrack",
"adapter": {
"type": "ChromSizesAdapter",
"chromSizesLocation": {
"uri": "peach.chrom.sizes"
}
}
}
}
],
"tracks": [
{
"trackId": "grape_peach_synteny_mcscan",
"type": "SyntenyTrack",
"assemblyNames": ["peach", "grape"],
"trackIds": [],
"renderDelay": 100,
"adapter": {
"mcscanAnchorsLocation": {
"uri": "grape.peach.anchors"
},
"subadapters": [
{
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/peach_gene/{refseq}/trackData.json"
}
},
{
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/grape_gene/{refseq}/trackData.json"
}
}
],
"assemblyNames": ["peach", "grape"],
"type": "MCScanAnchorsAdapter"
},
"name": "Grape peach synteny (MCScan)",
"category": ["Annotation"]
},
{
"trackId": "grape_peach_paf",
"type": "SyntenyTrack",
"name": "Grape vs Peach (PAF)",
"assemblyNames": ["peach", "grape"],
"adapter": {
"type": "PAFAdapter",
"pafLocation": {
"uri": "https://s3.amazonaws.com/jbrowse.org/genomes/synteny/peach_grape.paf"
},
"assemblyNames": ["peach", "grape"]
}
},
{
"type": "SyntenyTrack",
"trackId": "dotplot_track_small",
"name": "Grape vs peach small (PAF)",
"assemblyNames": ["grape", "peach"],
"adapter": {
"type": "PAFAdapter",
"pafLocation": {
"uri": "peach_grape_small.paf"
},
"assemblyNames": ["peach", "grape"]
}
}
],
"defaultSession": {
"name": "Grape vs Peach (small)",
"views": [
{
"id": "MiDMyyWpp",
"type": "DotplotView",
"assemblyNames": ["peach", "grape"],
"hview": {
"displayedRegions": [],
"bpPerPx": 100000,
"offsetPx": 0
},
"vview": {
"displayedRegions": [],
"bpPerPx": 100000,
"offsetPx": 0
},
"tracks": [
{
"type": "SyntenyTrack",
"configuration": "dotplot_track_small",
"displays": [
{
"type": "DotplotDisplay",
"configuration": "dotplot_track_small-DotplotDisplay"
}
]
}
],
"displayName": "Grape vs Peach dotplot"
}
]
}
}

Note that configuring the dotplot involves creating a "defaultSession"

Users can also open synteny views using the File->Add->Dotplot view workflow, and create their own synteny view outside of the default configuration

LinearSyntenyView config#

Currently, configuring synteny is made by pre-configuring a session in the view and adding synteny tracks

{
"defaultSession": {
"name": "Grape vs Peach Demo",
"drawerWidth": 384,
"views": [
{
"type": "LinearSyntenyView",
"id": "test1",
"headerHeight": 44,
"datasetName": "grape_vs_peach_dataset",
"tracks": [
{
"type": "SyntenyTrack",
"configuration": "grape_peach_synteny_mcscan",
"displays": [
{
"configuration": "grape_peach_synteny_mcscan-LinearSyntenyDisplay",
"height": 100,
"type": "LinearSyntenyDisplay"
}
]
}
],
"height": 400,
"displayName": "Grape vs Peach",
"trackSelectorType": "hierarchical",
"views": [
{
"type": "LinearGenomeView",
"id": "test1_1",
"offsetPx": 28249,
"bpPerPx": 1000,
"displayedRegions": [
{
"refName": "Pp01",
"assemblyName": "peach",
"start": 0,
"end": 100000000
}
],
"tracks": [
{
"type": "FeatureTrack",
"configuration": "peach_genes",
"displays": [
{
"configuration": "peach_genes_linear",
"height": 100,
"type": "LinearBasicDisplay"
}
]
}
],
"hideControls": false,
"hideHeader": true,
"hideCloseButton": true,
"trackSelectorType": "hierarchical"
},
{
"type": "LinearGenomeView",
"id": "test1_2",
"offsetPx": 0,
"bpPerPx": 1000,
"displayedRegions": [
{
"refName": "chr1",
"assemblyName": "grape",
"start": 0,
"end": 100000000
}
],
"tracks": [
{
"type": "FeatureTrack",
"configuration": "grape_genes",
"displays": [
{
"configuration": "grape_genes_linear",
"height": 100,
"type": "LinearBasicDisplay"
}
]
}
],
"hideControls": false,
"hideHeader": true,
"hideCloseButton": true,
"trackSelectorType": "hierarchical"
}
]
}
],
"widgets": {},
"activeWidgets": {},
"connections": {}
},
"assemblies": [
{
"name": "grape",
"sequence": {
"trackId": "grape_seq",
"type": "ReferenceSequenceTrack",
"adapter": {
"type": "ChromSizesAdapter",
"chromSizesLocation": {
"uri": "grape.chrom.sizes"
}
}
}
},
{
"name": "peach",
"sequence": {
"trackId": "peach_seq",
"type": "ReferenceSequenceTrack",
"adapter": {
"type": "ChromSizesAdapter",
"chromSizesLocation": {
"uri": "peach.chrom.sizes"
}
}
}
}
],
"tracks": [
{
"trackId": "grape_peach_synteny_mcscan",
"type": "SyntenyTrack",
"assemblyNames": ["peach", "grape"],
"trackIds": [],
"renderDelay": 100,
"adapter": {
"mcscanAnchorsLocation": {
"uri": "grape.peach.anchors"
},
"subadapters": [
{
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/peach_gene/{refseq}/trackData.json"
}
},
{
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/grape_gene/{refseq}/trackData.json"
}
}
],
"assemblyNames": ["peach", "grape"],
"type": "MCScanAnchorsAdapter"
},
"name": "Grape peach synteny (MCScan)",
"category": ["Annotation"]
},
{
"trackId": "peach_genes",
"type": "FeatureTrack",
"assemblyNames": ["peach"],
"name": "mcscan",
"category": ["Annotation"],
"adapter": {
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/peach_gene/{refseq}/trackData.json"
}
},
"displays": [
{
"type": "LinearBasicDisplay",
"displayId": "peach_genes_linear",
"renderer": {
"type": "PileupRenderer"
}
}
]
},
{
"trackId": "peach_genes2",
"type": "FeatureTrack",
"assemblyNames": ["peach"],
"name": "mcscan2",
"category": ["Annotation"],
"adapter": {
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/peach_gene/{refseq}/trackData.json"
}
}
},
{
"trackId": "grape_genes",
"type": "FeatureTrack",
"name": "mcscan",
"assemblyNames": ["grape"],
"category": ["Annotation"],
"adapter": {
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/grape_gene/{refseq}/trackData.json"
}
},
"displays": [
{
"type": "LinearBasicDisplay",
"displayId": "grape_genes_linear",
"renderer": {
"type": "PileupRenderer"
}
}
]
},
{
"trackId": "grape_genes2",
"type": "FeatureTrack",
"name": "mcscan2",
"category": ["Annotation"],
"assemblyNames": ["grape"],
"adapter": {
"type": "NCListAdapter",
"rootUrlTemplate": {
"uri": "https://jbrowse.org/genomes/synteny/grape_gene/{refseq}/trackData.json"
}
}
}
],
"configuration": {}
}

Configuring the theme#

Color#

The color scheme as well as some sizing options can be configured via the theme. This is done via a top-level configuration in the config file. For example:

{
"configuration": {
"theme": {
"palette": {
"primary": {
"main": "#4400a6"
}
}
}
}
}

JBrowse uses 4 colors that can be changed. For example, this is the default theme:

Example screenshot showing the default theme
Figure: Example screenshot showing the default theme
Example screenshot showing the customized theme
Figure: Example screenshot showing the customized theme

The customized theme screenshot uses the below configuration

Color codeColor
Primary#311b92Deep purple
Secondary#0097a7Cyan
Tertiary#f57c00Orange
Quaternary#d50000Red
{
"configuration": {
"theme" :{
"palette": {
"primary": {
"main": "#311b92"
},
"secondary": {
"main": "#0097a7"
},
"tertiary": {
"main": "#f57c00"
},
"quaternary": {
"main": "#d50000"
}
}
}
}

Sizing#

You can also change some sizing options by specifying the "typography" (to change font size) and "spacing" (to change the amount of space between elements) options:

{
"theme": {
"typography": { "fontSize": 10 },
"spacing": 2
}
}

Advanced#

JBrowse uses Material-UI for its theming. You can read more about Material-UI themes here. Generally, most options you could pass to Material-UI's createMuiTheme should work in the theme configuration.

Disabling analytics#

This is done via adding a field in the global configuration in the config file. For example:

{
"configuration": {
"disableAnalytics": true
}
}

Configuration callbacks#

We use Jexl (see https://github.com/TomFrost/Jexl) for defining configuration callbacks.

An example of a Jexl configuration callback might look like this

"color": "jexl:get(feature,'strand')==-1?'red':'blue'"

The notation get(feature,'strand') is the same as feature.get('strand') in javascript code.

We have a number of other functions such as

Feature operations - get

jexl:get(feature,'start') // start coordinate, 0-based half open
jexl:get(feature,'end') // end coordinate, 0-based half open
jexl:get(feature,'refName') // chromosome or reference sequence name
jexl:get(feature,'CIGAR') // BAM or CRAM feature CIGAR string
jexl:get(feature,'seq') // BAM or CRAM feature sequence
jexl:get(feature,'type') // feature type e.g. mRNA or gene

Feature operations - getTag

The getTag function smooths over slight differences in BAM and CRAM features to access their tags

jexl:getTag(feature, 'MD') // fetches MD string from BAM or CRAM feature
jexl:getTag(feature, 'HP') // fetches haplotype tag from BAM or CRAM feature

String functions

jexl:charAt('abc',2) // c
jexl:charCodeAt(' ',0) // 32
jexl:codePointAt(' ',0) // 32
jexl:startsWith('kittycat','kit') // true
jexl:endsWith('kittycat','cat') // true
jexl:padStart('cat', 8, 'kitty') // kittycat
jexl:padEnd('kitty', 8, 'cat') // kittycat
jexl:replace('kittycat','cat','') // kitty
jexl:replaceAll('kittycatcat','cat','') // kitty
jexl:slice('kittycat',5) // cat
jexl:substring('kittycat',0,5) // kitty
jexl:trim(' kitty ') // kitty, whitespace trimmed
jexl:trimStart(' kitty ') // kitty, starting whitespace trimmed
jexl:trimEnd(' kitty ') // kitty, ending whitespace trimmed
jexl:toUpperCase('kitty') // KITTY
jexl:toLowerCase('KITTY') // kitty

Math functions

jexl:min(0,2)
jexl:max(0,2)
jexl:abs(-5)
jexl:ceil(0.5)
jexl:floor(0.5)
jexl:round(0.5)

Console logging

jexl:log(feature) // console.logs output and returns value
jexl:cast({'mRNA':'green','pseudogene':'purple'})[get(feature,'type')] // returns either green or purple depending on feature type

Binary operators

jexl:get(feature,'flags')&2 // bitwise and to check if BAM or CRAM feature flags has 2 set

Command line tools#

This document covers the CLI tools.

Installation#

The command line tools can be installed using npm as follows

$ npm install -g @jbrowse/cli

You can test your installation with

$ jbrowse --version

It is also possible to do one-off executions using npx, e.g.

npx @jbrowse/cli create myfolder

It is likely preferable in most cases to install the tools first however

Commands#

jbrowse add-assembly SEQUENCE#

Add an assembly to a JBrowse 2 configuration

USAGE
$ jbrowse add-assembly SEQUENCE
ARGUMENTS
SEQUENCE
sequence file or URL
If TYPE is indexedFasta or bgzipFasta, the index file defaults to <location>.fai
and can be optionally specified with --faiLocation
If TYPE is bgzipFasta, the gzip index file defaults to <location>.gzi and can be
optionally specified with --gziLocation
OPTIONS
-a, --alias=alias
An alias for the assembly name (e.g. "hg38" if the name of the assembly is "GRCh38");
can be specified multiple times
-f, --force
Equivalent to `--skipCheck --overwrite`
-h, --help
show CLI help
-l, --load=copy|symlink|move|inPlace
Required flag when using a local file. Choose how to manage the data directory. Copy, symlink, or move the data
directory to the JBrowse directory. Or use inPlace to modify the config without doing any file operations
-n, --name=name
Name of the assembly; if not specified, will be guessed using the sequence file name
-t, --type=indexedFasta|bgzipFasta|twoBit|chromSizes|custom
type of sequence, by default inferred from sequence file
indexedFasta An index FASTA (e.g. .fa or .fasta) file;
can optionally specify --faiLocation
bgzipFasta A block-gzipped and indexed FASTA (e.g. .fa.gz or .fasta.gz) file;
can optionally specify --faiLocation and/or --gziLocation
twoBit A twoBit (e.g. .2bit) file
chromSizes A chromosome sizes (e.g. .chrom.sizes) file
custom Either a JSON file location or inline JSON that defines a custom
sequence adapter; must provide --name if using inline JSON
--faiLocation=faiLocation
[default: <fastaLocation>.fai] FASTA index file or URL
--gziLocation=gziLocation
[default: <fastaLocation>.gzi] FASTA gzip index file or URL
--out=out
synonym for target
--overwrite
Overwrite existing assembly if one with the same name exists
--refNameAliases=refNameAliases
Reference sequence name aliases file or URL; assumed to be a tab-separated aliases
file unless --refNameAliasesType is specified
--refNameAliasesType=aliases|custom
Type of aliases defined by --refNameAliases; if "custom", --refNameAliases is either
a JSON file location or inline JSON that defines a custom sequence adapter
--refNameColors=refNameColors
A comma-separated list of color strings for the reference sequence names; will cycle
through colors if there are fewer colors than sequences
--skipCheck
Don't check whether or not the sequence file or URL exists or if you are in a JBrowse directory
--target=target
path to config file in JB2 installation directory to write out to.
Creates ./config.json if nonexistent
EXAMPLES
$ jbrowse add-assembly GRCh38.fa --load copy
$ jbrowse add-assembly GRCh38.fasta.with.custom.extension.xyz --type indexedFasta --load move
$ jbrowse add-assembly myFile.fa.gz --name GRCh38 --alias hg38 --load inPlace
$ jbrowse add-assembly GRCh38.chrom.sizes --load inPlace
$ jbrowse add-assembly GRCh38.config.json --load copy
$ jbrowse add-assembly https://example.com/data/sample.2bit
$ jbrowse add-assembly GRCh38.fa --target /path/to/jb2/installation/customconfig.json --load copy

See code: src/commands/add-assembly.ts

jbrowse add-connection CONNECTIONURLORPATH#

Add a connection to a JBrowse 2 configuration

USAGE
$ jbrowse add-connection CONNECTIONURLORPATH
ARGUMENTS
CONNECTIONURLORPATH URL of data directory
For hub file, usually called hub.txt
For JBrowse 1, location of JB1 data directory similar to http://mysite.com/jbrowse/data/
OPTIONS
-a, --assemblyName=assemblyName Assembly name of the connection If none, will default to the assembly in your config
file
-c, --config=config Any extra config settings to add to connection in JSON object format, such as
'{"uri":"url":"https://sample.com"}}'
-f, --force Equivalent to `--skipCheck --overwrite`
-h, --help show CLI help
-n, --name=name Name of the connection. Defaults to connectionId if not provided
-t, --type=type type of connection, ex. JBrowse1Connection, UCSCTrackHubConnection, custom
--connectionId=connectionId Id for the connection that must be unique to JBrowse. Defaults to
'connectionType-assemblyName-currentTime'
--out=out synonym for target
--overwrite Overwrites any existing connections if same connection id
--skipCheck Don't check whether or not the data directory URL exists or if you are in a JBrowse
directory
--target=target path to config file in JB2 installation directory to write out to.
EXAMPLES
$ jbrowse add-connection http://mysite.com/jbrowse/data/
$ jbrowse add-connection http://mysite.com/jbrowse/custom_data_folder/ --type JBrowse1Connection
$ jbrowse add-connection http://mysite.com/path/to/hub.txt --assemblyName hg19
$ jbrowse add-connection http://mysite.com/path/to/custom_hub_name.txt --type UCSCTrackHubConnection --assemblyName
hg19
$ jbrowse add-connection http://mysite.com/path/to/custom --type custom --config
'{"uri":{"url":"https://mysite.com/path/to/custom"}}' --assemblyName hg19
$ jbrowse add-connection https://mysite.com/path/to/hub.txt --connectionId newId --name newName --target
/path/to/jb2/installation/config.json

See code: src/commands/add-connection.ts

jbrowse add-track TRACK#

Add a track to a JBrowse 2 configuration

USAGE
$ jbrowse add-track TRACK
ARGUMENTS
TRACK Track file or URL
OPTIONS
-a, --assemblyNames=assemblyNames Assembly name or names for track as comma separated string. If none, will
default to the assembly in your config file
-d, --description=description Optional description of the track
-f, --force Equivalent to `--skipCheck --overwrite`
-h, --help show CLI help
-l, --load=copy|symlink|move|inPlace Required flag when using a local file. Choose how to manage the track. Copy,
symlink, or move the track to the JBrowse directory. Or inPlace to leave track
alone
-n, --name=name Name of the track. Will be defaulted to the trackId if none specified
-t, --trackType=trackType Type of track, by default inferred from track file
--category=category Optional Comma separated string of categories to group tracks
--config=config Any extra config settings to add to a track. i.e '{"defaultRendering":
"density"}'
--indexFile=indexFile Optional index file for the track
--out=out synonym for target
--overwrite Overwrites existing track if it shares the same trackId
--protocol=protocol [default: uri] Force protocol to a specific value
--skipCheck Skip check for whether or not the file or URL exists or if you are in a JBrowse
directory
--subDir=subDir when using --load a file, output to a subdirectory of the target dir
--target=target path to config file in JB2 installation to write out to.
--trackId=trackId trackId for the track, by default inferred from filename, must be unique
throughout config
EXAMPLES
# --load copy copies my.bam and my.bam.bai to current directory and adds track to config.json
$ jbrowse add-track /path/to/my.bam --load copy
# same as above, but specify path to bai file
$ jbrowse add-track /path/to/my.bam --indexFile /path/to/my.bai --load copy
# --load symlink creates symlink in /path/to/jb2/ directory for this file, and adds track to config.json
$ jbrowse add-track /path/to/my.bam --target /path/to/jb2/config.json --load symlink
# no --load flag to add literal URL for this track to config.json
$ jbrowse add-track https://mywebsite.com/my.bam
# --load move to move the file
$ jbrowse add-track /path/to/my.bam --name 'New Track' --load move
# --load inPlace puts /url/relative/path.bam in the config without performing any file operations
$ jbrowse add-track /url/relative/path.bam --trackId AlignmentsTrack1 --load url --overwrite

See code: src/commands/add-track.ts

jbrowse add-track-json TRACK#

Add a track configuration directly from a JSON hunk to the JBrowse 2 configuration

USAGE
$ jbrowse add-track-json TRACK
ARGUMENTS
TRACK track JSON file or command line arg blob
OPTIONS
-u, --update update the contents of an existing track, matched based on trackId
--out=out synonym for target
--target=target path to config file in JB2 installation directory to write out to.
Creates ./config.json if nonexistent
EXAMPLES
$ jbrowse add-track-json track.json
$ jbrowse add-track-json track.json --update

See code: src/commands/add-track-json.ts

jbrowse admin-server#

Start up a small admin server for JBrowse configuration

USAGE
$ jbrowse admin-server
OPTIONS
-h, --help show CLI help
-p, --port=port Specifified port to start the server on;
Default is 9090.
--out=out synonym for target
--skipCheck Don't check whether or not you are in a JBrowse directory
--target=target path to config file in JB2 installation directory to write out to.
Creates ./config.json if nonexistent
EXAMPLES
$ jbrowse admin-server
$ jbrowse admin-server -p 8888

See code: src/commands/admin-server.ts

jbrowse create LOCALPATH#

Downloads and installs the latest JBrowse 2 release

USAGE
$ jbrowse create LOCALPATH
ARGUMENTS
LOCALPATH Location where JBrowse 2 will be installed
OPTIONS
-f, --force Overwrites existing JBrowse 2 installation if present in path
-h, --help show CLI help
-l, --listVersions Lists out all versions of JBrowse 2
-t, --tag=tag Version of JBrowse 2 to install. Format is v1.0.0.
Defaults to latest
-u, --url=url A direct URL to a JBrowse 2 release
--branch=branch Download a development build from a named git branch
--nightly Download the latest development build from the main branch
EXAMPLES
$ jbrowse create /path/to/new/installation
$ jbrowse create /path/to/new/installation --force
$ jbrowse create /path/to/new/installation --url url.com/directjbrowselink.zip
$ jbrowse create /path/to/new/installation --tag v1.0.0
$ jbrowse create --listVersions # Lists out all available versions of JBrowse 2

See code: src/commands/create.ts

jbrowse help [COMMAND]#

display help for jbrowse

USAGE
$ jbrowse help [COMMAND]
ARGUMENTS
COMMAND command to show help for
OPTIONS
--all see all commands in CLI

See code: @oclif/plugin-help

jbrowse set-default-session#

Set a default session with views and tracks

USAGE
$ jbrowse set-default-session
OPTIONS
-c, --currentSession List out the current default session
-h, --help show CLI help
-n, --name=name [default: New Default Session] Give a name for the default session
-s, --session=session set path to a file containing session in json format
-t, --tracks=tracks Track id or track ids as comma separated string to put into default session
-v, --view=view View type in config to be added as default session, i.e LinearGenomeView, CircularView,
DotplotView.
Must be provided if no default session file provided
--delete Delete any existing default session.
--out=out synonym for target
--target=target path to config file in JB2 installation directory to write out to
--viewId=viewId Identifier for the view. Will be generated on default
EXAMPLES
$ jbrowse set-default-session --session /path/to/default/session.json
$ jbrowse set-default-session --target /path/to/jb2/installation/config.json --view LinearGenomeView --tracks track1,
track2, track3
$ jbrowse set-default-session --view LinearGenomeView, --name newName --viewId view-no-tracks
$ jbrowse set-default-session --currentSession # Prints out current default session

See code: src/commands/set-default-session.ts

jbrowse upgrade [LOCALPATH]#

Upgrades JBrowse 2 to latest version

USAGE
$ jbrowse upgrade [LOCALPATH]
ARGUMENTS
LOCALPATH [default: .] Location where JBrowse 2 is installed
OPTIONS
-h, --help show CLI help
-l, --listVersions Lists out all versions of JBrowse 2
-t, --tag=tag Version of JBrowse 2 to install. Format is v1.0.0.
Defaults to latest
-u, --url=url A direct URL to a JBrowse 2 release
--branch=branch Download a development build from a named git branch
--nightly Download the latest development build from the main branch
EXAMPLES
$ jbrowse upgrade # Upgrades current directory to latest jbrowse release
$ jbrowse upgrade /path/to/jbrowse2/installation
$ jbrowse upgrade /path/to/jbrowse2/installation --tag v1.0.0
$ jbrowse upgrade --listVersions # Lists out all available versions of JBrowse 2
$ jbrowse upgrade --url https://sample.com/jbrowse2.zip

See code: src/commands/upgrade.ts

Debugging#

Debug logs (provided by debug) can be printed by setting the DEBUG environment variable. Setting DEBUG=* will print all debug logs. Setting DEBUG=jbrowse* will print only logs from this tool, and setting e.g. DEBUG=jbrowse:add-assembly will print only logs from the add-assembly command.

Developer guide#

In this guide, will introduce the JBrowse 2 ecosystem from the developer's point of view. We'll examine the core concepts of how code is packaged and structured, and then go over how to create new plugins and pluggable elements.

Introduction and overview#

Let's get a high-level view of the JBrowse 2 ecosystem.

Products and plugins#

The JBrowse 2 ecosystem has two main type of top-level artifacts that are published on their own: products and plugins.

Architecture diagram of JBrowse 2, showing how plugins encapsulate views (e.g. LinearGenomeView, DotplotView etc.), tracks (AlignmentsTrack, VariantTrack, etc.), adapters (BamAdapter, VcfTabixAdapter, etc.) and other logic like mobx state tree autoruns that add logic to other parts of the app (e.g. adding context menus)
Figure: Architecture diagram of JBrowse 2, showing how plugins encapsulate views (e.g. LinearGenomeView, DotplotView etc.), tracks (AlignmentsTrack, VariantTrack, etc.), adapters (BamAdapter, VcfTabixAdapter, etc.) and other logic like mobx state tree autoruns that add logic to other parts of the app (e.g. adding context menus)

A "product" is an application of some kind that is published on its own (a web app, an electron app, a CLI app, etc). jbrowse-web, jbrowse-desktop, and jbrowse-cli are products.

A "plugin" is a package of functionality that is designed to "plug in" to a product at runtime to add functionality. These can be written and published by anyone, not just the JBrowse core team. Not all of the products use plugins, but most of them do.

Also, most of the products are pretty standard in the way they are constructed. For example, jbrowse-web is a React web application that is made with Create React App (CRA), and jbrowse-cli is a command-line tool implemented with OCLIF.

This figure summarizes the general architecture of our state model and React component tree
Figure: This figure summarizes the general architecture of our state model and React component tree

Example plugins#

You can follow this guide for developing plugins, but you might also want to refer to working versions of plugins on the web now

This repo contains a template for creating new plugins https://github.com/GMOD/jbrowse-plugin-template.

Here are some examples of working plugins.

You can use these to see how plugins are generally structured, and can use the pluggable elements in them as templates for your own pluggable elements.

We will go over what plugins do and what is in them now

What's in a plugin#

A plugin is an independently distributed package of code that is designed to "plug in" to a JBrowse application.

It's implemented as a class that extends @jbrowse/core/Plugin. It gets instantiated by the application that it plugs into, and it has an install method and a configure method that the application calls. This class is distributed as a webpack bundle that exports it to a namespace on the browser's window object specifically for JBrowse plugins1.

It's common for a plugin to use its configure method to set up mobx autoruns or reactions that react to changes in the application's state to modify its behavior.

Plugins often also have their install method add "pluggable elements" into the host JBrowse application. This is how plugins can add new kinds of views, tracks, renderers, and so forth.

Pluggable elements#

Pluggable elements are basic "extension points" that you can customize in JBrowse 2 plugins

The pluggable types that we have in JBrowse 2 are

  • Adapters
  • Track types
  • Renderer types
  • Widgets
  • RPC calls
  • Display types
  • View types

In additional to creating plugins that create new adapters, track types, etc. note that you can also wrap the behavior of another track so these elements are composable

For example we can have adapters that perform calculations on the results of another adapter, views that contains other subviews, and tracks that contain other tracks, leading to a lot of interesting behavior. Details and examples below

Adapters#

Adapters basically are parsers for a given data format. We will review what adapters the alignments plugin has (to write your own adapter, see creating adapters)

Example adapters: the @jbrowse/plugin-alignments plugin creates multiple adapter types

  • BamAdapter - This adapter uses the @gmod/bam NPM module, and adapts it for use by the browser.
  • CramAdapter - This adapter uses the @gmod/cram NPM module. Note that CramAdapter also takes a sequenceAdapter as a subadapter configuration, and uses getSubAdapter to instantiate it
  • SNPCoverageAdapter - this adapter takes a BamAdapter or CramAdapter as a subadapter, and calculates feature coverage from it

Displays#

A display is a method for displaying a particular track in a particular view

For example, we have a notion of a synteny track type, and the synteny track type has two display models

  • DotplotDisplay, which is used in the dotplot view
  • LinearSyntenyDisplay, which is used in the linear synteny view

This enables a single track entry to be used in multiple view types e.g. if I run jbrowse add-track myfile.paf, this automatically creates a synteny track that can be opened in both a dotplot and a linear synteny view.

Most track types only have a "linear" display available, but one more example is the VariantTrack, which has two display methods

  • LinearVariantDisplay - used in linear genome view
  • ChordVariantDisplay - used in the circular view

Renderers#

Renderers are a new concept in JBrowse 2, and are related to the concept of server side rendering (SSR), but can be used not just on the server but also in contexts like the web worker (e.g. the webworker can draw the features to an OffscreenCanvas). For more info see creating renderers

Example renderers: the @jbrowse/plugin-alignments exports several renderer types

  • PileupRenderer - a renderer type that renders Pileup type display of alignments fetched from the BamAdapter/CramAdapter
  • SNPCoverageRenderer - a renderer that draws the coverage. Note that this renderer derives from the wiggle renderer, but does the additional step of drawing the mismatches over the coverage track

Track types#

Track types are a high level type that controls how features are drawn. In most cases, a track combines a renderer and an adapter, and can do additional things like

  • Control what widget pops up on feature click
  • Add extra menu items to the track menu
  • Create subtracks (See AlignmentsTrack)
  • Choose "static-blocks" rendering styles, which keeps contents stable while the user scrolls, or "dynamic-blocks" that update on each scroll

Example tracks: the @jbrowse/plugin-alignments exports multiple track types

  • SNPCoverageTrack - this track type actually derives from the WiggleTrack type
  • PileupTrack - a track type that draws alignment pileup results
  • AlignmentsTrack - combines SNPCoverageTrack and PileupTrack as "subtracks"

Widgets#

Widgets are custom info panels that can show up in side panels, modals, or other places in an app

Widgets can do multiple types of things including

  • Configuration widget
  • Feature detail widget
  • Add track widget
  • Add connection widget
  • etc.

These widgets can be extended via plugins, so for example, the @jbrowse/plugin-alignments extends the BaseFeatureDetailWidget to have custom display of the alignments

  • AlignmentsFeatureDetailWidget - this provides a custom widget for viewing the feature details of alignments features that customizes the basic feature detail widget

View types#

Creating view types is one of the most powerful features of JBrowse 2, because it allows us to put entirely different visualizations in the same context as the standard linear-genome-view.

We have demonstrated a couple new view types in JBrowse 2 already including

  • LinearGenomeView - the classic linear view of a genome
  • CircularView - a Circos-like circular whole genome view
  • DotplotView - a comparative 2-D genome view
  • SvInspectorView - superview containing CircularView and SpreadsheetView subviews
  • And more!

We think the boundaries for this are just your imagination, and there can also be interplay between view types e.g. popup dotplot from a linear view, etc.

RPC methods#

Plugins can register their own RPC methods, which can allow them to offload custom behaviors to a web-worker or server side process. The Wiggle track for example registers WiggleGetGlobalStats and WiggleGetMultiRegionStats

MenuItems#

You can add menus or add items to existing menus in several places.

A MenuItem object defines the menu item's text, icon, action, and other attributes.

Types of MenuItems:

  • Normal: a standard menu item that performs an action when clicked
  • Checkbox: a menu item that has a checkbox
  • Radio: a menu item that has a radio button icon
  • Divider: a horizontal line (not clickable) that can be used to visually divide menus
  • SubHeader: text (not clickable) that can be used to visually label a section of a menu
  • SubMenu: contains menu items, for making nested menus
NameDescription
typeOptions are 'normal', 'radio', 'checkbox', 'subMenu', 'subHeader', or 'divider'. If not provided, defaults to 'normal', unless a subMenu attribute is present, in which case it defaults to 'subMenu'.
labelThe text for the menu item. Not applicable to 'divider', required for all others.
subLabelAdditional descriptive text for the menu item. Not applicable to 'divider' or 'subHeader', optional for all others.
iconAn icon for the menu item. Must be compatible with Material-UI's Icons. Not applicable to 'divider' or 'subHeader', optional for all others.
disabledWhether or not the menu item is disabled (meaning grayed out and not clickable). Not applicable to 'divider' or 'subHeader', optional for all others.
checkedWhether or not the checkbox or radio button are selected. Only applicable to 'radio' and 'checkbox'
onClickCallback of action to perform on click. Function signature is (session) => undefined. Required for 'normal', 'radio', and 'checkbox', not applicable to any others.
subMenuAn array of menu items. Applicable only to 'subMenu'.

As an example, the here is an array of MenuItems and the resulting menu:

;[
{
label: 'Normal menu item',
icon: AddIcon,
onClick: () => {},
},
{
label: 'Normal',
subLabel: 'with subLabel',
icon: AddIcon,
onClick: () => {},
},
{
label: 'Disabled menu item',
disabled: true,
icon: AddIcon,
onClick: () => {},
},
{
type: 'radio',
label: 'Radio checked',
checked: true,
onClick: () => {},
},
{
type: 'radio',
label: 'Radio unchecked',
checked: false,
onClick: () => {},
},
{
type: 'checkbox',
label: 'Checkbox checked',
checked: true,
onClick: () => {},
},
{
type: 'checkbox',
label: 'Checkbox unchecked',
checked: false,
onClick: () => {},
},
{ type: 'divider' },
{ type: 'subHeader', label: 'This is a subHeader' },
{
label: 'SubMenu',
subMenu: [
{
label: 'SubMenu item one',
onClick: () => {},
},
{
label: 'SubMenu item two',
onClick: () => {},
},
],
},
]
This screenshot shows all the various track menu options, generated by the code listing
Figure: This screenshot shows all the various track menu options, generated by the code listing

Adding a top-level menu#

These are the menus that appear in the top bar of JBrowse Web and JBrowse Desktop. By default there are File and Help menus. You can add your own menu, or you can add menu items or sub-menus to the existing menus and sub-menus.

In the above screenshot, the `File` menu has several items and an `Add` sub-menu, which has more items. You can have arbitrarily deep sub-menus.
Figure: In the above screenshot, the `File` menu has several items and an `Add` sub-menu, which has more items. You can have arbitrarily deep sub-menus.

You add menus in the configure method of your plugin. Not all JBrowse products will have top-level menus, though. JBrowse Web and JBrowse Desktop have them, but something like JBrowse Linear View (which is an just a single view designed to be embedded in another page) does not. This means you need to check whether or not menus are supported using isAbstractMenuManager in the configure method. This way the rest of the plugin will still work if there is not a menu. Here's an example that adds an "Open My View" item to the File -> Add menu.

import Plugin from '@jbrowse/core/Plugin'
import { isAbstractMenuManager } from '@jbrowse/core/util'
import InfoIcon from '@material-ui/icons/Info'
class MyPlugin extends Plugin {
name = 'MyPlugin'
install(pluginManager) {
// install MyView here
}
configure(pluginManager) {
if (isAbstractMenuManager(pluginManager.rootModel)) {
pluginManager.rootModel.appendToSubMenu(['File', 'Add'], {
label: 'Open My View',
icon: InfoIcon,
onClick: session => {
session.addView('MyView', {})
},
})
}
}
}

This example uses rootModel.appendToSubMenu. These are all the menu-manipulation methods available on the root model:

appendMenu#

Add a top-level menu

Parameters#
NameDescription
menuNameName of the menu to insert.
Return Value#

The new length of the top-level menus array

insertMenu#

Insert a top-level menu

Parameters#
NameDescription
menuNameName of the menu to insert.
positionPosition to insert menu. If negative, counts from the end, e.g. insertMenu('My Menu', -1) will insert the menu as the second-to-last one.
Return Value#

The new length of the top-level menus array

appendToMenu#

Add a menu item to a top-level menu

Parameters#
NameDescription
menuNameName of the top-level menu to append to.
menuItemMenu item to append.
Return Value#

The new length of the menu

insertInMenu#

Insert a menu item into a top-level menu

Parameters#
NameDescription
menuNameName of the top-level menu to insert into.
menuItemMenu item to insert.
positionPosition to insert menu item. If negative, counts from the end, e.g. insertMenu('My Menu', -1) will insert the menu as the second-to-last one.
Return Value#

The new length of the menu

appendToSubMenu#

Add a menu item to a sub-menu

Parameters#
NameDescription
menuPathPath to the sub-menu to add to, starting with the top-level menu (e.g. ['File', 'Insert']).
menuItemMenu item to append.
Return value#

The new length of the sub-menu

insertInSubMenu#

Insert a menu item into a sub-menu

Parameters#
NameDescription
menuPathPath to the sub-menu to add to, starting with the top-level menu (e.g. ['File', 'Insert']).
menuItemMenu item to insert.
positionPosition to insert menu item. If negative, counts from the end, e.g. insertMenu('My Menu', -1) will insert the menu as the second-to-last one.
Return value#

The new length of the sub-menu

Adding menu items to a custom track#

If you create a custom track, you can populate the track menu items in it using the trackMenuItems property in the track model. For example:

types
.model({
// model
})
.views(self => ({
get trackMenuItems() {
return [
{
label: 'Menu Item',
icon: AddIcon,
onClick: () => {},
},
]
},
}))

Note that it is also common to use this scenario, because the base display may implement track menu items so this is like getting the superclasses track menu items

types
.model({
// model
})
.views(self => {
const { trackMenuitems } = self
return {
get composedTrackMenuItems() {
return [
{
label: 'Menu Item',
icon: AddIcon,
onClick: () => {},
},
]
},
get trackMenuItems() {
return [...trackMenuItems, ...this.composedTrackMenuItems]
},
}
})

Adding track context-menu items#

When you right-click in a linear track, a context menu will appear if there are any menu items defined for it. It's possible to add items to that menu, and you can also have different menu items based on if the click was on a feature or not, and based on what feature is clicked. This is done by adding a callback that takes the feature and track and returns a list of menu items to add based on those. This has to be done via a mobx autorun because it needs to add the callback to tracks after they are created. Here is an example:

class SomePlugin extends Plugin {
name = 'SomePlugin'
install(pluginManager) {
// install some stuff
}
configure(pluginManager) {
const menuItemCallback = (feature, track) => {
const menuItem = {
label: 'Some menu item',
icon: SomeIcon,
onClick: session => {
// do some stuff
},
}
return [menuItem]
}
const session = pluginManager.rootModel?.session
autorun(() => {
const views = session?.views
views.forEach(view => {
if (view.type === 'LinearGenomeView') {
const { tracks } = view
tracks.forEach(track => {
if (
track.type === 'VariantTrack' &&
!track.additionalContextMenuItemCallbacks.includes(
menuItemCallback,
)
) {
track.addAdditionalContextMenuItemCallback(menuItemCallback)
}
})
}
})
})
}
}

Configuration model concepts#

Configuration slot types#

Our configuration system is "typed" to facilitate graphical editing of the configuration. Each configuration has a "schema" that lists what "configuration slots" it has. Each configuration slot has a name, description, a type, and a value.

Here is a mostly comprehensive list of config types

  • stringEnum - allows assigning one of a limited set of entries, becomes a dropdown box in the GUI
  • color - allows selecting a color, becomes a color picker in the GUI
  • number - allows entering any numeric value
  • string - allows entering any string
  • integer - allows entering a integer value
  • boolean
  • frozen - an arbitrary JSON can be specified in this config slot, becomes textarea in the GUI
  • fileLocation - refers to a URL, local file path on desktop, or file blob object in the browser
  • text - allows entering a string, becomes textarea in the GUI
  • stringArray - allows entering a list of strings, becomes a "todolist" style editor in the GUI where you can add or delete things
  • stringArrayMap - allows entering a list of key-value entries

Let's examine the PileupRenderer configuration as an example.

Example config with multiple slot types#

This PileupRenderer config contains an example of several different slot types

import { types } from 'mobx-state-tree'
export default ConfigurationSchema('PileupRenderer', {
color: {
type: 'color',
description: 'the color of each feature in a pileup alignment',
defaultValue: `jexl:get(feature,'strand') == - 1 ? '#8F8FD8' : '#EC8B8B'`,
contextVariable: ['feature'],
},
displayMode: {
type: 'stringEnum',
model: types.enumeration('displayMode', ['normal', 'compact', 'collapse']),
description: 'Alternative display modes',
defaultValue: 'normal',
},
minSubfeatureWidth: {
type: 'number',
description: `the minimum width in px for a pileup mismatch feature. use for
increasing mismatch marker widths when zoomed out to e.g. 1px or
0.5px`,
defaultValue: 0,
},
maxHeight: {
type: 'integer',
description: 'the maximum height to be used in a pileup rendering',
defaultValue: 600,
},
})

Accessing config values#

So instead of accessing config.displayMode, we say

readConfObject(config, 'displayMode')

You might also see in the code like this

getConf(track, 'maxHeight')

Which would be equivalent to calling

readConfObject(track.configuration, 'maxHeight')`

Using config callbacks#

Config callbacks allow you to have a dynamic color based on some function logic you provide. All config slots can actually become config callback. The arguments that are given to the callback are listed by the 'contextVariable' but must be provided by the calling code (the code reading the config slot). To pass arguments to the a callback we say

readConfObject(config, 'color', { feature })

That implies the color configuration callback will be passed a feature, so the config callback can be a complex function determining the color to use based on various feature attributes

Example of a config callback#

We use Jexl to express callbacks. See https://github.com/TomFrost/Jexl for more details.

If you had an variant track in your config, and wanted to make a custom config callback for color, it might look like this

{
"type": "VariantTrack",
"trackId": "variant_colors",
"name": "volvox filtered vcf (green snp, purple indel)",
"category": ["VCF"],
"assemblyNames": ["volvox"],
"adapter": {
"type": "VcfTabixAdapter",
"vcfGzLocation": {
"uri": "volvox.filtered.vcf.gz"
},
"index": {
"location": {
"uri": "volvox.filtered.vcf.gz.tbi"
}
}
},
"displays": [
{
"type": "LinearVariantDisplay",
"displayId": "volvox_filtered_vcf_color-LinearVariantDisplay",
"renderer": {
"type": "SvgFeatureRenderer",
"color1": "jexl:get(feature,'type')=='SNV'?'green':'purple'"
}
}
]
}

This draws all SNV (single nucleotide variants) as green, and other types as purple (insertion, deletion, other structural variant).

Configuration internals#

A configuration is a type of mobx-state-tree model, in which leaf nodes are ConfigSlot types, and other nodes are ConfigurationSchema types.

Schema
/ | \
Slot Schema Slot
| \
Slot Slot

Configurations are all descendants of a single root configuration, which is root.configuration.

Configuration types should always be created by the ConfigurationSchema factory, e.g.

import { ConfigurationSchema } from '@jbrowse/core/utils/configuration'
const ThingStateModel = types.model('MyThingsState', {
foo: 42,
configuration: ConfigurationSchema('MyThing', {
backgroundColor: {
defaultValue: 'white',
type: 'string',
},
}),
})

An example of a config schema with a sub-config schema is the BamAdapter, with the index sub-config schema

ConfigurationSchema(
'BamAdapter',
{
bamLocation: {
type: 'fileLocation',
defaultValue: { uri: '/path/to/my.bam' },
},
// this is a sub-config schema
index: ConfigurationSchema('BamIndex', {
indexType: {
model: types.enumeration('IndexType', ['BAI', 'CSI']),
type: 'stringEnum',
defaultValue: 'BAI',
},
location: {
type: 'fileLocation',
defaultValue: { uri: '/path/to/my.bam.bai' },
},
}),
},
{ explicitlyTyped: true },
)

Reading the sub-config schema is as follows

const indexType = readConfObject(config, ['index', 'indexType'])

Alternatively can use

const indexConf = readConfObject(config, ['index'])
indexConf.indexType

However, this may miss default values from the slot, the readConfObject has special logic to fill in the default value

Creating adapters#

What is an adapter#

An adapter is essentially a class that fetches and parses your data and returns it in a format JBrowse understands.

For example, if you have some data source that contains genes, and you want to display those genes using JBrowse's existing gene displays, you can write a custom adapter to do so. If you want to do a custom display of your data, though, you'll probably need to create a custom display and/or renderer along with your adapter.

What types of adapters are there#

  • Feature adapter - This is the most common type of adapter. Essentially, it takes a request for a region (a chromosome, starting position, and ending position) and returns the features (e.g. genes, reads, variants, etc.) that are in that region. Examples of this in JBrowse include adapters for BAM and VCF file formats.
  • Regions adapter - This type of adapter is used to define what regions are in an assembly. It returns a list of chromosomes/contigs/scaffolds and their sizes. An example of this in JBrowse is an adapter for a chrome.sizes file.
  • Sequence adapter - This is basically a combination of a regions adapter and a feature adapter. It can give the list of regions in an assembly, and can also return the sequence of a queried region. Examples of this in JBrowse include adapters for FASTA and .2bit file formats.
  • RefName alias adapter - This type of adapter is used to return data about aliases for reference sequence names, for example to define that "chr1" is an alias for "1". An example of this in JBrowse is an adapter for (alias files)[http://software.broadinstitute.org/software/igv/LoadData/#aliasfile]

Note about refname alias adapter: the first column must match what is seen in your FASTA file

Skeleton of a feature adapter#

A basic feature adapter might look like this (with implementation omitted for simplicity):

class MyAdapter extends BaseFeatureDataAdapter {
constructor(config) {
// config
}
async getRefNames() {
// return refNames used in your adapter, used for refName renaming
}
getFeatures(region) {
// return features from your adapter, using rxjs observable
}
freeResources(region) {
// can be empty
}
}

So to make a feature adapter, you implement the getRefNames function (optional), the getFeatures function (returns an rxjs observable stream of features, discussed below) and freeResources (optional)

Example feature adapter#

To take this a little slow let's look at each function individually

This is a more complete description of the class interface that you can implement

import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
import SimpleFeature from '@jbrowse/core/util/simpleFeature'
import { readConfObject } from '@jbrowse/core/configuration'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
class MyAdapter extends BaseFeatureDataAdapter {
// your constructor gets a config object that you can read with readConfObject
// if you use "subadapters" then you can initialize those with getSubAdapter
constructor(config, getSubAdapter) {
const fileLocation = readConfObject(config, 'fileLocation')
const subadapter = readConfObject(config, 'sequenceAdapter')
const sequenceAdapter = getSubAdapter(subadapter)
}
// use rxjs observer.next(new SimpleFeature(...your feature data....) for each
// feature you want to return
getFeatures(region, options) {
return ObservableCreate(async observer => {
try {
const { refName, start, end } = region
const response = await fetch(
'http://myservice/genes/${refName}/${start}-${end}',
options,
)
if (response.ok) {
const features = await result.json()
features.forEach(feature => {
observer.next(
new SimpleFeature({
uniqueID: `${feature.refName}-${feature.start}-${feature.end}`,
refName: feature.refName,
start: feature.start,
end: feature.end,
}),
)
})
observer.complete()
} else {
throw new Error(`${response.status} - ${response.statusText}`)
}
} catch (e) {
observer.error(e)
}
})
}
async getRefNames() {
// returns the list of refseq names in the file, used for refseq renaming
// you can hardcode this if you know it ahead of time e.g. for your own
// remote data API or fetch this from your data file e.g. from the bam header
return ['chr1', 'chr2', 'chr3'] /// etc
}
freeResources(region) {
// optionally remove cache resources for a region
// can just be an empty function
}
}

What is needed from a feature adapter#

getRefNames#

Returns the refNames that are contained in the file, this is used for "refname renaming" and is optional but highly useful in scenarios like human chromosomes which have, for example, chr1 vs 1.

Returning the refNames used by a given file or resource allows JBrowse to automatically smooth these small naming disparities over. See reference renaming

getFeatures#

A function that returns features from the file given a genomic range query e.g.

getFeatures(region, options)

The region parameter contains

interface Region {
refName: string
start: number
end: number
originalRefName: string
assemblyName: string
}

The refName, start, end specify a simple genomic range. The "assemblyName" is used to query a specific assembly if your adapter responds to multiple assemblies e.g. for a synteny data file or a REST API that queries a backend with multiple assemblies.

The "originalRefName" are also passed, where originalRefName is the queried refname before ref renaming e.g. in BamAdapter, if the BAM file uses chr1, and your reference genome file uses 1, then originalRefName will be 1 and refName will be chr1

The options parameter to getFeatures can contain any number of things

interface Options {
bpPerPx: number
signal: AbortSignal
statusCallback: Function
headers: Record<string, string>
}
  • bpPerPx - number: resolution of the genome browser when the features were fetched
  • signal - can be used to abort a fetch request when it is no longer needed, from AbortController
  • statusCallback - not implemented yet but in the future may allow you to report the status of your loading operations
  • headers - set of HTTP headers as a JSON object

We return an rxjs Observable from getFeatures. This is similar to a JBrowse 1 getFeatures call, where we pass each feature to a featureCallback, tell it when we are done with finishCallback, and send errors to errorCallback, except we do all those things with the Observable

Here is a "conversion" of JBrowse 1 getFeatures callbacks to JBrowse 2 observable calls

  • featureCallback(new SimpleFeature(...)) -> observer.next(new SimpleFeature(...))
  • finishCallback() -> observer.complete()
  • errorCallback(error) -> observer.error(error)
freeResources#

This is uncommonly used, so most adapters make this an empty function

Most adapters in fact use an LRU cache to make resources go away over time instead of manually cleaning up resources

Writing your own plugin#

JBrowse 2 plugins can be used to add new pluggable elements (views, tracks, adapters, etc), and to modify behavior of the application by adding code that watches the application's state. For the full list of what kinds of pluggable element types plugins can add, see the pluggable elements page.

The first thing that we have is a src/index.js which exports a default class containing the plugin registration code

src/index.js

import AdapterType from '@jbrowse/core/pluggableElementTypes/AdapterType'
import Plugin from '@jbrowse/core/Plugin'
import { AdapterClass, configSchema } from './UCSCAdapter'
export default class UCSCPlugin extends Plugin {
name = 'UCSCPlugin'
install(pluginManager) {
pluginManager.addAdapterType(
() =>
new AdapterType({
name: 'UCSCAdapter',
configSchema,
AdapterClass,
}),
)
}
}

src/UCSCAdapter/index.ts

import {
ConfigurationSchema,
readConfObject,
} from '@jbrowse/core/configuration'
import { ObservableCreate } from '@jbrowse/core/util/rxjs'
import { BaseFeatureDataAdapter } from '@jbrowse/core/data_adapters/BaseAdapter'
import SimpleFeature from '@jbrowse/core/util/simpleFeature'
import stringify from 'json-stable-stringify'
export const configSchema = ConfigurationSchema(
'UCSCAdapter',
{
base: {
type: 'fileLocation',
description: 'base URL for the UCSC API',
defaultValue: {
uri: 'https://cors-anywhere.herokuapp.com/https://api.genome.ucsc.edu/',
},
},
track: {
type: 'string',
description: 'the track to select data from',
defaultValue: '',
},
},
{ explicitlyTyped: true },
)
export class AdapterClass extends BaseFeatureDataAdapter {
constructor(config) {
super(config)
this.config = config
}
getFeatures(region) {
const { assemblyName, start, end, refName } = region
return ObservableCreate(async observer => {
const { uri } = readConfObject(this.config, 'base')
const track = readConfObject(this.config, 'track')
try {
const result = await fetch(
`${uri}/getData/track?` +
`genome=${assemblyName};track=${track};` +
`chrom=${refName};start=${start};end=${end}`,
)
if (result.ok) {
const data = await result.json()
data[track].forEach(feature => {
observer.next(
new SimpleFeature({
...feature,
start: feature.chromStart,
end: feature.chromEnd,
refName: feature.chrom,
uniqueId: stringify(feature),
}),
)
})
observer.complete()
}
} catch (e) {
observer.error(e)
}
})
}
async getRefNames() {
const arr = []
for (let i = 0; i < 23; i++) {
arr.push(`chr${i}`)
}
return arr
}
freeResources() {}
}

Adding this track to our configuration#

We can create a track.json like this

track.json

{
"type": "FeatureTrack",
"trackId": "genehancer_ucsc",
"name": "UCSC GeneHancer",
"assemblyNames": ["hg38"],
"adapter": {
"type": "UCSCAdapter",
"track": "geneHancerInteractionsDoubleElite"
}
}

Then use the jbrowse CLI tool add-track-json

jbrowse add-track-json file.json

This will automatically add this track to the tracks array of our config.json

Alternatively, we can manually edit this JSON into the config.json.

When we open this track, we should see the GeneHancer regions are drawn as orange blocks.

Creating a custom renderer type#

Let's say we want to create a track that connects a gene to it's enhancer. On UCSC the GeneHancer tracks do exactly this. An instance of the UCSC with the GeneHancer tracks is here.

We can see data that we can get for the GeneHancer interactions from the UCSC API like this

curl 'https://api.genome.ucsc.edu/getData/track?genome=hg19;\
track=geneHancerInteractionsDoubleElite;chrom=chr1;start=750000;\
end=505700000'|less

Given that the functionality of rendering arcs is so distinct from UCSC API adaptation, we can actually make this a new plugin. Let's imagine starting a new plugin from scratch again

src/index.js

import Plugin from '@jbrowse/core/Plugin'
import PluginManager from '@jbrowse/core/PluginManager'
import ArcRenderer, {
configSchema as ArcRendererConfigSchema,
ReactComponent as ArcRendererReactComponent,
} from './ArcRenderer'
export default class ArcRendererPlugin extends Plugin {
name = 'ArcPlugin'
install(pluginManager) {
pluginManager.addRendererType(
() =>
new ArcRenderer({
name: 'ArcRenderer',
ReactComponent: ArcRendererReactComponent,
configSchema: ArcRendererConfigSchema,
pluginManager,
}),
)
}
}

src/ArcRenderer/index.js

import React from 'react'
// prettier-ignore
import {
ServerSideRendererType
} from '@jbrowse/core/pluggableElementTypes/renderers/ServerSideRendererType'
import {
ConfigurationSchema,
readConfObject,
} from '@jbrowse/core/configuration'
import { PrerenderedCanvas } from '@jbrowse/core/ui'
import { bpSpanPx } from '@jbrowse/core/util'
import {
createCanvas,
createImageBitmap,
} from '@jbrowse/core/util/offscreenCanvasPonyfill'
// Our config schema for arc track will be basic, include just a color
export const configSchema = ConfigurationSchema(
'ArcRenderer',
{
color: {
type: 'color',
description: 'color for the arcs',
defaultValue: 'darkblue',
},
},
{ explicitlyTyped: true },
)
// This ReactComponent is the so called "rendering" which is the component
// that contains the contents of what was rendered.
export const ReactComponent = props => {
return (
<div style={{ position: 'relative' }}>
<PrerenderedCanvas {...props} />
</div>
)
}
// Our ArcRenderer class does the main work in it's render method
// which draws to a canvas and returns the results in a React component
export default class ArcRenderer extends ServerSideRendererType {
async render(renderProps) {
const {
features,
config,
regions,
bpPerPx,
highResolutionScaling,
} = renderProps
const region = regions[0]
const width = (region.end - region.start) / bpPerPx
const height = 500
const canvas = createCanvas(
width * highResolutionScaling,
height * highResolutionScaling,
)
const ctx = canvas.getContext('2d')
ctx.scale(highResolutionScaling, highResolutionScaling)
for (const feature of features.values()) {
const [left, right] = bpSpanPx(
feature.get('start'),
feature.get('end'),
region,
bpPerPx,
)
ctx.beginPath()
ctx.strokeStyle = readConfObject(config, 'color', { feature })
ctx.lineWidth = 3
ctx.moveTo(left, 0)
ctx.bezierCurveTo(left, 200, right, 200, right, 0)
ctx.stroke()
}
const imageData = await createImageBitmap(canvas)
const reactElement = React.createElement(
this.ReactComponent,
{
...renderProps,
width,
height,
imageData,
},
null,
)
return { reactElement, imageData, width, height }
}
}

The above code is relatively simple but it is fairly quirky. Here are some notes:

  • renderers can be run in offscreen or even a node.js canvas, so we do not assume the document.createElement exists to create our canvas, instead using a utility function that makes a OffscreenCanvas or node-canvas (depends on context, e.g. webworker or node.js)
  • the "rendering" component contains the results of our renderer. in this case it delegates to the PrerenderedCanvas component, a component we use in other places throughout the codebase

Bringing the two together#

We can bring these two contexts together with a new track in our config.json. Remember our previous track.json? Now we can edit it to use our own ArcRenderer

track.json

{
"type": "BasicTrack",
"trackId": "genehancer_ucsc",
"name": "UCSC GeneHancer",
"assemblyNames": ["hg38"],
"adapter": {
"type": "UCSCAdapter",
"track": "geneHancerInteractionsDoubleElite"
},
"renderer": {
"type": "ArcRenderer"
}
}

Then add the track

jbrowse add-track-json track.json --update

Creating custom renderers#

What is a renderer#

In JBrowse 1, a track type typically would directly call the data parser and do it's own rendering. In JBrowse 2, the data parsing and rendering is offloaded to a web-worker or other RPC. This allows things to be faster in many cases. This is conceptually related to "server side rendering" or SSR in React terms.

Conceptual diagram of how a track calls a renderer using the RPC
Figure: Conceptual diagram of how a track calls a renderer using the RPC

Important note: you can make custom tracks types that do not use this workflow, but it is a built in workflow that works well for the core track types in JBrowse 2.

How to create a new renderer#

The fundamental aspect of creating a new renderer is creating a class that implements the "render" function. A renderer is actually a pair of a React component that contains the renderer's output, which we call the "rendering" and the renderer itself

class MyRenderer implements ServerSideRendererType {
render(props) {
const { width, height, regions, features } = props
const canvas = createCanvas(width, height)
const ctx = canvas.getContext('2d')
ctx.fillStyle = 'red'
ctx.drawRect(0, 0, 100, 100)
const imageData = createImageBitmap(canvas)
return {
reactElement: React.createElement(this.ReactComponent, { ...props }),
imageData,
height,
width,
}
}
}

In the above simplified example, our renderer creates a canvas using width and height that are supplied via arguments, and draw a rectangle. We then return a React.createElement call which creates a "rendering" component that will contain the output

Note that the above canvas operations use an OffscreenCanvas for Chrome, or in other browsers serialize the drawing commands to be drawn in the main thread

What are the props passed to the renderer#

The typical props that a renderer receives

export interface PileupRenderProps {
features: Map<string, Feature>
layout: { addRect: (featureId, leftBp, rightBp, height) => number }
config: AnyConfigurationModel
regions: Region[]
bpPerPx: number
height: number
width: number
highResolutionScaling: number
}

The layout is available on BoxRendererType renderers so that it can layout things in pileup format, and has an addRect function to get the y-coordinate to render your data at

The features argument is a map of feature ID to the feature itself. To iterate over the features Map, we can use an iterator or convert to an array

class MyRenderer extends ServerSideRendererType {
render(props) {
const { features, width, height } = props
// iterate over the ES6 map of features
for (const feature in features.values()) {
// render each feature to canvas or output SVG
}
// alternatively
const feats = Array.from(features.values())
feats.forEach(feat => {})
}
}

Adding custom props to the renderer#

Note that track models themselves can extend this using their renderProps function

For example the WiggleTrack has code similar to this, which adds a scaleOpts prop that gets passed to the renderer

const model = types
.compose(
'WiggleTrack',
blockBasedTrack,
types.model({
type: types.literal('WiggleTrack'),
}),
)
.views(self => ({
get renderProps() {
return {
...self.composedRenderProps, // props that the blockBasedTrack adds,
...getParentRenderProps(self), // props that the view wants to add,
scaleOpts: {
domain: this.domain,
stats: self.stats,
autoscaleType: getConf(self, 'autoscale'),
scaleType: getConf(self, 'scaleType'),
inverted: getConf(self, 'inverted'),
},
}
},
}))

Rendering SVG#

Our SVG renderer is an example, where it extends the existing built in renderer type with a custom ReactComponent only

export default class SVGPlugin extends Plugin {
install(pluginManager: PluginManager) {
pluginManager.addRendererType(
() =>
new BoxRendererType({
name: 'SvgFeatureRenderer',
ReactComponent: SvgFeatureRendererReactComponent,
configSchema: svgFeatureRendererConfigSchema,
pluginManager,
}),
)
}
}

Then, we have our Rendering component just be plain React code. This is a highly simplified SVG renderer just to illustrate

export default function SvgFeatureRendering(props) {
const { width, features, regions, layout, bpPerPx } = props
const region = regions[0]
const feats = Array.from(features.values())
const height = readConfObject(config, 'height', { feature })
return (
<svg>
{feats.map(feature => {
// our layout determines at what y-coordinate to
// plot our feature, given all the other features
const top = layout.addRect(
feature.id(),
feature.get('start'),
feature.get('end'),
height,
)
const [left, right] = bpSpanPx(
feature.get('start'),
feature.get('end'),
region,
bpPerPx,
)
return <rect x={left} y={top} height={height} width={right - left} />
})}
</svg>
)
}

Notes:

  • The above SVG renderer is highly simplified but serves an example, but it shows that you can have a simple React component that leverages the existing BoxRendererType, so that you do not have to necessarily create your own renderer class
  • The renderers receive an array of regions to render, but if they are only equipped to handle one region at a time then they can select only rendering to regions[0]

Overriding the renderer's getFeatures method#

Normally, it is sufficient to override the getFeatures function in your dataAdapter

If you want to drastically modify the feature fetching behavior, you can modify the renderer's getFeatures call

The base ServerSideRendererType class has a built-in getFeatures function that, in turn, calls your adapter's getFeatures function, but if you need tighter control over how your adapter's getFeatures method is called then your renderer. The Hi-C renderer type does not operate on conventional features and instead works with contact matrices, so the Hi-C renderer has a custom getFeatures function

import { toArray } from 'rxjs/operators'
class HicRenderer extends ServerSideRendererType {
async getFeatures(args) {
const { dataAdapter, regions } = args
const features = await dataAdapter
.getFeatures(regions[0])
.pipe(toArray())
.toPromise()
return features
}
}

Creating custom track types#

At a high level the track types are just "ReactComponents" that contain rendered track contents. Oftentimes, for custom drawing, we create a renderer instead of a track, but here are some reasons you might want a custom track

  • Drawing custom things over the rendered content (e.g. drawing the Y-scale bar in the wiggle track)
  • Implementing custom track menu items (e.g. Show soft clipping in the alignments track)
  • Adding custom widgets (e.g. custom VariantFeatureWidget in variant track)
  • You want to bundle your renderer and adapter as a specific thing that is automatically initialized rather than the BasicTrack (which combines any adapter and renderer)

For examples of custom track types, refer to things like

  • HicTrack, which uses a custom HicRenderer to draw contact matrix
  • GDCPlugin, which has a custom track type that registers custom feature detail widgets
  • VariantTrack, which also registers custom widgets, and has ChordVariantDisplay and LinearVariantDisplay
  • SyntenyTrack, which can be displayed with DotplotDisplay or LinearSyntenyDisplay

FAQ#

General#

What technologies does JBrowse 2 use#
  • React
  • mobx-state-tree
  • web-workers
  • Typescript
  • Electron (for desktop specifically)
What is special about JBrowse 2#

One thing that makes JBrowse 2 special is that we can create new view types via our plugin system, e.g. circular, dotplot, etc. Anything you want can be added as a view, and can be shown alongside our other views

This makes JBrowse 2 more than just a genome browser-- it is really a platform that can be built on.

What are new features in JBrowse 2#
  • Uses web workers for multi-core data parsing and rendering of tracks
  • Use ctrl+scroll to zoom in and out quickly
  • Status updates while track is loading (e.g. Downloading BAM index...)
  • Hi-C visualization from .hic format files
  • Can display multiple chromosomes or discontinuous regions on a single linear genome view
  • Can connect to UCSC trackhubs
  • Alignments track has both coverage and pileup display integrated in a single track
  • Read pileups can be sorted by various attributes
  • Has ability to show soft clipped bases on reads
  • Interactively edit the configuration using the GUI
  • Circular, dotplot, stacked synteny views
  • SV inspector, that gives tabular and circular overview of data in a single view
  • Linear genome view can be reverse complemented
Can the linear genome view be reverse complemented#

Yes! See here

Setup#

What web server do I need to run JBrowse 2#

JBrowse 2 by itself is just a set of JS, CSS, and HTML files that can be statically hosted on a webserver without any backend services running.

Therefore, running JBrowse 2 generally involves just copying the JBrowse 2 folder to your web server html folder e.g. /var/www/html/.

If you use a different platform such as Django, you may want to put it in the static resources folder.

Note that the server that you use should support byte-range requests (e.g. the Range HTTP header so that JBrowse can get small slices of large binary data files.

BAM files do not work on my server#

If you are using Apache then you will probably want to disable mime_magic. If mime_magic is enabled, you may see that your server responds with the HTTP header Content-Encoding: gzip which JBrowse does NOT want, because this instructs the browser to unzip the data but JBrowse should be in charge of this.

How can I start the JBrowse 2 app as a developer#

We recommend that you have the following

Then you can follow steps from our README

It basically boils down to git cloning our repo, and running yarn start which creates a development server on port 3000

You can use PORT=8080 yarn start to manually specify a different port

Note that this is a development server that gets started up. To install jbrowse 2 in production on your webserver, see below

Do you have any tips for learning React and mobx-state-tree#

Here is a short guide to React and mobx-state-tree that could help get you oriented

https://gist.github.com/cmdcolin/94d1cbc285e6319cc3af4b9a8556f03f

How can I setup JBrowse 2 in production#

We recommend following the steps in the quickstart web guide.

The general procedure is using the jbrowse create /var/www/html/jb2 and this will download the latest version of jbrowse to your web folder e.g. in /var/www/html

You can also use jbrowse upgrade /var/www/html/jb2 to get the latest version

How can I setup JBrowse 2 without the CLI tools#

The jbrowse CLI tools are basically a convenience, and are not strictly required

Simple tasks can be done without it

For example, for jbrowse create, you can visit the blog and download the latest jbrowse-web release tag, and unzip it into your web directory

For other things, like add-assembly and add-track, you can manually edit the config.json, reviewing the config docs and sample configs will be valuable

Understanding the config basics will come in handy also because you can manually edit in advanced configs after your tracks are loaded however be careful because corrupt configs can produce hard to understand errors, because our config system is strongly typed

Feel free to message the team if you encounter these

How do I load a track into JBrowse 2#

If you have followed the above steps and installed jbrowse 2 on your webserver and loaded the assembly, and have the CLI tools installed

jbrowse add-track myfile.bw -a hg19

This will setup a bigwig track on the hg19 assembly in your config.json. Make sure to run the command inside your current jbrowse2 folder e.g. /var/www/html/jbrowse2 or wherever you are currently setting up a config.json (you can have multiple configs)

Note that you can also use remote URLs

jbrowse add-track http://yourremote/myfile.bam

The add-track command will do as much as possible to infer from the file extension how to configure this track, and automatically infer the index to be myfile.bam.bai

Curiosities#

Why do all the tracks need an assembly specified#

We require that all tracks have a specific genome assembly specified in their config. This is because jbrowse 2 is a multi-genome-assembly browser (and can compare genomes given the data). This may be different to using say jbrowse 1 where it knows which genome assembly you are working with at any given time

How are the menus structured in the app#

In JBrowse 1, the app level menu operated on the single linear genome view, but with JBrowse 2, the top level menu only performs global operations and the linear genome view has it's own hamburger menu. Note that each track also has it's own track level menu.

Why do some of my reads not display soft clipping#

Some reads, such as secondary reads, do not have a SEQ field on their records, so they will not display softclipping.

The soft clipping indicators on these reads will appear black.


  1. This means it's only possible to have one version of a particular plugin loaded on any given webpage, even if multiple products are loaded and using it on the same page.