@jax-data-science/sci-image-visualizer 0.1.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 (311) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +404 -0
  3. package/esm2022/index.mjs +52 -0
  4. package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
  5. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
  6. package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
  7. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
  8. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
  9. package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
  10. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
  11. package/esm2022/lib/contracts/display-types.mjs +8 -0
  12. package/esm2022/lib/contracts/image.contract.mjs +11 -0
  13. package/esm2022/lib/contracts/intensity.mjs +28 -0
  14. package/esm2022/lib/contracts/plot-type.mjs +112 -0
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
  18. package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
  19. package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
  20. package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
  21. package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
  22. package/esm2022/lib/contracts/sam.contract.mjs +12 -0
  23. package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
  24. package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
  25. package/esm2022/lib/contracts/viz-config.mjs +3 -0
  26. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
  27. package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
  28. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
  29. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
  30. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
  31. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
  32. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
  33. package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
  34. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
  35. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
  36. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
  37. package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
  38. package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
  39. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
  40. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
  41. package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
  42. package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
  43. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
  44. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
  45. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
  46. package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
  47. package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
  48. package/esm2022/lib/models/bezier.mjs +120 -0
  49. package/esm2022/lib/models/class-preset.mjs +46 -0
  50. package/esm2022/lib/models/geometry.mjs +198 -0
  51. package/esm2022/lib/models/region.mjs +166 -0
  52. package/esm2022/lib/models/shape.mjs +53 -0
  53. package/esm2022/lib/plot.utilities.mjs +693 -0
  54. package/esm2022/lib/processing/image-converter.service.mjs +90 -0
  55. package/esm2022/lib/processing/image-crop.mjs +62 -0
  56. package/esm2022/lib/processing/processing-image.mjs +50 -0
  57. package/esm2022/lib/provide-visualization.mjs +63 -0
  58. package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
  59. package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
  60. package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
  61. package/esm2022/lib/region-ops.service.mjs +301 -0
  62. package/esm2022/lib/render-orchestrator.mjs +87 -0
  63. package/esm2022/lib/routing-visualizer.service.mjs +533 -0
  64. package/esm2022/lib/store/class-color.util.mjs +52 -0
  65. package/esm2022/lib/store/region-store.service.mjs +1029 -0
  66. package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
  67. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
  68. package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
  69. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
  70. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
  71. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
  72. package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
  73. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
  74. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
  75. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
  76. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
  77. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
  78. package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
  79. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
  80. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
  81. package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
  82. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
  83. package/esm2022/lib/visualization.module.mjs +162 -0
  84. package/esm2022/lib/visualizer.component.mjs +1597 -0
  85. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
  86. package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
  87. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
  88. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
  89. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
  90. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
  91. package/fesm2022/mask.worker.js +989 -0
  92. package/fesm2022/onnx-sam.worker.js +202 -0
  93. package/index.d.ts +39 -0
  94. package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
  95. package/lib/contracts/capabilities.contract.d.ts +30 -0
  96. package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
  97. package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
  98. package/lib/contracts/colormap-lut.d.ts +21 -0
  99. package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
  100. package/lib/contracts/display-types.d.ts +41 -0
  101. package/lib/contracts/image.contract.d.ts +72 -0
  102. package/lib/contracts/intensity.d.ts +18 -0
  103. package/lib/contracts/plot-type.d.ts +108 -0
  104. package/lib/contracts/ports/image-state.port.d.ts +29 -0
  105. package/lib/contracts/ports/preferences.port.d.ts +19 -0
  106. package/lib/contracts/ports/region-io.port.d.ts +29 -0
  107. package/lib/contracts/ports/tile-access.port.d.ts +27 -0
  108. package/lib/contracts/region-editor-api.contract.d.ts +83 -0
  109. package/lib/contracts/region-overlay.contract.d.ts +47 -0
  110. package/lib/contracts/region-store.contract.d.ts +74 -0
  111. package/lib/contracts/sam.contract.d.ts +98 -0
  112. package/lib/contracts/toolbar-config.d.ts +24 -0
  113. package/lib/contracts/visualizer.contract.d.ts +346 -0
  114. package/lib/contracts/viz-config.d.ts +25 -0
  115. package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
  116. package/lib/implementations/base-store-visualizer.d.ts +71 -0
  117. package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
  118. package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
  119. package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
  120. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
  121. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
  122. package/lib/implementations/osd/display-pipeline.d.ts +47 -0
  123. package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
  124. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
  125. package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
  126. package/lib/implementations/osd/osd-coords.d.ts +16 -0
  127. package/lib/implementations/osd/osd-lib.d.ts +19 -0
  128. package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
  129. package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
  130. package/lib/implementations/osd/slice-cache.d.ts +161 -0
  131. package/lib/implementations/osd/tile-client.d.ts +32 -0
  132. package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
  133. package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
  134. package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
  135. package/lib/implementations/plotly/plotly.service.d.ts +594 -0
  136. package/lib/implementations/simple-slice-access.service.d.ts +64 -0
  137. package/lib/models/bezier.d.ts +59 -0
  138. package/lib/models/class-preset.d.ts +39 -0
  139. package/lib/models/geometry.d.ts +66 -0
  140. package/lib/models/region.d.ts +132 -0
  141. package/lib/models/shape.d.ts +44 -0
  142. package/lib/plot.utilities.d.ts +107 -0
  143. package/lib/processing/image-converter.service.d.ts +28 -0
  144. package/lib/processing/image-crop.d.ts +18 -0
  145. package/lib/processing/processing-image.d.ts +17 -0
  146. package/lib/provide-visualization.d.ts +34 -0
  147. package/lib/region-editor/mask-raster.d.ts +61 -0
  148. package/lib/region-editor/mask-worker.d.ts +7 -0
  149. package/lib/region-editor/region-editor.component.d.ts +305 -0
  150. package/lib/region-ops.service.d.ts +92 -0
  151. package/lib/render-orchestrator.d.ts +59 -0
  152. package/lib/routing-visualizer.service.d.ts +227 -0
  153. package/lib/store/class-color.util.d.ts +26 -0
  154. package/lib/store/region-store.service.d.ts +315 -0
  155. package/lib/store/visualizer-store.service.d.ts +123 -0
  156. package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
  157. package/lib/toolbar/crop/slide-crop.d.ts +30 -0
  158. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
  159. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
  160. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
  161. package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
  162. package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
  163. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
  164. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
  165. package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
  166. package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
  167. package/lib/toolbar/toolbar.component.d.ts +167 -0
  168. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
  169. package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
  170. package/lib/toolbar/wand/wand.service.d.ts +133 -0
  171. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
  172. package/lib/visualization.module.d.ts +45 -0
  173. package/lib/visualizer.component.d.ts +378 -0
  174. package/package.json +73 -0
  175. package/src/lib/assets/3d-coordinates.svg +49 -0
  176. package/src/lib/assets/cells.svg +1 -0
  177. package/src/lib/assets/click.svg +1 -0
  178. package/src/lib/assets/colormap-luts.json +1 -0
  179. package/src/lib/assets/contour.svg +48 -0
  180. package/src/lib/assets/cube-3d.svg +1 -0
  181. package/src/lib/assets/edit-selection-white.svg +47 -0
  182. package/src/lib/assets/heatmap.svg +1 -0
  183. package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
  184. package/src/lib/assets/icons/colormap-accent.png +0 -0
  185. package/src/lib/assets/icons/colormap-afmhot.png +0 -0
  186. package/src/lib/assets/icons/colormap-autumn.png +0 -0
  187. package/src/lib/assets/icons/colormap-berlin.png +0 -0
  188. package/src/lib/assets/icons/colormap-binary.png +0 -0
  189. package/src/lib/assets/icons/colormap-blackbody.png +0 -0
  190. package/src/lib/assets/icons/colormap-bluered.png +0 -0
  191. package/src/lib/assets/icons/colormap-blues.png +0 -0
  192. package/src/lib/assets/icons/colormap-bone.png +0 -0
  193. package/src/lib/assets/icons/colormap-brbg.png +0 -0
  194. package/src/lib/assets/icons/colormap-brg.png +0 -0
  195. package/src/lib/assets/icons/colormap-bugn.png +0 -0
  196. package/src/lib/assets/icons/colormap-bupu.png +0 -0
  197. package/src/lib/assets/icons/colormap-bwr.png +0 -0
  198. package/src/lib/assets/icons/colormap-cividis.png +0 -0
  199. package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
  200. package/src/lib/assets/icons/colormap-cool.png +0 -0
  201. package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
  202. package/src/lib/assets/icons/colormap-copper.png +0 -0
  203. package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
  204. package/src/lib/assets/icons/colormap-dark2.png +0 -0
  205. package/src/lib/assets/icons/colormap-earth.png +0 -0
  206. package/src/lib/assets/icons/colormap-electric.png +0 -0
  207. package/src/lib/assets/icons/colormap-flag.png +0 -0
  208. package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
  209. package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
  210. package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
  211. package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
  212. package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
  213. package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
  214. package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
  215. package/src/lib/assets/icons/colormap-gnbu.png +0 -0
  216. package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
  217. package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
  218. package/src/lib/assets/icons/colormap-gray.png +0 -0
  219. package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
  220. package/src/lib/assets/icons/colormap-greens.png +0 -0
  221. package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
  222. package/src/lib/assets/icons/colormap-greys.png +0 -0
  223. package/src/lib/assets/icons/colormap-hot.png +0 -0
  224. package/src/lib/assets/icons/colormap-hsv.png +0 -0
  225. package/src/lib/assets/icons/colormap-inferno.png +0 -0
  226. package/src/lib/assets/icons/colormap-jet.png +0 -0
  227. package/src/lib/assets/icons/colormap-magma.png +0 -0
  228. package/src/lib/assets/icons/colormap-managua.png +0 -0
  229. package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
  230. package/src/lib/assets/icons/colormap-ocean.png +0 -0
  231. package/src/lib/assets/icons/colormap-oranges.png +0 -0
  232. package/src/lib/assets/icons/colormap-orrd.png +0 -0
  233. package/src/lib/assets/icons/colormap-pastel2.png +0 -0
  234. package/src/lib/assets/icons/colormap-picnic.png +0 -0
  235. package/src/lib/assets/icons/colormap-pink.png +0 -0
  236. package/src/lib/assets/icons/colormap-piyg.png +0 -0
  237. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  238. package/src/lib/assets/icons/colormap-plasma.png +0 -0
  239. package/src/lib/assets/icons/colormap-portland.png +0 -0
  240. package/src/lib/assets/icons/colormap-prgn.png +0 -0
  241. package/src/lib/assets/icons/colormap-prism.png +0 -0
  242. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  243. package/src/lib/assets/icons/colormap-pubugn.png +0 -0
  244. package/src/lib/assets/icons/colormap-puor.png +0 -0
  245. package/src/lib/assets/icons/colormap-purd.png +0 -0
  246. package/src/lib/assets/icons/colormap-purples.png +0 -0
  247. package/src/lib/assets/icons/colormap-rainbow.png +0 -0
  248. package/src/lib/assets/icons/colormap-rdbu.png +0 -0
  249. package/src/lib/assets/icons/colormap-rdgy.png +0 -0
  250. package/src/lib/assets/icons/colormap-rdpu.png +0 -0
  251. package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
  252. package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
  253. package/src/lib/assets/icons/colormap-reds.png +0 -0
  254. package/src/lib/assets/icons/colormap-seismic.png +0 -0
  255. package/src/lib/assets/icons/colormap-set1.png +0 -0
  256. package/src/lib/assets/icons/colormap-set2.png +0 -0
  257. package/src/lib/assets/icons/colormap-set3.png +0 -0
  258. package/src/lib/assets/icons/colormap-spectral.png +0 -0
  259. package/src/lib/assets/icons/colormap-spring.png +0 -0
  260. package/src/lib/assets/icons/colormap-summer.png +0 -0
  261. package/src/lib/assets/icons/colormap-tab10.png +0 -0
  262. package/src/lib/assets/icons/colormap-tab20.png +0 -0
  263. package/src/lib/assets/icons/colormap-tab20b.png +0 -0
  264. package/src/lib/assets/icons/colormap-tab20c.png +0 -0
  265. package/src/lib/assets/icons/colormap-terrain.png +0 -0
  266. package/src/lib/assets/icons/colormap-turbo.png +0 -0
  267. package/src/lib/assets/icons/colormap-twilight.png +0 -0
  268. package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
  269. package/src/lib/assets/icons/colormap-vanimo.png +0 -0
  270. package/src/lib/assets/icons/colormap-viridis.png +0 -0
  271. package/src/lib/assets/icons/colormap-winter.png +0 -0
  272. package/src/lib/assets/icons/colormap-wistia.png +0 -0
  273. package/src/lib/assets/icons/colormap-ylgn.png +0 -0
  274. package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
  275. package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
  276. package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
  277. package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
  278. package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
  279. package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
  280. package/src/lib/assets/invert.svg +1 -0
  281. package/src/lib/assets/isosurface.svg +7 -0
  282. package/src/lib/assets/mask.svg +1 -0
  283. package/src/lib/assets/paintbrush.svg +1 -0
  284. package/src/lib/assets/picture-segmentation.svg +43 -0
  285. package/src/lib/assets/polygon-vertices.svg +13 -0
  286. package/src/lib/assets/polyline.svg +3 -0
  287. package/src/lib/assets/redo.svg +39 -0
  288. package/src/lib/assets/region-editor.svg +37 -0
  289. package/src/lib/assets/region-move.svg +7 -0
  290. package/src/lib/assets/smooth.svg +56 -0
  291. package/src/lib/assets/spline-chart.svg +7 -0
  292. package/src/lib/assets/surface.svg +37 -0
  293. package/src/lib/assets/test/download-379.svg +1 -0
  294. package/src/lib/assets/test/download-98.svg +1 -0
  295. package/src/lib/assets/test/json-1.svg +1 -0
  296. package/src/lib/assets/test/load-53.svg +1 -0
  297. package/src/lib/assets/test/mask-44.svg +1 -0
  298. package/src/lib/assets/test/mask-download-44.svg +15 -0
  299. package/src/lib/assets/test/mask-save-44.svg +11 -0
  300. package/src/lib/assets/test/overlay-1.svg +1 -0
  301. package/src/lib/assets/test/overlay-4.svg +1 -0
  302. package/src/lib/assets/test/region-26.svg +1 -0
  303. package/src/lib/assets/test/save-56.svg +1 -0
  304. package/src/lib/assets/test/upload-43.svg +1 -0
  305. package/src/lib/assets/to-bezier.svg +15 -0
  306. package/src/lib/assets/to-polygon.svg +11 -0
  307. package/src/lib/assets/undo.svg +38 -0
  308. package/src/lib/assets/vertex-add.svg +12 -0
  309. package/src/lib/assets/vertex-delete.svg +12 -0
  310. package/src/lib/assets/wand.svg +54 -0
  311. package/src/lib/assets/zoom-box.svg +10 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Physical scale bar for the napari-js WebGPU image view (jit-ui#102), mirroring the OSD
3
+ * backend's {@link OsdScaleBar}. napari keeps layers at pixel scale, so the camera's `zoom`
4
+ * (CSS px per world unit) is exactly screen px per image pixel; combined with the image's
5
+ * µm/pixel (`mppX`, from Bio-Formats `/tiles/info`) that gives a real-world bar length.
6
+ * Recomputes on every camera change and host resize. Hidden when the image has no physical size.
7
+ */
8
+ /** Format a length given in micrometres, picking the unit that suits its magnitude (jit-service
9
+ * normalises whatever unit Bio-Formats reports to µm). */
10
+ export declare function formatUm(um: number): string;
11
+ /** The slice of the napari Camera the scale bar reads (zoom = CSS px per world/image pixel). */
12
+ interface ScaleBarCamera {
13
+ readonly zoom: number;
14
+ readonly changed: {
15
+ connect(listener: () => void): () => void;
16
+ };
17
+ }
18
+ export declare class NapariScaleBar {
19
+ private readonly host;
20
+ private readonly camera;
21
+ private readonly mppX;
22
+ private readonly bar;
23
+ private readonly line;
24
+ private readonly label;
25
+ private readonly disconnectCamera;
26
+ private readonly resizeObserver?;
27
+ constructor(host: HTMLElement, camera: ScaleBarCamera, mppX: number);
28
+ private update;
29
+ destroy(): void;
30
+ }
31
+ export {};
@@ -0,0 +1,455 @@
1
+ import { Observable } from 'rxjs';
2
+ import { Image } from 'image-js';
3
+ import { IImageInfo } from '../../contracts/image.contract';
4
+ import { PlotType, PlotTypeDescriptor } from '../../contracts/plot-type';
5
+ import { IVisualizer, PixelData, IntensityProfile, IIsosurfaceControls, IIntensityControls, ISurface3dControls } from '../../contracts/visualizer.contract';
6
+ import { ViewerCapabilities } from '../../contracts/capabilities.contract';
7
+ import { IRegionOverlay } from '../../contracts/region-overlay.contract';
8
+ import { IHistogram } from '../../contracts/channel-histogram-api.contract';
9
+ import { IWandOptions, IBrushOptions } from '../../contracts/display-types';
10
+ import { VizConfig } from '../../contracts/viz-config';
11
+ import { TileAccessPort } from '../../contracts/ports/tile-access.port';
12
+ import { BaseStoreVisualizer } from '../base-store-visualizer';
13
+ import { SimpleSliceAccessService } from '../simple-slice-access.service';
14
+ import { VisualizerStore } from '../../store/visualizer-store.service';
15
+ import { RegionStore } from '../../store/region-store.service';
16
+ import { WandToolService } from '../../toolbar/wand/wand-tool.service';
17
+ import { BrushToolService } from '../../toolbar/brush/brush-tool.service';
18
+ import { VertexEraserToolService } from '../../toolbar/vertex-eraser/vertex-eraser-tool.service';
19
+ import { ZoomToBoxToolService } from '../../toolbar/zoom-to-box/zoom-to-box-tool.service';
20
+ import { SamToolService } from '../../toolbar/segmentation/sam-tool.service';
21
+ import { SamPointToolService } from '../../toolbar/segmentation/sam-point-tool.service';
22
+ import { CellSegmentToolService } from '../../toolbar/segmentation/cell-segment-tool.service';
23
+ import { ICellSegmenter } from '../../contracts/cell-segmenter.contract';
24
+ import * as i0 from "@angular/core";
25
+ /** Opaque handle from {@link NapariVisualizerService.load}, passed back to plot(). */
26
+ interface NapariLoaded {
27
+ imageInfo: IImageInfo;
28
+ z: number;
29
+ /** Must match `IImageInfo.fileName` — the render orchestrator drops the result if the
30
+ * handle's `filename` doesn't match the requested image (guards against stale clicks). */
31
+ filename: string;
32
+ }
33
+ /**
34
+ * A WebGPU image backend built on the published `napari-js` library — the POC engine for
35
+ * jit-ui#102 (a browser-based napari shipped as a JS library, swapping image plotting with
36
+ * OpenSeadragon and 3D slicing/isosurfaces with Plotly).
37
+ *
38
+ * Render strategy: rather than re-implement the server's tile/pyramid protocol (which OSD
39
+ * already handles), this backend renders the **complete per-slice image URLs the app already
40
+ * produces** (`IImageInfo.urls`) — `urls[z]` for the 2D image, and the full `urls` stack
41
+ * assembled into a downsampled volume for the 3D types. Region state and display options
42
+ * delegate to the shared {@link RegionStore} / {@link VisualizerStore}, exactly as OSD does.
43
+ *
44
+ * Follow-ups (jit-ui#102): native-resolution pyramidal tiling, on-canvas tools, region
45
+ * overlay rendering, per-channel histograms, TIFF export.
46
+ */
47
+ export declare class NapariVisualizerService extends BaseStoreVisualizer implements IVisualizer {
48
+ private readonly tiles;
49
+ private readonly wandTool;
50
+ private readonly brushTool;
51
+ private readonly eraserTool;
52
+ private readonly zoomToBoxTool;
53
+ private readonly samTool;
54
+ private readonly samPointTool;
55
+ private readonly cellSegmentTool;
56
+ private readonly cellSegmenter;
57
+ private readonly simpleStack;
58
+ readonly capabilities: ViewerCapabilities;
59
+ private readonly api;
60
+ private viewer;
61
+ private canvas;
62
+ private host;
63
+ private loaded;
64
+ private lastPixels;
65
+ private currentPlotType;
66
+ /** napari-js high-level view owning the 3D volume layers (one additive tinted layer per channel
67
+ * for multichannel, or a single grayscale volume). Null in 2D. */
68
+ private volumeView;
69
+ /** True when the volume is composited from per-channel layers (vs a single grayscale volume). */
70
+ private volumeMultichannel;
71
+ /** napari-js height-field surface mesh (NAPARI_SURFACE plot type; null otherwise). Built from a
72
+ * single grayscale slice by {@link buildSurface} via napari-js's `heightField` + `addSurface`. */
73
+ private surfaceLayer;
74
+ /** Which band the surface samples (a channel index for multichannel, else the composite). */
75
+ private surfaceChannel;
76
+ /** Pre-loaded per-slice luminance planes (already decimated to the surface grid), keyed by z,
77
+ * so the stack slider rebuilds the surface instantly. Filled by {@link preloadSurfacePlanes}. */
78
+ private readonly surfacePlanes;
79
+ /** In-plane grid cap for the active surface load (full grid ÷ the decimate factor). */
80
+ private surfaceMaxGrid;
81
+ /** Contrast window [min,max] the current surface mesh was built with. A change reshapes the
82
+ * mesh (pixel height = intensity within [min,max]), so it triggers a geometry rebuild. */
83
+ private surfaceWindow;
84
+ /** Persisted wireframe choice for the surface (re-applied when a new surface mounts). */
85
+ private surfaceWireframe;
86
+ /** napari-js 2D scatter points (region centroids) + its region-change subscription. */
87
+ private scatter2dPoints;
88
+ private scatterRegionSub;
89
+ /** napari-js 3D scatter (voxel point cloud). */
90
+ private scatter3dLayer;
91
+ /** Monotonic load generation. Bumped by {@link reset} and {@link cancelLoading}; the frame-loading
92
+ * loops (volume assembly, surface preload) capture it and bail when it changes, so a Cancel (or a
93
+ * new plot) actually stops fetching frames instead of running to completion in the background. */
94
+ private loadToken;
95
+ /** Decimate factor for the napari 3D types (1 = Full, 2 = ½ default, 4 = ¼, 8 = ⅛). Applied when a
96
+ * volume/isosurface/surface (re)loads; changing it needs a re-plot (it changes fetched data). */
97
+ private resolutionScale;
98
+ /** 3D coordinate-axes / scale gizmo for the volume/isosurface view (null in 2D). */
99
+ private axesLayer;
100
+ /** DOM X/Y/Z + scale labels tracking the 3D axes gizmo (null in 2D). */
101
+ private axesLabels;
102
+ /** Draggable Z-height grip over the volume (null unless a volume/isosurface is mounted). */
103
+ private zHandle;
104
+ /** User Z-height factor for the volume (1 = the volume's natural proportions); driven by the
105
+ * in-view drag handle. Reset per mount. */
106
+ private volumeZScale;
107
+ /** Volume world box at `volumeZScale = 1` (base) + the sampled voxel depth — enough to recompute
108
+ * the Z-axis voxel scale, axes depth, and overlay anchors as the handle stretches Z. */
109
+ private volumeWorldBase;
110
+ private volumeSampledDepth;
111
+ /** Persisted axes on/off choice, re-applied when a new volume mounts. Defaults on. */
112
+ private axesVisible;
113
+ private volumeDims;
114
+ /** Assembled uint8 volume data per channel (key = channel index), kept for the volume intensity
115
+ * histogram. Key 0 holds the grayscale/composite volume in the single-channel case. */
116
+ private readonly volumeChannelData;
117
+ private imageW;
118
+ private imageH;
119
+ /** Monotonic slice-request id so a slow out-of-order slice fetch can't clobber a newer one. */
120
+ private sliceReq;
121
+ /** Cached `/tiles/info` pyramid descriptor + the infoB64 it was fetched for. */
122
+ private descriptor;
123
+ private descriptorKey;
124
+ /** How the current 2D image is composited (drives histogram + state application). */
125
+ private imageMode;
126
+ /** napari-js high-level view that owns the per-channel layer set (build + live display
127
+ * updates) for the current {@link imageMode}. Rebuilt on each (re)render. */
128
+ private channelView;
129
+ /** Live subscription applying channel-state / colormap changes to the layers. */
130
+ private displaySub;
131
+ /** Latest grayscale colormap selection from the store (applied to the single gray layer). */
132
+ private currentColormap;
133
+ private currentReverse;
134
+ /** Latest invert toggle from the store (flips intensity before the colormap, like OSD). */
135
+ private invertEnabled;
136
+ /** Physical scale bar overlay for the 2D image (null when 3D or the image has no µm/pixel). */
137
+ private scaleBar;
138
+ /** SVG region-drawing overlay for the 2D image (null until a 2D image is plotted). */
139
+ private regionOverlay;
140
+ /** Pixel-tool plumbing: the plot div id, coord transform, and bound tool hosts. */
141
+ private plotDivId;
142
+ private coordTransform;
143
+ private wandHost;
144
+ private eraserHost;
145
+ /** Cached CachedImageData built from the last readback (rebuilt when lastPixels changes). */
146
+ private cachedImage;
147
+ private cachedImageSource;
148
+ /** Visible world rect captured AT the last readback — must pair with `lastPixels` so the pixel
149
+ * tools' ratios/origin match the matrix's camera (using the live rect after a pan/zoom would
150
+ * mis-scale the region). */
151
+ private lastPixelsRect;
152
+ /** Image smoothing (bilinear) vs nearest-neighbour (crisp pixels, the default). */
153
+ private imageSmoothing;
154
+ /** True when the 2D image is rendered via pyramidal TiledSources (descriptor available). */
155
+ private tiled;
156
+ /** Debounced readback timer + camera-change unsubscribe (keep lastPixels current for tools). */
157
+ private readbackTimer;
158
+ private cameraReadbackOff;
159
+ /** Coarse per-channel luminance sample (keyed by channel index) for the histogram in tiled mode,
160
+ * where the layers have no full in-memory pixels. Refreshed on plot + slice change. */
161
+ private readonly histSamples;
162
+ /** Native-bit-depth histograms from `/histogram`, keyed `${z}|${channel}` (>8-bit images). */
163
+ private readonly nativeHistograms;
164
+ private readonly stackLoading$;
165
+ private readonly stackLoadingProgress$;
166
+ private readonly autoscaleEvent$;
167
+ private readonly intensityProfile$;
168
+ private readonly viewportChange$;
169
+ 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);
170
+ /**
171
+ * Fetch + cache the server pyramid descriptor (`GET /tiles/info`): the REAL per-level tile grid,
172
+ * tile size, channel metadata and physical pixel size. The backend returns 202 while the source
173
+ * is still caching, so we poll briefly. Cached per `infoB64`; returns null if it never becomes
174
+ * ready (callers fall back to a single-tile fetch). This is the authoritative grid — guessing
175
+ * level dims from `trueImageSize` overshoots the real grid and the server 400s out-of-range tiles.
176
+ */
177
+ private ensureDescriptor;
178
+ /**
179
+ * Fetch a COMPLETE rendered slice as an `ImageBitmap` by stitching the server's REAL tile grid
180
+ * (from `/tiles/info`) — not just the top-left tile, which only ever showed a large image's
181
+ * corner. Picks the finest pyramid level whose grid fits `budgetTiles` and whose longest side is
182
+ * within the GPU texture limit, fetches that grid concurrently, and stitches it into one canvas.
183
+ *
184
+ * `channel` selects a single band as grayscale (real levels only); omit for the server composite.
185
+ * `budgetTiles` caps the grid: the 2D view uses the full budget for detail; the 3D volume passes
186
+ * 1 for a cheap overview tile per slice (it downsamples to {@link VOLUME_MAX_SLICE}). Falls back
187
+ * to a single `col=0,row=0` tile when no descriptor is available (small/simple images, volumes).
188
+ */
189
+ private fetchSlice;
190
+ load(imageInfo: IImageInfo, zIndex: number): Promise<NapariLoaded>;
191
+ plot(plotDiv: string, imageLoaded: unknown, imageInfo: IImageInfo, screenHeight: number, plotType: PlotType, _inPlace?: boolean): Promise<boolean>;
192
+ /** The grayscale display colormap from the store selection (+reverse), defaulting to gray.
193
+ * Maps the jit-ui store colormap node to a napari `Colormap` via the library's LUT factory;
194
+ * the multichannel tint ramps are built inside {@link MultiChannelImageView} from each
195
+ * channel's hex colour. */
196
+ private grayscaleColormap;
197
+ /** Fetch a stitched slice and read it back as a single-channel uint8 plane. `channel` selects a
198
+ * band (multichannel); omit it for the grayscale composite (all overview levels available, so a
199
+ * large image picks a fitting downscaled level rather than only the full-res real level). */
200
+ private fetchChannelData;
201
+ /** Decode an `ImageBitmap` (server bands are grayscale, R=G=B) to a single-channel uint8 plane.
202
+ * `maxSide` caps the longest side (downscaling on the canvas draw) — used to keep pre-loaded
203
+ * surface slice planes small. */
204
+ private bitmapToLuminance;
205
+ /**
206
+ * Render the 2D image for slice `z`. With a server pyramid descriptor we use a pyramidal
207
+ * {@link TiledSource} per layer so the view refines to higher resolution on zoom (like OSD) and
208
+ * sits naturally in full-resolution coordinates; without one we fall back to the single-level
209
+ * stitch. Three display modes either way: multichannel additive tint, grayscale colormap, RGB.
210
+ */
211
+ private renderImage;
212
+ /** Single-level stitch fallback (no descriptor): the pre-tiling path. */
213
+ private renderImageStitched;
214
+ /**
215
+ * Render the 2D image with pyramidal {@link TiledSource}s — the view refines to higher resolution
216
+ * as you zoom in (the visual fetches the level whose texels ≈ screen pixels) and sits in full-res
217
+ * coordinates so regions align. Same three modes as the stitch path. Per-channel layers use the
218
+ * REAL pyramid levels (per-channel tiles only exist there); the composite uses all levels.
219
+ */
220
+ private renderImageTiled;
221
+ /** Build a pyramidal TiledSource backed by the server `/tile` endpoint. `channel` selects a band
222
+ * (grayscale luminance, real levels only); omit it for the composite (RGBA, all levels). */
223
+ private buildTiledSource;
224
+ /** (Re)fetch a coarse per-channel luminance sample for the histogram (tiled mode has no full
225
+ * in-memory pixels). One cheap overview tile per channel; cached by channel index. */
226
+ private refreshHistogramSamples;
227
+ /** Subscribe channel states + grayscale colormap → live-apply to the rendered layers (no
228
+ * re-fetch; only z changes re-fetch). Replaces any prior subscription. */
229
+ private subscribeDisplayState;
230
+ /** Subscribe the store colormap (+reverse), invert, and channel state → the volume/isosurface
231
+ * transfer function: colour (channel tint or selected colormap), the intensity **window
232
+ * (min/max → contrastLimits)** and **gamma**, mirroring the grayscale image's display controls
233
+ * so the histogram pane drives the 3D render. Replaces any prior subscription. */
234
+ private subscribeVolumeDisplayState;
235
+ /** A channel's tint colormap (black→colour) with reverse-scale / invert applied by flipping. */
236
+ private channelTintColormap;
237
+ /**
238
+ * Colour map for the volume/isosurface. A real colormap selection (viridis/magma/…) wins;
239
+ * otherwise the channel's colour tints it (so the channel-dialog colour swatch recolors the 3D
240
+ * render). Reverse-scale and invert each flip the ramp — the `VolumeLayer` has no per-layer
241
+ * invert, so both are emulated by reversing the colormap.
242
+ */
243
+ private volumeColormap;
244
+ /** Apply the current channel states / colormap to the live layers (no re-fetch), delegating the
245
+ * per-channel layer mutations to the {@link MultiChannelImageView}. */
246
+ private applyDisplayState;
247
+ /** (Re)install the physical scale bar over the 2D image, sized from the image's µm/pixel
248
+ * (`/tiles/info` mppX, falling back to the image metadata). No-op without a physical size. */
249
+ private installScaleBar;
250
+ /** Convert a napari-js `Histogram` (bin count + min/max) to the pane's `IHistogram` (bin edges). */
251
+ private toIHistogram;
252
+ /**
253
+ * Mount the 3D volume/isosurface. A multichannel image becomes one additive, tinted
254
+ * {@link VolumeLayer} per channel (so each channel's colour composites into the render); a
255
+ * grayscale/composite image uses a single volume. Adds the axes gizmo + labels and wires the
256
+ * display-state subscription. The caller owns `viewer.ready`.
257
+ */
258
+ private mountVolume;
259
+ /**
260
+ * Restretch the volume's Z height live (driven by the in-view {@link NapariVolumeZHandle}). Only
261
+ * the per-axis `voxelSize` / axes depth change — the voxel textures are untouched — so dragging is
262
+ * smooth. `factor` is relative to the volume's natural proportions (1). Persists across re-mounts
263
+ * (resolution changes) so the chosen height sticks.
264
+ */
265
+ private setVolumeZScale;
266
+ /** Build the X/Y/Z axis-end label specs for the 3D gizmo. Anchors are in the volume's centred
267
+ * world box (matching the AxesLayer geometry); the scale text reflects the FULL image extent —
268
+ * physical µm when µm/pixel is known, else pixel (X/Y) / slice (Z) counts. */
269
+ private buildAxesLabels;
270
+ /**
271
+ * Assemble a downsampled uint8 volume (luminance) from the per-slice tile endpoint. Slices are
272
+ * fetched with bounded concurrency (keeps the connection pool full without flooding it on a deep
273
+ * stack) and read into the volume as each arrives, driving {@link stackLoadingProgress$} so the
274
+ * host shows a determinate progress bar instead of a bare spinner.
275
+ */
276
+ private assembleVolume;
277
+ /**
278
+ * Mount the NAPARI_SCATTER 2D scatter: the slice image with a points layer at each region's
279
+ * centroid (napari-js analog of Plotly's region-centroid scatter). Rebuilds the points live as
280
+ * regions change.
281
+ */
282
+ private mountScatter;
283
+ /** (Re)build the 2D scatter's point layer at the current region centroids. */
284
+ private rebuildScatterPoints;
285
+ /** Region centroids as flat `[x, y, …]` data coords (rectangle / polygon / multipolygon). */
286
+ private regionCentroids;
287
+ /**
288
+ * Mount the NAPARI_SCATTER3D 3D scatter: the downsampled voxel grid as a 3D point cloud colored
289
+ * by intensity (napari-js analog of Plotly's voxel scatter3d). Assembles a coarse volume, then
290
+ * emits a flat-strided sample of voxels (capped at {@link SCATTER3D_MAX_POINTS}) via `addPoints3D`.
291
+ */
292
+ private mountScatter3d;
293
+ /** Store colormap / reverse / invert / channel window → the 3D scatter's colormap + contrast. */
294
+ private subscribeScatter3dDisplayState;
295
+ /**
296
+ * Mount the NAPARI_SURFACE height-field surface. A height field is single-scalar, so for a
297
+ * multichannel image the surface follows ONE band — the first visible channel (fallback 0) —
298
+ * coloured by that channel's window/colormap (like the Plotly SURFACE, which is grayscale-only).
299
+ * Pre-loads every slice's height data with a progress bar (as the volume does) so the stack
300
+ * slider re-slices instantly, then builds the mesh for the current slice. All mesh + GPU work
301
+ * lives in napari-js (`heightField` + `Viewer.addSurface`); this backend supplies scalar slices.
302
+ */
303
+ private mountSurface;
304
+ /** Add the 3D axes gizmo + DOM labels around the (origin-centered) surface mesh, matching the
305
+ * volume/isosurface. Installed once per mount; the box tracks the mesh bounds, X/Y show the
306
+ * physical (or pixel) extent, and Z is the intensity/height axis. */
307
+ private installSurfaceAxes;
308
+ /** X/Y/Z end-labels for the surface gizmo: X/Y are the physical (µm) or pixel extent of the FULL
309
+ * image; Z is the intensity/height axis. Anchors are in the centered box (matching AxesLayer). */
310
+ private buildSurfaceAxesLabels;
311
+ /**
312
+ * Pre-fetch every stack slice's luminance plane (decimated to the surface grid) into
313
+ * {@link surfacePlanes}, driving {@link stackLoadingProgress$} — the same load-with-progress UX
314
+ * as the volume, but keeping one 2D plane per slice rather than packing a 3D volume. Bounded
315
+ * concurrency keeps the connection pool busy without flooding it on a deep stack.
316
+ */
317
+ private preloadSurfacePlanes;
318
+ /**
319
+ * Fetch slice `z` as a single WHOLE-image luminance plane (decimated to `maxGrid`). Prefers the
320
+ * app's complete per-slice image (`smallUrls`/`urls`, exactly like the Plotly surface) so the
321
+ * surface always covers the FULL slice — the tile-pyramid `fetchSlice` path would fall back to a
322
+ * single top-left tile (a corner) for self-contained / non-`/tiles/info` images. Falls back to
323
+ * stitching the tile grid only when no complete-image URL is available.
324
+ */
325
+ /** Tile budget to stitch a whole slice at ~`targetPx` resolution from the pyramid: a higher target
326
+ * pulls a FINER pyramid level (more real detail). Shared by the surface plane fetch and the volume
327
+ * assembly so both scale their in-plane resolution with the decimate factor. */
328
+ private tileBudgetFor;
329
+ private fetchSurfacePlane;
330
+ /** The channel state driving the surface: the chosen band for multichannel (matched by index),
331
+ * else the single grayscale channel. */
332
+ private surfaceState;
333
+ /**
334
+ * (Re)build the surface mesh for slice `z` from the pre-loaded plane cache (instant — this is
335
+ * what the stack slider calls); a slice missing from the cache is fetched on demand. napari-js's
336
+ * pure `heightField` builds the triangle grid (z = normalized intensity), then `addSurface`
337
+ * renders it. The slice plane also feeds the intensity histogram (key 0).
338
+ */
339
+ private buildSurface;
340
+ /** Subscribe the store colormap / reverse / invert / channel window → the surface, so histogram
341
+ * & channel-dialog edits update it live without a re-fetch. **min/max reshapes the surface's
342
+ * height** (a pixel's height = its intensity within [min,max]), so a window change rebuilds the
343
+ * mesh geometry (from the cached slice); colour-only edits (colormap/LUT, gamma, reverse, invert)
344
+ * just update the layer's uniforms. */
345
+ private subscribeSurfaceDisplayState;
346
+ private fitCameraSoon;
347
+ /** @deprecated Plotly-specific; host re-drives plot() from its image stream. */
348
+ reloadAndPlot(): void;
349
+ reset(): void;
350
+ relayout(_trueImageSize?: number[]): void;
351
+ /** @deprecated Plotly-specific axis reset. */
352
+ resetAxes(): void;
353
+ /** @deprecated Plotly-specific autoscale. */
354
+ autoscale(): void;
355
+ zoomIn(): void;
356
+ zoomOut(): void;
357
+ setDragMode(_mode: string | false): void;
358
+ setNavigatorVisible(_visible: boolean): void;
359
+ setImageSmoothingEnabled(enabled: boolean): void;
360
+ setShowStack(_showstack: boolean): void;
361
+ setZIndex(zIndex: number): void;
362
+ setStackLoading(stackLoading: boolean): void;
363
+ /** Cancel in-flight frame loading: bump the load generation so the volume-assembly / surface
364
+ * preload workers stop fetching more frames, and clear the loading flag + progress. */
365
+ cancelLoading(): void;
366
+ isStackLoading(): Observable<boolean>;
367
+ getStackLoadingProgress(): Observable<number>;
368
+ getTrueImageSize(): {
369
+ width: number;
370
+ height: number;
371
+ } | null;
372
+ getCurrentImage(): Promise<Image | null>;
373
+ getDisplayedPixelData(): PixelData | null;
374
+ getDisplayedSourceRect(): {
375
+ x: number;
376
+ y: number;
377
+ width: number;
378
+ height: number;
379
+ } | null;
380
+ downloadImage(): void;
381
+ setPlotType(plotType: PlotType): void;
382
+ /** Map a Plotly-style 3D drag mode onto napari-js's camera drag mode. */
383
+ setSurfaceDragMode(mode: string): void;
384
+ /** Re-frame the 3D camera on the current 3D layer. A surface mesh sits in the positive octant
385
+ * (not centred), so frame it by its own bounds; a volume/isosurface uses its centred box. */
386
+ resetSurfaceCamera(): void;
387
+ getAutoscaleEvent(): Observable<unknown>;
388
+ getPlotTypeDescriptors(): PlotTypeDescriptor[];
389
+ /** The napari 3D decimate factor (1 = full … 8 = ⅛). Read by the toolbar to init the control. */
390
+ getResolutionScale(): number;
391
+ /** Set the decimate factor for the napari 3D types. Takes effect on the next (re)load — the host
392
+ * re-plots after calling this, since decimation changes the fetched/assembled data. */
393
+ setResolutionScale(scale: number): void;
394
+ getIntensityProfile$(): Observable<IntensityProfile[]>;
395
+ renderIntensityInset(_divId: string, _profiles: IntensityProfile[]): void;
396
+ /** Read the displayed composite into `lastPixels` (the pixel-tools' source) + emit the clamped
397
+ * visible region. A fresh PixelData object means cachedImageData() rebuilds automatically. */
398
+ private runReadback;
399
+ private scheduleReadback;
400
+ /** Debounced readback — armed on camera changes so `lastPixels` tracks the current view after a
401
+ * pan/zoom settles (and after tiled levels finish loading), which the on-canvas pixel tools
402
+ * (wand/brush/SAM) read synchronously. Coalesces rapid changes. */
403
+ private armReadback;
404
+ /** Build the coordinate transform + tool hosts for the current viewer (called from plot()). The
405
+ * pixel tools read displayed pixels synchronously from the last readback and convert pointer
406
+ * coords via the napari camera, exactly mirroring the OSD host. */
407
+ private buildToolHosts;
408
+ private zoomBoxHost;
409
+ /** Zoom/pan the camera to fit a data-space rectangle `[xMin, xMax, yMax, yMin]`. */
410
+ private applyZoomToBox;
411
+ /** Build CachedImageData from the most recent readback (RGBA device pixels → [y][x]=[r,g,b]),
412
+ * with ratios/origin mapping image coords ↔ readback pixels. Cached until the readback changes. */
413
+ private cachedImageData;
414
+ setWandMode(active: boolean, options?: IWandOptions): void;
415
+ setWandOptions(options: IWandOptions): void;
416
+ clearActiveWandRegion(): void;
417
+ setBrushMode(active: boolean, options?: IBrushOptions): void;
418
+ setBrushOptions(options: IBrushOptions): void;
419
+ setVertexEraserMode(active: boolean): void;
420
+ setVertexEraserRadius(radius: number): void;
421
+ setZoomToBoxMode(active: boolean): void;
422
+ segmentRectangles(): Promise<number>;
423
+ segmentRectanglesCellpose(): Promise<number>;
424
+ setSamModel(id: string): void;
425
+ setSamPointMode(active: boolean): void;
426
+ commitSamPoints(): void;
427
+ clearSamPoints(): void;
428
+ ensureIntensitySampling(_imageInfo: IImageInfo, _zIndex: number): Promise<void>;
429
+ refreshIntensitySamplingForRoi(_x: number, _y: number, _width: number, _height: number, _zIndex: number): void;
430
+ getViewportChange$(): Observable<{
431
+ x: number;
432
+ y: number;
433
+ width: number;
434
+ height: number;
435
+ }>;
436
+ getRegionOverlay(): IRegionOverlay | null;
437
+ getIsosurfaceControls(): IIsosurfaceControls | null;
438
+ getIntensityControls(): IIntensityControls | null;
439
+ getSurface3dControls(): ISurface3dControls | null;
440
+ getHistogram(channelIndex: number, bins: number): IHistogram | null;
441
+ getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
442
+ /** Fetch + cache one channel's native-bit-depth histogram from `GET /histogram` (>8-bit). */
443
+ private fetchNativeHistogram;
444
+ /** Per-channel histogram of the displayed RGB composite (R/G/B byte), from the last readback. */
445
+ private rgbHistogram;
446
+ exportComposite(): void;
447
+ /** Native-bit-depth (16/32-bit) multi-band TIFF export via the server `/export/tiff` endpoint —
448
+ * the displayed PNG is an 8-bit figure, this preserves the true pixel values. Visible channels
449
+ * only (omitted when all are visible → server default). Mirrors the OSD backend. */
450
+ exportData(): Promise<void>;
451
+ unsubscribe(): void;
452
+ static ɵfac: i0.ɵɵFactoryDeclaration<NapariVisualizerService, [null, null, null, null, null, null, null, null, null, null, { optional: true; }, null, null]>;
453
+ static ɵprov: i0.ɵɵInjectableDeclaration<NapariVisualizerService>;
454
+ }
455
+ export {};
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Draggable Z-height handle for the napari-js WebGPU volume (jit-ui#102). A small DOM grip is drawn
3
+ * over the 3D canvas at the projected top-face centre of the volume box (reusing the axes-label
4
+ * {@link projectPoint} projection, so it tracks the box as the volume orbits). Dragging it up makes
5
+ * the volume taller, down makes it flatter — the host maps the drag to a Z-scale factor and
6
+ * restretches the volume + axes live (only the model matrix changes; the voxel texture is untouched).
7
+ *
8
+ * Direct-manipulation counterpart of {@link NapariAxesLabels}: both are absolute-positioned overlays
9
+ * updated on every `camera3d.changed`, but this one accepts pointer input.
10
+ */
11
+ import { AxesLabelCamera3D } from './napari-axes-labels';
12
+ export interface VolumeZHandleOptions {
13
+ /** Current top-face-centre world point (the box is centred at the origin, so `[0, 0, +halfZ]`). */
14
+ topAnchor: () => [number, number, number];
15
+ /** The current Z-scale factor (1 = the volume's default proportions). */
16
+ getScale: () => number;
17
+ /** Apply a new Z-scale factor — the host restretches the volume + axes and repositions overlays. */
18
+ setScale: (scale: number) => void;
19
+ /** Vertical drag (px) for one doubling/halving of the Z height. Larger = less sensitive. */
20
+ pixelsPerDouble?: number;
21
+ /** Clamp for the Z-scale factor. */
22
+ minScale?: number;
23
+ maxScale?: number;
24
+ }
25
+ export declare class NapariVolumeZHandle {
26
+ private readonly host;
27
+ private readonly camera3d;
28
+ private readonly el;
29
+ private readonly disconnectCamera;
30
+ private readonly resizeObserver?;
31
+ private readonly opts;
32
+ private visible;
33
+ private dragging;
34
+ private startY;
35
+ private startScale;
36
+ constructor(host: HTMLElement, camera3d: AxesLabelCamera3D, opts: VolumeZHandleOptions);
37
+ setVisible(visible: boolean): void;
38
+ /** Reproject the handle to the current top-face anchor. Called on camera move, resize, and after
39
+ * the host applies a new scale (so the grip follows the growing/shrinking box). */
40
+ reposition(): void;
41
+ private readonly onPointerDown;
42
+ private readonly onPointerMove;
43
+ private readonly onPointerUp;
44
+ private readonly onDoubleClick;
45
+ destroy(): void;
46
+ }
@@ -0,0 +1,47 @@
1
+ import { IChannelState } from '../../contracts/channel-histogram-api.contract';
2
+ import { Rgb } from '../../contracts/colormap-lut';
3
+ /**
4
+ * The OSD pixel display pipeline (refactoring plan, Step 4 — a pure move of
5
+ * the recolor math out of the visualizer service). Stateless: every call reads
6
+ * the current display state through the host closures, exactly like the moved
7
+ * code read the service's fields. Shared by tile recoloring and the composite
8
+ * export so they stay identical.
9
+ */
10
+ export interface DisplayPipelineHost {
11
+ /** Grayscale image (colormap LUT path) vs RGB/multichannel (additive tint). */
12
+ isGrayscale(): boolean;
13
+ /** 256-entry colormap LUT (grayscale path); null while options resolve. */
14
+ colorLut(): Rgb[] | null;
15
+ /** Latest per-channel display state from the store. */
16
+ channelStates(): IChannelState[];
17
+ /** Inverted background (white = zero). */
18
+ invertBg(): boolean;
19
+ }
20
+ export declare class DisplayPipeline {
21
+ private host;
22
+ constructor(host: DisplayPipelineHost);
23
+ /**
24
+ * Apply the current display pipeline to an RGBA buffer in place; returns
25
+ * whether any opaque pixel was written.
26
+ * - Grayscale: intensity → window + gamma + invert → colormap LUT.
27
+ * - RGB/multichannel: additive pseudo-colour merge — each visible channel's
28
+ * windowed intensity is tinted by its assigned colour and summed (Fiji
29
+ * "Merge Channels"). Defaults (R=red, G=green, B=blue) are the identity.
30
+ */
31
+ applyToRgba(d: Uint8ClampedArray): boolean;
32
+ /** Precomputed lum(0..255) → tinted-RGB lookup for a channel's window/gamma/
33
+ * colour. Building it costs 256 channelIntensity() calls; using it makes a
34
+ * full-tile recolor ~262k array lookups instead of ~262k Math.pow() calls. */
35
+ channelRgbLut(st?: IChannelState): {
36
+ r: Uint8ClampedArray;
37
+ g: Uint8ClampedArray;
38
+ b: Uint8ClampedArray;
39
+ };
40
+ /** Windowed + gamma intensity (0..255) for a channel, ignoring tint/invert. */
41
+ channelIntensity(val: number, c?: IChannelState): number;
42
+ /** A channel's pseudo-colour tint as [r,g,b] in 0..1 (default white). */
43
+ tint01(c?: IChannelState): [number, number, number];
44
+ /** True when any RGB channel is windowed/hidden/gamma'd/re-tinted or the
45
+ * background is inverted — otherwise the tile passes through unchanged. */
46
+ rgbNeedsRecolor(): boolean;
47
+ }