Clustered heatmaps in JavaScript with CanvasXpress
The clustered heatmap is the default way to look at an expression matrix: rows and columns reordered by similarity, dendrograms on the margins, and sample metadata alongside. CanvasXpress clusters inside the render, so in the browser you pass a plain matrix and get an interactive, reproducible figure.
Load the library
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@69.6.1/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@69.6.1/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>The markup and the spec
Genes are the variables (rows), samples the columns; the matrix goes in as data, and the sample annotation becomes a track over the columns. samplesClustered / variablesClustered turn on hierarchical clustering with dendrograms.
<canvas id="heatmap" width="650" height="550"></canvas>
<script>
// standard normal via Box–Muller
function gauss() {
var u = 0, v = 0;
while (u === 0) u = Math.random();
while (v === 0) v = Math.random();
return Math.sqrt(-2 * Math.log(u)) * Math.cos(2 * Math.PI * v);
}
var ng = 40, ns = 30, genes = [], samps = [], cond = [], matrix = [];
for (var j = 0; j < ns; j++) { samps.push("S" + (j + 1)); cond.push(j < ns / 2 ? "Tumor" : "Normal"); }
for (var i = 0; i < ng; i++) {
genes.push("Gene" + (i + 1));
var row = [];
for (var k = 0; k < ns; k++) {
var val = gauss();
if (i < 20 && cond[k] === "Tumor") val += 2; // first block up in Tumor
if (i >= 20 && cond[k] === "Normal") val += 2; // second block up in Normal
row.push(Math.round(val * 1000) / 1000);
}
matrix.push(row);
}
var data = {
y: { vars: genes, smps: samps, data: matrix },
x: { Condition: cond }
};
var config = {
graphType: "Heatmap",
samplesClustered: true, variablesClustered: true,
colorSpectrum: ["navy", "white", "firebrick3"],
showSmpDendrogram: true, showVarDendrogram: true,
title: "Clustered expression heatmap"
};
new CanvasXpress("heatmap", data, config);
</script>Live result
Rows and columns are reordered by similarity, the dendrograms show the clustering, and the samples separate cleanly by condition. Hover a cell for its gene, sample and value; the whole figure is one portable spec you can store, validate and re-render from R or Python.