@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,346 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ import { Observable } from 'rxjs';
3
+ import { Image } from 'image-js';
4
+ import { IImageInfo, IImageMetadata } from './image.contract';
5
+ import { Region } from '../models/region';
6
+ import { PlotType, PlotTypeDescriptor } from './plot-type';
7
+ import { ViewerCapabilities } from './capabilities.contract';
8
+ import { IRegionOverlay } from './region-overlay.contract';
9
+ import { IHistogram } from './channel-histogram-api.contract';
10
+ import { ColormapNode, IWandOptions, IBrushOptions } from './display-types';
11
+ /**
12
+ * Backend-neutral visualization contract. Plotly is one implementation;
13
+ * OpenSeadragon is another (for the image plot type). The abstraction renders
14
+ * data — a raster image OR a scientific plot (heatmap, surface, contour,
15
+ * scatter, line, isosurface) — draws regions on it, and drives on-canvas tools.
16
+ *
17
+ * Split into role interfaces so a consumer can depend only on the slice it
18
+ * uses, then composed into `IVisualizer`.
19
+ *
20
+ * Types are intentionally permissive (`any` where the current Plotly service
21
+ * is untyped) so `PlotlyService` satisfies the contract without a typing
22
+ * rewrite — tightening is a follow-up, not part of standing the interface up.
23
+ */
24
+ /** Pixel readback shape returned by `getDisplayedPixelData`. */
25
+ export interface PixelData {
26
+ width: number;
27
+ height: number;
28
+ channels: number;
29
+ data: Uint8ClampedArray;
30
+ }
31
+ /** Intensity sampled along a line ROI (PlotType.LINE over image data). */
32
+ export interface IntensityProfile {
33
+ /** Distance along the line. In microns when the image carries a physical
34
+ * pixel size (mpp); otherwise in image pixels. See {@link unit}. */
35
+ positions: number[];
36
+ /** Sampled intensity (grayscale value or RGB luminance). */
37
+ values: number[];
38
+ /** Unit of {@link positions}: 'µm' when scaled by the image's mpp, else 'px'. */
39
+ unit?: 'µm' | 'px';
40
+ /** Stable id of the line ROI this profile came from (multi-line support). */
41
+ id?: number;
42
+ /** Colour of the line ROI — the inset trace is drawn in the same colour. */
43
+ color?: string;
44
+ }
45
+ /**
46
+ * The render/viewport role: load data, render it (image or plot), and handle
47
+ * zoom, stack navigation, and pixel readback.
48
+ */
49
+ export interface IDataRenderer {
50
+ load(imageInfo: IImageInfo, zIndex: number): Promise<any>;
51
+ /** `imageLoaded` is the backend-specific handle returned by `load()` —
52
+ * treat it as opaque and pass it straight through. */
53
+ plot(plotDiv: string, imageLoaded: unknown, imageInfo: IImageInfo, screenHeight: number, plotType: PlotType, inPlace?: boolean): Promise<boolean>;
54
+ /** @deprecated Plotly-specific re-render; the OSD backend no-ops it. The host
55
+ * re-drives `plot()` from its image stream instead. */
56
+ reloadAndPlot(): void;
57
+ reset(): void;
58
+ relayout(trueImageSize?: number[]): void;
59
+ /** @deprecated Plotly-specific (axis reset); the OSD backend no-ops it. Gate
60
+ * on {@link ViewerCapabilities} before calling. */
61
+ resetAxes(): void;
62
+ /** @deprecated Plotly-specific (autoscale); the OSD backend no-ops it. Gate
63
+ * on {@link ViewerCapabilities} before calling. */
64
+ autoscale(): void;
65
+ zoomIn(): void;
66
+ zoomOut(): void;
67
+ setDragMode(mode: string | false): void;
68
+ /** Show/hide the overview navigator (the minimap). OpenSeadragon only — Plotly
69
+ * no-ops it (it has no navigator). Applied when the viewer is (re)created, and
70
+ * toggled live when one is already mounted. */
71
+ setNavigatorVisible(visible: boolean): void;
72
+ /** Image smoothing (bilinear interpolation). `false` = nearest-neighbour, so
73
+ * zooming past 1:1 shows crisp pixel blocks (pixel-level inspection).
74
+ * OpenSeadragon only — Plotly no-ops it. Applied at viewer creation and live
75
+ * (with a redraw) when one is mounted. */
76
+ setImageSmoothingEnabled(enabled: boolean): void;
77
+ setShowStack(showstack: boolean): void;
78
+ setZIndex(zIndex: number): void;
79
+ setStackLoading(stackLoading: boolean): void;
80
+ isStackLoading(): Observable<boolean>;
81
+ getStackLoadingProgress(): Observable<number>;
82
+ /** Cancel any in-flight multi-frame loading (volume-assembly / surface preload) so it stops
83
+ * fetching more frames and clears the loading state. Optional — only backends that stream a
84
+ * z-stack (napari-js WebGPU) do real work here; others no-op. */
85
+ cancelLoading?(): void;
86
+ getTrueImageSize(): {
87
+ width: number;
88
+ height: number;
89
+ } | null;
90
+ getCurrentImage(): Promise<Image | null>;
91
+ getDisplayedPixelData(): PixelData | null;
92
+ /**
93
+ * The region of the original, full-resolution image that the pixels returned
94
+ * by {@link getDisplayedPixelData} currently cover — `{ x, y, width, height }`
95
+ * in full-image pixel coordinates. When zoomed/panned into a sub-area this is
96
+ * the crop's origin + extent; when zoomed out/panned beyond the edges, the
97
+ * rectangle may extend outside the image bounds (matching the pixel readback
98
+ * canvas). Lets a consumer map displayed-pixel coordinates back to the original
99
+ * image via `origin + displayedPx * (extent / displayedDim)`.
100
+ *
101
+ * Returns `null` when the viewport isn't laid out yet or the backend can't
102
+ * report it — callers should then fall back to the full-image scale (treat
103
+ * the displayed pixels as a downsample of the whole image).
104
+ */
105
+ getDisplayedSourceRect(): {
106
+ x: number;
107
+ y: number;
108
+ width: number;
109
+ height: number;
110
+ } | null;
111
+ downloadImage(): void;
112
+ setPlotType(plotType: PlotType): void;
113
+ /** Set the napari 3D decimate factor (1 = full … 8 = ⅛). Optional — only the napari-js WebGPU
114
+ * backend honors it; changing it re-loads the current 3D plot at the coarser/finer sampling. */
115
+ setResolutionScale?(scale: number): void;
116
+ /** The current napari 3D decimate factor (to initialize the Resolution control). Optional. */
117
+ getResolutionScale?(): number;
118
+ /** @deprecated Use `getSurface3dControls()` — 3D scene controls only exist on
119
+ * a backend that renders 3D plot types; this method silently no-ops on OSD. */
120
+ setSurfaceDragMode(mode: string): void;
121
+ /** @deprecated Use `getSurface3dControls()` — see {@link setSurfaceDragMode}. */
122
+ resetSurfaceCamera(): void;
123
+ getAutoscaleEvent(): Observable<any>;
124
+ /** Plot types this backend advertises (drives the UI selector). */
125
+ getPlotTypeDescriptors(): PlotTypeDescriptor[];
126
+ /** Intensity along the line ROIs; emits the full set as any line is added,
127
+ * moved, or removed (PlotType.LINE). One entry per line ROI. */
128
+ getIntensityProfile$(): Observable<IntensityProfile[]>;
129
+ /** Render the floating intensity-profile inset chart into `divId` from the
130
+ * given profiles (one trace per line ROI, coloured to match its line).
131
+ * Owned by the backend so consumers never reach a charting library directly. */
132
+ renderIntensityInset(divId: string, profiles: IntensityProfile[]): void;
133
+ }
134
+ /** Region/shape state: CRUD, selection, classification colours, GeoJSON I/O. */
135
+ export interface IRegionStore {
136
+ setRegions(regions: Region[], showRegionLabel?: boolean, isRegionSaveOn?: boolean, fillColor?: string, append?: boolean): void;
137
+ /** Framework-neutral accessor — the canonical way to read current regions. */
138
+ getRegions(): Region[];
139
+ getRegionPolygons(): any[];
140
+ getRegionUpdateEvent(): Observable<any[]>;
141
+ setSelectedShapeIndices(indices: number[]): void;
142
+ getSelectedShapeIndices$(): Observable<number[]>;
143
+ /** Select a specific region (by identity), highlighting it on whichever
144
+ * backend is rendering — Plotly sets its active-shape handles, OpenSeadragon
145
+ * highlights the SVG element. No-op if the region isn't in the store. */
146
+ selectRegion(region: Region): void;
147
+ deleteActiveShape(): void;
148
+ getShowShapeLabel(): boolean;
149
+ getShapeColor(): string;
150
+ getFillColor(): string;
151
+ getClassificationColors(): Map<string, string>;
152
+ setClassificationColor(label: string, color: string): void;
153
+ plotPreviousShapes(): void;
154
+ setPreviousShapes(shapes: any[]): void;
155
+ getPreviousShapes(): any[];
156
+ /** Undo the most recent region action (jit-ui#85). Restores the region set to
157
+ * the state before that action; up to a small fixed depth (10) is retained,
158
+ * so it can be invoked up to 10 times in a row. No-op when nothing is left to
159
+ * undo. */
160
+ undo(): void;
161
+ /** Re-apply the most recently undone region action. No-op when there's
162
+ * nothing to redo (any fresh region action clears the redo future). */
163
+ redo(): void;
164
+ /** Synchronous read of {@link getCanUndo$}. */
165
+ canUndo(): boolean;
166
+ /** Synchronous read of {@link getCanRedo$}. */
167
+ canRedo(): boolean;
168
+ /** Emits whether an undo step is currently available — drives the toolbar
169
+ * Undo button's enabled (greyed-out) state. */
170
+ getCanUndo$(): Observable<boolean>;
171
+ /** Emits whether a redo step is currently available — drives the toolbar
172
+ * Redo button's enabled (greyed-out) state. */
173
+ getCanRedo$(): Observable<boolean>;
174
+ /** Clear the undo/redo history (e.g. on image load/switch). */
175
+ resetUndoHistory(): void;
176
+ importRegions(geoJsonStr: string): Region[];
177
+ exportRegions(regions: Region[]): void;
178
+ getGeoJsonString(regions: Region[]): string;
179
+ /** Begin a per-slice z-stack region session (jit-ui#93). `slices` maps each
180
+ * zero-based slice index to that slice's regions; the store shows `initialZ`
181
+ * live while holding the rest, so scrubbing swaps region sets and edits on a
182
+ * slice persist. `saveLayout` records how the stack persists — `combined`
183
+ * (one z-indexed geojson, single-file z-stack) or `per-slice-file` (folder
184
+ * stack). See {@link setDisplaySlice}, {@link getSliceRegions}. */
185
+ enterStackMode(slices: Map<number, Region[]>, initialZ?: number, saveLayout?: 'combined' | 'per-slice-file'): void;
186
+ /** End the per-slice session (single-plane image, or the stack was closed). */
187
+ exitStackMode(): void;
188
+ /** True while a per-slice z-stack session is active. */
189
+ isStackMode(): boolean;
190
+ /** How the current stack persists to disk (jit-ui#93). */
191
+ getStackSaveLayout(): 'combined' | 'per-slice-file';
192
+ /** Swap the live region set to slice `z` (stack mode only), capturing the
193
+ * current slice's edits first. Called on every committed slice scrub. */
194
+ setDisplaySlice(z: number): void;
195
+ /** Every slice's regions for save/export, each tagged with its zero-based
196
+ * {@link Region.z}; the flat set outside stack mode. */
197
+ getSliceRegions(): Region[];
198
+ /** Slices to write on a per-slice-file save (folder stack, jit-ui#93): each
199
+ * slice with regions, plus slices cleared since load (empty, to overwrite).
200
+ * Keyed by zero-based slice index; regions tagged with their z. */
201
+ getStackSaveSlices(): Map<number, Region[]>;
202
+ }
203
+ /** On-canvas tool modes (wand, brush, vertex eraser, zoom-to-box). */
204
+ export interface IToolController {
205
+ setWandMode(active: boolean, options?: IWandOptions): void;
206
+ setWandOptions(options: IWandOptions): void;
207
+ clearActiveWandRegion(): void;
208
+ /** Brush region tool. `size` (matrix-pixel diameter) sizes the painted disc. */
209
+ setBrushMode(active: boolean, options?: IBrushOptions): void;
210
+ setBrushOptions(options: IBrushOptions): void;
211
+ setVertexEraserMode(active: boolean): void;
212
+ setVertexEraserRadius(radius: number): void;
213
+ setZoomToBoxMode(active: boolean): void;
214
+ /** Box-prompted SAM segmentation: segment every rectangle region into masks.
215
+ * Returns the number of mask regions added. (jit-ui#90) */
216
+ segmentRectangles(): Promise<number>;
217
+ /** Cellpose-on-crop: client slide-crop each rectangle and segment cells in it
218
+ * (cellpose-SAM via the host's CELL_SEGMENTER). Returns regions added. */
219
+ segmentRectanglesCellpose(): Promise<number>;
220
+ /** Choose the registered SAM model the segment tools use (jit-ui#90 P1). */
221
+ setSamModel(id: string): void;
222
+ /** Toggle the interactive SAM point-prompt tool (click = +point, Shift = -). */
223
+ setSamPointMode(active: boolean): void;
224
+ /** Finalise / discard the in-progress SAM point object. */
225
+ commitSamPoints(): void;
226
+ clearSamPoints(): void;
227
+ }
228
+ /**
229
+ * Controls specific to the ISOSURFACE plot type. Optional and capability-gated
230
+ * (`ViewerFeature.Isosurface`): only a backend that renders isosurfaces exposes
231
+ * it, via `IVisualizer.getIsosurfaceControls()`. Kept off the always-on
232
+ * contract so consumers never call a control that's meaningless for the current
233
+ * plot type / backend.
234
+ */
235
+ export interface IIsosurfaceControls {
236
+ /** Live-update the isosurface intensity band [isomin, isomax] over 0–255. */
237
+ setIsoRange(isoMin: number, isoMax: number): void;
238
+ }
239
+ /**
240
+ * Controls specific to the 3D plot types (SURFACE / SCATTER3D / ISOSURFACE
241
+ * scenes). Capability-gated like {@link IIsosurfaceControls}: only a backend
242
+ * that renders 3D scenes exposes it, via `IVisualizer.getSurface3dControls()` —
243
+ * the deprecated top-level `setSurfaceDragMode`/`resetSurfaceCamera` silently
244
+ * no-op on 2D-only backends.
245
+ */
246
+ export interface ISurface3dControls {
247
+ /** Switch the 3D scene interaction mode (orbit / turntable / pan / zoom). */
248
+ setSurfaceDragMode(mode: string): void;
249
+ /** Reset the 3D scene camera to its default eye position. */
250
+ resetSurfaceCamera(): void;
251
+ /** Toggle the 3D coordinate-axes / scale gizmo on/off. Optional — only the napari-js WebGPU
252
+ * volume/isosurface backend renders one (jit-ui#102). */
253
+ setAxesVisible?(visible: boolean): void;
254
+ /** Whether the axes gizmo is currently shown (for initializing the toggle UI). Optional. */
255
+ axesVisible?(): boolean;
256
+ /** Render the surface as a wireframe (edges) instead of a filled surface. Optional — only the
257
+ * napari-js WebGPU surface backend supports it (jit-ui#102). */
258
+ setWireframe?(on: boolean): void;
259
+ /** Whether the surface is currently drawn as a wireframe (for initializing the toggle UI). */
260
+ wireframe?(): boolean;
261
+ }
262
+ /**
263
+ * Controls specific to the LINE (intensity-profile) plot type. Capability-gated
264
+ * like {@link IIsosurfaceControls}: only a backend that renders the line-ROI /
265
+ * inset exposes it, via `IVisualizer.getIntensityControls()`.
266
+ */
267
+ export interface IIntensityControls {
268
+ /** Add another line ROI (next bright palette colour) and its inset trace.
269
+ * Returns the created region so the caller can select it on the active
270
+ * backend, or null if no image extent is known yet. */
271
+ addProfileLine(): Region | null;
272
+ }
273
+ /** Display options (colormap/LUT, reverse scale, image metadata). */
274
+ export interface IDisplayOptions {
275
+ getColormap(): Observable<ColormapNode | null>;
276
+ setColormap(colormap: ColormapNode): void;
277
+ getColormapOptions(): ColormapNode[];
278
+ getReverseScale(): Observable<boolean>;
279
+ setReverseScale(reverscale: any): void;
280
+ setImageMeta(imageMeta: IImageMetadata[]): void;
281
+ getImageMeta(): Observable<IImageMetadata[]>;
282
+ }
283
+ /**
284
+ * Intensity-profile sampling (PlotType.LINE). The sampling *source* lives in the
285
+ * Plotly backend (it owns pixel readback); OpenSeadragon contributes only the
286
+ * viewport-change signal that drives re-sampling at the current zoom. Each
287
+ * backend implements the part it owns and no-ops the rest — mirroring the
288
+ * deprecated no-op pattern on {@link IDataRenderer} — so the contract is uniform
289
+ * and a consumer can depend on `IVisualizer` alone (no concrete-type reach-in).
290
+ */
291
+ export interface IIntensitySampling {
292
+ /** Populate the intensity-sampling cache for the current image/slice so the
293
+ * line-ROI profiles have pixel data. Real on Plotly; no-op on OSD. */
294
+ ensureIntensitySampling(imageInfo: IImageInfo, zIndex: number): Promise<void>;
295
+ /** Re-sample the profiles from a fresh crop of the given image-pixel ROI at
296
+ * display resolution. Real on Plotly; no-op on OSD. */
297
+ refreshIntensitySamplingForRoi(x: number, y: number, width: number, height: number, zIndex: number): void;
298
+ /** Visible-region changes (image-pixel coords), emitted when the view settles,
299
+ * so the inset can re-sample at the current zoom. Real on OSD; empty on Plotly
300
+ * (its high-def zoom updates the sampling cache inline instead). */
301
+ getViewportChange$(): Observable<{
302
+ x: number;
303
+ y: number;
304
+ width: number;
305
+ height: number;
306
+ }>;
307
+ }
308
+ /** Composite contract a visualization backend implements. */
309
+ export interface IVisualizer extends IDataRenderer, IRegionStore, IToolController, IDisplayOptions, IIntensitySampling {
310
+ readonly capabilities: ViewerCapabilities;
311
+ /** This backend's region renderer. May be null until a plot is mounted
312
+ * (OpenSeadragon). Drives region draw/select modes uniformly. */
313
+ getRegionOverlay(): IRegionOverlay | null;
314
+ /** Isosurface controls when this backend advertises `ViewerFeature.Isosurface`,
315
+ * else null — so consumers gate on the returned object, not a no-op method. */
316
+ getIsosurfaceControls(): IIsosurfaceControls | null;
317
+ /** Intensity (line-ROI) controls when the backend renders the LINE plot type,
318
+ * else null. */
319
+ getIntensityControls(): IIntensityControls | null;
320
+ /** 3D scene controls when this backend renders 3D plot types, else null —
321
+ * the capability-gated replacement for the deprecated top-level
322
+ * `setSurfaceDragMode`/`resetSurfaceCamera`. */
323
+ getSurface3dControls(): ISurface3dControls | null;
324
+ /** Binned intensity histogram for a channel from the currently-displayed
325
+ * pixels, or null when none are available. Feeds the Channels & Histogram
326
+ * pane. */
327
+ getHistogram(channelIndex: number, bins: number): IHistogram | null;
328
+ /** Async histogram stream — native bit depth for >8-bit images (server), else
329
+ * the 8-bit client histogram. */
330
+ getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
331
+ /** Export the displayed image, composited with the current display settings,
332
+ * as a publication-ready PNG download. */
333
+ exportComposite(): void;
334
+ /** Export the underlying image data as a data-preserving multi-band TIFF
335
+ * (native bit depth). No-op on backends that can't provide it. */
336
+ exportData(): void;
337
+ unsubscribe(): void;
338
+ }
339
+ /**
340
+ * DI token for the active visualization backend. Bind it (`useExisting`) to the
341
+ * `RoutingVisualizerService`, which selects Plotly vs OpenSeadragon per plot
342
+ * type. Consumers — including this library's own `VisualizerComponent` —
343
+ * inject `IVisualizer` through this token rather than the concrete router, so
344
+ * the routing/fallback implementation can change without touching constructors.
345
+ */
346
+ export declare const VISUALIZER: InjectionToken<IVisualizer>;
@@ -0,0 +1,25 @@
1
+ import { InjectionToken } from '@angular/core';
2
+ /**
3
+ * Static configuration the visualization library needs from the host, supplied
4
+ * via DI so the library never imports the app's `environment`.
5
+ */
6
+ export interface VizConfig {
7
+ /** Base URL of the tile/crop server (`/tile`, `/tiles/info`, zoom). */
8
+ slideCropServer: string;
9
+ /**
10
+ * Optional CSS selector for a host element whose current width the Region
11
+ * Editor dialog should match when it first opens (e.g. the app's right
12
+ * panel). Measured once per open — it does not track later resizes. When
13
+ * absent or the element isn't found, the dialog falls back to a quarter of
14
+ * the page width (25vw).
15
+ */
16
+ regionEditorWidthSelector?: string;
17
+ /**
18
+ * Opt in to the experimental WebGPU **napari-js** backend for the IMAGE plot type
19
+ * (jit-ui#102). When `true`, the router renders images through napari-js with OpenSeadragon
20
+ * as the fallback; when absent/false, OpenSeadragon remains the default. Other plot types
21
+ * are unaffected.
22
+ */
23
+ useNapariRenderer?: boolean;
24
+ }
25
+ export declare const VIZ_CONFIG: InjectionToken<VizConfig>;
@@ -0,0 +1,47 @@
1
+ import { ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, Renderer2 } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export declare class HexColorPickerComponent implements OnDestroy {
4
+ private elRef;
5
+ private renderer;
6
+ private cdr;
7
+ private static readonly DROPDOWN_WIDTH;
8
+ private _color;
9
+ colorChange: EventEmitter<string>;
10
+ open: boolean;
11
+ swatchBtn: ElementRef<HTMLButtonElement>;
12
+ dropdownRef: ElementRef<HTMLDivElement>;
13
+ hue: number;
14
+ saturation: number;
15
+ lightness: number;
16
+ red: number;
17
+ green: number;
18
+ blue: number;
19
+ readonly colorRows: string[][];
20
+ private normalizeHexColor;
21
+ get color(): string;
22
+ set color(val: string);
23
+ constructor(elRef: ElementRef, renderer: Renderer2, cdr: ChangeDetectorRef);
24
+ ngOnDestroy(): void;
25
+ toggle(): void;
26
+ private appendDropdownToBody;
27
+ private removeDropdownFromBody;
28
+ selectColor(hex: string): void;
29
+ selectAndClose(hex: string): void;
30
+ close(): void;
31
+ onHexInput(value: string): void;
32
+ onHslChange(): void;
33
+ onRgbChange(): void;
34
+ get hueGradient(): string;
35
+ get satGradient(): string;
36
+ get lightGradient(): string;
37
+ onDocumentClick(event: Event): void;
38
+ private syncFromHex;
39
+ private syncRgbFromHex;
40
+ private syncHslFromRgb;
41
+ private hexToRgb;
42
+ private rgbToHex;
43
+ private rgbToHsl;
44
+ private hslToHex;
45
+ static ɵfac: i0.ɵɵFactoryDeclaration<HexColorPickerComponent, never>;
46
+ static ɵcmp: i0.ɵɵComponentDeclaration<HexColorPickerComponent, "hex-color-picker", never, { "color": { "alias": "color"; "required": false; }; }, { "colorChange": "colorChange"; }, never, never, false, never>;
47
+ }
@@ -0,0 +1,71 @@
1
+ import { Observable } from 'rxjs';
2
+ import { IDisplayOptions, IRegionStore } from '../contracts/visualizer.contract';
3
+ import { Region } from '../models/region';
4
+ import { ColormapNode } from '../contracts/display-types';
5
+ import { IImageMetadata } from '../contracts/image.contract';
6
+ import { RegionStore } from '../store/region-store.service';
7
+ import { VisualizerStore } from '../store/visualizer-store.service';
8
+ /**
9
+ * Shared store-delegation base for the OpenSeadragon and napari-js
10
+ * `IVisualizer` backends. The entire `IRegionStore` and `IDisplayOptions`
11
+ * surfaces (plus the two classification-colour members) are pure forwarders to
12
+ * the shared `RegionStore` / `VisualizerStore` in BOTH backends — so they live
13
+ * here once, as a single source of truth, rather than being copied per backend.
14
+ * (This is the "cross-backend behaviour that isn't rendering belongs in a
15
+ * shared abstraction" convention from CLAUDE.md; the extraction closes
16
+ * SHARED-BACKEND-REFACTOR.md.)
17
+ *
18
+ * Backend-specific members — `load`/`plot`/`reset`/zoom/`setZIndex`/readback,
19
+ * the region OVERLAY, tool wiring, histograms, scale bar, tiling, colormap LUT
20
+ * application — deliberately stay in each subclass.
21
+ *
22
+ * NOT `@Injectable`: an abstract base doesn't participate in Angular DI. Each
23
+ * subclass stays `@Injectable`, declares its own injected dependencies
24
+ * (including the two stores), and passes them to `super(...)`. Plotly is
25
+ * intentionally not a subclass — it has its own region model.
26
+ */
27
+ export declare abstract class BaseStoreVisualizer implements IRegionStore, IDisplayOptions {
28
+ protected readonly regionStore: RegionStore;
29
+ protected readonly store: VisualizerStore;
30
+ protected constructor(regionStore: RegionStore, store: VisualizerStore);
31
+ setRegions(regions: Region[], showRegionLabel?: boolean, isRegionSaveOn?: boolean, fillColor?: string, append?: boolean): void;
32
+ getRegions(): Region[];
33
+ getRegionPolygons(): any[];
34
+ getRegionUpdateEvent(): Observable<any[]>;
35
+ setSelectedShapeIndices(indices: number[]): void;
36
+ getSelectedShapeIndices$(): Observable<number[]>;
37
+ selectRegion(region: Region): void;
38
+ deleteActiveShape(): void;
39
+ getShowShapeLabel(): boolean;
40
+ getShapeColor(): string;
41
+ getFillColor(): string;
42
+ plotPreviousShapes(): void;
43
+ setPreviousShapes(shapes: any[]): void;
44
+ getPreviousShapes(): any[];
45
+ undo(): void;
46
+ redo(): void;
47
+ canUndo(): boolean;
48
+ canRedo(): boolean;
49
+ getCanUndo$(): Observable<boolean>;
50
+ getCanRedo$(): Observable<boolean>;
51
+ resetUndoHistory(): void;
52
+ importRegions(geoJsonStr: string): Region[];
53
+ exportRegions(regions: Region[]): void;
54
+ getGeoJsonString(regions: Region[]): string;
55
+ enterStackMode(slices: Map<number, Region[]>, initialZ?: number, saveLayout?: 'combined' | 'per-slice-file'): void;
56
+ exitStackMode(): void;
57
+ isStackMode(): boolean;
58
+ getStackSaveLayout(): 'combined' | 'per-slice-file';
59
+ setDisplaySlice(z: number): void;
60
+ getSliceRegions(): Region[];
61
+ getStackSaveSlices(): Map<number, Region[]>;
62
+ getClassificationColors(): Map<string, string>;
63
+ setClassificationColor(label: string, color: string): void;
64
+ getColormap(): Observable<ColormapNode | null>;
65
+ setColormap(colormap: ColormapNode): void;
66
+ getColormapOptions(): ColormapNode[];
67
+ getReverseScale(): Observable<boolean>;
68
+ setReverseScale(reverscale: any): void;
69
+ setImageMeta(imageMeta: IImageMetadata[]): void;
70
+ getImageMeta(): Observable<IImageMetadata[]>;
71
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * DOM text labels for the napari-js 3D axes gizmo (jit-ui#102). The {@link AxesLayer} draws the
3
+ * axis lines/ticks/box in WebGPU; this overlay adds the crisp X/Y/Z + scale text on top, projected
4
+ * with the 3D camera's view-projection so each label tracks its anchor as the volume orbits.
5
+ * Mirrors the {@link NapariScaleBar} overlay pattern (absolute-positioned over the host, updated on
6
+ * every `camera3d.changed`). Falls back to pixel/slice counts when no physical µm/pixel is known.
7
+ */
8
+ /** One axis label: a world-space anchor (the axis end, in the volume's centred box), the text to
9
+ * show, and its colour (matching the WebGPU axis colour). */
10
+ export interface AxisLabelSpec {
11
+ anchor: [number, number, number];
12
+ text: string;
13
+ color: string;
14
+ }
15
+ /** The slice of napari's Camera3D this overlay reads. `viewProjection` is column-major (gl-matrix). */
16
+ export interface AxesLabelCamera3D {
17
+ viewProjection(vw: number, vh: number): ArrayLike<number>;
18
+ readonly changed: {
19
+ connect(listener: () => void): () => void;
20
+ };
21
+ }
22
+ /**
23
+ * Project a world point through a column-major 4×4 MVP to CSS-pixel screen coordinates.
24
+ * Returns `visible: false` when the point is at/behind the camera (w ≤ 0). Pure — unit-tested.
25
+ */
26
+ export declare function projectPoint(mvp: ArrayLike<number>, p: [number, number, number], vw: number, vh: number): {
27
+ x: number;
28
+ y: number;
29
+ visible: boolean;
30
+ };
31
+ export declare class NapariAxesLabels {
32
+ private readonly host;
33
+ private readonly camera3d;
34
+ private readonly labels;
35
+ private readonly els;
36
+ private readonly disconnectCamera;
37
+ private readonly resizeObserver?;
38
+ private visible;
39
+ constructor(host: HTMLElement, camera3d: AxesLabelCamera3D, labels: AxisLabelSpec[]);
40
+ setVisible(visible: boolean): void;
41
+ /** Replace the label anchors/text in place (same count) and reproject — lets a host move the
42
+ * labels when the box geometry changes live (e.g. a Z-height gizmo restretching the volume)
43
+ * without tearing down and recreating the DOM elements (which would flicker). */
44
+ updateAnchors(labels: AxisLabelSpec[]): void;
45
+ private update;
46
+ destroy(): void;
47
+ }
@@ -0,0 +1,115 @@
1
+ import { IRegionOverlay, RegionToolMode } from '../../contracts/region-overlay.contract';
2
+ import { RegionStore } from '../../store/region-store.service';
3
+ /** The slice of the napari Viewer the overlay needs (coord transforms + control gating). */
4
+ interface OverlayViewer {
5
+ canvasToWorld(clientX: number, clientY: number): [number, number];
6
+ worldToCanvas(worldX: number, worldY: number): [number, number];
7
+ setControlsEnabled(enabled: boolean): void;
8
+ readonly camera: {
9
+ readonly changed: {
10
+ connect(listener: () => void): () => void;
11
+ };
12
+ };
13
+ }
14
+ /**
15
+ * SVG region overlay for the napari-js WebGPU image view (jit-ui#102), mirroring the OSD backend's
16
+ * {@link OsdRegionOverlay} but driven by napari's `canvasToWorld`/`worldToCanvas` transforms.
17
+ * Vector shapes are drawn in an absolutely-positioned `<svg>` over the canvas (no need to push
18
+ * them through WebGPU). It writes completed shapes to the shared {@link RegionStore} (so save /
19
+ * undo / export work identically to OSD) and re-renders from the store on every camera move,
20
+ * region change, and selection change.
21
+ *
22
+ * Supports (jit-ui#102): rectangle / polygon / freehand path drawing, click-select and rubber-band
23
+ * marquee select, pan/zoom gating via `setControlsEnabled`, body move, vertex move/add/delete,
24
+ * bezier handle editing, and donut holes (including hole vertex + hole-bezier-handle editing) —
25
+ * full parity with {@link OsdRegionOverlay}.
26
+ */
27
+ export declare class NapariRegionOverlay implements IRegionOverlay {
28
+ private readonly host;
29
+ private readonly viewer;
30
+ private readonly store;
31
+ private readonly svg;
32
+ private readonly subs;
33
+ private readonly disconnectCamera;
34
+ private mode;
35
+ private selected;
36
+ /** In-progress drawing state (image-space). */
37
+ private draftRect;
38
+ /** In-progress rubber-band selection marquee (select mode), image-space. */
39
+ private marquee;
40
+ /** Dedicated marquee rect element, updated directly during the drag (no full region redraw). */
41
+ private marqueeEl;
42
+ private draftPath;
43
+ private drawing;
44
+ /** In-progress manipulation (select/move modes): dragging a body, a polygon vertex, or a
45
+ * rectangle corner. `anchor` is the fixed opposite corner for a rectangle resize. */
46
+ private edit;
47
+ constructor(host: HTMLElement, viewer: OverlayViewer, store: RegionStore);
48
+ setMode(mode: RegionToolMode): void;
49
+ setSelectedBezier(bezier: boolean): void;
50
+ destroy(): void;
51
+ /** Pointer client coords → rounded image coords. */
52
+ private toImage;
53
+ /** Image coords → SVG-local px (the svg overlays the canvas at the same client rect). */
54
+ private toLocal;
55
+ private readonly onPointerDown;
56
+ private readonly onPointerMove;
57
+ private readonly onPointerUp;
58
+ /** Click-to-place polygon: add a vertex, or close when clicking near the first one. */
59
+ private handlePolygonClick;
60
+ private readonly onDblClick;
61
+ /** The currently-selected region (single selection), or null. */
62
+ private selectedRegion;
63
+ /** Screen distance (px) between a client point and an image coord. */
64
+ private screenDist;
65
+ /**
66
+ * Start a select/move interaction: grab a handle (rectangle corner) or vertex of the already-
67
+ * selected region first; otherwise select the topmost region under the cursor and drag its body.
68
+ */
69
+ private beginManipulation;
70
+ /** Create/update the marquee rect element directly (avoids a full region redraw per move). */
71
+ private updateMarqueeEl;
72
+ /** Remove the marquee element from the SVG. */
73
+ private clearMarqueeEl;
74
+ /** Test whether a client point grabs a rectangle corner or a polygon vertex of `region`. */
75
+ private hitHandle;
76
+ /** Apply the live drag for the active manipulation (image coords `ix,iy`). */
77
+ private applyManipulation;
78
+ /** addpoint mode: insert a vertex on the selected polygon's nearest edge at the click. */
79
+ private handleAddPoint;
80
+ /** deletepoint mode: remove the selected polygon's vertex nearest the click. */
81
+ private handleDeletePoint;
82
+ /** Distance from point (px,py) to segment (ax,ay)-(bx,by), in image units. */
83
+ private pointSegDist;
84
+ /** Finalize a rubber-band marquee: select every region whose bounding box it overlaps (a tiny
85
+ * marquee is treated as a click on empty space → clear the selection). */
86
+ private finishMarquee;
87
+ /** A region's bounding box in image coords (rectangle, polygon, or multipolygon), or null. */
88
+ private regionBBox;
89
+ private commitRectangle;
90
+ private commitPolygon;
91
+ private hitTest;
92
+ redraw(): void;
93
+ /** Draw a region's classification label at its top-left, when labels are enabled (matches OSD). */
94
+ private drawLabel;
95
+ /** Draw grab handles for the selected region: rectangle corners or polygon vertices. */
96
+ private drawHandles;
97
+ /** Draw one bezier control point (anchor + handle offset) as a small circle connected to its
98
+ * anchor by a tangent line. `handle` is the [dx,dy] offset from the anchor in image space. */
99
+ private drawBezierHandle;
100
+ private buildRegionEl;
101
+ /** Path data for a polygon: the exterior ring (bezier or straight) plus any holes (bezier when
102
+ * the donut carries hole handles, else straight) as sub-paths — even-odd fill cuts them out. */
103
+ private polygonPathData;
104
+ /** SVG path data for a straight ring/polyline in image coords (closed appends `Z`). */
105
+ private straightPath;
106
+ /** SVG cubic-bezier path data for any ring (exterior or hole): anchors joined by cubic segments
107
+ * whose control points are `anchor + handleOut` (leaving) and `nextAnchor + handleIn` (arriving),
108
+ * in image space. Used for both the exterior and (donut) hole rings. */
109
+ private ringBezierPath;
110
+ private style;
111
+ /** Draw the in-progress rectangle / path preview. */
112
+ private drawDraft;
113
+ private styleDraft;
114
+ }
115
+ export {};