Skip to content

feat(image-map): select whole clusters and dim the rest of the map - #325

Open
lstein wants to merge 3 commits into
mainfrom
perf/image-map-cluster-selection
Open

lstein wants to merge 3 commits into
mainfrom
perf/image-map-cluster-selection

Conversation

@lstein

@lstein lstein commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Stacked on #301 (perf/image-map-zoom); merge that first.

On a large gallery, clicking a big cluster with "click selects cluster" on used to select only part of it. MAX_CLUSTER_SELECTION = 5000 silently kept the 5,000 members nearest the click. A user with a 170,000-image gallery saw most of each large cluster left unselected.

  • Whole clusters: the cap is removed. The gallery lists every member and the map lights every member.
  • Dimmed map instead of an outline: while a cluster is selected, every other point is desaturated toward grey and faded, and the selected cluster is redrawn on top at full colour. The white outline stays for hand-picked multi-selections in the gallery.
  • Selection chip: a chip in the map's top-left corner names the selection (● beaches · 336 items ✕). Its ✕ clears the selection, and so does Esc while the map has focus; the clear is also a palette command. Clearing drops the gallery's cluster listing, the same state the gallery's own chip clears, and restores the map's colours. Esc does nothing unless a cluster is selected, so it never wipes an ordinary search.
  • Overlay column: the chip and the existing "Indexing…" badge share one top-left column, offset by --wb-center-chrome-inset. When the map is in the center panel, the floating view selector previously covered both.

Why dimming is affordable

After #301, the base points are one trace per appearance, and every marker property is a scalar. The old highlight overlay carried per-point color and symbol arrays, which is the slow path #301 removed from the base points.

  • Selected cluster: it is redrawn as two traces, one for images and one for videos, each with a single colour. That colour belongs to the cluster most members are in now, so it stays correct after a refresh renumbers clusters.
  • Dimming: each base trace is restyled with one scalar colour and one scalar opacity. The originals are kept, so undimming restores them exactly.

QA Instructions

  1. Turn on "click selects cluster" and click a large cluster. The whole cluster stays lit, the rest greys out, and the chip shows the label and the full member count.
  2. Press Esc with the map focused, or click the chip's ✕. Colours return, the gallery drops the cluster listing, and after ✕, focus stays on the map.
  3. With an ordinary text search in the gallery, press Esc on the map. The search is untouched.
  4. Move the map to the center panel. The chip sits below the "Image Map ▾" selector.

Measurements: 170,000 synthetic points in real Chromium on a Radeon W7900 (ANGLE/EGL), with a GPU sync on every step.

Selected Zoom ms/frame: this PR Zoom ms/frame: old outline on #301 Select / clear ms
none 13–26 13–26
20,000 14 26 55 / 26
50,000 15 47 63 / 28
100,000 31 106 100 / 52

Under SwiftShader (software GL), dimming zoomed faster than either outline variant at 100k: 128 ms, against 162 ms for a single-colour outline and 251 ms for the old outline.

Checks:

  • pnpm check:release passes:
    • lint;
    • 8,292 unit tests;
    • 1,549 browser tests;
    • fixtures;
    • architecture build and browser performance budgets;
    • project-file journeys;
    • accessibility.
  • Verified in Chromium against the mock backend:
    • select, then Esc, then reselect, then ✕;
    • the chip clears the center selector;
    • keyboard focus returns to the map after ✕.

Limitations:

  • The maps in the performance numbers are synthetic blobs, not real UMAP output.
  • The WebGL dim lifecycle has no automated test; unit tests cover the trace builders and restyle payloads.

Review

Findings resolved:

  • Esc and palette registrations went stale after a project switch. The widget runtime is rebuilt per project without remounting the view, so registration now follows the runtime.
  • Focus was lost when the chip's ✕ unmounted.
  • An unlabeled cluster could read "2 items · 1 item" after deletions.
  • Size formatting depended on the browser locale.
  • Long labels had no way to be read in full.

Remaining limitations:

  • The chip's count stays stale after a deletion until the next map refresh.
  • The chip and hotkey text are English-only, like the rest of the map widget.
  • Each socket refresh during a selection restyles the overlay twice.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Meaningful regression coverage added / updated where needed; obsolete tests/code removed
  • Persisted-state and API changes include required migrations / compatibility validation
  • Relevant performance/efficiency opportunities considered; material claims have evidence
  • Material review findings resolved and relevant checks rerun
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

Removes the 5,000-member cap on cluster selection; the selected cluster is redrawn at full colour over a desaturated, faded map using scalar per-trace styles.
A top-left chip names the selection and clears it (also Esc); overlays clear the center area's floating view selector.
…mage-map-cluster-selection

# Conflicts:
#	invokeai/frontend/webv2/src/workbench/image-map/imageMapTraces.ts
#	invokeai/frontend/webv2/src/workbench/widgets/image-map/ImageIndexProgress.tsx
#	invokeai/frontend/webv2/src/workbench/widgets/image-map/ImageMapPlot.tsx
#	invokeai/frontend/webv2/src/workbench/widgets/image-map/ImageMapWidgetView.tsx
Base automatically changed from perf/image-map-zoom to main September 23, 2026 20:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant