juicebox.js is an embeddable interactive contact map viewer for .hic files written in JavaScript and CSS. It is based on the desktop Juicebox visualization application.
Requirements:
-
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css"> -
Juicebox CSS
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/juicebox.js@2.4.8/dist/css/juicebox.css"> -
Juicebox javascript -- see below
To import juicebox as an ES6 module
import juicebox from "https://cdn.jsdelivr.net/npm/juicebox.js@2.4.8/dist/juicebox.esm.js";Or as a script include (defines the "juicebox" global)
<script src="https://cdn.jsdelivr.net/npm/juicebox.js@2.4.8/dist/juicebox.min.js"></script>Alternatively you can install with npm
npm install juicebox
and source the appropriate file for your module system (juicebox.min.js or juicebox.esm.js) in node_modules/juicebos.js/dist. Or build from source (see Development section below).
To create an juicebox instance call juicebox.init with a container div and an initial configuration object as
illustrated below.
juicebox.init(container, config)
.then(function (hicBrowser) {
console.log("Juicebox loaded");
})Configuration config object examples follow
- A minimal juicebox config containing only a hic map with all default settings (see examples/juicebox-minimal):
const config = {
"url": "https://hicfiles.s3.amazonaws.com/hiseq/gm12878/dilution/combined.hic",
}
- Juicebox config with contact map, gene annotations, CTCF wig track, and 2D annotations (see examples/juicebox.html):
const config = {
"url": "https://hicfiles.s3.amazonaws.com/hiseq/gm12878/dilution/combined.hic",
"name": "Combined",
"locus": "18:28,504,357-29,748,974 18:28,504,357-29,748,974",
"normalization": "VC_SQRT",
"backgroundColor": "255,255,255",
"colorScale": "60,255,0,0",
"tracks": [
{
"url": "https://www.encodeproject.org/files/ENCFF144KUK/@@download/ENCFF144KUK.bigWig",
"type": "wig",
"format": "bigwig",
"name": "Homo sapiens GM12878 CTCF "
"color": "green"
},
{
"url": "https://hgdownload.soe.ucsc.edu/goldenPath/hg19/database/ncbiRefSeq.txt.gz",
"type": "annotation",
"format": "refgene",
"name": "Refseq Genes",
},
{
"url": "https://hicfiles.s3.amazonaws.com/hiseq/gm12878/in-situ/combined_peaks.txt",
"name": "Rao & Huntley et al. | Cell 2014 | GM12878 combined loops"
},
{
"url": "https://hicfiles.s3.amazonaws.com/hiseq/hap1/in-situ/combined_peaks.txt",
"name": "Sanborn & Rao et al. | PNAS 2015 | Hap1 loops",
"color": "#fffa03",
"displayMode": "upper"
},
{
"url": "https://hicfiles.s3.amazonaws.com/external/mumbach/GSE80820_HiChIP_GM_cohesin_peaks.txt",
"name": "Mumbach Rubin Flynn et al. | Nature Methods 2016 | GM12878 cohesin combined loops",
"color": "#000000",
"displayMode": "lower"
}
]
}
The juicebox.init function returns a promise for a HICBrowser object. This object exposes functions for interacting with the viewer including
- loadHicFile({url: urlString, name: string})
- loadTracks([array of track configs...])
For a description of track configurations see the documentation for igv.js. Example of a basic track configuration object:
See examples/juicebox-api.html for an example of using the API to load hicfiles and tracks.
Building juicebox.js requires Linux or MacOS, and node.js.
Other Unix environments will probably work but have not been tested. Windows users can use Windows Subsystem for Linux.
git clone https://github.com/igvteam/juicebox.js.git
cd juicebox.js
npm install
npm run build
juicebox.js is designed to be embedded in a host application (e.g., Juicebox-web), so it does not run standalone. To give developers a quick way to see the library in action and to aid in debugging, a lightweight Vite dev server is included with a launch dashboard.
npm run dev
This opens a dashboard at http://localhost:3000 with links to all available pages, organized into two sections:
- Examples — Minimal, stripped-down pages that demonstrate juicebox.js features and API usage, giving developers a quick look and feel without the overhead of a full host application.
- Dev Files — Test harnesses for developing and debugging specific features such as live contact maps, 2D annotations, normalization, and bug reproductions.
Note: The Vite dev server is required because the source files use bare npm import specifiers and SCSS, which browsers cannot resolve from a plain static file server.
Some data hosts refuse the request a browser is able to make, so their maps cannot be loaded in development without help. Two gates are known:
- A bot challenge keyed on
Origin—www.encodeproject.orgputs AWS WAF in front of its files and answers any origin not on its allowlist with a CAPTCHA page, under a misleading405.localhostis never allowlisted. - A
User-Agentallowlist —hicfiles.s3.amazonaws.comanddnazoo.s3.amazonaws.comserve403unless the request carries an allowlistedUser-Agent. No browser can comply:User-Agentis a forbidden header name in the Fetch spec, so the value the client libraries set is dropped before the request leaves.
dev-proxy/ is a development-only workaround: a Vite plugin that refetches the file from Node, where those headers are ours to set, plus the client-side rule that decides which hosts get routed that way. It is already wired into this repo's dev server — see dev/encode-dev-proxy.html. In a host application:
// vite.config.js
import { devProxy } from 'juicebox.js/dev-proxy/plugin'
export default defineConfig({ plugins: [devProxy()] })// app startup
import hic from 'juicebox.js'
import { devMapUrl } from 'juicebox.js/dev-proxy/map-url'
if (import.meta.env.DEV) hic.setUrlMapper(devMapUrl)devProxy() takes an origin option (default https://aidenlab.org) — the Origin the proxy claims for hosts whose gate keys on one. Set it to a domain you actually control.
Which hosts get routed, and what headers each is sent, are declared together in CHALLENGED_HOSTS in dev-proxy/map-url.js. Adding the next such host is an entry there and nothing else. Every other host keeps fetching directly, so a genuine CORS or permissions problem still surfaces in development exactly as it would in production.
For the Origin-challenged host the proxy hands the redirect back and the file streams to the browser from storage directly. The User-Agent-gated buckets serve their objects with no redirect to hand back, so for those the dev server relays the bytes.
apply: 'serve' means the plugin can never enter a production build, and setUrlMapper is unset by default: a host app that never calls it behaves exactly as before.
The mapper covers .hic reads through hic-straw, 2D annotations, and 1D tracks read by igv. A 1D track is the awkward one: igv reads it through its own bundled loaders, which juicebox cannot reach into, so the mapped URL has to go into the config igv is handed. It never escapes from there — browser.toJSON() serializes the original, so a session saved in development loads in production. Still uncovered: gene search and session-file reads. Details and measurements: docs/adr/0001-dev-proxy-for-waf-protected-hosts.md.
This creates a dist folder with the following files
- juicebox.js - ES5 compatible file. A script include will define the "juicebox" global.
- juicebox.min.js - minified version of juicebox.js
- juicebox.esm.js -- ES6 module
- css -- folder containing required css file juicebox.css and associated images
juicebox.js require a modern web browser with support for Javascript ECMAScript 2015.
For an out-of-the box web application for viewing and sharing contact maps from .hic files see Juicebox-web, a web application embedding a juicebox.js viewer.
juicebox.js is MIT licensed.