@jax-data-science/sci-image-visualizer 0.8.3 → 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 +358 -4218
  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 -34467
  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 -883
  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,713 +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
- /** Image tiles in flight, and the scene they belong to: a fetch that outlives {@link reset}
193
- * settles against the old generation and leaves the new scene's count alone. */
194
- private imageTilesLoading;
195
- private imageTilesGeneration;
196
- /** Monotonic load generation. Bumped by {@link reset} and {@link cancelLoading}; the frame-loading
197
- * loops (volume assembly, surface preload) capture it and bail when it changes, so a Cancel (or a
198
- * new plot) actually stops fetching frames instead of running to completion in the background. */
199
- private loadToken;
200
- /** Decimate factor for the napari 3D types (1 = Full, 2 = ½ default, 4 = ¼, 8 = ⅛). Applied when a
201
- * volume/isosurface/surface (re)loads; changing it needs a re-plot (it changes fetched data). */
202
- private resolutionScale;
203
- /** 3D coordinate-axes / scale gizmo for the volume/isosurface view (null in 2D). */
204
- private axesLayer;
205
- /** DOM X/Y/Z + scale labels tracking the 3D axes gizmo (null in 2D). */
206
- private axesLabels;
207
- /** Draggable Z-height grip over the volume (null unless a volume/isosurface is mounted). */
208
- private zHandle;
209
- /** User Z-height factor for the volume (1 = the volume's natural proportions); driven by the
210
- * in-view drag handle. Reset per mount. */
211
- private volumeZScale;
212
- /** Volume world box at `volumeZScale = 1` (base) + the sampled voxel depth — enough to recompute
213
- * the Z-axis voxel scale, axes depth, and overlay anchors as the handle stretches Z. */
214
- private volumeWorldBase;
215
- private volumeSampledDepth;
216
- /** Persisted axes on/off choice, re-applied when a new volume mounts. Defaults on. */
217
- private axesVisible;
218
- private volumeDims;
219
- /** Assembled uint8 volume data per channel (key = channel index), kept for the volume intensity
220
- * histogram. Key 0 holds the grayscale/composite volume in the single-channel case. */
221
- 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). */
222
105
  private imageW;
223
106
  private imageH;
224
- /** Monotonic slice-request id so a slow out-of-order slice fetch can't clobber a newer one. */
225
- private sliceReq;
226
- /** Cached `/tiles/info` pyramid descriptor + the infoB64 it was fetched for. */
227
- private descriptor;
228
- private descriptorKey;
229
- /** How the current 2D image is composited (drives histogram + state application). */
230
- private imageMode;
231
- /** napari-js high-level view that owns the per-channel layer set (build + live display
232
- * updates) for the current {@link imageMode}. Rebuilt on each (re)render. */
233
- private channelView;
234
- /** Live subscription applying channel-state / colormap changes to the layers. */
235
- private displaySub;
236
- /** Latest grayscale colormap selection from the store (applied to the single gray layer). */
237
- private currentColormap;
238
- private currentReverse;
239
- /** Latest invert toggle from the store (flips intensity before the colormap, like OSD). */
240
- private invertEnabled;
241
- /** Physical scale bar overlay for the 2D image (null when 3D or the image has no µm/pixel). */
242
- private scaleBar;
243
- /** Overview minimap (bottom-right), as OSD's navigator. */
244
- private navigator;
245
- /** Whether the navigator is shown — the same host setting OSD's navigator honours. */
246
- private navigatorVisible;
247
- /** Bumped per thumbnail request, so a slow one cannot overwrite a newer slice's. */
248
- private navigatorToken;
249
- /** SVG region-drawing overlay for the 2D image (null until a 2D image is plotted). */
250
- private regionOverlay;
251
- /** Pixel-tool plumbing: the plot div id, coord transform, and bound tool hosts. */
252
- private plotDivId;
253
- private coordTransform;
254
- private wandHost;
255
- private eraserHost;
256
- /** Cached CachedImageData built from the last readback (rebuilt when lastPixels changes). */
257
- private cachedImage;
258
- private cachedImageSource;
259
- /** Visible world rect captured AT the last readback — must pair with `lastPixels` so the pixel
260
- * tools' ratios/origin match the matrix's camera (using the live rect after a pan/zoom would
261
- * mis-scale the region). */
262
- private lastPixelsRect;
263
- /** Image smoothing (bilinear) vs nearest-neighbour (crisp pixels, the default). */
264
- private imageSmoothing;
265
- /** True when the 2D image is rendered via pyramidal TiledSources (descriptor available). */
266
- private tiled;
267
- /** Debounced readback timer + camera-change unsubscribe (keep lastPixels current for tools). */
268
- private readbackTimer;
269
- private cameraReadbackOff;
270
- /** Coarse per-channel luminance sample (keyed by channel index) for the histogram in tiled mode,
271
- * where the layers have no full in-memory pixels. Refreshed on plot + slice change. */
272
- private readonly histSamples;
273
- /** Native-bit-depth histograms from `/histogram`, keyed `${z}|${channel}` (>8-bit images). */
274
- 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;
275
111
  private readonly stackLoading$;
276
112
  private readonly stackLoadingProgress$;
277
113
  private readonly autoscaleEvent$;
278
- private readonly intensityProfile$;
279
114
  private readonly viewportChange$;
