Skip to content

feat: in-browser dimensional reduction with KNN backend param controls#38

Merged
patcon merged 20 commits into
mainfrom
feat/in-browser-dimensional-reduction
May 21, 2026
Merged

feat: in-browser dimensional reduction with KNN backend param controls#38
patcon merged 20 commits into
mainfrom
feat/in-browser-dimensional-reduction

Conversation

@patcon

@patcon patcon commented May 21, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds in-browser dimensional reduction via DruidJS — after importing an .h5ad file, a Recompute button opens a dialog to pick a vote matrix layer, choose UMAP/PaCMAP/LocalMAP and its parameters, and run the reduction in a web worker; result is added as a selectable projection
  • Extracts dimensional reduction logic (runReducer, types, param defs) into reddwarf-ts; also extracts zeroMaskedColumns, imputeColumnMeans, and refactors the stats/DB split and AnalysisOptions unification
  • Unifies KNN backend params under KNN_PARAM_DEFS/defaultKnnParamsFor() mirroring the reducer pattern — Annoy now exposes numTrees/maxPointsPerLeaf/seed; HNSW exposes ef/ef_construction/m/seed; HNSW defaults match the voyager (Spotify) library used by pacmap-python

Test plan

  • Import an .h5ad file and open the Recompute dialog
  • Run each algorithm (UMAP, PaCMAP, LocalMAP) and confirm projection is added and auto-selected
  • Switch KNN backend between Annoy and HNSW and confirm the correct params appear for each
  • Adjust KNN params and confirm values are forwarded (check worker message in devtools)
  • Confirm progress bar and "Building KNN graph…" phase indicator display correctly

🤖 Generated with Claude Code (code and ~150 words of PR description from ~60 words of human prompts across this session)

patcon and others added 20 commits May 19, 2026 16:56
Lets users re-run dimensional reduction on an imported .h5ad without an
upstream pipeline. A "Recompute" button in the projection selector opens
a dialog to pick a dense layers/ matrix as the vote matrix, choose an
algorithm (UMAP/PaCMAP/LocalMAP) and parameters, and run the reduction
in a web worker. The result is added as a new selectable projection and
auto-selected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use DruidJS generator API to step through iterations and post progress
messages from the worker. The dialog shows a 0-100% progress bar while
computing instead of just a spinner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
While status is running but no progress tick has arrived yet, the
dialog shows "Building KNN graph…" with a pulse animation. Once the
first progress message lands the bar replaces it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Column means of observed values replace any NaN entries so DruidJS
never sees missing data. Falls back to 0 for all-NaN columns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes range sliders in favour of number inputs laid out in a 2-column
grid. Both Select dropdowns get w-full so their width stays stable across
selected options.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "Column mask" select left of the Algorithm select that zeros
out var columns whose value is truthy before running reduction. The
only current option is "moderated". App.tsx applies the mask using
the varNames array (original h5ad var order) to map column indices to
statement metadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All layers share the same shape, so display rows×cols once next to
the label rather than repeating it inside every dropdown item.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Progress bar and KNN phase text now appear to the left of the Cancel/Run
buttons in the footer row, freeing up space in the main content area.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…backend controls

Adds a collapsible Advanced section exposing all remaining DruidJS
parameters (seed, epochs, learning rate, UMAP internals) and a KNN
backend select (Annoy / HNSW) for PaCMAP and LocalMAP. All params are
merged into a single Record before being sent to the worker.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updates DruidJS to the latest add-pacmap-support branch commit (which
added knn_params passthrough to PaCMAP and LocalMAP). Wires knn_params
through ReducerRequest → useDruidWorker → worker, and adds ef/
ef_construction inputs to the Advanced section of the recompute dialog,
shown only when the HNSW backend is selected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts types, config, and a pure `runReducer()` generator from the
app into the reddwarf-ts library package, enabling the polis pipeline
to run in JavaScript outside the browser (e.g. Node.js scripts).

The app worker and React hook become thin shells; no consuming files
needed import changes. `@saehrimnir/druidjs` added as a reddwarf-ts
runtime dependency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pure statistical functions stay in stats.ts; DB types (VoteConnection,
  VoteQueryResult) and getGroupVoteMatrices move to new db.ts
- Collapse analyzeLabeledGroups + calculateRepresentativeStatements into
  one function in representative-statements.ts; stats.ts is now DB-free
- Unified AnalysisOptions covers all options incl. commentTextMap;
  removes two divergent options shapes across the package
- App adapter updated: commentTextMap folds into options object

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The class was never instantiated — App.tsx owns isCalculatingRepStatements
state directly via useState. Removes both the package class and the app
adapter's wrapper, flattening the delegation chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ld listing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add KNN_PARAM_DEFS and defaultKnnParamsFor() mirroring the reducer
param pattern. Annoy now exposes numTrees/maxPointsPerLeaf/seed; HNSW
gains m and seed alongside its existing ef/ef_construction. The dialog
shows whichever backend's params are active and always forwards them
as knn_params. HNSW_PARAM_DEFS/defaultHnswParams() kept as deprecated
aliases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@patcon patcon merged commit 8adbda4 into main May 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant