Every browser on this page is a live, interactive JBrowse 2 — pan, zoom, and click features directly in the page. This article is part of the website only (it is not a package vignette), so it can embed the full widget; the Introduction uses screenshots to keep the package small.

A hosted genome

Name a genome hub and you get the assembly, reference-name aliases, cytobands, and gene-name search for free. Here location = "BRCA1" resolves through the hub’s search index.

JBrowseR(
  assembly = "hg38",
  tracks = list(list(
    uri =
    paste0(
      "https://jbrowse.org/genomes/GRCh38/ncbi_refseq/",
      "GCA_000001405.15_GRCh38_full_analysis_set.refseq_annotation.sorted.gff.gz"
    ),
    name = "NCBI RefSeq Genes"
  )),
  location = "BRCA1"
)

A custom genome from a FASTA URL

No hub needed for your own genome: pass a sequence-file URL straight to assembly. The view builds the assembly from it (naming it after the file), and a bare data-file URL in tracks is inferred into a track — here an alignments track from a BAM.

JBrowseR(
  assembly = "https://jbrowse.org/genomes/volvox/volvox.fa",
  tracks = list("https://jbrowse.org/genomes/volvox/volvox.bam"),
  location = "ctgA:1..5,000"
)

An R result as a track

Turn a data frame of features into a track with track_data_frame() — no files, no web server. A score column makes it quantitative.

peaks <- data.frame(
  chrom = "17",
  start = seq(43000000, 43120000, by = 12000),
  end = seq(43000000, 43120000, by = 12000) + 4000,
  name = paste0("peak", seq_len(11)),
  score = round(runif(11, 5, 100))
)

JBrowseR(
  assembly = "hg38",
  tracks = list(track_data_frame(peaks, "R_peaks")),
  location = "17:43,000,000..43,125,000"
)

A plot from a data frame

A displays entry says how to draw the rows. LinearMarkDisplay is JBrowse’s grammar of graphics: encoding maps columns to channels the way aes() does, and the axis, legend and reference lines come from the scales. A windowed Fst scan between two Drosophila populations, computed in base R from hosted allele frequencies, becomes a bar per window on a value axis, coloured by a threshold scale over the same column; the sweep at Cyp6g1 is the run of bars past the 0.25 rule.

freqs <- read.csv("https://jbrowse.org/demos/popgen/dest_cyp6g1_freqs.csv")
p1 <- freqs$afr_freq
p2 <- freqs$cosmo_freq
window <- freqs$pos %/% 10000 * 10000
num <- tapply((p1 - p2)^2, window, sum)
den <- tapply(p1 * (1 - p2) + p2 * (1 - p1), window, sum)
fst <- data.frame(
  chrom = "chr2R",
  start = as.integer(names(num)),
  end = as.integer(names(num)) + 10000,
  fst = round(pmax(num / den, 0), 3),
  n_snps = as.vector(table(window))
)
fst <- fst[fst$n_snps >= 20, ]

JBrowseR(
  assembly = "dm6",
  tracks = list(track_data_frame(
    fst, "Fst (African vs cosmopolitan)",
    displays = list(list(
      type = "LinearMarkDisplay",
      scales = list(y = list(title = "Fst", rules = list(0.25))),
      marks = list(list(
        shape = "bar",
        encoding = list(
          y = "fst",
          color = list(
            field = "fst", scale = "threshold",
            domain = list(0.12, 0.25),
            range = list("#90a4ae", "#f9a825", "#d84315")
          )
        )
      ))
    ))
  )),
  location = "chr2R:11,900,000..12,450,000"
)

A file from this R session, with no server

track_data_frame() above puts every feature in the page as JSON, which stops scaling somewhere past a few thousand of them. local_files is the other way to have no web server: write a real file and hand JBrowse its bytes. Each path registers under its basename, and that name is what a track’s uri refers to — so the .bed extension still picks the adapter, exactly as a URL’s would.

bed <- file.path(tempdir(), "peaks.bed")
write.table(
  peaks[c("chrom", "start", "end", "name")],
  bed,
  sep = "\t", quote = FALSE, row.names = FALSE, col.names = FALSE
)

JBrowseR(
  assembly = "hg38",
  tracks = list(list(uri = "peaks.bed", name = "Peaks from a file")),
  local_files = bed,
  location = "17:43,000,000..43,125,000"
)

Nothing is served here: the bytes travel inside this page and JBrowse reads them out of a Blob. That also means an indexed file stays indexed, which is the reason to reach for this rather than inline the features — a bgzipped+tabixed table, or a BAM with its .bai, is read by byte range, so only the region on screen is ever touched. Put the index next to the data file and it comes along under the name the adapter derives:

JBrowseR(
  assembly = "hg38",
  tracks = list(list(uri = "peaks.bed.gz", name = "Peaks")),
  local_files = "~/analysis/peaks.bed.gz" # picks up peaks.bed.gz.tbi beside it
)

The bytes are base64-encoded into the document, so this is for a file on your own machine rather than for a reference genome; local_files warns past ~50 MB, and the Hosting data vignette covers what to do above that.

A statistical plot (GWAS Manhattan)

A track isn’t only features and coverage — a display can plot data. Point a GWASTrack at genome-wide summary statistics and give it a LinearManhattanDisplay, and the same linear view becomes a Manhattan plot: the displays block picks the plot; no special widget needed. The adapter’s uri shorthand finds the .tbi index next to the data, and JBrowse fills in displayId, so the config stays short.

JBrowseR(
  assembly = "hg19",
  tracks = list(list(
    type = "GWASTrack",
    trackId = "gwas_track",
    name = "GWAS",
    adapter = list(
      type = "GWASAdapter",
      scoreColumn = "neg_log_pvalue",
      uri = "https://jbrowse.org/genomes/hg19/gwas/summary_stats.txt.gz"
    ),
    displays = list(list(type = "LinearManhattanDisplay", height = 250))
  )),
  location = "2"
)

For comparative genomics — synteny and dotplots across two assemblies — see the comparing genomes article, which uses JBrowseRApp().