Initial Release help-frontend

Dr. Frontend

WebGL Heatmap

WebGL-rendered heatmap for large gene expression matrices with zoom, pan, and annotation bars. Based on the OrbisGL andExtendedRectplotGL classes fromperturb-seq.gl, built on top of epiviz.gl andepiviz.heatmap.gl.

Live Demo

40 perturbations x 50 response genes | Scroll to zoom, drag to pan

Log2 Fold Change

2.00.0-2.0

Gene Category

Tumor Suppressor
Oncogene
Epigenetic
Kinase

Implementation Guide

Dual-Canvas Architecture

The heatmap uses two overlapping canvases: a WebGL canvas for the cell grid (high-performance rendering of thousands of rectangles) and a 2D canvas overlay for labels, annotations, and interaction handling.

// WebGL canvas: renders heatmap cells as triangles
// Each cell = 2 triangles = 6 vertices
const verts = new Float32Array(rows * cols * 6 * 5);
// 5 floats per vertex: x, y, r, g, b

// 2D canvas overlay: renders labels and annotations
ctx.fillText(rowLabels[r], x, y);
ctx.fillRect(annoX, annoY, ANNO_WIDTH, cellHeight);

Color Scale Mapping

Values are mapped to colors using piecewise linear interpolation across a color scale array. Supports diverging (blue-red) and sequential (viridis, magma) scales.

function interpolateColor(scale, t) {
  t = clamp(t, 0, 1);
  const idx = t * (scale.length - 1);
  const lo = Math.floor(idx);
  const hi = Math.min(lo + 1, scale.length - 1);
  const f = idx - lo;
  return [
    lerp(scale[lo][0], scale[hi][0], f),
    lerp(scale[lo][1], scale[hi][1], f),
    lerp(scale[lo][2], scale[hi][2], f),
  ];
}

Viewport-Based Zoom

Zoom state is tracked as a viewport rectangle [x0, y0, x1, y1] in normalized data coordinates. The vertex shader maps this viewport to clip space, and the label renderer filters visible labels based on the same viewport.

Architecture

┌──────────────────────────────────────────────┐
│              React Component                 │
│                                              │
│  ┌──────────────────────────────────────────┐│
│  │  WebGL Canvas (bottom layer)             ││
│  │  ├─ Triangle pairs per cell              ││
│  │  ├─ Color from value → scale mapping     ││
│  │  └─ Viewport uniforms for zoom/pan       ││
│  ├──────────────────────────────────────────┤│
│  │  2D Canvas (top layer)                   ││
│  │  ├─ Row labels (gene names)              ││
│  │  ├─ Column labels (rotated)              ││
│  │  ├─ Row annotation color bars            ││
│  │  └─ Mouse event handling                 ││
│  └──────────────────────────────────────────┘│
│                                              │
│  Data: Float32Array (rows × cols)            │
│  View: { x0, y0, x1, y1 } normalized rect   │
└──────────────────────────────────────────────┘

Production Architecture (perturb-seq.gl)

The production version uses web workers for off-main-thread rendering viaepiviz.gl, Zarr-based lazy data loading for matrices too large to fit in memory, and synchronized viewport state across multiple linked heatmap instances.

Source Reference

  • perturb-seq.gl/src/OrbisGL.ts - Main WebGL wrapper
  • perturb-seq.gl/src/ExtendedRectplotGL.js - Heatmap spec generation
  • perturbseqapp/src/components/Heatmap/Heatmap.js - React integration
  • perturbseqapp/src/components/Heatmap/HeatmapCanvas.js - SVG overlay

Use Cases

Perturbation Screens

Visualize gene knockout/knockdown effects across thousands of measured response genes. Identify pathway-level patterns in perturbation data.

Correlation Matrices

Display gene-gene or sample-sample correlation matrices with hierarchical clustering and annotation tracks.

Differential Expression

Show log-fold-change values across conditions with diverging color scales to highlight up- and down-regulated genes.