280
- 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);
281
- /**
282
- * Fetch + cache the server pyramid descriptor (`GET /tiles/info`): the REAL per-level tile grid,
283
- * tile size, channel metadata and physical pixel size. The backend returns 202 while the source
284
- * is still caching, so we poll briefly. Cached per `infoB64`; returns null if it never becomes
285
- * ready (callers fall back to a single-tile fetch). This is the authoritative grid — guessing
286
- * level dims from `trueImageSize` overshoots the real grid and the server 400s out-of-range tiles.
287
- */
288
- private ensureDescriptor;
289
- /**
290
- * Fetch a COMPLETE rendered slice as an `ImageBitmap` by stitching the server's REAL tile grid
291
- * (from `/tiles/info`) — not just the top-left tile, which only ever showed a large image's
292
- * corner. Picks the finest pyramid level whose grid fits `budgetTiles` and whose longest side is
293
- * within the GPU texture limit, fetches that grid concurrently, and stitches it into one canvas.
294
- *
295
- * `channel` selects a single band as grayscale (real levels only); omit for the server composite.
296
- * `budgetTiles` caps the grid: the 2D view uses the full budget for detail; the 3D volume passes
297
- * 1 for a cheap overview tile per slice (it downsamples to {@link VOLUME_MAX_SLICE}). Falls back
298
- * to a single `col=0,row=0` tile when no descriptor is available (small/simple images, volumes).
299
- */
300
- private fetchSlice;
301
- load(imageInfo: IImageInfo, zIndex: number): Promise<NapariLoaded>;
302
- plot(plotDiv: string, imageLoaded: unknown, imageInfo: IImageInfo, screenHeight: number, plotType: PlotType, _inPlace?: boolean): Promise<boolean>;
303
- /** The grayscale display colormap from the store selection (+reverse), defaulting to gray.
304
- * Maps the jit-ui store colormap node to a napari `Colormap` via the library's LUT factory;
305
- * the multichannel tint ramps are built inside {@link MultiChannelImageView} from each
306
- * channel's hex colour. */
307
- private grayscaleColormap;
308
- /** Fetch a stitched slice and read it back as a single-channel uint8 plane. `channel` selects a
309
- * band (multichannel); omit it for the grayscale composite (all overview levels available, so a
310
- * large image picks a fitting downscaled level rather than only the full-res real level). */
311
- private fetchChannelData;
312
- /** Decode an `ImageBitmap` (server bands are grayscale, R=G=B) to a single-channel uint8 plane.
313
- * `maxSide` caps the longest side (downscaling on the canvas draw) — used to keep pre-loaded
314
- * surface slice planes small. */
315
- private bitmapToLuminance;
316
- /**
317
- * Render the 2D image for slice `z`. With a server pyramid descriptor we use a pyramidal
318
- * {@link TiledSource} per layer so the view refines to higher resolution on zoom (like OSD) and
319
- * sits naturally in full-resolution coordinates; without one we fall back to the single-level
320
- * stitch. Three display modes either way: multichannel additive tint, grayscale colormap, RGB.
321
- */
322
- private renderImage;
323
- /** Single-level stitch fallback (no descriptor): the pre-tiling path. */
324
- private renderImageStitched;
325
- /**
326
- * Render the 2D image with pyramidal {@link TiledSource}s — the view refines to higher resolution
327
- * as you zoom in (the visual fetches the level whose texels ≈ screen pixels) and sits in full-res
328
- * coordinates so regions align. Same three modes as the stitch path. Per-channel layers use the
329
- * REAL pyramid levels (per-channel tiles only exist there); the composite uses all levels.
330
- */
331
- private renderImageTiled;
332
- /** Build a pyramidal TiledSource backed by the server `/tile` endpoint. `channel` selects a band
333
- * (grayscale luminance, real levels only); omit it for the composite (RGBA, all levels).
334
- * `scene` is the generation of the render that asked for it, taken before that render's awaits. */
335
- private buildTiledSource;
336
- /** (Re)fetch a coarse per-channel luminance sample for the histogram (tiled mode has no full
337
- * in-memory pixels). One cheap overview tile per channel; cached by channel index. */
338
- private refreshHistogramSamples;
339
- /** Subscribe channel states + grayscale colormap → live-apply to the rendered layers (no
340
- * re-fetch; only z changes re-fetch). Replaces any prior subscription. */
341
- private subscribeDisplayState;
342
- /** Subscribe the store colormap (+reverse), invert, and channel state → the volume/isosurface
343
- * transfer function: colour (channel tint or selected colormap), the intensity **window
344
- * (min/max → contrastLimits)** and **gamma**, mirroring the grayscale image's display controls
345
- * so the histogram pane drives the 3D render. Replaces any prior subscription. */
346
- private subscribeVolumeDisplayState;
347
- /** A channel's tint colormap (black→colour) with reverse-scale / invert applied by flipping. */
348
- private channelTintColormap;
349
- /**
350
- * Colour map for the volume/isosurface. A real colormap selection (viridis/magma/…) wins;
351
- * otherwise the channel's colour tints it (so the channel-dialog colour swatch recolors the 3D
352
- * render). Reverse-scale and invert each flip the ramp — the `VolumeLayer` has no per-layer
353
- * invert, so both are emulated by reversing the colormap.
354
- */
355
- private volumeColormap;
356
- /** Apply the current channel states / colormap to the live layers (no re-fetch), delegating the
357
- * per-channel layer mutations to the {@link MultiChannelImageView}. */
358
- private applyDisplayState;
359
- /** (Re)install the physical scale bar over the 2D image, sized from the image's µm/pixel
360
- * (`/tiles/info` mppX, falling back to the image metadata). No-op without a physical size. */
361
- private installScaleBar;
362
- /**
363
- * The overview navigator for a 2D view with an image: a coarse thumbnail of the whole
364
- * image with the viewport on it; click or drag to pan at the current zoom (as OSD).
365
- */
366
- private showLoading;
367
- private installNavigator;
368
- /**
369
- * Draw the navigator's thumbnail from the coarsest pyramid level. A multichannel image
370
- * is composited from its channels in their display colours, so the overview looks like
371
- * the view rather than like channel 0 in grey.
372
- */
373
- 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;
374
131
  /** Show/hide the overview navigator (same setting as OSD's). */
