Skip to content

Roadmap & status

A snapshot of where the toolbox is. Legend: ✅ done · 🚧 in progress · 📋 planned.

These are implemented as composable GPU kernels, each with a CPU golden test.

AreaPrimitiveStatus
Transforms5/3 & 9/7 DWT (forward + inverse, CPU + GPU)✅
SpatialNN distance, empty-space (F), ANNI✅
SpatialKDE density splat, separable convolution, Getis-Ord, fuzzy adjacency✅
Spatialk-th neighbour distance, CkNN rescaled distance✅
FieldsGaussian KDE, distance-to-nearest, distance-to-measure (DTM)✅
TopologyVietoris–Rips persistence (H₀/H₁), cubical sublevel-set persistence (H₀/H₁)✅
FeatureStatusNotes
CkNN connectivity & persistence demos✅CkNN page
Filtration sweep (Vietoris–Rips, 2D / cones)✅Filtrations page
Fuzzy filtration (hard vs KDE/DTM, side-by-side diagrams)✅Filtrations page
Tunable parameters (resolution, falloff σ/k, noise band)✅
WebGPU field backend with CPU fallback✅on by default where supported
Hover a component → highlight it + its points + its diagram dot✅the fuzzy demo; linked by identity (the reducer’s birthCell)
Hover an enclosed hole → highlight the loop + its H₁ diagram dot✅linked via the reducer’s deathCell (the cell that fills the hole)
Reverse link: hover a diagram point → highlight its region📋
Linked brushing across the hard ↔ fuzzy panels📋
Rendering directly from the GPU primitives (not three.js approximations)📋the VR sweep is still an illustrative approximation

The demos are a means to an end: making spatial/topological structure queryable and composable. These are the ergonomic surfaces we want.

CapabilityStatusNotes
Query the points inside a feature🚧the hover demo previews it (it rings the contained points + counts them); the library API to return them is next
Feed a feature’s points/region along dataflow edges to the next operation📋depends on the resource-sync model — a feature becomes a node output other ops consume
Persistence-based feature selection (keep features above a threshold, mask the rest)📋the noise-band control is the manual version
Tissue/cell applications (MuSpAn-style): robust loops/components on real point clouds📋the fuzzy-TDA motivation

The operation-graph runtime (src/gpu/graph/) chains primitives into a dependency-ordered graph of GPU operations — demand-pulled, with per-node memoisation and feedback/simulation loops. That runtime is built and tested; see Operation graphs. What remains is Tier-2: keeping buffers resident across interior edges so a chain shares pooled resources without round-tripping to the CPU between stages — today’s Tier-1 nodes round-trip on interior edges (correct, and kept as the bit-exact golden reference). The sequencing rules are the five invariants in the docs/gpu-resource-sync.md design note (every sync bug we have hit is one mutable resource read by a consumer not ordered after its writer). Status: ✅ runtime + Tier-1 ops + feedback/sim · 📋 Tier-2 resident buffers.

A separate, prototype track: a view-driven multiscale datasource and a WebGPU volume renderer (per-chunk LOD via a brick atlas + page table, ADR-0008). The technique — and, importantly, how it scales, where the ceilings are, and the planned fixes — is written up on the brick-atlas page table page. Status: 🚧 (prototype; scope and how it fits the rest of the toolbox is still being shaped).

What costs what, so you can size a problem. Numbers below are single-thread CPU (JS, this machine) and indicative — the shape matters more than the digits.

A demo “rebuild” is: generate the field(s) once, then reduce persistence once (the sweep slider afterwards is just redraw — cheap). Two independent axes:

Persistence reduction (the cubical boundary-matrix reduction) is the dominant cost and scales with resolution², independent of point count — it runs on the grid, not the points:

Gridcellspersistence (one field)
48²2.3k~7–15 ms
64²4.1k~15–23 ms
96²9.2k~45–60 ms
128²16k~100–110 ms

Field generation scales with points × cells, and is where the GPU earns its keep. KDE (truncated Gaussian) is cheap; DTM (k-nearest gather) is the heaviest:

Field30 pts @ 64²1000 pts @ 64²1000 pts @ 128²
KDE~0.2 ms~6 ms~25 ms
distance~0.2 ms~5 ms~17 ms
DTM~0.7 ms~27 ms~96 ms

Takeaways:

  • Resolution is the lever, via the persistence reducer (~quadratic in grid side). The demo defaults to 64² for interactivity; 128² is a ~100 ms one-time rebuild.
  • Point count mostly hits field generation, which the WebGPU path offloads (the brute-force gather is embarrassingly parallel) — most so for DTM. The persistence reduction stays on the CPU (it is inherently sequential).
  • The clear next optimisation is the reducer itself: the general boundary-matrix reduction is overkill for a 2D image, where H₀ and H₁ persistence can be computed with union-find in near-linear time (a planned swap) — that would make high resolution cheap and shift the bottleneck back to field generation, which is already on the GPU.
  • The Vietoris–Rips sweep is an illustrative three.js approximation; counts come from the real reducer but the drawing can drift (documented on that page).
  • Persistence here targets the small-to-medium regime (tens to low-hundreds of points / ≤128² grids). Larger problems want a real Ripser/GUDHI binding or the union-find reducer above.
  • WebGPU coverage varies by browser; the field path validates its output and falls back to the CPU so correctness never depends on the backend.