@jax-data-science/sci-image-visualizer 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +361 -4184
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34430
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -878
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -1,30 +1,28 @@
1
1
  import { Observable, BehaviorSubject } from 'rxjs';
2
2
  import { Image } from 'image-js';
3
3
  import { IImageInfo } from '../../contracts/image.contract';
4
- import { SpatialDataPort } from '../../contracts/ports/spatial-data.port';
5
- import { SpatialObservations } from '../../contracts/spatial-dataset.contract';
6
- import { TranscriptEstimate } from './napari-spatial-tiles';
7
- import { SpatialSelectionStore } from '../../store/spatial-selection.service';
8
- import { PlotType, PlotTypeDescriptor } from '../../contracts/plot-type';
9
- import { IVisualizer, PixelData, IntensityProfile, IIsosurfaceControls, IIntensityControls, ISurface3dControls } from '../../contracts/visualizer.contract';
10
- import { ViewerCapabilities } from '../../contracts/capabilities.contract';
11
- import { IRegionOverlay } from '../../contracts/region-overlay.contract';
12
4
  import { IHistogram } from '../../contracts/channel-histogram-api.contract';
13
- import { IWandOptions, IBrushOptions } from '../../contracts/display-types';
14
- import { VizConfig } from '../../contracts/viz-config';
5
+ import { CanvasToolId } from '../../contracts/display-types';
6
+ import { IRegionOverlay } from '../../contracts/region-overlay.contract';
7
+ import { SpatialObservations } from '../../contracts/spatial-dataset.contract';
8
+ import { SpatialDataPort } from '../../contracts/ports/spatial-data.port';
15
9
  import { TileAccessPort } from '../../contracts/ports/tile-access.port';
16
- import { BaseStoreVisualizer } from '../base-store-visualizer';
17
- import { SimpleSliceAccessService } from '../simple-slice-access.service';
10
+ import { VizConfig } from '../../contracts/viz-config';
11
+ import { ICellSegmenter } from '../../contracts/cell-segmenter.contract';
12
+ import { ViewerCapabilities } from '../../contracts/capabilities.contract';
13
+ import { PlotType, PlotTypeDescriptor } from '../../contracts/plot-type';
14
+ import { IViewerBackend, PixelData, IIsosurfaceControls, IIntensityControls, ISurface3dControls, IOsdViewOptions, IVolumeResolution, IIntensityViewportSource } from '../../contracts/visualizer.contract';
18
15
  import { VisualizerStore } from '../../store/visualizer-store.service';
19
16
  import { RegionStore } from '../../store/region-store.service';
20
- import { WandToolService } from '../../toolbar/wand/wand-tool.service';
21
- import { BrushToolService } from '../../toolbar/brush/brush-tool.service';
22
- import { VertexEraserToolService } from '../../toolbar/vertex-eraser/vertex-eraser-tool.service';
23
- import { ZoomToBoxToolService } from '../../toolbar/zoom-to-box/zoom-to-box-tool.service';
17
+ import { SpatialSelectionStore } from '../../store/spatial-selection.service';
18
+ import { CanvasToolManager } from '../../toolbar/tool-kit/canvas-tool-manager';
19
+ import { WandService } from '../../toolbar/wand/wand.service';
24
20
  import { SamToolService } from '../../toolbar/segmentation/sam-tool.service';
25
21
  import { SamPointToolService } from '../../toolbar/segmentation/sam-point-tool.service';
26
22
  import { CellSegmentToolService } from '../../toolbar/segmentation/cell-segment-tool.service';
27
- import { ICellSegmenter } from '../../contracts/cell-segmenter.contract';
23
+ import { BaseStoreVisualizer } from '../base-store-visualizer';
24
+ import { SimpleSliceAccessService } from '../simple-slice-access.service';
25
+ import { TranscriptEstimate } from './napari-spatial-tiles';
28
26
  import * as i0 from "@angular/core";
29
27
  /** Opaque handle from {@link NapariVisualizerService.load}, passed back to plot(). */
30
28
  interface NapariLoaded {
@@ -34,138 +32,42 @@ interface NapariLoaded {
34
32
  * handle's `filename` doesn't match the requested image (guards against stale clicks). */
35
33
  filename: string;
36
34
  }
37
- export declare class NapariVisualizerService extends BaseStoreVisualizer implements IVisualizer {
38
- private readonly tiles;
39
- private readonly wandTool;
40
- private readonly brushTool;
41
- private readonly eraserTool;
42
- private readonly zoomToBoxTool;
35
+ /**
36
+ * The WebGPU image backend, built on the published `napari-js` library (jit-ui#102: a
37
+ * browser-based napari shipped as a JS library, alongside OpenSeadragon for images and Plotly
38
+ * for 3D).
39
+ *
40
+ * One scene is mounted per {@link plot}, chosen by plot type:
41
+ * - **2D image** (and the region-centroid scatter and spatial-omics views over it): pyramidal
42
+ * `TiledSource`s against the jit-service `/tile` endpoint when `/tiles/info` describes the
43
+ * image, else a single stitched level (`tiled:false` stacks fetch each slice's own URL);
44
+ * multichannel additive tints, grayscale colormap or RGB; scale bar, navigator, region
45
+ * overlay and the shared pixel tools (wand, brush, eraser, zoom-to-box, SAM/cellpose).
46
+ * - **Volume / isosurface / 3D scatter / surface**: slices assembled into a decimated volume
47
+ * (or one height field per slice), with the axes gizmo and the Z-height handle.
48
+ * - **Spatial omics 2D / 3D**: observation markers or a 3D cloud, gene maps, density volumes,
49
+ * level-of-detail tiles, hover tooltip and click-to-select.
50
+ *
51
+ * Per-channel histograms come from the client data, or from the server's `/histogram` for
52
+ * >8-bit images; TIFF export from `/export/tiff`. Region state and display options delegate to
53
+ * the shared {@link RegionStore} / {@link VisualizerStore} through {@link BaseStoreVisualizer},
54
+ * exactly as OSD does. napari-js's render loop and the hot pointer paths run outside the
55
+ * Angular zone.
56
+ */
57
+ export declare class NapariVisualizerService extends BaseStoreVisualizer implements IViewerBackend {
43
58
  private readonly samTool;
44
59
  private readonly samPointTool;
45
- private readonly cellSegmentTool;
46
- private readonly cellSegmenter;
47
60
  private readonly simpleStack;
48
- private readonly spatialData;
49
- private readonly selectionStore;
50
61
  readonly capabilities: ViewerCapabilities;
51
- private readonly api;
62
+ /** The jit-service tile server: descriptor, slices, tiled sources, histograms, export. */
63
+ private readonly tileClient;
64
+ /** napari-js's render loop and the hot pointer/timer paths run outside the Angular zone
65
+ * (NAPARI-SVC-25); what they produce for the UI re-enters it through {@link inZone}. */
66
+ private readonly zone;
52
67
  private viewer;
53
68
  private canvas;
54
69
  private host;
55
70
  private loaded;
56
- private lastPixels;
57
- private currentPlotType;
58
- /** napari-js high-level view owning the 3D volume layers (one additive tinted layer per channel
59
- * for multichannel, or a single grayscale volume). Null in 2D. */
60
- private volumeView;
61
- /** True when the volume is composited from per-channel layers (vs a single grayscale volume). */
62
- private volumeMultichannel;
63
- /** napari-js height-field surface mesh (NAPARI_SURFACE plot type; null otherwise). Built from a
64
- * single grayscale slice by {@link buildSurface} via napari-js's `heightField` + `addSurface`. */
65
- private surfaceLayer;
66
- /** Which band the surface samples (a channel index for multichannel, else the composite). */
67
- private surfaceChannel;
68
- /** True when the mounted Surface follows one band of a multichannel image. */
69
- private surfaceMultichannel;
70
- /** Pre-loaded per-slice luminance planes (already decimated to the surface grid), keyed by z,
71
- * so the stack slider rebuilds the surface instantly. Filled by {@link preloadSurfacePlanes}. */
72
- private readonly surfacePlanes;
73
- /** In-plane grid cap for the active surface load (full grid ÷ the decimate factor). */
74
- private surfaceMaxGrid;
75
- /** Contrast window [min,max] the current surface mesh was built with. A change reshapes the
76
- * mesh (pixel height = intensity within [min,max]), so it triggers a geometry rebuild. */
77
- private surfaceWindow;
78
- /** Persisted wireframe choice for the surface (re-applied when a new surface mounts). */
79
- private surfaceWireframe;
80
- /** napari-js 2D scatter points (region centroids) + its region-change subscription. */
81
- private scatter2dPoints;
82
- private scatterRegionSub;
83
- /** napari-js 3D scatter (voxel point cloud). */
84
- private scatter3dLayer;
85
- /** Spatial-omics observation markers + the dataset/view subscription driving them. */
86
- private spatialPoints;
87
- /** The 3D point cloud. One layer: selection is a per-point alpha on it, not a second. */
88
- private spatialPoints3d;
89
- private spatialLayerKey3d;
90
- /** Interleaved x,y,z, cached so a colour change does not re-walk 3.7M observations. */
91
- private spatialPositions3d;
92
- /** Identity of the scalars currently uploaded — see {@link rebuildSpatialPoints3d}. */
93
- private spatialScalarKey3d;
94
- /** The anatomical volume the cloud sits inside, when the dataset has one. */
95
- private spatialVolume;
96
- private spatialVolumeKey;
97
- /** Per-cluster density volumes drawn alongside the cloud, and what they were
98
- * built from — rasterising is seconds of work, so it must not repeat for a
99
- * change that cannot affect the field. */
100
- private densityLayers;
101
- private densityKey;
102
- /** Selection identity, as a number the density key can carry. */
103
- private lastSelectionSeen;
104
- private selectionRevision;
105
- /** The gene map: its layer, the field it was estimated from, and the inputs each
106
- * was built for — the field is the expensive half and survives a recolour. */
107
- private geneMapLayer;
108
- private geneMapKey;
109
- private geneMapField;
110
- private geneMapFieldKey;
111
- /** The 3D gene map: its volume layer, the field behind it, and the inputs each
112
- * was built for — same two clocks as the 2D map. */
113
- private geneMapVolumeLayer;
114
- private geneMapVolumeKey;
115
- private geneMapVolumeField;
116
- private geneMapVolumeFieldKey;
117
- /** Offset applied to observation coordinates to sit them in the volume's box. */
118
- private spatialOrigin3d;
119
- /** Cursor tooltip for the spatial views, and everything it needs: what the
120
- * cloud is coloured by, and where each drawn observation is. */
121
- private spatialTooltip;
122
- private hoverSource;
123
- private hoverSourceKey;
124
- /** Sequences the async resolutions. The KEY is only committed once one lands,
125
- * so a superseded fetch cannot leave the cache claiming to hold a source it
126
- * never stored. */
127
- private hoverSourceToken;
128
- /** Drawn observations' positions for hit-testing, indexed BY OBSERVATION with
129
- * NaN for anything not drawn. Screen pixels in 3D (the camera moves them, so
130
- * they are rebuilt when it does) and WORLD units in 2D (where the camera only
131
- * scales, so the pointer is converted instead of 374k points). */
132
- private hoverPositions;
133
- private hoverPositionsRev;
134
- /**
135
- * Screen-space bucket index over the 3D projection, built on the first hover after the
136
- * scene moved rather than when it moves.
137
- *
138
- * Lazily, and that is the whole design: an orbit drag changes the camera every frame, so
139
- * building eagerly would spend tens of milliseconds a frame indexing for picks nobody is
140
- * making. Deferred, it is built once when the drag stops and the pointer next moves —
141
- * measured upstream at 3.7M points, that turns a 12.6 ms scan per pointermove into
142
- * 0.066 ms.
143
- */
144
- private hoverIndex;
145
- /** Bumped whenever the cached positions go stale: a marker rebuild, or — in 3D
146
- * only, where the projection depends on it — a camera move. */
147
- private spatialSceneRev;
148
- private hoverPointer;
149
- private hoverFrame;
150
- private hoverOff;
151
- /** Observation indices the cached 3D positions belong to, in the same order;
152
- * null when every observation is drawn. Without it a projection built from the
153
- * positions is indexed by DRAWN order and silently attributes each point to
154
- * the wrong observation as soon as a section is isolated. */
155
- private spatialDrawn3d;
156
- /** Reused projection buffers — see {@link getSpatialScreenProjection}. */
157
- private spatialProjection3d;
158
- /** Per-observation depth from the last projection, for the depth-aware hover pick. */
159
- private spatialDepths3d;
160
- /** The (viewer, dataset) whose 3D scene has already had its opening framing. */
161
- /** Whose 2D observations the camera has been framed on — see {@link frameSpatialPointsOnce}. */
162
- private spatial2dFramed;
163
- /** Dataset the 3D scale bar was built for. */
164
- private spatialScaleBarKey;
165
- private spatialSub;
166
- /** Level-of-detail cell outlines, transcripts and density over the 2D view — created on
167
- * first use, and only when a spatial port is bound. */
168
- private spatialTilesMgr;
169
71
  /** For the panel: the transcripts-in-view estimate and the density window in use. */
170
72
  readonly transcriptEstimate$: BehaviorSubject<TranscriptEstimate | null>;
171
73
  /** Transcripts of each selected gene in view (see NapariSpatialTileLayers.geneCountsIn). */
@@ -175,708 +77,70 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
175
77
  hi: number;
176
78
  max: number;
177
79
  } | null>;
178
- /** Latest (dataset, view, selection) the spatial subscription saw, so a slice
179
- * change can rebuild the markers for the new plane. */
180
- private spatialLatest;
181
- /** Which dataset the current marker layer was built for, so a display-only
182
- * change (size, colour, opacity, selection) can update it in place. */
183
- private spatialLayerKey;
184
- /** Monotonic guard for the async colour rebuild: fetching a gene vector is a
185
- * round-trip, so a fast sequence of colour-by changes can resolve out of
186
- * order. Only the newest rebuild is allowed to touch the layer. */
187
- private spatialRebuildToken;
188
80
  /** "x reloading…" at the bottom of the canvas: the tile layers' loads and the observations'. */
189
- private loadingBadge;
190
- private tileLoading;
191
- private observationsLoading;
192
- /** Monotonic load generation. Bumped by {@link reset} and {@link cancelLoading}; the frame-loading
193
- * loops (volume assembly, surface preload) capture it and bail when it changes, so a Cancel (or a
194
- * new plot) actually stops fetching frames instead of running to completion in the background. */
195
- private loadToken;
196
- /** Decimate factor for the napari 3D types (1 = Full, 2 = ½ default, 4 = ¼, 8 = ⅛). Applied when a
197
- * volume/isosurface/surface (re)loads; changing it needs a re-plot (it changes fetched data). */
198
- private resolutionScale;
199
- /** 3D coordinate-axes / scale gizmo for the volume/isosurface view (null in 2D). */
200
- private axesLayer;
201
- /** DOM X/Y/Z + scale labels tracking the 3D axes gizmo (null in 2D). */
202
- private axesLabels;
203
- /** Draggable Z-height grip over the volume (null unless a volume/isosurface is mounted). */
204
- private zHandle;
205
- /** User Z-height factor for the volume (1 = the volume's natural proportions); driven by the
206
- * in-view drag handle. Reset per mount. */
207
- private volumeZScale;
208
- /** Volume world box at `volumeZScale = 1` (base) + the sampled voxel depth — enough to recompute
209
- * the Z-axis voxel scale, axes depth, and overlay anchors as the handle stretches Z. */
210
- private volumeWorldBase;
211
- private volumeSampledDepth;
212
- /** Persisted axes on/off choice, re-applied when a new volume mounts. Defaults on. */
213
- private axesVisible;
214
- private volumeDims;
215
- /** Assembled uint8 volume data per channel (key = channel index), kept for the volume intensity
216
- * histogram. Key 0 holds the grayscale/composite volume in the single-channel case. */
217
- private readonly volumeChannelData;
81
+ private readonly badge;
82
+ /** The store's display state (colormap, reverse, invert) and the colormaps derived from it. */
83
+ private readonly display;
84
+ /**
85
+ * The mounted scene's lifetime: aborted by {@link reset}, so everything a plot starts — its
86
+ * descriptor poll, its tile fetches, its badge counts, its awaits — can tell that a newer plot
87
+ * has replaced it. A tile that settles after a reset belongs to the aborted scene and leaves the
88
+ * new scene's count alone.
89
+ */
90
+ private lifetime;
91
+ /** What {@link plot} mounted, while it is mounted. */
92
+ private scene;
93
+ /** Spatial state that outlives a scene (latest data, windows, estimated gene-map fields). */
94
+ private readonly spatial;
95
+ /** Viewer settings that outlive a scene. */
96
+ private readonly settings;
97
+ /**
98
+ * Frame loading (volume assembly, surface preload): aborted by {@link reset} AND by
99
+ * {@link cancelLoading}, so a Cancel actually stops fetching frames instead of running to
100
+ * completion in the background, while the scene itself stays mounted. (Latest-wins WITHIN a
101
+ * scene — a scrub, a colour rebuild, a hover-source fetch — is each scene's own business.)
102
+ */
103
+ private loading;
104
+ /** The image's full-resolution size as the last scene drew it (it outlives the scene). */
218
105
  private imageW;
219
106
  private imageH;
220
- /** Monotonic slice-request id so a slow out-of-order slice fetch can't clobber a newer one. */
221
- private sliceReq;
222
- /** Cached `/tiles/info` pyramid descriptor + the infoB64 it was fetched for. */
223
- private descriptor;
224
- private descriptorKey;
225
- /** How the current 2D image is composited (drives histogram + state application). */
226
- private imageMode;
227
- /** napari-js high-level view that owns the per-channel layer set (build + live display
228
- * updates) for the current {@link imageMode}. Rebuilt on each (re)render. */
229
- private channelView;
230
- /** Live subscription applying channel-state / colormap changes to the layers. */
231
- private displaySub;
232
- /** Latest grayscale colormap selection from the store (applied to the single gray layer). */
233
- private currentColormap;
234
- private currentReverse;
235
- /** Latest invert toggle from the store (flips intensity before the colormap, like OSD). */
236
- private invertEnabled;
237
- /** Physical scale bar overlay for the 2D image (null when 3D or the image has no µm/pixel). */
238
- private scaleBar;
239
- /** Overview minimap (bottom-right), as OSD's navigator. */
240
- private navigator;
241
- /** Whether the navigator is shown — the same host setting OSD's navigator honours. */
242
- private navigatorVisible;
243
- /** Bumped per thumbnail request, so a slow one cannot overwrite a newer slice's. */
244
- private navigatorToken;
245
- /** SVG region-drawing overlay for the 2D image (null until a 2D image is plotted). */
246
- private regionOverlay;
247
- /** Pixel-tool plumbing: the plot div id, coord transform, and bound tool hosts. */
248
- private plotDivId;
249
- private coordTransform;
250
- private wandHost;
251
- private eraserHost;
252
- /** Cached CachedImageData built from the last readback (rebuilt when lastPixels changes). */
253
- private cachedImage;
254
- private cachedImageSource;
255
- /** Visible world rect captured AT the last readback — must pair with `lastPixels` so the pixel
256
- * tools' ratios/origin match the matrix's camera (using the live rect after a pan/zoom would
257
- * mis-scale the region). */
258
- private lastPixelsRect;
259
- /** Image smoothing (bilinear) vs nearest-neighbour (crisp pixels, the default). */
260
- private imageSmoothing;
261
- /** True when the 2D image is rendered via pyramidal TiledSources (descriptor available). */
262
- private tiled;
263
- /** Debounced readback timer + camera-change unsubscribe (keep lastPixels current for tools). */
264
- private readbackTimer;
265
- private cameraReadbackOff;
266
- /** Coarse per-channel luminance sample (keyed by channel index) for the histogram in tiled mode,
267
- * where the layers have no full in-memory pixels. Refreshed on plot + slice change. */
268
- private readonly histSamples;
269
- /** Native-bit-depth histograms from `/histogram`, keyed `${z}|${channel}` (>8-bit images). */
270
- private readonly nativeHistograms;
107
+ /** The region overlay, the pixel tools and the displayed-pixel readback they read. */
108
+ private readonly tools;
109
+ /** This backend's own wand, brush, eraser, zoom-to-box and SAM point tools. */
110
+ protected readonly canvasTools: CanvasToolManager;
271
111
  private readonly stackLoading$;
272
112
  private readonly stackLoadingProgress$;
273
113
  private readonly autoscaleEvent$;
274
- private readonly intensityProfile$;
275
114
  private readonly viewportChange$;
276
- constructor(tiles: TileAccessPort, store: VisualizerStore, regionStore: RegionStore, wandTool: WandToolService, brushTool: BrushToolService, eraserTool: VertexEraserToolService, zoomToBoxTool: ZoomToBoxToolService, samTool: SamToolService, samPointTool: SamPointToolService, cellSegmentTool: CellSegmentToolService, cellSegmenter: ICellSegmenter | null, simpleStack: SimpleSliceAccessService, config: VizConfig, spatialData?: SpatialDataPort | null, selectionStore?: SpatialSelectionStore | null);
277
- /**
278
- * Fetch + cache the server pyramid descriptor (`GET /tiles/info`): the REAL per-level tile grid,
279
- * tile size, channel metadata and physical pixel size. The backend returns 202 while the source
280
- * is still caching, so we poll briefly. Cached per `infoB64`; returns null if it never becomes
281
- * ready (callers fall back to a single-tile fetch). This is the authoritative grid — guessing
282
- * level dims from `trueImageSize` overshoots the real grid and the server 400s out-of-range tiles.
283
- */
284
- private ensureDescriptor;
285
- /**
286
- * Fetch a COMPLETE rendered slice as an `ImageBitmap` by stitching the server's REAL tile grid
287
- * (from `/tiles/info`) — not just the top-left tile, which only ever showed a large image's
288
- * corner. Picks the finest pyramid level whose grid fits `budgetTiles` and whose longest side is
289
- * within the GPU texture limit, fetches that grid concurrently, and stitches it into one canvas.
290
- *
291
- * `channel` selects a single band as grayscale (real levels only); omit for the server composite.
292
- * `budgetTiles` caps the grid: the 2D view uses the full budget for detail; the 3D volume passes
293
- * 1 for a cheap overview tile per slice (it downsamples to {@link VOLUME_MAX_SLICE}). Falls back
294
- * to a single `col=0,row=0` tile when no descriptor is available (small/simple images, volumes).
295
- */
296
- private fetchSlice;
297
- load(imageInfo: IImageInfo, zIndex: number): Promise<NapariLoaded>;
298
- plot(plotDiv: string, imageLoaded: unknown, imageInfo: IImageInfo, screenHeight: number, plotType: PlotType, _inPlace?: boolean): Promise<boolean>;
299
- /** The grayscale display colormap from the store selection (+reverse), defaulting to gray.
300
- * Maps the jit-ui store colormap node to a napari `Colormap` via the library's LUT factory;
301
- * the multichannel tint ramps are built inside {@link MultiChannelImageView} from each
302
- * channel's hex colour. */
303
- private grayscaleColormap;
304
- /** Fetch a stitched slice and read it back as a single-channel uint8 plane. `channel` selects a
305
- * band (multichannel); omit it for the grayscale composite (all overview levels available, so a
306
- * large image picks a fitting downscaled level rather than only the full-res real level). */
307
- private fetchChannelData;
308
- /** Decode an `ImageBitmap` (server bands are grayscale, R=G=B) to a single-channel uint8 plane.
309
- * `maxSide` caps the longest side (downscaling on the canvas draw) — used to keep pre-loaded
310
- * surface slice planes small. */
311
- private bitmapToLuminance;
312
- /**
313
- * Render the 2D image for slice `z`. With a server pyramid descriptor we use a pyramidal
314
- * {@link TiledSource} per layer so the view refines to higher resolution on zoom (like OSD) and
315
- * sits naturally in full-resolution coordinates; without one we fall back to the single-level
316
- * stitch. Three display modes either way: multichannel additive tint, grayscale colormap, RGB.
317
- */
318
- private renderImage;
319
- /** Single-level stitch fallback (no descriptor): the pre-tiling path. */
320
- private renderImageStitched;
321
- /**
322
- * Render the 2D image with pyramidal {@link TiledSource}s — the view refines to higher resolution
323
- * as you zoom in (the visual fetches the level whose texels ≈ screen pixels) and sits in full-res
324
- * coordinates so regions align. Same three modes as the stitch path. Per-channel layers use the
325
- * REAL pyramid levels (per-channel tiles only exist there); the composite uses all levels.
326
- */
327
- private renderImageTiled;
328
- /** Build a pyramidal TiledSource backed by the server `/tile` endpoint. `channel` selects a band
329
- * (grayscale luminance, real levels only); omit it for the composite (RGBA, all levels). */
330
- private buildTiledSource;
331
- /** (Re)fetch a coarse per-channel luminance sample for the histogram (tiled mode has no full
332
- * in-memory pixels). One cheap overview tile per channel; cached by channel index. */
333
- private refreshHistogramSamples;
334
- /** Subscribe channel states + grayscale colormap → live-apply to the rendered layers (no
335
- * re-fetch; only z changes re-fetch). Replaces any prior subscription. */
336
- private subscribeDisplayState;
337
- /** Subscribe the store colormap (+reverse), invert, and channel state → the volume/isosurface
338
- * transfer function: colour (channel tint or selected colormap), the intensity **window
339
- * (min/max → contrastLimits)** and **gamma**, mirroring the grayscale image's display controls
340
- * so the histogram pane drives the 3D render. Replaces any prior subscription. */
341
- private subscribeVolumeDisplayState;
342
- /** A channel's tint colormap (black→colour) with reverse-scale / invert applied by flipping. */
343
- private channelTintColormap;
344
- /**
345
- * Colour map for the volume/isosurface. A real colormap selection (viridis/magma/…) wins;
346
- * otherwise the channel's colour tints it (so the channel-dialog colour swatch recolors the 3D
347
- * render). Reverse-scale and invert each flip the ramp — the `VolumeLayer` has no per-layer
348
- * invert, so both are emulated by reversing the colormap.
349
- */
350
- private volumeColormap;
351
- /** Apply the current channel states / colormap to the live layers (no re-fetch), delegating the
352
- * per-channel layer mutations to the {@link MultiChannelImageView}. */
353
- private applyDisplayState;
354
- /** (Re)install the physical scale bar over the 2D image, sized from the image's µm/pixel
355
- * (`/tiles/info` mppX, falling back to the image metadata). No-op without a physical size. */
356
- private installScaleBar;
357
- /**
358
- * The overview navigator for a 2D view with an image: a coarse thumbnail of the whole
359
- * image with the viewport on it; click or drag to pan at the current zoom (as OSD).
360
- */
361
- private showLoading;
362
- private installNavigator;
363
- /**
364
- * Draw the navigator's thumbnail from the coarsest pyramid level. A multichannel image
365
- * is composited from its channels in their display colours, so the overview looks like
366
- * the view rather than like channel 0 in grey.
367
- */
368
- private refreshNavigatorImage;
115
+ constructor(tiles: TileAccessPort, store: VisualizerStore, regionStore: RegionStore, wandService: WandService, samTool: SamToolService, samPointTool: SamPointToolService, cellSegmentTool: CellSegmentToolService, cellSegmenter: ICellSegmenter | null, simpleStack: SimpleSliceAccessService, config: VizConfig, spatialData?: SpatialDataPort | null, selectionStore?: SpatialSelectionStore | null);
116
+ /** Run `fn` inside the Angular zone: for output (subjects the UI renders, store writes)
117
+ * produced by work that runs outside it. */
118
+ private inZone;
119
+ /** What a scene is built from (see {@link SceneContext}). */
120
+ private sceneContext;
121
+ /**
122
+ * Record the image to draw. No network work happens here — the descriptor poll and the tile,
123
+ * volume and spatial fetches all run in {@link plot} under its scene signal, which a newer plot,
124
+ * {@link reset} or `cancelLoading()` aborts — so `signal` is only checked: an already-aborted
125
+ * load rejects with an `AbortError` and leaves the recorded image alone.
126
+ */
127
+ load(imageInfo: IImageInfo, zIndex: number, signal?: AbortSignal): Promise<NapariLoaded>;
128
+ plot(plotDiv: string, imageLoaded: unknown, imageInfo: IImageInfo, screenHeight: number, plotType: PlotType, inPlace?: boolean): Promise<boolean>;
129
+ /** The scene a plot type mounts. */
130
+ private createScene;
369
131
  /** Show/hide the overview navigator (same setting as OSD's). */
370
132
  setNavigatorVisible(visible: boolean): void;
371
- /** Convert a napari-js `Histogram` (bin count + min/max) to the pane's `IHistogram` (bin edges). */
372
- private toIHistogram;
373
- /**
374
- * Mount the 3D volume/isosurface. A multichannel image becomes one additive, tinted
375
- * {@link VolumeLayer} per channel (so each channel's colour composites into the render); a
376
- * grayscale/composite image uses a single volume. Adds the axes gizmo + labels and wires the
377
- * display-state subscription. The caller owns `viewer.ready`.
378
- */
379
- private mountVolume;
380
- /**
381
- * Restretch the volume's Z height live (driven by the in-view {@link NapariVolumeZHandle}). Only
382
- * the per-axis `voxelSize` / axes depth change — the voxel textures are untouched — so dragging is
383
- * smooth. `factor` is relative to the volume's natural proportions (1). Persists across re-mounts
384
- * (resolution changes) so the chosen height sticks.
385
- */
386
- private setVolumeZScale;
387
- /** Build the X/Y/Z axis-end label specs for the 3D gizmo. Anchors are in the volume's centred
388
- * world box (matching the AxesLayer geometry); the scale text reflects the FULL image extent —
389
- * physical µm when µm/pixel is known, else pixel (X/Y) / slice (Z) counts. */
390
- private buildAxesLabels;
391
- /**
392
- * The image's declared extent in pixels/slices, and its physical spacing per
393
- * axis in µm (0 = undeclared, and then that axis reads in pixels).
394
- *
395
- * One place, because the volume world box and the axis labels have to agree
396
- * about what the image's real dimensions are — the sampled grid is decimated and
397
- * says nothing about either.
398
- */
399
- private imageExtent;
400
- /**
401
- * Assemble a downsampled uint8 volume (luminance) from the per-slice tile endpoint. Slices are
402
- * fetched with bounded concurrency (keeps the connection pool full without flooding it on a deep
403
- * stack) and read into the volume as each arrives, driving {@link stackLoadingProgress$} so the
404
- * host shows a determinate progress bar instead of a bare spinner.
405
- */
406
- private assembleVolume;
407
- /**
408
- * Mount the NAPARI_SCATTER 2D scatter: the slice image with a points layer at each region's
409
- * centroid (napari-js analog of Plotly's region-centroid scatter). Rebuilds the points live as
410
- * regions change.
411
- */
412
- private mountScatter;
413
- /** (Re)build the 2D scatter's point layer at the current region centroids. */
414
- private rebuildScatterPoints;
415
- /** Region centroids as flat `[x, y, …]` data coords (rectangle / polygon / multipolygon). */
416
- private regionCentroids;
417
- /**
418
- * The interaction stack every 2D mode needs: the region overlay (draw/select/edit), the pixel
419
- * tools that read back displayed pixels (wand, brush, vertex eraser, zoom-to-box, SAM/cellpose),
420
- * and a camera hook that keeps that readback current as the view pans/zooms and tiled levels
421
- * load.
422
- *
423
- * Extracted because forgetting it is invisible: the toolbar gates its region buttons on 2D-vs-3D
424
- * rather than on plot type, so a 2D mode that skips this shows every tool and silently does
425
- * nothing. That is exactly what happened to the spatial and region-centroid scatter modes.
426
- */
427
- private install2dInteraction;
428
- /** Marker radius (image px) for a dataset that declares none — segmented cells often don't. */
429
- private static readonly SPATIAL_FALLBACK_RADIUS;
430
- /** Smallest marker DIAMETER, in slice pixels, over a volume-backed dataset. A cell's real
431
- * size is honoured wherever it survives the grid: the ABC atlas serves 5 µm radii on a
432
- * 40 µm/px template, so drawing them to scale would put every cell a fifth of a pixel wide
433
- * and the section would come up empty. The point-size control scales up from this floor. */
434
- private static readonly SPATIAL_SLICE_MIN_DIAMETER_PX;
435
- /** Longest side of the gene-map raster, in field pixels. A gene map is a smooth
436
- * field read as territory, so it gains nothing from matching a 2 Gpx slide's
437
- * resolution — and the estimate costs one pass over this many pixels. */
438
- private static readonly GENE_MAP_MAX_SIDE;
439
- /** Kernel σ in field pixels at smoothing 1: wide enough to read between cells,
440
- * tight enough to keep a nucleus-scale structure distinct. */
441
- private static readonly GENE_MAP_SIGMA;
442
- /** Clusters drawn as density volumes at once. Past a handful, additive translucent
443
- * clouds stop being separable by eye — and each one is a full rasterisation. */
444
- private static readonly DENSITY_MAX_CLUSTERS;
445
- /** Colour for observations when nothing is selected to colour by: visible, neutral, and
446
- * obviously not encoding anything. */
447
- /** How much larger a selected marker is drawn, so a small selection is findable inside a
448
- * 3.7M-point cloud rather than merely brighter. */
449
- private static readonly SPATIAL_SELECTED_SIZE_SCALE;
450
- private static readonly SPATIAL_NEUTRAL_COLOR;
451
- /**
452
- * Mount the SPATIAL_OMICS view: the tissue image with one marker per observation, coloured by
453
- * an annotation column or a gene. The markers rebuild whenever the dataset or the view state
454
- * changes, so switching the colour-by column does not remount the scene.
455
- *
456
- * Sets up the full 2D interaction stack — region overlay, pixel-tool hosts, readback currency —
457
- * exactly as the plain image view does. That is NOT optional here: this mode's selection is
458
- * driven by drawn ROIs, so without the overlay there is no way to make a selection at all.
459
- */
460
- private mountSpatialOmics;
461
- /**
462
- * Whether the 2D observation markers are drawn: when the user wants them, and not while
463
- * cell outlines are on screen — then a cell IS its outline, and a circle on top of it is
464
- * noise. Zoomed out past the outline threshold, the circles stand in for the cells.
465
- */
466
- private spatialPointsVisible;
467
- /**
468
- * The tiled-geometry manager, built on first use. Its host callbacks read this
469
- * service's live state, so it never holds a stale dataset or colormap.
470
- */
471
- private spatialTiles;
472
- /**
473
- * Region drawing for the 3D cloud.
474
- *
475
- * Reuses {@link NapariRegionOverlay} verbatim by handing it a SCREEN-SPACE viewer: the drawn
476
- * shape is a lasso in canvas pixels, so "world" is the canvas and both transforms are identity
477
- * (bar the client→canvas offset). Every existing tool — rectangle, polygon, freehand — therefore
478
- * works in 3D with no new drawing code.
479
- *
480
- * A screen-space shape stops meaning anything the moment the camera moves, so an orbit clears
481
- * the drawn regions. The SELECTION it produced is kept: that is the durable artefact, and the
482
- * highlighted points stay highlighted from every angle.
483
- */
484
- private install3dInteraction;
485
- /** Movement, in screen pixels, under which a press-release is a CLICK and not a
486
- * drag. An orbit or a pan starts the same way, so the two have to be told
487
- * apart by how far the pointer travelled. */
488
- private static readonly CLICK_SLOP_PX;
489
- /** Longest press-release still treated as a click. A long press with the mouse
490
- * held still is more likely an interrupted drag than a selection. */
491
- private static readonly CLICK_MAX_MS;
492
- /** Pointer distance, in screen pixels, that still counts as "on" a marker.
493
- * Generous relative to a 1.5px disc: the cursor is a blunt instrument, and a
494
- * tooltip you have to hunt for is worse than none. */
495
- private static readonly HOVER_RADIUS_PX;
496
- /**
497
- * Cursor tooltip for the spatial views: hover a marker, read its class.
498
- *
499
- * A 34-entry legend cannot be read back from a dot — several classes get
500
- * similar colours, and matching one to a swatch by eye is exactly the task this
501
- * removes. It reports whatever the cloud is CURRENTLY coloured by, so it and
502
- * the legend can never say different things.
503
- *
504
- * Listens on the HOST rather than the canvas so it keeps working over the region
505
- * overlay (an SVG covering the canvas, which would otherwise swallow every
506
- * move), and throttles to one hit-test per animation frame: a pointermove can
507
- * fire far more often than that, and each test is a pass over the cloud.
508
- */
509
- private installSpatialHover;
510
- private removeSpatialHover;
511
- /** Hit-test the last pointer position and show or hide the tooltip. */
512
- private updateHover;
513
- /**
514
- * Select the class of the marker at a client position — the canvas equivalent of
515
- * clicking that class in the panel's legend, and the same selection object, so
516
- * the two controls cannot produce different results.
517
- *
518
- * Clicking a class that is already the whole selection CLEARS it, which is what
519
- * the legend does. Compared against the selection itself rather than against a
520
- * remembered click, so selecting from the legend and then clicking the same
521
- * class on the canvas still toggles.
522
- */
523
- private selectClassAt;
524
- /**
525
- * Which observation is under the cursor.
526
- *
527
- * In 3D this defers to napari-js's {@link nearestProjectedIndex} WITH the depths the
528
- * projection produced, so the front-most candidate wins. That matters more than it
529
- * sounds: the renderer depth-tests the billboards, and in a 3.7M-point cloud the cursor
530
- * covers many of them — picking the one nearest the cursor's centre regularly names a
531
- * cell that something else is drawn over, which reads as a wrong tooltip rather than as
532
- * a subtlety of picking.
533
- *
534
- * In 2D the positions are WORLD coordinates on one plane, so there is no depth to break
535
- * ties with and the existing nearest-marker rule is the right one.
536
- */
537
- private pickObservation;
538
- /**
539
- * Positions to hit-test against, rebuilt only when the scene or camera moved.
540
- *
541
- * A pass over 3.7M observations is not something to do per pointermove, and the
542
- * cloud does not move between frames unless something says it did.
543
- */
544
- private hoverPositionsFor;
545
- /**
546
- * The 2D markers' WORLD positions, indexed by observation, NaN for any not on
547
- * the displayed plane — the same affine and the same subset the marker layer was
548
- * built from, so the tooltip cannot point at a cell that is not drawn.
549
- */
550
- private hoverWorldPositions;
551
- /**
552
- * What the tooltip says, resolved once per colour source rather than per hover.
553
- *
554
- * Fetched separately from the colouring on purpose: the reference port caches
555
- * columns, but a host's need not, and re-fetching a 3.7M-element vector because
556
- * the pointer moved would be indefensible either way.
557
- */
558
- private resolveHoverSource;
559
- /**
560
- * Project every observation to canvas pixels under the current 3D camera.
561
- *
562
- * The projection itself is the renderer's: `viewer.projectPoints` owns the camera, the
563
- * viewport in CSS pixels, the perspective divide and the y-flip. This used to be fifteen
564
- * lines of column-major matrix arithmetic here, duplicating a second copy in
565
- * `napari-axes-labels` — and the two had drifted on what to do with a NaN w.
566
- *
567
- * What is left is the part that is genuinely this adapter's: SCATTERING the drawn subset
568
- * back into observation order. The cloud holds only the points of the displayed section,
569
- * in its own packing; every consumer indexes by observation. NaN stands for "not on
570
- * screen", which is also the right answer for an observation whose section is hidden.
571
- *
572
- * Null when the 3D cloud is not mounted, so the caller falls back to the 2D affine path.
573
- */
133
+ /** Observations projected to canvas pixels under the 3D camera (the spatial 3D cloud), indexed
134
+ * by observation with NaN for any not drawn; null when no cloud is mounted. */
574
135
  getSpatialScreenProjection(obs: SpatialObservations): Float32Array | null;
575
- /** Rebuild the markers on any dataset or view-state change. */
576
- private subscribeSpatial;
577
- /** (Re)build the observation marker layer for the current dataset + view state. */
578
- private rebuildSpatialPoints;
579
- /**
580
- * Tell the region overlay how finely a drawn vertex may be placed.
581
- *
582
- * Region geometry is stored in whole world units, which is right when the world IS
583
- * pixels — a region should align to them. It is wrong for a dataset that registers onto
584
- * no image: seqFISH's observations span about 5 x 7 units in total, so whole-unit
585
- * vertices leave roughly six by eight placeable positions across the entire sample and
586
- * an ROI cannot be drawn at any zoom. Nothing errors; the tool just cannot express the
587
- * shape.
588
- *
589
- * Keyed on whether the dataset brings PIXELS rather than on the extent, because the
590
- * extent cannot tell the two apart — 2,000 units is a small slide or a large section
591
- * depending only on what the units are, and only the dataset knows.
592
- */
593
- private setRegionGridFor;
594
- /**
595
- * Frame the 2D camera on the observations, for a dataset that brings no image.
596
- *
597
- * The 2D camera is normally fitted to the IMAGE, because the observations are in that
598
- * image's pixel space and framing the image frames them too. A dataset with no
599
- * reference image has coordinates in its own units instead — seqFISH's span about
600
- * 5x7 — so the image framing left over from whatever was on screen before puts the
601
- * whole cloud offscreen: measured at 9.7 x 13.4 PIXELS, centred 256px from where the
602
- * camera was looking. The points are all there and drawn; they are a speck. Which
603
- * looks exactly like the dataset having failed to load.
604
- *
605
- * Once per dataset, as napari-js's `fit3d: 'once'` does for the cloud: re-colouring,
606
- * slicing or picking a gene re-adds this layer, and re-framing on those would move
607
- * the camera under the user — the camera tools and the canvas drag are meant to be
608
- * the only things that do.
609
- */
610
- /**
611
- * Hide the image layer for a dataset that brings no image of its own.
612
- *
613
- * The host's viewer keeps whatever image was last loaded, and for a dataset that
614
- * registers onto none that picture belongs to something else entirely — the example's
615
- * default slide, say. It is not merely irrelevant: the two live in different coordinate
616
- * spaces (image pixels against the embedding's own units), so the leftover is magnified
617
- * roughly a hundredfold. At the fitted zoom the camera sits inside its corner, where it
618
- * reads as blank background, and it appears only once you zoom out far enough to find
619
- * it — which is exactly how it gets noticed.
620
- *
621
- * Hidden rather than removed, and hidden HERE rather than by clearing the host's image
622
- * state: that state drives the whole render pipeline, including a Plotly backend whose
623
- * fields are declared with definite-assignment assertions, so emptying it throws from
624
- * whichever field the next path happens to read. This touches one layer's visibility
625
- * and nothing else.
626
- */
627
- private hideForeignImage;
628
- private frameSpatialPointsOnce;
629
- /**
630
- * The **gene map**: the active gene's expression as a continuous field drawn under
631
- * the cells.
632
- *
633
- * A scatter coloured by a gene says which cells express it; it cannot say where,
634
- * because the eye will not integrate thousands of dots into a territory. The field
635
- * is a kernel-weighted MEAN per cell (see `spatial-expression.ts`), so a dense
636
- * region does not glow merely for being dense, and it is transparent wherever no
637
- * cell was measured — an unsampled gap must not read as "not expressed".
638
- *
639
- * It shares the points' LUT, percentile window and log flag, so the layer under
640
- * the cells and the cells themselves cannot disagree about what a colour means.
641
- *
642
- * Estimated on the DISPLAYED image's pixel grid, coarsened so the long side is at
643
- * most {@link GENE_MAP_MAX_SIDE}: a smooth field gains nothing from a slide's full
644
- * resolution. For a volume-backed dataset that grid is the current slice, and only
645
- * that plane's observations are included — the same rule the markers follow.
646
- */
647
- private ensureGeneMap;
648
- /**
649
- * The plane a volume-backed dataset is currently showing: its pixel affine, the
650
- * observations that fall in it, and the marker floor that grid needs.
651
- *
652
- * Null for a dataset with a real `imageRef` (its coordinates are already the
653
- * image's pixels and every observation belongs to the one section) and for one
654
- * with no volume at all — both of which draw exactly as before.
655
- */
656
- private spatialSlab;
657
- /** Per-point colours for the drawn subset. A broadcast tuple stays broadcast —
658
- * it is one colour for every point either way. */
659
- private gatherColors;
660
- /**
661
- * Redraw the observation markers over a freshly rendered image.
662
- *
663
- * Two reasons, both invisible from the spatial store — which is why a scrub or a
664
- * re-render never reached the markers on its own:
665
- * - the image render CLEARS the layer list, taking the markers with it;
666
- * - over a volume-backed dataset the displayed plane decides which
667
- * observations belong on screen at all, so the cells have to move with the
668
- * section rather than hang over a different one.
669
- *
670
- * Uses the latest values the marker subscription saw; a no-op until it has seen
671
- * any, in the 3D cloud (no image, no plane), and with no dataset to draw.
672
- */
673
- private redrawSpatialMarkers;
674
- /**
675
- * Mount the SPATIAL_OMICS_3D view: observations as a 3D point cloud under the orbit camera.
676
- *
677
- * Deliberately much thinner than the 2D mount. There is no tissue image to render (a registered
678
- * volume like the Allen CCF has no single reference plane), so no scale bar, no readback, and no
679
- * 2D interaction stack — the region tools draw in screen space and have no meaning against an
680
- * orbiting camera, which is why `Select from ROIs` is hidden in this mode. `addPoints3D` puts
681
- * the viewer in 3D and frames the camera on the cloud itself.
682
- */
683
- private mountSpatialOmics3d;
684
- /**
685
- * Scale bar for the 3D cloud, measured at the ORBIT PIVOT.
686
- *
687
- * A perspective camera has no single scale — things farther away are smaller — so a bar can
688
- * only be true at one depth. The pivot is the honest choice: it is what the camera is framing,
689
- * what a zoom moves towards, and where the eye is anyway. napari's own 3D scale bar works the
690
- * same way.
691
- *
692
- * `NapariScaleBar` needs CSS px per world unit, which an orbit camera does not expose, but at
693
- * the pivot it is exactly `viewportHeight / (2 * distance * tan(fov / 2))` — the same
694
- * relationship `Camera3D.pan` uses to track the cursor. The bar then converts through
695
- * `micronsPerUnit`, and draws nothing at all when the dataset does not declare one, because a
696
- * bar labelled in microns over unknown units would read as a measurement.
697
- */
698
- private installSpatial3dScaleBar;
699
- /** Base marker diameter for the 3D cloud, in SCREEN pixels (the layer's unit). */
700
- private static readonly SPATIAL_3D_BASE_SIZE;
701
- /** (Re)build the 3D point cloud for the current dataset + view state. */
702
- private rebuildSpatialPoints3d;
703
- /**
704
- * The **3D gene map**: the active gene's expression over the whole sectioned
705
- * specimen, as one raymarched volume.
706
- *
707
- * Two things it can be, and the panel's `Volume rendering` toggle picks which:
708
- *
709
- * - **sheets** — exactly the planes that were imaged, each carrying that
710
- * slide's own 2D gene map, with the gaps between sections empty. A stack of
711
- * measured fields, at their true z.
712
- * - **volume** — the same fields smoothed along z, so the planes between the
713
- * sections carry an interpolated value. An estimate, and drawn as a
714
- * translucent cloud for the same reason the density volumes are.
715
- *
716
- * One `VolumeLayer` rather than a textured quad per section: an `ImageLayer`
717
- * renders only at `ndisplay === 2`, so 53 sheets in the orbit view would need a
718
- * new layer type upstream — while a scalar volume whose z sampling already IS
719
- * the section spacing expresses the sheets exactly, and the same lattice then
720
- * gives the interpolated version for free.
721
- *
722
- * Estimated on the reference volume's own lattice (`densityGrid` at stride 1),
723
- * so the field lands voxel-for-voxel on the anatomy and needs no offset — a
724
- * `VolumeLayer` has no translate, and napari centres both boxes on the world
725
- * origin.
726
- */
727
- private ensureGeneMapVolume;
728
- /**
729
- * Cluster density volumes: each cluster rasterised into a smooth scalar field and
730
- * raymarched alongside the cloud, tinted with the cluster's own legend colour.
731
- *
732
- * This is what makes a serially sectioned dataset readable as an anatomical
733
- * distribution. The cloud shows measured cells and nothing else — but at 200 µm
734
- * section spacing the eye cannot integrate a stack of discs into a shape, and
735
- * every gap reads as absence. A density field is a different object from a cell:
736
- * an estimate, defined between the imaged planes, drawn as a translucent cloud so
737
- * it cannot be mistaken for measurement. Individual cells are never interpolated —
738
- * consecutive sections sample different cells, so there is nothing to interpolate
739
- * along.
740
- *
741
- * One volume per cluster rather than one for everything: additive blending is what
742
- * makes two clusters' territories comparable, and a single blended field would
743
- * answer no question anyone asks of a taxonomy. Capped at
744
- * {@link DENSITY_MAX_CLUSTERS} by cell count.
745
- *
746
- * Keyed so it rebuilds only when the field would actually differ — the dataset,
747
- * the colour column, the bandwidth, or the selection.
748
- */
749
- private ensureDensityVolumes;
750
- /**
751
- * Identity of the colour scale a continuous spatial layer will draw with, for a
752
- * cache key: the explicit choice, or else the display colormap and its reverse
753
- * flag, since that is what {@link spatialContinuousLut} falls back to.
754
- *
755
- * The gene maps cache their coloured output, so without this in the key a change
756
- * of colour scale left the field on screen in the previous colours — the markers
757
- * recoloured and the map under them did not.
758
- */
759
- private continuousColormapKey;
760
- /**
761
- * A revision number for a selection object.
762
- *
763
- * The store hands out a NEW mask object per change, so object identity is the
764
- * cheap and exact way to tell two selections apart — a fingerprint over 3.7M
765
- * mask bytes would be neither. Counting revisions keeps the cache key a short
766
- * string.
767
- */
768
- private selectionRev;
769
- /**
770
- * The clusters to rasterise: the categories of the active categorical colouring,
771
- * biggest first and capped, each with its legend colour.
772
- *
773
- * Restricted to the current selection when there is one, so "select a region,
774
- * check the box" answers which clusters live there. With no categorical colouring
775
- * there is one group — total cell density, which is a real question on its own
776
- * ("where is the tissue dense?") and the honest thing to show when the view is
777
- * not encoding a taxonomy.
778
- */
779
- private densityGroups;
780
- /**
781
- * Add (or keep) the dataset's reference volume, and derive the offset that sits the
782
- * observations inside it.
783
- *
784
- * `VolumeLayer` has no translate: napari-js maps the volume's unit cube to a world box
785
- * **centred on the origin**, sized `dims x voxelSize`. The observations, by contract, are in
786
- * the volume's own frame with its near corner at the coordinate origin. So the two only line
787
- * up if the POINTS move — by half the box — which is what {@link spatialOrigin3d} is.
788
- *
789
- * A failed or absent volume is not fatal: the cloud renders on its own, at its own
790
- * coordinates, and the camera frames the points instead.
791
- */
792
- private ensureSpatialVolume;
793
- private removeSpatial3dLayers;
794
- /** A one-colour colormap, for the "nothing to colour by" state. */
795
- private spatialFlatColormap;
796
- /**
797
- * The per-point scalar + colormap + window that colour the 3D cloud.
798
- *
799
- * Continuous data is the natural fit: values go straight through the active colormap with the
800
- * same percentile window the 2D path uses. Categorical data has to be smuggled through the same
801
- * scalar channel — see {@link SPATIAL_3D_MAX_CATEGORIES}. Codes map to LUT blocks, and
802
- * `contrastLimits` of `[-0.5, K - 0.5]` puts code `i` at the centre of block `i`, which is what
803
- * makes the round-trip exact instead of approximately right.
804
- */
805
- private spatialScalar3d;
806
- /** Category codes → a stepped LUT, exact for up to {@link SPATIAL_3D_MAX_CATEGORIES}. */
807
- private encodeSpatial3dCategorical;
808
- /** Continuous values → the active colormap over a percentile-clipped window. */
809
- private encodeSpatial3dContinuous;
810
- /**
811
- * Per-observation colours for the current view state, or a single flat colour when nothing is
812
- * selected to colour by. Categorical columns use the column's own palette; continuous columns
813
- * and gene vectors go through the active colormap with a percentile-clipped window.
814
- */
815
- private spatialFaceColors;
816
- /** Continuous values → RGBA through the active colormap and a clipped window. */
817
- private encodeSpatialContinuous;
818
- /**
819
- * Mount the NAPARI_SCATTER3D 3D scatter: the downsampled voxel grid as a 3D point cloud colored
820
- * by intensity (napari-js analog of Plotly's voxel scatter3d). Assembles a coarse volume, then
821
- * emits a flat-strided sample of voxels (capped at {@link SCATTER3D_MAX_POINTS}) via `addPoints3D`.
822
- */
823
- private mountScatter3d;
824
- /** Store colormap / reverse / invert / channel window → the 3D scatter's colormap + contrast. */
825
- private subscribeScatter3dDisplayState;
826
- /**
827
- * Mount the NAPARI_SURFACE height-field surface. A height field is single-scalar, so for a
828
- * multichannel image the surface follows ONE band — the first visible channel (fallback 0) —
829
- * coloured by that channel's window/colormap (like the Plotly SURFACE, which is grayscale-only).
830
- * Pre-loads every slice's height data with a progress bar (as the volume does) so the stack
831
- * slider re-slices instantly, then builds the mesh for the current slice. All mesh + GPU work
832
- * lives in napari-js (`heightField` + `Viewer.addSurface`); this backend supplies scalar slices.
833
- */
834
- private mountSurface;
835
- /** Add the 3D axes gizmo + DOM labels around the (origin-centered) surface mesh, matching the
836
- * volume/isosurface. Installed once per mount; the box tracks the mesh bounds, X/Y show the
837
- * physical (or pixel) extent, and Z is the intensity/height axis. */
838
- private installSurfaceAxes;
839
- /** X/Y/Z end-labels for the surface gizmo: X/Y are the physical (µm) or pixel extent of the FULL
840
- * image; Z is the intensity/height axis. Anchors are in the centered box (matching AxesLayer). */
841
- private buildSurfaceAxesLabels;
842
- /**
843
- * Pre-fetch every stack slice's luminance plane (decimated to the surface grid) into
844
- * {@link surfacePlanes}, driving {@link stackLoadingProgress$} — the same load-with-progress UX
845
- * as the volume, but keeping one 2D plane per slice rather than packing a 3D volume. Bounded
846
- * concurrency keeps the connection pool busy without flooding it on a deep stack.
847
- */
848
- private preloadSurfacePlanes;
849
- /**
850
- * Fetch slice `z` as a single WHOLE-image luminance plane (decimated to `maxGrid`). Prefers the
851
- * app's complete per-slice image (`smallUrls`/`urls`, exactly like the Plotly surface) so the
852
- * surface always covers the FULL slice — the tile-pyramid `fetchSlice` path would fall back to a
853
- * single top-left tile (a corner) for self-contained / non-`/tiles/info` images. Falls back to
854
- * stitching the tile grid only when no complete-image URL is available.
855
- */
856
- /** Tile budget to stitch a whole slice at ~`targetPx` resolution from the pyramid: a higher target
857
- * pulls a FINER pyramid level (more real detail). Shared by the surface plane fetch and the volume
858
- * assembly so both scale their in-plane resolution with the decimate factor. */
859
- private tileBudgetFor;
860
- private fetchSurfacePlane;
861
- /** The channel state driving the surface: the chosen band for multichannel (matched by index),
862
- * else the single grayscale channel. */
863
- private surfaceState;
864
- /**
865
- * (Re)build the surface mesh for slice `z` from the pre-loaded plane cache (instant — this is
866
- * what the stack slider calls); a slice missing from the cache is fetched on demand. napari-js's
867
- * pure `heightField` builds the triangle grid (z = normalized intensity), then `addSurface`
868
- * renders it. The slice plane also feeds the intensity histogram (key 0).
869
- */
870
- private buildSurface;
871
- /** Subscribe the store colormap / reverse / invert / channel window → the surface, so histogram
872
- * & channel-dialog edits update it live without a re-fetch. **min/max reshapes the surface's
873
- * height** (a pixel's height = its intensity within [min,max]), so a window change rebuilds the
874
- * mesh geometry (from the cached slice); colour-only edits (colormap/LUT, gamma, reverse, invert)
875
- * just update the layer's uniforms. */
876
- private subscribeSurfaceDisplayState;
877
136
  private fitCameraSoon;
878
137
  /** @deprecated Plotly-specific; host re-drives plot() from its image stream. */
879
138
  reloadAndPlot(): void;
139
+ /**
140
+ * End the mounted scene: abort its lifetime (its descriptor poll, tile counts, frame loading and
141
+ * awaits) and dispose it — its layers, keys, subscriptions and listeners go with it, so the next
142
+ * plot can never inherit an "already built" key (NAPARI-SVC-1) — then tear the viewer down.
143
+ */
880
144
  reset(): void;
881
145
  relayout(_trueImageSize?: number[]): void;
882
146
  /** @deprecated Plotly-specific axis reset. */
@@ -885,12 +149,15 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
885
149
  autoscale(): void;
886
150
  zoomIn(): void;
887
151
  zoomOut(): void;
152
+ /** Zoom by `factor` (> 1 = in) on whichever camera is live: the 2D camera's zoom, or — in a 3D
153
+ * scene, where that would change nothing visible — the orbit camera's distance. */
154
+ private zoomBy;
888
155
  setDragMode(_mode: string | false): void;
889
156
  setImageSmoothingEnabled(enabled: boolean): void;
890
157
  setShowStack(_showstack: boolean): void;
891
158
  setZIndex(zIndex: number): void;
892
159
  setStackLoading(stackLoading: boolean): void;
893
- /** Cancel in-flight frame loading: bump the load generation so the volume-assembly / surface
160
+ /** Cancel in-flight frame loading: abort {@link loading} so the volume-assembly / surface
894
161
  * preload workers stop fetching more frames, and clear the loading flag + progress. */
895
162
  cancelLoading(): void;
896
163
  isStackLoading(): Observable<boolean>;
@@ -908,78 +175,54 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
908
175
  height: number;
909
176
  } | null;
910
177
  downloadImage(): void;
911
- setPlotType(plotType: PlotType): void;
178
+ /** No-op: the mounted scene is fixed per {@link plot}; a new plot type takes a re-plot. */
179
+ setPlotType(_plotType: PlotType): void;
912
180
  /** Map a Plotly-style 3D drag mode onto napari-js's camera drag mode. */
913
181
  setSurfaceDragMode(mode: string): void;
914
- /** Re-frame the 3D camera on the current 3D layer. A surface mesh sits in the positive octant
915
- * (not centred), so frame it by its own bounds; a volume/isosurface uses its centred box. */
182
+ /** Re-frame the 3D camera on the scene: napari-js frames the union of every 3D layer's bounds
183
+ * (surface, volume, point cloud), with the viewport-aware framing its adders use. */
916
184
  resetSurfaceCamera(): void;
917
185
  getAutoscaleEvent(): Observable<unknown>;
186
+ /**
187
+ * The plot types this backend can mount — every type {@link plot} dispatches on.
188
+ *
189
+ * Contract-only in production: the router answers `getPlotTypeDescriptors` from the Plotly
190
+ * service, so nothing reaches this one through it; it is kept accurate for direct callers.
191
+ */
918
192
  getPlotTypeDescriptors(): PlotTypeDescriptor[];
919
193
  /** The napari 3D decimate factor (1 = full … 8 = ⅛). Read by the toolbar to init the control. */
920
194
  getResolutionScale(): number;
921
195
  /** Set the decimate factor for the napari 3D types. Takes effect on the next (re)load — the host
922
196
  * re-plots after calling this, since decimation changes the fetched/assembled data. */
923
197
  setResolutionScale(scale: number): void;
924
- getIntensityProfile$(): Observable<IntensityProfile[]>;
925
- renderIntensityInset(_divId: string, _profiles: IntensityProfile[]): void;
926
- /** Read the displayed composite into `lastPixels` (the pixel-tools' source) + emit the clamped
927
- * visible region. A fresh PixelData object means cachedImageData() rebuilds automatically. */
928
- private runReadback;
929
- private scheduleReadback;
930
- /** Debounced readback — armed on camera changes so `lastPixels` tracks the current view after a
931
- * pan/zoom settles (and after tiled levels finish loading), which the on-canvas pixel tools
932
- * (wand/brush/SAM) read synchronously. Coalesces rapid changes. */
933
- private armReadback;
934
- /** Build the coordinate transform + tool hosts for the current viewer (called from plot()). The
935
- * pixel tools read displayed pixels synchronously from the last readback and convert pointer
936
- * coords via the napari camera, exactly mirroring the OSD host. */
937
- private buildToolHosts;
938
- private zoomBoxHost;
939
- /** Zoom/pan the camera to fit a data-space rectangle `[xMin, xMax, yMax, yMin]`. */
940
- private applyZoomToBox;
941
- /** Build CachedImageData from the most recent readback (RGBA device pixels → [y][x]=[r,g,b]),
942
- * with ratios/origin mapping image coords ↔ readback pixels. Cached until the readback changes. */
943
- private cachedImageData;
944
- setWandMode(active: boolean, options?: IWandOptions): void;
945
- setWandOptions(options: IWandOptions): void;
946
- clearActiveWandRegion(): void;
947
- setBrushMode(active: boolean, options?: IBrushOptions): void;
948
- setBrushOptions(options: IBrushOptions): void;
949
- setVertexEraserMode(active: boolean): void;
950
- setVertexEraserRadius(radius: number): void;
951
- setZoomToBoxMode(active: boolean): void;
198
+ /** napari-js has the navigator and image smoothing too (its 2D views). */
199
+ getOsdViewOptions(): IOsdViewOptions;
200
+ private readonly viewOptions;
201
+ /** The 3D decimate factor (the 3D types' Resolution control). */
202
+ getVolumeResolution(): IVolumeResolution;
203
+ private readonly volumeResolution;
204
+ /** Where the camera settled, for the intensity inset's re-sampling. */
205
+ getIntensitySampling(): IIntensityViewportSource;
206
+ private readonly viewportSource;
207
+ protected beforeToolChange(next: CanvasToolId | null): boolean;
952
208
  segmentRectangles(): Promise<number>;
953
209
  segmentRectanglesCellpose(): Promise<number>;
954
210
  setSamModel(id: string): void;
955
- setSamPointMode(active: boolean): void;
956
- commitSamPoints(): void;
957
- clearSamPoints(): void;
958
- ensureIntensitySampling(_imageInfo: IImageInfo, _zIndex: number): Promise<void>;
959
- refreshIntensitySamplingForRoi(_x: number, _y: number, _width: number, _height: number, _zIndex: number): void;
960
- getViewportChange$(): Observable<{
961
- x: number;
962
- y: number;
963
- width: number;
964
- height: number;
965
- }>;
966
211
  getRegionOverlay(): IRegionOverlay | null;
967
212
  getIsosurfaceControls(): IIsosurfaceControls | null;
968
213
  getIntensityControls(): IIntensityControls | null;
969
214
  getSurface3dControls(): ISurface3dControls | null;
970
215
  getHistogram(channelIndex: number, bins: number): IHistogram | null;
971
216
  getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
972
- /** Fetch + cache one channel's native-bit-depth histogram from `GET /histogram` (>8-bit). */
973
- private fetchNativeHistogram;
974
- /** Per-channel histogram of the displayed RGB composite (R/G/B byte), from the last readback. */
975
- private rgbHistogram;
217
+ /** Save the displayed composite as a PNG. Through file-saver, which (unlike revoking an object
218
+ * URL straight after `a.click()`) does not race the browser's download. */
976
219
  exportComposite(): void;
977
220
  /** Native-bit-depth (16/32-bit) multi-band TIFF export via the server `/export/tiff` endpoint —
978
221
  * the displayed PNG is an 8-bit figure, this preserves the true pixel values. Visible channels
979
222
  * only (omitted when all are visible → server default). Mirrors the OSD backend. */
980
223
  exportData(): Promise<void>;
981
224
  unsubscribe(): void;
982
- static ɵfac: i0.ɵɵFactoryDeclaration<NapariVisualizerService, [null, null, null, null, null, null, null, null, null, null, { optional: true; }, null, null, { optional: true; }, null]>;
225
+ static ɵfac: i0.ɵɵFactoryDeclaration<NapariVisualizerService, [null, null, null, null, null, null, null, { optional: true; }, null, null, { optional: true; }, null]>;
983
226
  static ɵprov: i0.ɵɵInjectableDeclaration<NapariVisualizerService>;
984
227
  }
985
228
  export {};