Skip to content

v0.3.0#43

Merged
RaredonLab merged 9 commits into
mainfrom
dev
Jun 1, 2026
Merged

v0.3.0#43
RaredonLab merged 9 commits into
mainfrom
dev

Conversation

@RaredonLab

Copy link
Copy Markdown
Owner

No description provided.

msraredon and others added 9 commits May 29, 2026 11:53
Addresses issue #32 and related UX feedback: the app now only computes
and renders the final state after a user stops interacting, stale
in-flight responses are cancelled rather than overwriting current data,
and a 'Computing...' badge gives real-time feedback during any fetch.

AbortController added to all five data-fetching hooks (useEdges,
useTranscripts, useCellBoundaries, useCellColors, useEdgeColors): when a
new debounce fires the previous in-flight request is cancelled, so
intermediate pan positions or partially-dialled settings never flash onto
the canvas. Debounce for settings-driven hooks (useCellColors,
useEdgeColors metadata) bumped from 150 ms to 400 ms so rapid sequential
gene/LRM/colorBy changes collapse to a single server request.

useEdges is split into two independent effects:
- Structural effect (viewport/density deps only): POSTs to /query-grouped
  for positions, metadata, lrm_count, and score_sum. Never re-runs on
  LRM filter changes.
- Score effect (viewport + hiddenLrms deps): POSTs to new /query-scores
  endpoint for {edge, visible_lrm_count, visible_score_sum} only. Picks
  the cheaper query direction automatically — WHERE lrm IN (visible_set)
  when the visible set is small (e.g. user selects 10/559 LRMs → ~98%
  less parquet scanned), CASE WHEN NOT IN otherwise. Short-circuits
  entirely when no LRM filter is active.

New RenderingStatus component shows a spinner badge in the viewer corner
after a 400 ms onset delay whenever any layer for that panel is fetching.
Disappears immediately on completion. Works per-panel in split-screen.
Loading state tracked via loadingKeys Set in Zustand store.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
perf: debounce final-state rendering and decouple LRM score fetches
Two related bugs fixed in useCellColors and useEdgeColors:

1. Clamp/palette changes (slider drag, palette swap, reset range) were
   triggering a full 400 ms debounce + server re-fetch before the canvas
   updated, because clamp?.low, clamp?.high, and palette were deps of the
   fetch effect. Slider position and canvas were therefore out of sync
   until the fetch returned, producing the "drag then image jumps" effect.

   Fix: split each hook into a fetch effect (data params only — no clamp
   or palette deps) and a separate remap effect that applies clamp +
   palette synchronously to cached raw values. Canvas now updates in the
   same render cycle as the slider.

2. After "reset range" in lrm_set edge color mode the canvas showed a
   false bright-yellow render (most edges saturated) while the legend
   correctly showed vmax. Root cause: lrmSetResult useMemo used
   clamp?.high ?? p95 as the upper bound, but ClampableLegend used
   clamp?.high ?? vmax. When clamp.high was null after reset these
   diverged, so the rendering silently clamped at p95 while the legend
   displayed vmax.

   Fix: lrmSetResult now uses clamp?.high ?? max (matching the legend).
   The Viewer.jsx auto-calibration effect that sets clamp.high = edgeP95
   on each data load still fires normally and provides the p95-calibrated
   initial view.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Rotation (resolves #31):
- ⟲ / ⟳ toolbar buttons rotate each panel ±90°; number input accepts any
  arbitrary angle 0–359°. A green ×-reset appears when non-zero.
- OSD viewport.setRotation() keeps tile display and pan/zoom correct.
- All 14 deck.gl layers receive a modelMatrix (CW rotation around the
  current viewport pivot), recomputed on every OSD viewport-change event.
  Deck.gl applies the same matrix during its picking pass, so
  click-to-select requires no manual coordinate transforms.
- syncDeckFromOSD expands the data-fetch bbox to cover the full rotated
  rectangle's footprint (rotatedBbox helper), ensuring corner data is
  always fetched at arbitrary angles.
- viewportActual added to store (un-expanded OSD bounds) so the ⇔ Match
  zoom feature continues to use the true visible width rather than the
  padded fetch bbox — fixes the Match regression introduced by rotation.
- screenToData inverse-rotates screen→image coords so annotation
  polygons and measurements are stored in original image space.
- Measurement labels forward-rotate before screen projection.
- panelRotations [0,0] in store; per-panel, survives split ↔ single toggle.

Versioning:
- Bump to v0.3.0 in backend/app/main.py and frontend/package.json.
- vite.config.js injects __APP_VERSION__ from package.json at build time.
- App.jsx sets document.title = "TissuePlex v0.3.0" on mount.
- LayerPanel version badge now shows immediately (build-time constant)
  rather than waiting for the /health fetch; /health is still checked and
  a mismatch warning is shown if frontend/backend versions differ.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@RaredonLab RaredonLab merged commit 1627e4a into main Jun 1, 2026
3 checks 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.

2 participants