@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,123 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { Observable } from 'rxjs';
3
+ import { ClassPreset, PresetSet } from '../models/class-preset';
4
+ import { PreferencesPort } from '../contracts/ports/preferences.port';
5
+ import { IImageMetadata } from '../contracts/image.contract';
6
+ import { IChannelState } from '../contracts/channel-histogram-api.contract';
7
+ import * as i0 from "@angular/core";
8
+ /**
9
+ * Backend-neutral store for the **visualization session** — the state that
10
+ * describes *how* the current image is being viewed, independent of which
11
+ * rendering backend (Plotly or OpenSeadragon) is on screen:
12
+ *
13
+ * - the active colormap / LUT and its reverse-scale toggle,
14
+ * - the current image's physical metadata (µm/pixel etc.),
15
+ * - the classification label → colour map,
16
+ * - which on-canvas tool is currently active.
17
+ *
18
+ * Both backends read and write this single instance, so they stay in lock-step
19
+ * regardless of which one is rendering. Previously this state lived inside
20
+ * `PlotlyService`, which forced the OpenSeadragon backend to depend on the
21
+ * Plotly service purely to read the shared colormap; this store removes that
22
+ * coupling — neither backend owns the session state.
23
+ *
24
+ * NOTE: region *geometry* (the drawn shapes / per-image region cache) still
25
+ * lives in `PlotlyService` for now; extracting it into a sibling region store
26
+ * is a separate follow-up.
27
+ */
28
+ export declare class VisualizerStore {
29
+ private readonly http;
30
+ private readonly prefsPort;
31
+ private readonly colormap$;
32
+ private readonly reverseScale$;
33
+ private readonly imageMeta$;
34
+ private readonly channelStates$;
35
+ private defaultChannelStates;
36
+ private readonly grayscale$;
37
+ private readonly invert$;
38
+ private presetSet;
39
+ private readonly presetSet$;
40
+ private readonly savePresets$;
41
+ private presetsLoaded;
42
+ private readonly activeTool$;
43
+ constructor(http?: HttpClient | null, prefsPort?: PreferencesPort | null);
44
+ /**
45
+ * Resolve the colormap tree's LUT keys (e.g. "GREYS_LUT") to their colour
46
+ * arrays from a served JSON asset. The ~630 KB of LUT data lives outside the
47
+ * bundle (as `/assets/plotting/colormap-luts.json`) so it never enters the TS
48
+ * / webpack module graph — that data-in-source was the main driver of the
49
+ * build's >2 GB heap. Named Plotly scales (e.g. "Viridis") aren't keys in the
50
+ * JSON, so they're left untouched. The default LUT ("Greys Inv" → the Plotly
51
+ * "Greys" scale) needs no JSON, so the first render works before this resolves.
52
+ */
53
+ private loadColormapLuts;
54
+ private initPresetPersistence;
55
+ private normalizePresetSet;
56
+ /** Queue a debounced save. No-ops until the initial load resolves (and when no port is bound). */
57
+ private queuePresetSave;
58
+ /** Persist the current preset set immediately, bypassing the incremental-edit
59
+ * debounce. Used for explicit bulk actions (Apply / Import / Reset). */
60
+ private savePresetsNow;
61
+ /** The available colormap options (tree for the LUT dropdown). */
62
+ getColormapOptions(): any;
63
+ getColormap(): Observable<any>;
64
+ /** Synchronous current value — for render paths that read it while building
65
+ * a frame (e.g. Plotly's colorscale) rather than subscribing. */
66
+ currentColormap(): any;
67
+ setColormap(colormap: any): void;
68
+ getReverseScale(): Observable<boolean>;
69
+ currentReverseScale(): boolean;
70
+ setReverseScale(reverse: boolean): void;
71
+ getImageMeta(): Observable<IImageMetadata[]>;
72
+ /**
73
+ * Patch the physical pixel size (µm/pixel) onto the current image meta and
74
+ * re-emit, without touching the derived channels. The OSD tile descriptor
75
+ * (from the server's Bio-Formats `/tiles/info`) is authoritative for scaled
76
+ * images — `imageInfo.imageMeta` often carries no mpp — so the renderer feeds
77
+ * it here once the descriptor loads, letting area/scale consumers (the Region
78
+ * Editor) show µm²/mm² instead of px². No-op when neither axis is positive.
79
+ */
80
+ setPhysicalPixelSize(mppX?: number, mppY?: number): void;
81
+ setImageMeta(imageMeta: IImageMetadata[]): void;
82
+ /** Channels for an image:
83
+ * - RGB (rgbChannels ≥ 3) → Red/Green/Blue;
84
+ * - multichannel fluorescence (channelCount > 1) → one channel per band,
85
+ * named/tinted from the server `channelInfo` when present, else a palette;
86
+ * - otherwise a single grayscale "Intensity" channel. */
87
+ private deriveChannels;
88
+ getChannelStates(): Observable<IChannelState[]>;
89
+ currentChannelStates(): IChannelState[];
90
+ /** Patch one channel by index (immutable update). */
91
+ setChannelState(index: number, partial: Partial<IChannelState>): void;
92
+ /** Replace all channel states (used by auto/reset). */
93
+ setChannelStates(states: IChannelState[]): void;
94
+ /** Reset one channel's display window, gamma AND colour to the values derived
95
+ * for the current image (full 0..255 range, gamma 1, the channel's default
96
+ * tint). Falls back to neutral defaults if no baseline was captured. */
97
+ resetChannelState(index: number): void;
98
+ getGrayscale(): Observable<boolean>;
99
+ currentGrayscale(): boolean;
100
+ setGrayscale(on: boolean): void;
101
+ getInvert(): Observable<boolean>;
102
+ currentInvert(): boolean;
103
+ setInvert(on: boolean): void;
104
+ /** Name→colour view of the current preset set (compat for backend renderers
105
+ * that still read a Map). */
106
+ getClassificationColors(): Map<string, string>;
107
+ /** Upsert a single class colour (used by the editor's per-class colour picker). */
108
+ setClassificationColor(label: string, color: string): void;
109
+ getPresetSet(): PresetSet;
110
+ getPresetSet$(): Observable<PresetSet>;
111
+ setPresetSet(set: PresetSet): void;
112
+ /** Add or update a class (keyed by exact stored `name`). */
113
+ upsertClass(preset: ClassPreset): void;
114
+ removeClass(name: string): void;
115
+ resetPresets(): void;
116
+ /** Force a (debounced) write-back of the current preset set. */
117
+ persistPresets(): void;
118
+ getActiveTool$(): Observable<string | null>;
119
+ getActiveTool(): string | null;
120
+ setActiveTool(tool: string | null): void;
121
+ static ɵfac: i0.ɵɵFactoryDeclaration<VisualizerStore, [{ optional: true; }, { optional: true; }]>;
122
+ static ɵprov: i0.ɵɵInjectableDeclaration<VisualizerStore>;
123
+ }
@@ -0,0 +1,143 @@
1
+ import { WandService } from '../wand/wand.service';
2
+ import { WandToolHost } from '../wand/wand-tool.service';
3
+ import * as i0 from "@angular/core";
4
+ /** Brush parameters. `size` is the brush *diameter* in matrix (image) pixels. */
5
+ export interface BrushOptions {
6
+ size?: number;
7
+ }
8
+ /**
9
+ * The brush host is identical to the wand's — both need the cached-image
10
+ * coordinate frame, the overlay container, the coordinate transform, and
11
+ * read/write access to the shared region list. The brush ignores the wand's
12
+ * pixel values (it paints a geometric disc rather than flood-filling by colour),
13
+ * so reusing {@link WandToolHost} lets each backend bind the same host object.
14
+ */
15
+ export type BrushToolHost = WandToolHost;
16
+ /**
17
+ * QuPath-style brush tool. Painting a stroke unions a disc of the configured
18
+ * size into the active region as the cursor drags; holding <kbd>Shift</kbd>
19
+ * subtracts instead (eraser brush), matching the wand's modifier. The stroke is
20
+ * accumulated as a bbox-relative mask (exactly like {@link WandToolService}) so
21
+ * the brush inherits the wand's adopt-existing-region and merge-on-touch
22
+ * behaviour, then the union boundary is traced back into a polygon Region.
23
+ *
24
+ * No pixel sampling and no cursor indicator: the painted stroke itself shows the
25
+ * brush size. The overlay canvas only captures the pointer.
26
+ *
27
+ * Lifecycle mirrors the wand: a backend binds its host once, then toggles the
28
+ * tool with `setMode(true | false, options)`.
29
+ *
30
+ * Holes / donuts (jit-ui#85): brushing a ring that encloses an unpainted area
31
+ * keeps the enclosed hole — {@link WandService.maskToPolygons} traces interior
32
+ * rings into {@link Polygon.holes}, which adopt/merge preserve (the re-rasterize
33
+ * punches the holes back out). The OpenSeadragon overlay renders them with
34
+ * even-odd fill and GeoJSON round-trips them as extra Polygon rings. The Plotly
35
+ * (Heatmap) backend currently renders the filled exterior only.
36
+ */
37
+ export declare class BrushToolService {
38
+ private wandService;
39
+ private host;
40
+ private overlay;
41
+ private active;
42
+ /**
43
+ * Accumulated brush region (bbox-relative mask). Persists across mouseup so a
44
+ * subsequent stroke extends the *same* region until the user switches tool —
45
+ * matching QuPath, and the wand.
46
+ */
47
+ private stroke;
48
+ /** Id of the region this stroke is editing (null = a fresh region). For an
49
+ * erase that splits the region, this tracks the largest resulting piece. */
50
+ private strokeRegionId;
51
+ /** Readback ratio/origin signature the active stroke is tied to; a change (zoom/pan) invalidates
52
+ * it so it isn't re-committed at a different scale (jit-ui#102). */
53
+ private strokeRatioSig;
54
+ /** Ids of the extra regions produced when an erase stroke splits a region
55
+ * into disconnected pieces — reused across drag ticks so the split pieces
56
+ * keep stable identities instead of being recreated each tick. */
57
+ private strokeExtraIds;
58
+ /** Previous cursor position (matrix coords) within the current drag, so fast
59
+ * drags paint a continuous stroke rather than disconnected dabs. */
60
+ private lastMatrix;
61
+ private dragging;
62
+ private size;
63
+ private readonly boundMouseDown;
64
+ private readonly boundMouseMove;
65
+ private readonly boundMouseUp;
66
+ constructor(wandService: WandService);
67
+ /** Wire the tool to its host. Must be called once before `setMode(true)`. */
68
+ bindHost(host: BrushToolHost): void;
69
+ /** Toggle the brush on/off. */
70
+ setMode(active: boolean, options?: BrushOptions): void;
71
+ /** Live-update the brush size (matrix-pixel diameter). */
72
+ setSize(size: number): void;
73
+ /** Drop the active brush region so the next stroke starts a new one. */
74
+ clearActiveRegion(): void;
75
+ private createOverlay;
76
+ private destroyOverlay;
77
+ private onMouseDown;
78
+ private onMouseMove;
79
+ private onMouseUp;
80
+ private resetStroke;
81
+ /**
82
+ * Paint (or erase) a disc — or a swept line of discs since the previous
83
+ * tick — into the active region's accumulator mask, re-trace the boundary,
84
+ * and commit the updated Region. Shift = erase.
85
+ */
86
+ private applyAtClient;
87
+ /**
88
+ * OR (add) or AND-NOT (erase) a filled disc of `radius` matrix-pixels centred
89
+ * at (cx, cy) into the accumulator, growing its bbox to fit when adding.
90
+ */
91
+ private stampDisc;
92
+ /**
93
+ * Ensure the accumulator's bbox covers [px0,py0,px1,py1) (clamped to the
94
+ * image), allocating/copying a larger mask when it must grow. Returns false if
95
+ * the requested box is empty after clamping.
96
+ */
97
+ private ensureStrokeCovers;
98
+ /** True if (matrixX, matrixY) lies inside the current stroke accumulator. */
99
+ private pointInStroke;
100
+ /**
101
+ * Remove the region(s) referenced by the stroke and reset it — used when an
102
+ * erase stroke deletes every pixel.
103
+ */
104
+ private dropActiveShape;
105
+ /** A region's closed-polygon vertices (image/data coords), or null when it
106
+ * isn't a fillable closed polygon (rectangles, open polylines). */
107
+ private regionVerts;
108
+ /** Whether a region can be faithfully rasterized at this zoom (rx/ry = data units per matrix px).
109
+ * Editing rasterizes + re-traces the region, so one whose matrix-space bbox exceeds the
110
+ * rasterizer cap would come back rescaled/corrupted (e.g. a whole-slide annotation while zoomed
111
+ * out) — skip adopt/merge for those and only edit them near native zoom (jit-ui#102). */
112
+ private fitsForEdit;
113
+ /** Convert a region's hole rings from image/data coords into matrix coords so
114
+ * they line up with the stroke accumulator (jit-ui#85). */
115
+ private holesToMatrix;
116
+ /**
117
+ * If (matrixX, matrixY) falls inside an existing region, rasterize it into the
118
+ * stroke accumulator so subsequent brush input extends it rather than starting
119
+ * a new region.
120
+ */
121
+ private tryAdoptShapeAt;
122
+ /**
123
+ * Fold every region whose rasterized mask overlaps the stroke mask into the
124
+ * stroke and remove it from the list, so brushing across regions merges them.
125
+ */
126
+ private mergeOverlappingShapes;
127
+ /**
128
+ * Commit the stroke's connected pieces as regions — the largest keeps the
129
+ * stroke's region identity, additional pieces (from an erase that split the
130
+ * region) become their own regions tracked in `strokeExtraIds` so they keep
131
+ * stable identities across drag ticks. The store mints ids on commit, which
132
+ * we read back so subsequent ticks replace the same regions.
133
+ */
134
+ private commitComponents;
135
+ /**
136
+ * Build a Region for one component and insert it into `regions`: replace the
137
+ * region with `id` in place if it exists, otherwise append a new one. Returns
138
+ * the Region instance (its id is minted later by the store when new).
139
+ */
140
+ private upsertComponent;
141
+ static ɵfac: i0.ɵɵFactoryDeclaration<BrushToolService, never>;
142
+ static ɵprov: i0.ɵɵInjectableDeclaration<BrushToolService>;
143
+ }
@@ -0,0 +1,30 @@
1
+ import { CachedImageData } from '../wand/wand-tool.service';
2
+ /** A client-side crop of the loaded image — the browser equivalent of the JIT
3
+ * server slide-crop, taken from the pixels already in the viewer. */
4
+ export interface CroppedImage {
5
+ /** RGBA pixels of the crop, row-major. */
6
+ data: Uint8ClampedArray;
7
+ width: number;
8
+ height: number;
9
+ /** Crop origin in image (matrix) coords — lets masks map back to the frame. */
10
+ matrixX0: number;
11
+ matrixY0: number;
12
+ }
13
+ /** A box in image *data* coordinates (as stored on a Rectangle region). */
14
+ export interface DataBox {
15
+ x0: number;
16
+ y0: number;
17
+ x1: number;
18
+ y1: number;
19
+ }
20
+ /**
21
+ * Browser "slide crop": extract the box region (data coords) from a cached image
22
+ * frame as an RGBA image, clamped to the image bounds. Grayscale frames are
23
+ * replicated across R/G/B; RGB tuples are copied through. Returns null when the
24
+ * box is empty/outside the image.
25
+ *
26
+ * The output feeds an automatic segmenter (e.g. cellpose-SAM): run it on the
27
+ * crop, then offset the resulting masks by (matrixX0, matrixY0) to place them
28
+ * back on the full frame.
29
+ */
30
+ export declare function cropImageRegion(cached: CachedImageData, frameIndex: number, box: DataBox): CroppedImage | null;
@@ -0,0 +1,32 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { WandService } from '../wand/wand.service';
3
+ import { WandToolHost } from '../wand/wand-tool.service';
4
+ import { ICellSegmenter } from '../../contracts/cell-segmenter.contract';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * Automatic cell segmentation inside drawn boxes (jit-ui#90). For each rectangle
8
+ * it client slide-crops the box from the loaded image, runs an automatic
9
+ * segmenter (cellpose-SAM, supplied by the host via {@link ICellSegmenter}) on
10
+ * the crop, and turns every cell instance into a region — offset back onto the
11
+ * frame. The prompt rectangle is replaced by its cell regions.
12
+ *
13
+ * This is the complement to the promptable SAM tool: cellpose-SAM can't take a
14
+ * box prompt, so the box just bounds the crop it segments automatically.
15
+ */
16
+ export declare class CellSegmentToolService {
17
+ private wandService;
18
+ private host;
19
+ readonly status$: BehaviorSubject<string>;
20
+ readonly busy$: BehaviorSubject<boolean>;
21
+ readonly progress$: BehaviorSubject<number>;
22
+ constructor(wandService: WandService);
23
+ bindHost(host: WandToolHost): void;
24
+ /**
25
+ * Crop + cellpose-segment every rectangle; append the cell regions and drop
26
+ * the prompt rectangles that produced cells. Returns the number of regions added.
27
+ */
28
+ segmentBoxes(segmenter: ICellSegmenter): Promise<number>;
29
+ private makeRegion;
30
+ static ɵfac: i0.ɵɵFactoryDeclaration<CellSegmentToolService, never>;
31
+ static ɵprov: i0.ɵɵInjectableDeclaration<CellSegmentToolService>;
32
+ }
@@ -0,0 +1,39 @@
1
+ import type { ICellSegmenter, CellSegmentation, CellSegmentProgress } from '../../contracts/cell-segmenter.contract';
2
+ import type { Cellpose } from 'cellpose-js';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Default in-library {@link ICellSegmenter} backed by cellpose-js (WebGPU/WASM
6
+ * ONNX) — so the toolbar's automatic **Cellpose** tool works out of the box in
7
+ * any app, with no host wiring (jit-ui#90). `cellpose-js` is a peer dependency
8
+ * and is **lazy-imported** on first use, so apps that never run Cellpose pay
9
+ * nothing for it. A host can still override the {@link CELL_SEGMENTER} token to
10
+ * supply a different implementation.
11
+ *
12
+ * Owns a single shared {@link Cellpose} instance (one model load, one WebGPU
13
+ * session, one worker). {@link getModel} exposes that instance so a host's
14
+ * processing pipeline can reuse it instead of loading the ~588 MB model twice.
15
+ */
16
+ export declare class CellposeSegmenterService implements ICellSegmenter {
17
+ private instance;
18
+ private loading;
19
+ private modelUrl;
20
+ /** Point the segmenter at a different hosted CPSAM ONNX (before first use). */
21
+ setModelUrl(url: string): void;
22
+ segmentCells(image: {
23
+ data: Uint8ClampedArray;
24
+ width: number;
25
+ height: number;
26
+ }, progress?: CellSegmentProgress): Promise<CellSegmentation>;
27
+ /**
28
+ * The shared Cellpose instance, lazily created on first use and reused
29
+ * thereafter (deduped across concurrent callers). Exposed so a host pipeline
30
+ * engine can run richer `segment()` options on the same instance. `onProgress`
31
+ * reports raw downloaded/total bytes (`total` is null when unknown); `onStatus`
32
+ * reports worker-init phase strings.
33
+ */
34
+ getModel(onProgress?: (loaded: number, total: number | null) => void, onStatus?: (status: string) => void): Promise<Cellpose>;
35
+ /** Whether the shared model is already loaded (warm). */
36
+ isLoaded(): boolean;
37
+ static ɵfac: i0.ɵɵFactoryDeclaration<CellposeSegmenterService, never>;
38
+ static ɵprov: i0.ɵɵInjectableDeclaration<CellposeSegmenterService>;
39
+ }
@@ -0,0 +1,25 @@
1
+ import { ISamSession, SamEmbedding, SamMaskResult, SamModelDef, SamPrompt } from '../../contracts/sam.contract';
2
+ export declare class OnnxSamSession implements ISamSession {
3
+ private mode;
4
+ private loaded;
5
+ private model;
6
+ private inputSize;
7
+ private worker;
8
+ private seq;
9
+ private readonly pending;
10
+ private encoder;
11
+ private decoder;
12
+ private nextToken;
13
+ private readonly embeddings;
14
+ loadModel(model: SamModelDef, onProgress?: (fraction: number) => void): Promise<void>;
15
+ isLoaded(): boolean;
16
+ embed(image: {
17
+ data: Uint8ClampedArray;
18
+ width: number;
19
+ height: number;
20
+ }): Promise<SamEmbedding>;
21
+ decode(embedding: SamEmbedding, prompt: SamPrompt): Promise<SamMaskResult>;
22
+ dispose(): void;
23
+ private ensureWorker;
24
+ private call;
25
+ }
@@ -0,0 +1,4 @@
1
+ /** Override where onnxruntime-web loads its WASM sidecars from. See module docs. */
2
+ export declare function setOrtWasmBase(base: string): void;
3
+ /** The configured onnxruntime-web WASM base (default `'/assets/ort/'`). */
4
+ export declare function getOrtWasmBase(): string;
@@ -0,0 +1,36 @@
1
+ import { SamModelDef } from '../../contracts/sam.contract';
2
+ /**
3
+ * Registry of promptable SAM models for the browser segment tool.
4
+ *
5
+ * micro-sam (microscopy-finetuned, promptable) and patho-sam (histopathology-
6
+ * finetuned) are entries; SAM3 slots in here once its quantized ONNX export and
7
+ * a `variant: 'sam3'` decoder path are published. The
8
+ * automatic cellpose-SAM model is intentionally NOT here — it's not promptable
9
+ * and lives in the processing-pipeline's cellpose engine as the automatic tool.
10
+ *
11
+ * `encoderUrl` / `decoderUrl` point at the public HF-hosted ONNX pairs by
12
+ * default, so the segment tools work out of the box in any host (mirroring the
13
+ * cellpose default). A host can repoint them at its own hosting (e.g. a GCS
14
+ * bucket) at runtime via {@link setSamModelUrls}; an empty URL disables a model
15
+ * (the session throws a clear "not configured" error). Export/quantization
16
+ * tooling: the sibling `browser-onnx-tools` project; see docs/sam-segmentation-design.md.
17
+ */
18
+ export declare const SAM_MODELS: SamModelDef[];
19
+ /** Initial default model id (overridden at runtime once the host configures a
20
+ * hosted model via {@link setSamModelUrls}). */
21
+ export declare const DEFAULT_SAM_MODEL_ID: string;
22
+ /** Look up a model by id; falls back to the active default when id is
23
+ * unknown/absent. */
24
+ export declare function getSamModel(id?: string): SamModelDef;
25
+ /** The active default model id (what the tools/picker use when unset). */
26
+ export declare function getDefaultSamModelId(): string;
27
+ /** Set the active default model id (must be a registered model). */
28
+ export declare function setDefaultSamModel(id: string): void;
29
+ /** True when a model has both ONNX URLs configured (i.e. it can actually run). */
30
+ export declare function isSamModelReady(model: SamModelDef): boolean;
31
+ /**
32
+ * Point a registered model at its hosted ONNX pair (HF / GCS). Called by the
33
+ * host's composition root once hosting is decided, keeping deployment URLs out
34
+ * of the library.
35
+ */
36
+ export declare function setSamModelUrls(id: string, encoderUrl: string, decoderUrl: string): void;
@@ -0,0 +1,48 @@
1
+ import * as ort from 'onnxruntime-web';
2
+ import type { SamPrompt } from '../../contracts/sam.contract';
3
+ /**
4
+ * Shared, DOM-free SAM inference primitives used by BOTH inference backends:
5
+ * the in-process session (`OnnxSamSession`, main thread) and the dedicated
6
+ * Web Worker (`onnx-sam.worker`). Keeping these here avoids duplicating the
7
+ * preprocessing / decoder-prompt math and keeps the worker DOM-free (it can't
8
+ * import sam-prompt.ts, which pulls in DOM types).
9
+ */
10
+ export declare const PIXEL_MEAN: number[];
11
+ export declare const PIXEL_STD: number[];
12
+ /** Encoder output for one image, reused across prompts. */
13
+ export interface CoreEmbedding {
14
+ data: Float32Array;
15
+ dims: number[];
16
+ scale: number;
17
+ imageWidth: number;
18
+ imageHeight: number;
19
+ }
20
+ /** Decoder output: a binary mask at original-image resolution. */
21
+ export interface CoreMask {
22
+ mask: Uint8Array;
23
+ width: number;
24
+ height: number;
25
+ iou: number;
26
+ }
27
+ /** Fetch a model as an ArrayBuffer, streaming progress and caching in the Cache
28
+ * API (so it isn't re-downloaded). Cache hit → progress jumps to 1. Works on
29
+ * the main thread and in a worker (both have `fetch` + `caches`). */
30
+ export declare function fetchModel(url: string, onProgress?: (f: number) => void): Promise<ArrayBuffer>;
31
+ /** Resize (long side → size, bilinear), pad to size×size, SAM-normalize → CHW float32. */
32
+ export declare function preprocess(data: Uint8ClampedArray, width: number, height: number, size: number, scale: number): Float32Array;
33
+ /** Assemble decoder `point_coords`/`point_labels` from a prompt, in encoder
34
+ * (resized) space. Box = two points labelled 2/3; points use 1/0; a points-only
35
+ * prompt pads the absent box slot with `[0,0]` labelled -1. */
36
+ export declare function buildDecoderPrompt(prompt: SamPrompt, scale: number): {
37
+ pointCoords: Float32Array;
38
+ pointLabels: Float32Array;
39
+ numPoints: number;
40
+ };
41
+ /** Binarize mask logits (`> threshold`) into a 0/1 mask. */
42
+ export declare function binarizeMask(logits: Float32Array, threshold?: number): Uint8Array;
43
+ /** Index of the highest-scoring mask in a multimask decoder output. */
44
+ export declare function bestMaskIndex(iou: Float32Array | number[]): number;
45
+ /** Run the encoder on an RGBA image → a reusable embedding. */
46
+ export declare function runEncoder(encoder: ort.InferenceSession, data: Uint8ClampedArray, width: number, height: number, inputSize: number): Promise<CoreEmbedding>;
47
+ /** Run the decoder for one prompt against a cached embedding → a binary mask. */
48
+ export declare function runDecoder(decoder: ort.InferenceSession, e: CoreEmbedding, prompt: SamPrompt): Promise<CoreMask>;
@@ -0,0 +1,59 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { WandService } from '../wand/wand.service';
3
+ import { WandToolHost } from '../wand/wand-tool.service';
4
+ import { ISamSession } from '../../contracts/sam.contract';
5
+ import * as i0 from "@angular/core";
6
+ /** Interactive SAM point-prompt tool (jit-ui#90, P1).
7
+ *
8
+ * Each plain (positive) click segments the clicked object as its OWN new region
9
+ * — clicking a second fiber doesn't extend the first into it. Shift/Alt-click
10
+ * adds a negative (exclude) point that refines the CURRENT object, re-running
11
+ * the decoder against the (cached) image embedding and updating its live region.
12
+ * `commit()` (Enter) finalises early; `clear()` (Esc) discards the current
13
+ * prompt + its preview region. Mirrors the wand/brush on-canvas tool pattern and
14
+ * reuses WandService.maskToPolygons + the shared region store.
15
+ *
16
+ * Inference is behind {@link ISamSession} (lazy onnxruntime-web in production,
17
+ * a fake in tests).
18
+ */
19
+ export declare class SamPointToolService {
20
+ private wandService;
21
+ private host;
22
+ private overlay;
23
+ private session;
24
+ /** In-flight session load — dedupes a warm-up preload against the first click. */
25
+ private sessionLoad;
26
+ private model;
27
+ private embedding;
28
+ private embeddingKey;
29
+ /** Accumulated point prompts, in image (matrix) coords. */
30
+ private points;
31
+ /** Id of the in-progress (preview) region being refined, if committed to store. */
32
+ private regionId;
33
+ readonly status$: BehaviorSubject<string>;
34
+ readonly busy$: BehaviorSubject<boolean>;
35
+ /** Encoder-download progress (0..1) on the first click; -1 when not downloading. */
36
+ readonly progress$: BehaviorSubject<number>;
37
+ private readonly boundMouseDown;
38
+ constructor(wandService: WandService);
39
+ bindHost(host: WandToolHost): void;
40
+ setModel(id: string): void;
41
+ /** Test seam: inject a fake/alternate session. */
42
+ useSession(session: ISamSession): void;
43
+ setMode(active: boolean): void;
44
+ /** Eagerly load the model in the background (fire-and-forget). Safe to call
45
+ * repeatedly — it dedupes against an in-flight load and an existing session. */
46
+ preload(): void;
47
+ /** Finalise the current object: keep its region, start fresh next click. */
48
+ commit(): void;
49
+ /** Discard the in-progress prompt + its preview region. */
50
+ clear(): void;
51
+ private createOverlay;
52
+ private destroyOverlay;
53
+ private onMouseDown;
54
+ /** Replace (or insert) the in-progress preview region in the shared store. */
55
+ private upsertPreview;
56
+ private ensureSession;
57
+ static ɵfac: i0.ɵɵFactoryDeclaration<SamPointToolService, never>;
58
+ static ɵprov: i0.ɵɵInjectableDeclaration<SamPointToolService>;
59
+ }
@@ -0,0 +1,34 @@
1
+ import { CachedImageData } from '../wand/wand-tool.service';
2
+ import { SamPrompt } from '../../contracts/sam.contract';
3
+ /**
4
+ * Pure helpers for SAM inference — no DOM, no ORT, no `this` — so they're unit
5
+ * testable. The session uses these to assemble decoder inputs and to convert
6
+ * the cached image frame into the RGBA buffer the encoder preprocesses.
7
+ */
8
+ /**
9
+ * Build an RGBA buffer (the encoder's input image) from a cached image frame.
10
+ * Grayscale frames are replicated across R/G/B; RGB tuples are copied through.
11
+ * Out-of-range/missing pixels become opaque black.
12
+ */
13
+ export declare function frameToRgba(cached: CachedImageData, frameIndex: number): Uint8ClampedArray;
14
+ /**
15
+ * Assemble the SAM decoder's `point_coords` / `point_labels` from a prompt.
16
+ *
17
+ * Coordinates are scaled into the encoder's resized space (`scale =
18
+ * inputSize / max(imageW, imageH)`). A box is encoded as two points labelled
19
+ * `2` (top-left) and `3` (bottom-right); positive/negative points use `1`/`0`.
20
+ * When there are points but no box, a padding point `[0,0]` labelled `-1` is
21
+ * appended (the decoder expects the box slots padded when absent).
22
+ */
23
+ export declare function buildDecoderPrompt(prompt: SamPrompt, scale: number): {
24
+ pointCoords: Float32Array;
25
+ pointLabels: Float32Array;
26
+ numPoints: number;
27
+ };
28
+ /**
29
+ * Binarize SAM mask logits (`> threshold`, default 0 per SAM's mask_threshold)
30
+ * into a 0/1 mask the contour tracer (WandService.maskToPolygons) consumes.
31
+ */
32
+ export declare function binarizeMask(logits: Float32Array | number[], threshold?: number): Uint8Array;
33
+ /** Index of the highest-scoring mask in a multimask decoder output. */
34
+ export declare function bestMaskIndex(iouPredictions: Float32Array | number[]): number;
@@ -0,0 +1,50 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { WandService } from '../wand/wand.service';
3
+ import { WandToolHost } from '../wand/wand-tool.service';
4
+ import { ISamSession } from '../../contracts/sam.contract';
5
+ import * as i0 from "@angular/core";
6
+ /** The SAM tool binds to the same host the wand/brush use, so each backend
7
+ * reuses its existing pixel readback + coordinate transform + region store. */
8
+ export type SamToolHost = WandToolHost;
9
+ /**
10
+ * Box-prompted SAM segmentation tool (jit-ui#90, P0). On `segmentBoxes()` it
11
+ * reads every rectangle region, runs the (cached) encoder once for the image,
12
+ * then runs the decoder per box, traces each mask to a polygon (reusing
13
+ * WandService.maskToPolygons) and commits them as regions.
14
+ *
15
+ * Inference is abstracted behind {@link ISamSession}: production uses the
16
+ * onnxruntime-web session (lazy-imported so ORT never loads in unit tests);
17
+ * tests inject a fake via {@link useSession}.
18
+ */
19
+ export declare class SamToolService {
20
+ private wandService;
21
+ private host;
22
+ private session;
23
+ private model;
24
+ /** Cached encoder embedding + the key (image identity) it was computed for. */
25
+ private embedding;
26
+ private embeddingKey;
27
+ /** Status text + busy flag for a spinner / toast in the host. */
28
+ readonly status$: BehaviorSubject<string>;
29
+ readonly busy$: BehaviorSubject<boolean>;
30
+ /** Encoder-download progress: -1 = not downloading, 0..1 = downloading. */
31
+ readonly progress$: BehaviorSubject<number>;
32
+ constructor(wandService: WandService);
33
+ /** Bind to the active backend's host (called by the backend, like the wand). */
34
+ bindHost(host: SamToolHost): void;
35
+ /** Choose the registered model to use; invalidates any cached embedding. */
36
+ setModel(id: string): void;
37
+ /** Drop the cached embedding (e.g. after the image/slice changes). */
38
+ invalidateEmbedding(): void;
39
+ /** Test seam: inject a fake/alternate inference session. */
40
+ useSession(session: ISamSession): void;
41
+ /**
42
+ * Segment every rectangle region with a box prompt and append the resulting
43
+ * masks as new polygon regions. Returns how many regions were added.
44
+ */
45
+ segmentBoxes(): Promise<number>;
46
+ private makeRegion;
47
+ private ensureSession;
48
+ static ɵfac: i0.ɵɵFactoryDeclaration<SamToolService, never>;
49
+ static ɵprov: i0.ɵɵInjectableDeclaration<SamToolService>;
50
+ }