Skip to content

Architecture

Bin2Cell Explorer combines a Python backend (Flask plugin) and a JavaScript frontend layered onto TissUUmaps’ OpenSeadragon viewer. This section documents the main components and the engineering decisions that shaped them.

High-level Diagram

┌─────────────────────┐
│ Bin2CellExplorer.js │  UI controls, overlays, minimap, AJAX calls
└────────┬────────────┘
         │/plugins/Bin2CellExplorer/{endpoint}
┌─────────────────────┐
│ Bin2CellExplorer.py │  Dataset loaders, cache, overlay builder, presets, exports
└────────┬────────────┘
         │Local FS + in-memory cache
┌─────────────────────┐
│ Data assets         │  he.tiff, he.npz, P2_CRC_annotated.h5ad
└─────────────────────┘

Backend (Bin2CellExplorer.py)

Dataset Loading Path

  1. Normalize paths and expand ~.
  2. Load H&E TIFF via skimage.io.imread (uses imagecodecs for LZW).
  3. Load sparse labels (scipy.sparse.load_npz).
  4. Load AnnData with anndata.read_h5ad.
  5. Cache the context (H&E, sparse labels, centroid coordinates, AnnData) and tile definitions in a module-level state.
  6. Persist dataset metadata to dataset_state.json for rehydration across sessions.

Key choices

  • Caching: heavy assets only load once. Subsequent overlay calls reuse cached data, preventing repeated 4 GB loads.
  • Lazy rehydration: _ensure_context() can rebuild B2CContext if the module is reloaded or the Flask plugin is re-instantiated.
  • Error handling: try/except around every endpoint with _error_response ensures the UI receives structured JSON (never raw HTML error pages).
  • TileCache: per-tile overlay data (expanded labels, polygons) is cached with an LRU eviction to avoid recomputing for repeated requests.

Overlay Generation

get_overlay accepts a tile ID plus gene/observation parameters and returns:

  • Expanded and raw label polygons (per cell) plus outlines.
  • Centroid bookkeeping (used server-side to aggregate expression and majority votes).
  • Legend metadata (continuous gradient or categorical swatches).

Steps:

  1. Retrieve tile info (_tile_entry) — computes or fetches cached expanded labels, polygons, outlines.
  2. Branch on overlay type:
  3. Gene: compute maximum expression per expanded cell, map to colors, optionally limit top N or quantile.
  4. Observation: majority vote over expanded cell, map categories, filter if requested.
  5. Return structured JSON for the frontend to draw.

Exporting & Presets

  • export_overlay: reuses get_overlay, converts polygons to GeoJSON.
  • save_preset/list_presets/delete_preset: CRUD operations on a JSON file stored under ~/.tissuumaps/plugins/Bin2CellExplorer/presets.json.

Frontend (Bin2CellExplorer.js)

UI Construction

Declared parameters drive the autogenerated form (via TissUUmaps plugin system). Key custom elements:

  • Tile overview canvas (minimap) with click-to-jump behavior.
  • Outline toggles (expanded vs. nuclei) that switch both fills and helper outlines.
  • Overlay legend with checkboxes to toggle categories or genes without rerendering.

Data Flow

  1. User actions trigger inputTrigger.
  2. Load dataset → load_dataset endpoint → update internal state and the tile overview.
  3. Update overlay → get_overlay endpoint → render overlay and legend.
  4. Export/preset actions follow similar request/response loops.

Rendering

  • SVG overlay: uses OpenSeadragon’s SVG overlay (overlayUtils._d3nodes) to draw polygons and helper outlines.
  • Tile overview: HTML canvas minimap (~320 px square) with gradient styling; clicking selects and centers tiles, so an extra on-slide grid is unnecessary.
  • Viewport utilities: helper functions convert pixel coordinates to viewport space (accounting for image flip).

Interaction Helpers

  • panToTile(tileId, animate) → centers the viewer on a tile by converting pixel coordinates to OpenSeadragon Rect.
  • renderTileOverview() → redraws minimap whenever tiles load or selection changes.
  • attachTileSelectListener() → keeps dropdown, minimap, and viewer selection in sync.

Performance Considerations

  • Initial load: dominated by reading TIFF + .h5ad; expect ~20–30 seconds on SSD. Loading is single-threaded (library limitation).
  • Overlay computation: per tile, typically < 1 s thanks to caching of expanded labels.
  • Memory footprint: entire H&E (≈1.2 GB in RAM), sparse labels, AnnData (4 GB), plus caches. Ensure ≥8 GB free RAM during development.
  • Tile overview: drawn in canvas to avoid heavy DOM operations; scaled rendering keeps hover/selection lightweight even for thousands of tiles.