375
132
  setNavigatorVisible(visible: boolean): void;
376
- /** Convert a napari-js `Histogram` (bin count + min/max) to the pane's `IHistogram` (bin edges). */
377
- private toIHistogram;
378
- /**
379
- * Mount the 3D volume/isosurface. A multichannel image becomes one additive, tinted
380
- * {@link VolumeLayer} per channel (so each channel's colour composites into the render); a
381
- * grayscale/composite image uses a single volume. Adds the axes gizmo + labels and wires the
382
- * display-state subscription. The caller owns `viewer.ready`.
383
- */
384
- private mountVolume;
385
- /**
386
- * Restretch the volume's Z height live (driven by the in-view {@link NapariVolumeZHandle}). Only
387
- * the per-axis `voxelSize` / axes depth change — the voxel textures are untouched — so dragging is
388
- * smooth. `factor` is relative to the volume's natural proportions (1). Persists across re-mounts
389
- * (resolution changes) so the chosen height sticks.
390
- */
391
- private setVolumeZScale;
392
- /** Build the X/Y/Z axis-end label specs for the 3D gizmo. Anchors are in the volume's centred
393
- * world box (matching the AxesLayer geometry); the scale text reflects the FULL image extent —
394
- * physical µm when µm/pixel is known, else pixel (X/Y) / slice (Z) counts. */
395
- private buildAxesLabels;
396
- /**
397
- * The image's declared extent in pixels/slices, and its physical spacing per
398
- * axis in µm (0 = undeclared, and then that axis reads in pixels).
399
- *
400
- * One place, because the volume world box and the axis labels have to agree
401
- * about what the image's real dimensions are — the sampled grid is decimated and
402
- * says nothing about either.
403
- */
404
- private imageExtent;
405
- /**
406
- * Assemble a downsampled uint8 volume (luminance) from the per-slice tile endpoint. Slices are
407
- * fetched with bounded concurrency (keeps the connection pool full without flooding it on a deep
408
- * stack) and read into the volume as each arrives, driving {@link stackLoadingProgress$} so the
409
- * host shows a determinate progress bar instead of a bare spinner.
410
- */
411
- private assembleVolume;
412
- /**
413
- * Mount the NAPARI_SCATTER 2D scatter: the slice image with a points layer at each region's
414
- * centroid (napari-js analog of Plotly's region-centroid scatter). Rebuilds the points live as
415
- * regions change.
416
- */
417
- private mountScatter;
418
- /** (Re)build the 2D scatter's point layer at the current region centroids. */
419
- private rebuildScatterPoints;
420
- /** Region centroids as flat `[x, y, …]` data coords (rectangle / polygon / multipolygon). */
421
- private regionCentroids;
422
- /**
423
- * The interaction stack every 2D mode needs: the region overlay (draw/select/edit), the pixel
424
- * tools that read back displayed pixels (wand, brush, vertex eraser, zoom-to-box, SAM/cellpose),
425
- * and a camera hook that keeps that readback current as the view pans/zooms and tiled levels
426
- * load.
427
- *
428
- * Extracted because forgetting it is invisible: the toolbar gates its region buttons on 2D-vs-3D
429
- * rather than on plot type, so a 2D mode that skips this shows every tool and silently does
430
- * nothing. That is exactly what happened to the spatial and region-centroid scatter modes.
431
- */
432
- private install2dInteraction;
433
- /** Marker radius (image px) for a dataset that declares none — segmented cells often don't. */
434
- private static readonly SPATIAL_FALLBACK_RADIUS;
435
- /** Smallest marker DIAMETER, in slice pixels, over a volume-backed dataset. A cell's real
436
- * size is honoured wherever it survives the grid: the ABC atlas serves 5 µm radii on a
437
- * 40 µm/px template, so drawing them to scale would put every cell a fifth of a pixel wide
438
- * and the section would come up empty. The point-size control scales up from this floor. */
439
- private static readonly SPATIAL_SLICE_MIN_DIAMETER_PX;
440
- /** Longest side of the gene-map raster, in field pixels. A gene map is a smooth
441
- * field read as territory, so it gains nothing from matching a 2 Gpx slide's
442
- * resolution — and the estimate costs one pass over this many pixels. */
443
- private static readonly GENE_MAP_MAX_SIDE;
444
- /** Kernel σ in field pixels at smoothing 1: wide enough to read between cells,
445
- * tight enough to keep a nucleus-scale structure distinct. */
446
- private static readonly GENE_MAP_SIGMA;
447
- /** Clusters drawn as density volumes at once. Past a handful, additive translucent
448
- * clouds stop being separable by eye — and each one is a full rasterisation. */
449
- private static readonly DENSITY_MAX_CLUSTERS;
450
- /** Colour for observations when nothing is selected to colour by: visible, neutral, and
451
- * obviously not encoding anything. */
452
- /** How much larger a selected marker is drawn, so a small selection is findable inside a
453
- * 3.7M-point cloud rather than merely brighter. */
454
- private static readonly SPATIAL_SELECTED_SIZE_SCALE;
455
- private static readonly SPATIAL_NEUTRAL_COLOR;
456
- /**
457
- * Mount the SPATIAL_OMICS view: the tissue image with one marker per observation, coloured by
458
- * an annotation column or a gene. The markers rebuild whenever the dataset or the view state
459
- * changes, so switching the colour-by column does not remount the scene.
460
- *
461
- * Sets up the full 2D interaction stack — region overlay, pixel-tool hosts, readback currency —
462
- * exactly as the plain image view does. That is NOT optional here: this mode's selection is
463
- * driven by drawn ROIs, so without the overlay there is no way to make a selection at all.
464
- */
465
- private mountSpatialOmics;
466
- /**
467
- * Whether the 2D observation markers are drawn: when the user wants them, and not while
468
- * cell outlines are on screen — then a cell IS its outline, and a circle on top of it is
469
- * noise. Zoomed out past the outline threshold, the circles stand in for the cells.
470
- */
471
- private spatialPointsVisible;
472
- /**
473
- * The tiled-geometry manager, built on first use. Its host callbacks read this
474
- * service's live state, so it never holds a stale dataset or colormap.
475
- */
476
- private spatialTiles;
477
- /**
478
- * Region drawing for the 3D cloud.
479
- *
480
- * Reuses {@link NapariRegionOverlay} verbatim by handing it a SCREEN-SPACE viewer: the drawn
481
- * shape is a lasso in canvas pixels, so "world" is the canvas and both transforms are identity
482
- * (bar the client→canvas offset). Every existing tool — rectangle, polygon, freehand — therefore
483
- * works in 3D with no new drawing code.
484
- *
485
- * A screen-space shape stops meaning anything the moment the camera moves, so an orbit clears
486
- * the drawn regions. The SELECTION it produced is kept: that is the durable artefact, and the
487
- * highlighted points stay highlighted from every angle.
488
- */
489
- private install3dInteraction;
490
- /** Movement, in screen pixels, under which a press-release is a CLICK and not a
491
- * drag. An orbit or a pan starts the same way, so the two have to be told
492
- * apart by how far the pointer travelled. */
493
- private static readonly CLICK_SLOP_PX;
494
- /** Longest press-release still treated as a click. A long press with the mouse
495
- * held still is more likely an interrupted drag than a selection. */
496
- private static readonly CLICK_MAX_MS;
497
- /** Pointer distance, in screen pixels, that still counts as "on" a marker.
498
- * Generous relative to a 1.5px disc: the cursor is a blunt instrument, and a
499
- * tooltip you have to hunt for is worse than none. */
500
- private static readonly HOVER_RADIUS_PX;
501
- /**
502
- * Cursor tooltip for the spatial views: hover a marker, read its class.
503
- *
504
- * A 34-entry legend cannot be read back from a dot — several classes get
505
- * similar colours, and matching one to a swatch by eye is exactly the task this
506
- * removes. It reports whatever the cloud is CURRENTLY coloured by, so it and
507
- * the legend can never say different things.
508
- *
509
- * Listens on the HOST rather than the canvas so it keeps working over the region
510
- * overlay (an SVG covering the canvas, which would otherwise swallow every
511
- * move), and throttles to one hit-test per animation frame: a pointermove can
512
- * fire far more often than that, and each test is a pass over the cloud.
513
- */
514
- private installSpatialHover;
515
- private removeSpatialHover;
516
- /** Hit-test the last pointer position and show or hide the tooltip. */
517
- private updateHover;
518
- /**
519
- * Select the class of the marker at a client position — the canvas equivalent of
520
- * clicking that class in the panel's legend, and the same selection object, so
521
- * the two controls cannot produce different results.
522
- *
523
- * Clicking a class that is already the whole selection CLEARS it, which is what
524
- * the legend does. Compared against the selection itself rather than against a
525
- * remembered click, so selecting from the legend and then clicking the same
526
- * class on the canvas still toggles.
527
- */
528
- private selectClassAt;
529
- /**
530
- * Which observation is under the cursor.
531
- *
532
- * In 3D this defers to napari-js's {@link nearestProjectedIndex} WITH the depths the
533
- * projection produced, so the front-most candidate wins. That matters more than it
534
- * sounds: the renderer depth-tests the billboards, and in a 3.7M-point cloud the cursor
535
- * covers many of them — picking the one nearest the cursor's centre regularly names a
536
- * cell that something else is drawn over, which reads as a wrong tooltip rather than as
537
- * a subtlety of picking.
538
- *
539
- * In 2D the positions are WORLD coordinates on one plane, so there is no depth to break
540
- * ties with and the existing nearest-marker rule is the right one.
541
- */
542
- private pickObservation;
543
- /**
544
- * Positions to hit-test against, rebuilt only when the scene or camera moved.
545
- *
546
- * A pass over 3.7M observations is not something to do per pointermove, and the
547
- * cloud does not move between frames unless something says it did.
548
- */
549
- private hoverPositionsFor;
550
- /**
551
- * The 2D markers' WORLD positions, indexed by observation, NaN for any not on
552
- * the displayed plane — the same affine and the same subset the marker layer was
553
- * built from, so the tooltip cannot point at a cell that is not drawn.
554
- */
555
- private hoverWorldPositions;
556
- /**
557
- * What the tooltip says, resolved once per colour source rather than per hover.
558
- *
559
- * Fetched separately from the colouring on purpose: the reference port caches
560
- * columns, but a host's need not, and re-fetching a 3.7M-element vector because
561
- * the pointer moved would be indefensible either way.
562
- */
563
- private resolveHoverSource;
564
- /**
565
- * Project every observation to canvas pixels under the current 3D camera.
566
- *
567
- * The projection itself is the renderer's: `viewer.projectPoints` owns the camera, the
568
- * viewport in CSS pixels, the perspective divide and the y-flip. This used to be fifteen
569
- * lines of column-major matrix arithmetic here, duplicating a second copy in
570
- * `napari-axes-labels` — and the two had drifted on what to do with a NaN w.
571
- *
572
- * What is left is the part that is genuinely this adapter's: SCATTERING the drawn subset
573
- * back into observation order. The cloud holds only the points of the displayed section,
574
- * in its own packing; every consumer indexes by observation. NaN stands for "not on
575
- * screen", which is also the right answer for an observation whose section is hidden.
576
- *
577
- * Null when the 3D cloud is not mounted, so the caller falls back to the 2D affine path.
578
- */
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. */
579
135
  getSpatialScreenProjection(obs: SpatialObservations): Float32Array | null;
580
- /** Rebuild the markers on any dataset or view-state change. */
581
- private subscribeSpatial;
582
- /** (Re)build the observation marker layer for the current dataset + view state. */
583
- private rebuildSpatialPoints;
584
- /**
585
- * Tell the region overlay how finely a drawn vertex may be placed.
586
- *
587
- * Region geometry is stored in whole world units, which is right when the world IS
588
- * pixels — a region should align to them. It is wrong for a dataset that registers onto
589
- * no image: seqFISH's observations span about 5 x 7 units in total, so whole-unit
590
- * vertices leave roughly six by eight placeable positions across the entire sample and
591
- * an ROI cannot be drawn at any zoom. Nothing errors; the tool just cannot express the
592
- * shape.
593
- *
594
- * Keyed on whether the dataset brings PIXELS rather than on the extent, because the
595
- * extent cannot tell the two apart — 2,000 units is a small slide or a large section
596
- * depending only on what the units are, and only the dataset knows.
597
- */
598
- private setRegionGridFor;
599
- /**
600
- * Frame the 2D camera on the observations, for a dataset that brings no image.
601
- *
602
- * The 2D camera is normally fitted to the IMAGE, because the observations are in that
603
- * image's pixel space and framing the image frames them too. A dataset with no
604
- * reference image has coordinates in its own units instead — seqFISH's span about
605
- * 5x7 — so the image framing left over from whatever was on screen before puts the
606
- * whole cloud offscreen: measured at 9.7 x 13.4 PIXELS, centred 256px from where the
607
- * camera was looking. The points are all there and drawn; they are a speck. Which
608
- * looks exactly like the dataset having failed to load.
609
- *
610
- * Once per dataset, as napari-js's `fit3d: 'once'` does for the cloud: re-colouring,
611
- * slicing or picking a gene re-adds this layer, and re-framing on those would move
612
- * the camera under the user — the camera tools and the canvas drag are meant to be
613
- * the only things that do.
614
- */
615
- /**
616
- * Hide the image layer for a dataset that brings no image of its own.
617
- *
618
- * The host's viewer keeps whatever image was last loaded, and for a dataset that
619
- * registers onto none that picture belongs to something else entirely — the example's
620
- * default slide, say. It is not merely irrelevant: the two live in different coordinate
621
- * spaces (image pixels against the embedding's own units), so the leftover is magnified
622
- * roughly a hundredfold. At the fitted zoom the camera sits inside its corner, where it
623
- * reads as blank background, and it appears only once you zoom out far enough to find
624
- * it — which is exactly how it gets noticed.
625
- *
626
- * Hidden rather than removed, and hidden HERE rather than by clearing the host's image
627
- * state: that state drives the whole render pipeline, including a Plotly backend whose
628
- * fields are declared with definite-assignment assertions, so emptying it throws from
629
- * whichever field the next path happens to read. This touches one layer's visibility
630
- * and nothing else.
631
- */
632
- private hideForeignImage;
633
- private frameSpatialPointsOnce;
634
- /**
635
- * The **gene map**: the active gene's expression as a continuous field drawn under
636
- * the cells.
637
- *
638
- * A scatter coloured by a gene says which cells express it; it cannot say where,
639
- * because the eye will not integrate thousands of dots into a territory. The field
640
- * is a kernel-weighted MEAN per cell (see `spatial-expression.ts`), so a dense
641
- * region does not glow merely for being dense, and it is transparent wherever no
642
- * cell was measured — an unsampled gap must not read as "not expressed".
643
- *
644
- * It shares the points' LUT, percentile window and log flag, so the layer under
645
- * the cells and the cells themselves cannot disagree about what a colour means.
646
- *
647
- * Estimated on the DISPLAYED image's pixel grid, coarsened so the long side is at
648
- * most {@link GENE_MAP_MAX_SIDE}: a smooth field gains nothing from a slide's full
649
- * resolution. For a volume-backed dataset that grid is the current slice, and only
650
- * that plane's observations are included — the same rule the markers follow.
651
- */
652
- private ensureGeneMap;
653
- /**
654
- * The plane a volume-backed dataset is currently showing: its pixel affine, the
655
- * observations that fall in it, and the marker floor that grid needs.
656
- *
657
- * Null for a dataset with a real `imageRef` (its coordinates are already the
658
- * image's pixels and every observation belongs to the one section) and for one
659
- * with no volume at all — both of which draw exactly as before.
660
- */
661
- private spatialSlab;
662
- /** Per-point colours for the drawn subset. A broadcast tuple stays broadcast —
663
- * it is one colour for every point either way. */
664
- private gatherColors;
665
- /**
666
- * Redraw the observation markers over a freshly rendered image.
667
- *
668
- * Two reasons, both invisible from the spatial store — which is why a scrub or a
669
- * re-render never reached the markers on its own:
670
- * - the image render CLEARS the layer list, taking the markers with it;
671
- * - over a volume-backed dataset the displayed plane decides which
672
- * observations belong on screen at all, so the cells have to move with the
673
- * section rather than hang over a different one.
674
- *
675
- * Uses the latest values the marker subscription saw; a no-op until it has seen
676
- * any, in the 3D cloud (no image, no plane), and with no dataset to draw.
677
- */
678
- private redrawSpatialMarkers;
679
- /**
680
- * Mount the SPATIAL_OMICS_3D view: observations as a 3D point cloud under the orbit camera.
681
- *
682
- * Deliberately much thinner than the 2D mount. There is no tissue image to render (a registered
683
- * volume like the Allen CCF has no single reference plane), so no scale bar, no readback, and no
684
- * 2D interaction stack — the region tools draw in screen space and have no meaning against an
685
- * orbiting camera, which is why `Select from ROIs` is hidden in this mode. `addPoints3D` puts
686
- * the viewer in 3D and frames the camera on the cloud itself.
687
- */
688
- private mountSpatialOmics3d;
689
- /**
690
- * Scale bar for the 3D cloud, measured at the ORBIT PIVOT.
691
- *
692
- * A perspective camera has no single scale — things farther away are smaller — so a bar can
693
- * only be true at one depth. The pivot is the honest choice: it is what the camera is framing,
694
- * what a zoom moves towards, and where the eye is anyway. napari's own 3D scale bar works the
695
- * same way.
696
- *
697
- * `NapariScaleBar` needs CSS px per world unit, which an orbit camera does not expose, but at
698
- * the pivot it is exactly `viewportHeight / (2 * distance * tan(fov / 2))` — the same
699
- * relationship `Camera3D.pan` uses to track the cursor. The bar then converts through
700
- * `micronsPerUnit`, and draws nothing at all when the dataset does not declare one, because a
701
- * bar labelled in microns over unknown units would read as a measurement.
702
- */
703
- private installSpatial3dScaleBar;
704
- /** Base marker diameter for the 3D cloud, in SCREEN pixels (the layer's unit). */
705
- private static readonly SPATIAL_3D_BASE_SIZE;
706
- /** (Re)build the 3D point cloud for the current dataset + view state. */
707
- private rebuildSpatialPoints3d;
708
- /**
709
- * The **3D gene map**: the active gene's expression over the whole sectioned
710
- * specimen, as one raymarched volume.
711
- *
712
- * Two things it can be, and the panel's `Volume rendering` toggle picks which:
713
- *
714
- * - **sheets** — exactly the planes that were imaged, each carrying that
715
- * slide's own 2D gene map, with the gaps between sections empty. A stack of
716
- * measured fields, at their true z.
717
- * - **volume** — the same fields smoothed along z, so the planes between the
718
- * sections carry an interpolated value. An estimate, and drawn as a
719
- * translucent cloud for the same reason the density volumes are.
720
- *
721
- * One `VolumeLayer` rather than a textured quad per section: an `ImageLayer`
722
- * renders only at `ndisplay === 2`, so 53 sheets in the orbit view would need a
723
- * new layer type upstream — while a scalar volume whose z sampling already IS
724
- * the section spacing expresses the sheets exactly, and the same lattice then
725
- * gives the interpolated version for free.
726
- *
727
- * Estimated on the reference volume's own lattice (`densityGrid` at stride 1),
728
- * so the field lands voxel-for-voxel on the anatomy and needs no offset — a
729
- * `VolumeLayer` has no translate, and napari centres both boxes on the world
730
- * origin.
731
- */
732
- private ensureGeneMapVolume;
733
- /**
734
- * Cluster density volumes: each cluster rasterised into a smooth scalar field and
735
- * raymarched alongside the cloud, tinted with the cluster's own legend colour.
736
- *
737
- * This is what makes a serially sectioned dataset readable as an anatomical
738
- * distribution. The cloud shows measured cells and nothing else — but at 200 µm
739
- * section spacing the eye cannot integrate a stack of discs into a shape, and
740
- * every gap reads as absence. A density field is a different object from a cell:
741
- * an estimate, defined between the imaged planes, drawn as a translucent cloud so
742
- * it cannot be mistaken for measurement. Individual cells are never interpolated —
743
- * consecutive sections sample different cells, so there is nothing to interpolate
744
- * along.
745
- *
746
- * One volume per cluster rather than one for everything: additive blending is what
747
- * makes two clusters' territories comparable, and a single blended field would
748
- * answer no question anyone asks of a taxonomy. Capped at
749
- * {@link DENSITY_MAX_CLUSTERS} by cell count.
750
- *
751
- * Keyed so it rebuilds only when the field would actually differ — the dataset,
752
- * the colour column, the bandwidth, or the selection.
753
- */
754
- private ensureDensityVolumes;
755
- /**
756
- * Identity of the colour scale a continuous spatial layer will draw with, for a
757
- * cache key: the explicit choice, or else the display colormap and its reverse
758
- * flag, since that is what {@link spatialContinuousLut} falls back to.
759
- *
760
- * The gene maps cache their coloured output, so without this in the key a change
761
- * of colour scale left the field on screen in the previous colours — the markers
762
- * recoloured and the map under them did not.
763
- */
764
- private continuousColormapKey;
765
- /**
766
- * A revision number for a selection object.
767
- *
768
- * The store hands out a NEW mask object per change, so object identity is the
769
- * cheap and exact way to tell two selections apart — a fingerprint over 3.7M
770
- * mask bytes would be neither. Counting revisions keeps the cache key a short
771
- * string.
772
- */
773
- private selectionRev;
774
- /**
775
- * The clusters to rasterise: the categories of the active categorical colouring,
776
- * biggest first and capped, each with its legend colour.
777
- *
778
- * Restricted to the current selection when there is one, so "select a region,
779
- * check the box" answers which clusters live there. With no categorical colouring
780
- * there is one group — total cell density, which is a real question on its own
781
- * ("where is the tissue dense?") and the honest thing to show when the view is
782
- * not encoding a taxonomy.
783
- */
784
- private densityGroups;
785
- /**
786
- * Add (or keep) the dataset's reference volume, and derive the offset that sits the
787
- * observations inside it.
788
- *
789
- * `VolumeLayer` has no translate: napari-js maps the volume's unit cube to a world box
790
- * **centred on the origin**, sized `dims x voxelSize`. The observations, by contract, are in
791
- * the volume's own frame with its near corner at the coordinate origin. So the two only line
792
- * up if the POINTS move — by half the box — which is what {@link spatialOrigin3d} is.
793
- *
794
- * A failed or absent volume is not fatal: the cloud renders on its own, at its own
795
- * coordinates, and the camera frames the points instead.
796
- */
797
- private ensureSpatialVolume;
798
- private removeSpatial3dLayers;
799
- /** A one-colour colormap, for the "nothing to colour by" state. */
800
- private spatialFlatColormap;
801
- /**
802
- * The per-point scalar + colormap + window that colour the 3D cloud.
803
- *
804
- * Continuous data is the natural fit: values go straight through the active colormap with the
805
- * same percentile window the 2D path uses. Categorical data has to be smuggled through the same
806
- * scalar channel — see {@link SPATIAL_3D_MAX_CATEGORIES}. Codes map to LUT blocks, and
807
- * `contrastLimits` of `[-0.5, K - 0.5]` puts code `i` at the centre of block `i`, which is what
808
- * makes the round-trip exact instead of approximately right.
809
- */
810
- private spatialScalar3d;
811
- /** Category codes → a stepped LUT, exact for up to {@link SPATIAL_3D_MAX_CATEGORIES}. */
812
- private encodeSpatial3dCategorical;
813
- /** Continuous values → the active colormap over a percentile-clipped window. */
814
- private encodeSpatial3dContinuous;
815
- /**
816
- * Per-observation colours for the current view state, or a single flat colour when nothing is
817
- * selected to colour by. Categorical columns use the column's own palette; continuous columns
818
- * and gene vectors go through the active colormap with a percentile-clipped window.
819
- */
820
- private spatialFaceColors;
821
- /** Continuous values → RGBA through the active colormap and a clipped window. */
822
- private encodeSpatialContinuous;
823
- /**
824
- * Mount the NAPARI_SCATTER3D 3D scatter: the downsampled voxel grid as a 3D point cloud colored
825
- * by intensity (napari-js analog of Plotly's voxel scatter3d). Assembles a coarse volume, then
826
- * emits a flat-strided sample of voxels (capped at {@link SCATTER3D_MAX_POINTS}) via `addPoints3D`.
827
- */
828
- private mountScatter3d;
829
- /** Store colormap / reverse / invert / channel window → the 3D scatter's colormap + contrast. */
830
- private subscribeScatter3dDisplayState;
831
- /**
832
- * Mount the NAPARI_SURFACE height-field surface. A height field is single-scalar, so for a
833
- * multichannel image the surface follows ONE band — the first visible channel (fallback 0) —
834
- * coloured by that channel's window/colormap (like the Plotly SURFACE, which is grayscale-only).
835
- * Pre-loads every slice's height data with a progress bar (as the volume does) so the stack
836
- * slider re-slices instantly, then builds the mesh for the current slice. All mesh + GPU work
837
- * lives in napari-js (`heightField` + `Viewer.addSurface`); this backend supplies scalar slices.
838
- */
839
- private mountSurface;
840
- /** Add the 3D axes gizmo + DOM labels around the (origin-centered) surface mesh, matching the
841
- * volume/isosurface. Installed once per mount; the box tracks the mesh bounds, X/Y show the
842
- * physical (or pixel) extent, and Z is the intensity/height axis. */
843
- private installSurfaceAxes;
844
- /** X/Y/Z end-labels for the surface gizmo: X/Y are the physical (µm) or pixel extent of the FULL
845
- * image; Z is the intensity/height axis. Anchors are in the centered box (matching AxesLayer). */
846
- private buildSurfaceAxesLabels;
847
- /**
848
- * Pre-fetch every stack slice's luminance plane (decimated to the surface grid) into
849
- * {@link surfacePlanes}, driving {@link stackLoadingProgress$} — the same load-with-progress UX
850
- * as the volume, but keeping one 2D plane per slice rather than packing a 3D volume. Bounded
851
- * concurrency keeps the connection pool busy without flooding it on a deep stack.
852
- */
853
- private preloadSurfacePlanes;
854
- /**
855
- * Fetch slice `z` as a single WHOLE-image luminance plane (decimated to `maxGrid`). Prefers the
856
- * app's complete per-slice image (`smallUrls`/`urls`, exactly like the Plotly surface) so the
857
- * surface always covers the FULL slice — the tile-pyramid `fetchSlice` path would fall back to a
858
- * single top-left tile (a corner) for self-contained / non-`/tiles/info` images. Falls back to
859
- * stitching the tile grid only when no complete-image URL is available.
860
- */
861
- /** Tile budget to stitch a whole slice at ~`targetPx` resolution from the pyramid: a higher target
862
- * pulls a FINER pyramid level (more real detail). Shared by the surface plane fetch and the volume
863
- * assembly so both scale their in-plane resolution with the decimate factor. */
864
- private tileBudgetFor;
865
- private fetchSurfacePlane;
866
- /** The channel state driving the surface: the chosen band for multichannel (matched by index),
867
- * else the single grayscale channel. */
868
- private surfaceState;
869
- /**
870
- * (Re)build the surface mesh for slice `z` from the pre-loaded plane cache (instant — this is
871
- * what the stack slider calls); a slice missing from the cache is fetched on demand. napari-js's
872
- * pure `heightField` builds the triangle grid (z = normalized intensity), then `addSurface`
873
- * renders it. The slice plane also feeds the intensity histogram (key 0).
874
- */
875
- private buildSurface;
876
- /** Subscribe the store colormap / reverse / invert / channel window → the surface, so histogram
877
- * & channel-dialog edits update it live without a re-fetch. **min/max reshapes the surface's
878
- * height** (a pixel's height = its intensity within [min,max]), so a window change rebuilds the
879
- * mesh geometry (from the cached slice); colour-only edits (colormap/LUT, gamma, reverse, invert)
880
- * just update the layer's uniforms. */
881
- private subscribeSurfaceDisplayState;
882
136
  private fitCameraSoon;
883
137
  /** @deprecated Plotly-specific; host re-drives plot() from its image stream. */
884
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
+ */
885
144
  reset(): void;
886
145
  relayout(_trueImageSize?: number[]): void;
887
146
  /** @deprecated Plotly-specific axis reset. */
@@ -890,12 +149,15 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
890
149
  autoscale(): void;
891
150
  zoomIn(): void;
892
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;
893
155
  setDragMode(_mode: string | false): void;
894
156
  setImageSmoothingEnabled(enabled: boolean): void;
895
157
  setShowStack(_showstack: boolean): void;
896
158
  setZIndex(zIndex: number): void;
897
159
  setStackLoading(stackLoading: boolean): void;
898
- /** 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
899
161
  * preload workers stop fetching more frames, and clear the loading flag + progress. */
900
162
  cancelLoading(): void;
901
163
  isStackLoading(): Observable<boolean>;
@@ -913,78 +175,54 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
913
175
  height: number;
914
176
  } | null;
915
177
  downloadImage(): void;
916
- 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;
917
180
  /** Map a Plotly-style 3D drag mode onto napari-js's camera drag mode. */
918
181
  setSurfaceDragMode(mode: string): void;
919
- /** Re-frame the 3D camera on the current 3D layer. A surface mesh sits in the positive octant
920
- * (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. */
921
184
  resetSurfaceCamera(): void;
922
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
+ */
923
192
  getPlotTypeDescriptors(): PlotTypeDescriptor[];
924
193
  /** The napari 3D decimate factor (1 = full … 8 = ⅛). Read by the toolbar to init the control. */
925
194
  getResolutionScale(): number;
926
195
  /** Set the decimate factor for the napari 3D types. Takes effect on the next (re)load — the host
927
196
  * re-plots after calling this, since decimation changes the fetched/assembled data. */
928
197
  setResolutionScale(scale: number): void;
929
- getIntensityProfile$(): Observable<IntensityProfile[]>;
930
- renderIntensityInset(_divId: string, _profiles: IntensityProfile[]): void;
931
- /** Read the displayed composite into `lastPixels` (the pixel-tools' source) + emit the clamped
932
- * visible region. A fresh PixelData object means cachedImageData() rebuilds automatically. */
933
- private runReadback;
934
- private scheduleReadback;
935
- /** Debounced readback — armed on camera changes so `lastPixels` tracks the current view after a
936
- * pan/zoom settles (and after tiled levels finish loading), which the on-canvas pixel tools
937
- * (wand/brush/SAM) read synchronously. Coalesces rapid changes. */
938
- private armReadback;
939
- /** Build the coordinate transform + tool hosts for the current viewer (called from plot()). The
940
- * pixel tools read displayed pixels synchronously from the last readback and convert pointer
941
- * coords via the napari camera, exactly mirroring the OSD host. */
942
- private buildToolHosts;
943
- private zoomBoxHost;
944
- /** Zoom/pan the camera to fit a data-space rectangle `[xMin, xMax, yMax, yMin]`. */
945
- private applyZoomToBox;
946
- /** Build CachedImageData from the most recent readback (RGBA device pixels → [y][x]=[r,g,b]),
947
- * with ratios/origin mapping image coords ↔ readback pixels. Cached until the readback changes. */
948
- private cachedImageData;
949
- setWandMode(active: boolean, options?: IWandOptions): void;
950
- setWandOptions(options: IWandOptions): void;
951
- clearActiveWandRegion(): void;
952
- setBrushMode(active: boolean, options?: IBrushOptions): void;
953
- setBrushOptions(options: IBrushOptions): void;
954
- setVertexEraserMode(active: boolean): void;
955
- setVertexEraserRadius(radius: number): void;
956
- 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;
957
208
  segmentRectangles(): Promise<number>;
958
209
  segmentRectanglesCellpose(): Promise<number>;
959
210
  setSamModel(id: string): void;
960
- setSamPointMode(active: boolean): void;
961
- commitSamPoints(): void;
962
- clearSamPoints(): void;
963
- ensureIntensitySampling(_imageInfo: IImageInfo, _zIndex: number): Promise<void>;
964
- refreshIntensitySamplingForRoi(_x: number, _y: number, _width: number, _height: number, _zIndex: number): void;
965
- getViewportChange$(): Observable<{
966
- x: number;
967
- y: number;
968
- width: number;
969
- height: number;
970
- }>;
971
211
  getRegionOverlay(): IRegionOverlay | null;
972
212
  getIsosurfaceControls(): IIsosurfaceControls | null;
973
213
  getIntensityControls(): IIntensityControls | null;
974
214
  getSurface3dControls(): ISurface3dControls | null;
975
215
  getHistogram(channelIndex: number, bins: number): IHistogram | null;
976
216
  getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
977
- /** Fetch + cache one channel's native-bit-depth histogram from `GET /histogram` (>8-bit). */
978
- private fetchNativeHistogram;
979
- /** Per-channel histogram of the displayed RGB composite (R/G/B byte), from the last readback. */
980
- 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. */
981
219
  exportComposite(): void;
982
220
  /** Native-bit-depth (16/32-bit) multi-band TIFF export via the server `/export/tiff` endpoint —
983
221
  * the displayed PNG is an 8-bit figure, this preserves the true pixel values. Visible channels
984
222
  * only (omitted when all are visible → server default). Mirrors the OSD backend. */
985
223
  exportData(): Promise<void>;
986
224
  unsubscribe(): void;
987
- 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]>;
988
226
  static ɵprov: i0.ɵɵInjectableDeclaration<NapariVisualizerService>;
989
227
  }
990
228
  export {};