@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,85 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { Observable } from 'rxjs';
3
+ import { IHistogram } from '../../contracts/channel-histogram-api.contract';
4
+ /**
5
+ * Histogram + auto-window sampling for the OSD backend (refactoring plan,
6
+ * Step 4 — a pure move out of the visualizer service). Owns the per-slice
7
+ * 8-bit histograms (sampled from displayed tiles) and the native-bit-depth
8
+ * histograms (fetched from the server `/histogram` endpoint). Read-only with
9
+ * respect to the tile/display pipeline.
10
+ */
11
+ /** The descriptor fields the samplers read (structurally satisfied by the
12
+ * service's TileDescriptor). */
13
+ export interface SampledDescriptor {
14
+ width: number;
15
+ height: number;
16
+ tileSize: number;
17
+ channels?: number;
18
+ levels?: Array<{
19
+ width: number;
20
+ height: number;
21
+ }>;
22
+ }
23
+ export interface HistogramSamplerHost {
24
+ /** Real Bio-Formats levels (per-channel tiles exist only there). */
25
+ realLevels(): number;
26
+ /** Channel count for the multichannel sampler. */
27
+ channelCount(d: SampledDescriptor): number;
28
+ /** Grayscale (intensity histogram + auto-window) vs RGB (R/G/B histograms). */
29
+ isGrayscale(): boolean;
30
+ /** Histograms landed — nudge the pane to re-read (its retry window may have
31
+ * lapsed). */
32
+ onChannelHistogramsSampled(): void;
33
+ /** A grayscale auto-window was measured from full-res tiles — seed the
34
+ * Intensity channel (or re-invalidate if the user already windowed). */
35
+ onGrayWindowSampled(min: number, max: number): void;
36
+ }
37
+ export declare class HistogramSampler {
38
+ private http;
39
+ private api;
40
+ private host;
41
+ /** 256-bin intensity histogram per z-slice, from sampled tiles. */
42
+ private sliceHistograms;
43
+ /** Native-bit-depth histograms from `/histogram`, keyed `${z}|${channel}`. */
44
+ private nativeHistograms;
45
+ /** Per-app-load cache-buster for `/histogram` — the server marks the
46
+ * response cacheable for 24h, and a hard refresh can't bust a post-load
47
+ * XHR. A token stable within a session but new on each full load keeps the
48
+ * in-session dedup (via `nativeHistograms`) while always reflecting the
49
+ * live backend after a reload. */
50
+ private readonly histCacheBuster;
51
+ constructor(http: HttpClient, api: string, host: HistogramSamplerHost);
52
+ /** The sampled histogram for one channel of slice z, or null until the
53
+ * async sampling resolves (or if it was skipped). */
54
+ get(z: number, channelIndex: number): IHistogram | null;
55
+ /** Drop everything (teardown / image switch). */
56
+ clear(): void;
57
+ /**
58
+ * Per-channel intensity histograms for multichannel images: sample each
59
+ * channel's single-band tiles at the coarsest real level and bin the
60
+ * luminance. Fire-and-forget.
61
+ */
62
+ computeMultiChannelHistograms(d: SampledDescriptor, infoB64: string, z: number): Promise<void>;
63
+ /**
64
+ * Compute a per-image intensity window [min,max] for grayscale auto-ranging,
65
+ * mirroring the heatmap's auto-stretch. Two constraints force the sampling
66
+ * strategy:
67
+ * - The window MUST be in the same value space as the displayed tiles: the
68
+ * `/preview` endpoint is server-normalized while `/tile` serves raw
69
+ * un-normalized 8-bit — a window from the preview wouldn't match.
70
+ * - It must read FULL-RESOLUTION tiles, not a downsampled overview:
71
+ * averaging sparse low values (label masks) toward 0 wipes the signal.
72
+ * So we sample the full-res level across the whole image — bounded to 64
73
+ * tiles (a huge grayscale image samples the coarsest overview for histograms
74
+ * only). Fire-and-forget; failures leave the window unset (identity 0..255).
75
+ */
76
+ computeImageWindow(d: SampledDescriptor, infoB64: string, z: number): Promise<void>;
77
+ /**
78
+ * Native-bit-depth histogram for >8-bit images, from the server `/histogram`
79
+ * endpoint (the 8-bit canvas tiles can't carry 16-bit values). Cached per
80
+ * slice+channel for the session.
81
+ */
82
+ native$(infoB64: string, z: number, channel: number, bins: number): Observable<IHistogram | null>;
83
+ /** Fetch + cache one channel's native histogram from `GET /histogram`. */
84
+ private fetchNative;
85
+ }
@@ -0,0 +1,476 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { Observable } from 'rxjs';
3
+ import { Image } from 'image-js';
4
+ import { VisualizerStore } from '../../store/visualizer-store.service';
5
+ import { RegionStore } from '../../store/region-store.service';
6
+ import { IImageInfo } from '../../contracts/image.contract';
7
+ import { TileAccessPort } from '../../contracts/ports/tile-access.port';
8
+ import { VizConfig } from '../../contracts/viz-config';
9
+ import { PlotType, PlotTypeDescriptor } from '../../contracts/plot-type';
10
+ import { IVisualizer, PixelData, IntensityProfile, IIsosurfaceControls, IIntensityControls, ISurface3dControls } from '../../contracts/visualizer.contract';
11
+ import { ViewerCapabilities } from '../../contracts/capabilities.contract';
12
+ import { IRegionOverlay } from '../../contracts/region-overlay.contract';
13
+ import { BaseStoreVisualizer } from '../base-store-visualizer';
14
+ import { SimpleSliceAccessService } from '../simple-slice-access.service';
15
+ import { WandToolService } from '../../toolbar/wand/wand-tool.service';
16
+ import { BrushToolService } from '../../toolbar/brush/brush-tool.service';
17
+ import { SamToolService } from '../../toolbar/segmentation/sam-tool.service';
18
+ import { SamPointToolService } from '../../toolbar/segmentation/sam-point-tool.service';
19
+ import { CellSegmentToolService } from '../../toolbar/segmentation/cell-segment-tool.service';
20
+ import { ICellSegmenter } from '../../contracts/cell-segmenter.contract';
21
+ import { VertexEraserToolService } from '../../toolbar/vertex-eraser/vertex-eraser-tool.service';
22
+ import { ZoomToBoxToolService } from '../../toolbar/zoom-to-box/zoom-to-box-tool.service';
23
+ import { IHistogram } from '../../contracts/channel-histogram-api.contract';
24
+ import * as i0 from "@angular/core";
25
+ /** One pyramid level from `GET /tiles/info`. */
26
+ interface TileLevel {
27
+ res: number;
28
+ width: number;
29
+ height: number;
30
+ }
31
+ /** Tile-source descriptor returned by `GET /tiles/info`. */
32
+ interface TileDescriptor {
33
+ width: number;
34
+ height: number;
35
+ tileSize: number;
36
+ z: number;
37
+ channels: number;
38
+ /** True only for genuine multi-channel composites (indexed/LUT-bearing
39
+ * fluorescence stacks) the client should split into per-channel layers. The
40
+ * server sets it; an RGB photo read as separated planes has channels>1 but
41
+ * multichannel=false, so it stays a single composite tile source. */
42
+ multichannel?: boolean;
43
+ /** Real Bio-Formats resolution levels at the front of `levels`; the remaining
44
+ * levels are synthetic composited overviews (no per-channel tiles). */
45
+ realLevels?: number;
46
+ /** Per-channel metadata (name/color/bitDepth/min-maxAllowed) for native 16-bit
47
+ * windowing + histogram; null for plain 8-bit/RGB sources. */
48
+ channelInfo?: Array<{
49
+ name?: string;
50
+ color?: string;
51
+ bitDepth?: number;
52
+ minAllowed?: number;
53
+ maxAllowed?: number;
54
+ }> | null;
55
+ levels: TileLevel[];
56
+ /** Physical pixel size in µm (0 when the format doesn't report it). */
57
+ mppX?: number;
58
+ mppY?: number;
59
+ }
60
+ /** What `load()` hands to `plot()`. */
61
+ interface OsdLoaded {
62
+ descriptor: TileDescriptor | null;
63
+ infoB64: string;
64
+ z: number;
65
+ /** Mirrors the loaded image's filename — the diagram's render pipeline
66
+ * guards on `loaded.filename === phaseInfo.fileName` before calling plot(). */
67
+ filename: string | undefined;
68
+ /** Simple (non-tiled) image: `plot()` opens {@link url} directly via OSD's
69
+ * single-image source — no tile pyramid, no server. Set when the image
70
+ * carries `tiled === false` (see {@link IImageInfo.tiled}). */
71
+ simple?: boolean;
72
+ /** The directly-loadable image URL (`blob:`/`data:`/`http`) for simple mode. */
73
+ url?: string;
74
+ }
75
+ /**
76
+ * OpenSeadragon visualization backend.
77
+ *
78
+ * Renders the *image* plot type as a natively-tiled, zoomable raster, backed by
79
+ * the jit-service tile endpoints (`GET /tiles/info` + `GET /tile`, which reuse
80
+ * the Bio-Formats ROI renderer). Plotly keeps the scientific/data plot types
81
+ * (scalar heatmap, surface, contour, scatter, line, scatter3d, isosurface) —
82
+ * hence this backend advertises only `ImageDisplay`.
83
+ *
84
+ * Wired: load → descriptor, plot → mount viewer with a custom tile source,
85
+ * zoom/pan → viewport API. NOT wired yet (follow-ups): region overlays + tools
86
+ * (a positioned canvas/SVG overlay or Annotorious), pixel readback, and the
87
+ * per-tile LUT/contrast params. Not registered in DI providers — `PlotlyService`
88
+ * is still the only active backend; this proves the contract supports a second
89
+ * implementation against real endpoints.
90
+ */
91
+ export declare class OpenSeadragonVisualizerService extends BaseStoreVisualizer implements IVisualizer {
92
+ private http;
93
+ private tiles;
94
+ private wandTool;
95
+ private brushTool;
96
+ private samTool;
97
+ private samPointTool;
98
+ private cellSegmentTool;
99
+ private cellSegmenter;
100
+ private eraserTool;
101
+ private zoomToBoxTool;
102
+ private simpleStack;
103
+ /** OSD's strength is displaying a large zoomable image — nothing else here. */
104
+ readonly capabilities: ViewerCapabilities;
105
+ private readonly api;
106
+ private viewer;
107
+ private overlay;
108
+ private scaleBar;
109
+ private descriptor;
110
+ /** Base64 RawFileInfo + current z-slice, kept so setZIndex can rebuild the
111
+ * tile source and swap slices live (stack navigation). */
112
+ private infoB64;
113
+ private currentZ;
114
+ /** True while the current image is "simple" (tiled:false — self-contained
115
+ * per-slice URLs, no tile server; e.g. a numbered image series assembled
116
+ * client-side into a stack). setZIndex swaps the single-image source for
117
+ * the new slice's URL instead of updating a tiled z-param. */
118
+ private simpleMode;
119
+ /** urls[] for the current simple-mode image, so setZIndex can look up the
120
+ * slice being scrubbed to (via {@link SimpleSliceAccessService.urlFor}).
121
+ * Unused (and left stale, harmlessly) in tiled mode. */
122
+ private simpleUrls;
123
+ /** preview blob URL → full-res upscaled blob URL (see toFullResUrl), so
124
+ * re-visiting a simple-mode slice doesn't re-upscale. Revoked on file change. */
125
+ private readonly simpleFullResUrls;
126
+ /** Skip the full-res upscale above this longest-side dimension — a folder
127
+ * stack is per-file previews (well under this); this only guards against an
128
+ * accidental enormous canvas allocation. */
129
+ private readonly SIMPLE_UPSCALE_MAX_DIM;
130
+ private coordTransform;
131
+ private wandHost;
132
+ private eraserHost;
133
+ /** Wand sampling matrix read back from the rendered viewport; cached until
134
+ * the viewport changes (see readbackViewport). */
135
+ private viewportPixels;
136
+ /** The DOM id of the element OSD is mounted in (shared with Plotly); the
137
+ * on-canvas tools attach their overlays here. */
138
+ private plotDiv;
139
+ /** Current file name, tagged onto wand-created shapes. */
140
+ private currentFileName;
141
+ /** 256-entry RGB LUT for the active colormap, applied to grayscale tiles via
142
+ * the tile-invalidated pixel pipeline (mirrors Plotly's heatmap colorscale).
143
+ * Null while options resolve; recoloring is skipped until it's built. */
144
+ private colorLut;
145
+ /** Only grayscale images get a colormap (RGB tiles pass through untouched). */
146
+ private isGrayscaleImage;
147
+ private colormapSub;
148
+ /** Latest per-channel display state (window/gamma/visibility) from the store,
149
+ * read synchronously by recolorTile. Channel 0 drives grayscale windowing;
150
+ * R/G/B (indices 0-2) drive RGB per-channel windowing. */
151
+ private channelStates;
152
+ /** True for multichannel fluorescence (channelCount > 1, not RGB): tiles are
153
+ * composited client-side from per-channel single-band fetches (see
154
+ * recolorMultiChannelTile) rather than recolored in place. */
155
+ private isMultiChannel;
156
+ /** Count of real Bio-Formats resolution levels (per-channel tiles exist only
157
+ * here). For multichannel images the tile source is built from these alone so
158
+ * every displayed tile supports a per-channel fetch. */
159
+ private realLevels;
160
+ /** Inverted background (white = zero): inverts the display value before the
161
+ * LUT (grayscale) / per channel (RGB). */
162
+ private invertBg;
163
+ /** Bearer token for OSD's own tile fetches (HttpClient calls get it via the
164
+ * interceptor; OSD's loader does not, so we pass it as an ajax header). */
165
+ private authHeaders;
166
+ /** Whether the overview navigator (minimap) is shown. Read at viewer creation;
167
+ * a consumer that doesn't want it (e.g. a small embedded preview) sets it off
168
+ * via {@link setNavigatorVisible} before the first render. */
169
+ private navigatorVisible;
170
+ /** Image smoothing (bilinear). `false` → nearest-neighbour, so zoomed-in pixels
171
+ * render as crisp blocks (pixel inspection). Defaults to `false` so the image
172
+ * opens showing raw pixels. Read at viewer creation; toggled via
173
+ * {@link setImageSmoothingEnabled}. */
174
+ private smoothingEnabled;
175
+ /** Overall deadline for the /tiles/info poll loop. An uncached whole-slide
176
+ * image (e.g. .ndpi) is cached server-side first (GCS->PVC), which can take
177
+ * several minutes — we poll (short requests; the cache-progress overlay
178
+ * shows the wait) until it's ready. Generous because each poll is cheap; on
179
+ * expiry the render pipeline gives up and the router falls back to Plotly. */
180
+ private readonly tilesInfoTimeoutMs;
181
+ /** Per-channel fit-view tile budget (tiles at the coarsest real level × channels).
182
+ * Above it, a multichannel image renders server-composited instead of per-channel
183
+ * — its full-res reads (it has no overview pyramid) would be too many × N channels.
184
+ * 64 (e.g. a 4x4 single-FOV z-stack × 4ch) stays per-channel; a whole-slide
185
+ * (hundreds–thousands) falls back. */
186
+ private readonly MAX_MULTICHANNEL_FIT_TILES;
187
+ /** Pixel display pipeline (window/gamma/invert/colormap + additive tint) —
188
+ * shared by tile recoloring and the composite export so they stay identical
189
+ * (see DisplayPipeline). Host closures read the service's live fields. */
190
+ private readonly display;
191
+ /** Histogram + auto-window sampling (see HistogramSampler). Constructed in
192
+ * the ctor body because it captures the resolved API base URL. */
193
+ private sampler;
194
+ /** Stack-slice cache + background preloader (see SliceCache — refactoring
195
+ * plan Step 3). The host accessors are live closures, so the cache always
196
+ * reads the service's current viewer/descriptor/z — exactly the fields the
197
+ * moved code used to read directly. */
198
+ private readonly cache;
199
+ constructor(http: HttpClient, tiles: TileAccessPort, wandTool: WandToolService, brushTool: BrushToolService, samTool: SamToolService, samPointTool: SamPointToolService, cellSegmentTool: CellSegmentToolService, cellSegmenter: ICellSegmenter | null, eraserTool: VertexEraserToolService, zoomToBoxTool: ZoomToBoxToolService, store: VisualizerStore, regionStore: RegionStore, simpleStack: SimpleSliceAccessService, config: VizConfig);
200
+ private readonly stackLoading$;
201
+ private readonly stackLoadingProgress$;
202
+ private readonly autoscaleEvent$;
203
+ /** Visible image region (full-image pixel coords) emitted when the view
204
+ * settles, so the intensity inset can re-sample at the current zoom level. */
205
+ private readonly viewportChange$;
206
+ private readonly intensityProfile$;
207
+ /**
208
+ * Subscribe to the shared VisualizerStore colormap/reverse so OSD recolors in
209
+ * lock-step with Plotly. Idempotent and self-healing: this service is a root
210
+ * singleton, but `unsubscribe()` (called on VisualizerComponent destroy)
211
+ * tears the subscription down — and the constructor never runs again. So
212
+ * `plot()` calls this to re-establish it after a component teardown/recreate
213
+ * (e.g. switching images), otherwise colormap changes would be silently
214
+ * dropped on every image after the first switch.
215
+ */
216
+ private ensureColormapSubscription;
217
+ /** Seed the Intensity channel with a measured auto-window while it's still
218
+ * at full range (never clobber the user's manual window); if the user
219
+ * already windowed, just re-invalidate so painted tiles pick the LUT up. */
220
+ private seedGrayWindow;
221
+ /**
222
+ * Fetch the tile-source descriptor for the selected file. The `info` param is
223
+ * the base64 RawFileInfo the rest of the API uses; the GET goes through the
224
+ * auth interceptor (Bearer). We also grab a token here for OSD's own tile
225
+ * fetches (its loader bypasses HttpClient).
226
+ */
227
+ load(imageInfo: IImageInfo, zIndex: number): Promise<OsdLoaded>;
228
+ /** Build the `plot()` payload for a simple (tiled:false) image: a single-level
229
+ * descriptor sized from `trueImageSize`, plus the directly-loadable URL —
230
+ * resolved and fetched via {@link SimpleSliceAccessService} (shared with
231
+ * napari-js; see its docs for why this can't be a raw `fetch()`/`<img>`). */
232
+ private loadSimple;
233
+ /**
234
+ * OSD's `{type:'image'}` source sizes its coordinate world to the image's
235
+ * NATURAL pixels. A folder-stack slice is a server `/preview` whose pixel size
236
+ * needn't match the full-resolution image — it may be downscaled (large
237
+ * images) OR larger than the dimensions `/metadata` reports. Either way OSD's
238
+ * world would differ from the full-res ROI coordinate space (QuPath geojson,
239
+ * in level-0 pixels): a smaller preview renders ROIs oversized, a larger one
240
+ * renders them undersized/offset. Resample the preview to EXACTLY the
241
+ * full-resolution dimensions (blurry but positionally exact — scaling up or
242
+ * down as needed) so OSD's world matches the ROI coordinate space, while still
243
+ * using OSD's reliable single-image renderer. Cached per preview URL (revoked
244
+ * on file change); a no-op when the preview is already exactly full-res (small
245
+ * images, in-memory pipeline blobs), when the dims are unknown, or when
246
+ * they're implausibly large (guards against an enormous canvas). (jit-ui#93)
247
+ */
248
+ private toFullResUrl;
249
+ /** Load a URL into an HTMLImageElement (resolves once decoded). Uses
250
+ * document.createElement rather than `new Image()` because this file's
251
+ * `Image` import is image-js's decoder, not the DOM element. */
252
+ private loadImageEl;
253
+ private revokeSimpleFullResUrls;
254
+ /** Mount the viewer with a custom tile source pointing at `GET /tile`. */
255
+ plot(plotDiv: string, imageLoaded: any, imageInfo: IImageInfo, _screenHeight: number, _plotType: PlotType, inPlace?: boolean): Promise<boolean>;
256
+ /**
257
+ * Fit-to-home once `el` first has a non-zero size. If it's already sized we
258
+ * rely on the timed refits the caller scheduled; otherwise a one-shot
259
+ * ResizeObserver runs `refit` the moment the container is laid out (then
260
+ * disconnects), so the initial fit doesn't depend on the render's start time
261
+ * relative to the diagram container's layout. No-op without a container or
262
+ * ResizeObserver (the timed refits remain the fallback). One-shot + only
263
+ * attached on a fresh mount, so slice-scrub re-opens keep the user's zoom.
264
+ */
265
+ private fitWhenContainerSized;
266
+ /**
267
+ * Custom tile source built from the descriptor. OSD numbers levels
268
+ * coarsest-first; the backend numbers resolutions full-res-first, so
269
+ * `res = (levels-1) - osdLevel`. Overriding getLevelScale/getNumTiles lets us
270
+ * honour Bio-Formats' actual per-level dimensions (not assume power-of-two).
271
+ */
272
+ private buildTileSource;
273
+ /** Re-apply the display pipeline (window/gamma/colour/invert) after a state change.
274
+ * Multichannel invalidates ONLY the visible slice's channel images — invalidating
275
+ * the whole world would re-process every hidden/preloaded slice's tiles (hundreds),
276
+ * flooding OSD with "[CacheRecord] … InvalidStateError" and wasting work on tiles
277
+ * that aren't on screen. The other cached slices are marked stale and re-tinted
278
+ * lazily when revealed. Composite/grayscale invalidate the world as before. */
279
+ private invalidateDisplay;
280
+ private destroyViewer;
281
+ /** This backend's region renderer (the SVG overlay), once a plot is mounted. */
282
+ getRegionOverlay(): IRegionOverlay | null;
283
+ /** OSD renders only the image type — no isosurface, so no controls. */
284
+ getIsosurfaceControls(): IIsosurfaceControls | null;
285
+ /** OSD renders only the image type — no 3D scenes, so no controls. */
286
+ getSurface3dControls(): ISurface3dControls | null;
287
+ /** OSD renders only the image type — no LINE intensity ROIs, so no controls. */
288
+ getIntensityControls(): IIntensityControls | null;
289
+ private toOverlayMode;
290
+ reloadAndPlot(): void;
291
+ reset(): void;
292
+ relayout(_trueImageSize?: number[]): void;
293
+ resetAxes(): void;
294
+ autoscale(): void;
295
+ zoomIn(): void;
296
+ zoomOut(): void;
297
+ setDragMode(mode: string | false): void;
298
+ setShowStack(_showstack: boolean): void;
299
+ /** Show/hide the overview navigator. Stored for the next viewer creation, and
300
+ * applied live when a viewer is already mounted (hides/reveals its element —
301
+ * the navigator instance itself only exists when created with showNavigator). */
302
+ setNavigatorVisible(visible: boolean): void;
303
+ /** Toggle bilinear smoothing vs nearest-neighbour (crisp pixels). Stored for the
304
+ * next viewer creation, and applied live (with a redraw) to a mounted viewer. */
305
+ setImageSmoothingEnabled(enabled: boolean): void;
306
+ /**
307
+ * Swap the displayed z-slice live. Slices are kept as separate tiled images in
308
+ * the world, so switching is just an opacity toggle: a previously-visited slice
309
+ * shows instantly (its decoded + recolored tiles are still resident), and a
310
+ * never-seen slice is added once. The region overlay, coordinate transform,
311
+ * scale bar, colormap pipeline and current zoom/pan all persist — the x/y
312
+ * geometry is identical across slices.
313
+ *
314
+ * Simple mode (tiled:false — a numbered image series assembled client-side,
315
+ * each slice its own complete image with no shared tile server) has no
316
+ * pyramid to toggle opacity on, so it re-opens the viewer on the new
317
+ * slice's URL instead. preserveViewport (viewer option, see plot()) keeps
318
+ * the current zoom/pan across that reopen.
319
+ */
320
+ setZIndex(zIndex: number): void;
321
+ setStackLoading(stackLoading: boolean): void;
322
+ isStackLoading(): Observable<boolean>;
323
+ getStackLoadingProgress(): Observable<number>;
324
+ getTrueImageSize(): {
325
+ width: number;
326
+ height: number;
327
+ } | null;
328
+ getCurrentImage(): Promise<Image | null>;
329
+ /**
330
+ * The currently displayed pixels — the rendered viewport (what the user sees,
331
+ * including the current zoom and any colormap recolor), as RGBA. Feeds the
332
+ * processing-pipeline dialog's "use current view". Returns null until tiles
333
+ * are drawn.
334
+ */
335
+ getDisplayedPixelData(): PixelData | null;
336
+ /**
337
+ * Image-pixel rectangle the drawer canvas (what {@link getDisplayedPixelData}
338
+ * reads) currently covers. Unlike {@link emitViewportChange}, this is NOT
339
+ * clamped to the image bounds: the canvas maps 1:1 to the viewport rectangle,
340
+ * so leaving it unclamped keeps `canvasPx -> imagePx` an exact affine map
341
+ * (clamping would skew coordinates near the image edges). Routed through world
342
+ * item 0 (see {@link viewportRectToImage}) for multi-layer accuracy.
343
+ */
344
+ getDisplayedSourceRect(): {
345
+ x: number;
346
+ y: number;
347
+ width: number;
348
+ height: number;
349
+ } | null;
350
+ downloadImage(): void;
351
+ setPlotType(_plotType: PlotType): void;
352
+ setSurfaceDragMode(_mode: string): void;
353
+ resetSurfaceCamera(): void;
354
+ getAutoscaleEvent(): Observable<any>;
355
+ /** Visible image region (full-image pixel coords), emitted when the view
356
+ * settles. The intensity inset re-samples this region at the zoom resolution. */
357
+ getViewportChange$(): Observable<{
358
+ x: number;
359
+ y: number;
360
+ width: number;
361
+ height: number;
362
+ }>;
363
+ /** {@link IIntensitySampling} stub — intensity sampling lives in the Plotly
364
+ * backend (it owns pixel readback). OSD feeds it only via getViewportChange$;
365
+ * the sampling-cache priming itself is a no-op here. */
366
+ ensureIntensitySampling(_imageInfo: IImageInfo, _zIndex: number): Promise<void>;
367
+ /** {@link IIntensitySampling} stub — see {@link ensureIntensitySampling}. */
368
+ refreshIntensitySamplingForRoi(_x: number, _y: number, _width: number, _height: number, _zIndex: number): void;
369
+ /** Compute the current viewport's image-pixel rectangle (clamped to the image)
370
+ * and broadcast it. */
371
+ private emitViewportChange;
372
+ /** OSD targets the image display; the scalar/3D plot types belong to Plotly. */
373
+ getPlotTypeDescriptors(): PlotTypeDescriptor[];
374
+ getIntensityProfile$(): Observable<IntensityProfile[]>;
375
+ /** OSD only renders the image type; the LINE intensity inset is Plotly-only. */
376
+ renderIntensityInset(_divId: string, _profiles: IntensityProfile[]): void;
377
+ setWandMode(active: boolean, options?: any): void;
378
+ setWandOptions(options: any): void;
379
+ clearActiveWandRegion(): void;
380
+ setBrushMode(active: boolean, options?: any): void;
381
+ setBrushOptions(options: any): void;
382
+ setVertexEraserMode(active: boolean): void;
383
+ setVertexEraserRadius(radius: number): void;
384
+ setZoomToBoxMode(active: boolean): void;
385
+ /** Box-prompted SAM: segment the drawn rectangles. The SAM tool reuses the
386
+ * wand host (viewport readback + coordinate transform + region store). */
387
+ segmentRectangles(): Promise<number>;
388
+ segmentRectanglesCellpose(): Promise<number>;
389
+ setSamModel(id: string): void;
390
+ setSamPointMode(active: boolean): void;
391
+ commitSamPoints(): void;
392
+ clearSamPoints(): void;
393
+ /** Build the wand/eraser host objects bound to this backend. Both tools run
394
+ * over OSD via the shared coordinate transform + a viewport pixel readback,
395
+ * and read/write regions directly on the shared RegionStore (neutral model). */
396
+ private buildToolHosts;
397
+ /** The element the on-canvas tool overlays attach to (OSD is mounted here). */
398
+ private getOverlayContainer;
399
+ /** Size the navigator from the CURRENT container (navigatorSizeRatio of the
400
+ * viewer element) and keep it pinned to the corner. OSD computes the size
401
+ * once in the Viewer constructor — before the host flex layout settles —
402
+ * and never corrects it, leaving a stale-size element whose visible minimap
403
+ * floats above the bottom-right corner. */
404
+ private resizeNavigator;
405
+ /** Force the docked toolbar to repaint after an OSD zoom. Chrome leaves it
406
+ * laid-out-but-unpainted (the canvas's compositing churn strands the toolbar's
407
+ * raster). A synchronous display toggle re-rasters it with no visible gone-frame
408
+ * and no layout shift. Located via the DOM since this service doesn't own the
409
+ * toolbar; a no-op when there's no toolbar (e.g. embedded without one). */
410
+ private nudgeToolbarRepaint;
411
+ /** Host for the (shared) zoom-to-box tool: convert overlay pixels to image
412
+ * coords via the viewport, and fit the viewport to the chosen rectangle. */
413
+ private zoomBoxHost;
414
+ /** Fit the OSD viewport to an image-space rectangle (coords ordered
415
+ * [xMin, xMax, yMax, yMin]). */
416
+ private applyZoomToBox;
417
+ /**
418
+ * Read back the *currently rendered* OSD canvas as the wand's pixel matrix.
419
+ * The matrix covers only the visible viewport at screen resolution, so when
420
+ * the user is zoomed into a sub-region the wand samples that region's detail
421
+ * (rather than the whole image at preview resolution). `originX/originY` and
422
+ * `ratios` map image coords <-> readback-pixel coords for the wand's
423
+ * data/ratio/origin model. Cached until the viewport changes.
424
+ */
425
+ private readbackViewport;
426
+ /**
427
+ * Recolor a grayscale tile through the active colormap LUT, using OSD's
428
+ * tile-invalidated pixel pipeline (OSD 5+/6). Maps each pixel's grayscale
429
+ * value (r==g==b) to the LUT's RGB. No-op for RGB images or until the LUT is
430
+ * built. Handler is async — OSD awaits it (raiseEventAwaiting).
431
+ */
432
+ private recolorTile;
433
+ /**
434
+ * Tint a single channel's tile in place. Each channel is its own OpenSeadragon
435
+ * TiledImage (a single-band grayscale tile); OSD composites the N images
436
+ * additively ('lighter') in its drawer — so this just maps the tile's intensity
437
+ * through the channel's window/gamma and its pseudo-colour. Synchronous (no
438
+ * cross-tile fetch) → no race, no seams. Channel is parsed from the tile URL.
439
+ */
440
+ private recolorChannelTile;
441
+ /** Per-channel histogram for the Channels & Histogram pane, from the current
442
+ * slice's sampled tiles (grayscale → channel 0; RGB → R/G/B). Null until the
443
+ * async sampling resolves or if it was skipped. */
444
+ getHistogram(channelIndex: number, _bins: number): IHistogram | null;
445
+ /** Native bit depth of a channel from the tile descriptor (8 when unknown). */
446
+ private channelBitDepth;
447
+ /**
448
+ * Async histogram for the Channels & Histogram pane. For >8-bit images it
449
+ * fetches the **native** distribution from the server `/histogram` endpoint
450
+ * (the 8-bit canvas tiles can't carry 16-bit values) and caches it per
451
+ * slice+channel; for 8-bit/RGB it returns the existing client-sampled 8-bit
452
+ * histogram. Read-only — it never touches the tile/display pipeline.
453
+ */
454
+ getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
455
+ /**
456
+ * Export the underlying image data as a data-preserving multi-band TIFF at
457
+ * native bit depth via `GET /export/tiff` (the server reads the raw 16-bit
458
+ * planes — the client never sees them). Sends only the visible channels; the
459
+ * existing 8-bit composite PNG export is unaffected.
460
+ */
461
+ exportData(): Promise<void>;
462
+ /**
463
+ * Export the current slice as a publication-ready PNG composited with the
464
+ * active display settings (window / gamma / colormap or per-channel pseudo-
465
+ * colours / invert). Picks the largest pyramid level under a pixel cap (the
466
+ * coarser overview for huge whole-slides), fetches that level's tile grid,
467
+ * stitches it into one canvas, runs the shared display pipeline, and saves it.
468
+ */
469
+ exportComposite(): Promise<void>;
470
+ /** True if any pixel in the RGBA buffer is non-transparent. */
471
+ private hasOpaque;
472
+ unsubscribe(): void;
473
+ static ɵfac: i0.ɵɵFactoryDeclaration<OpenSeadragonVisualizerService, [null, null, null, null, null, null, null, { optional: true; }, null, null, null, null, null, null]>;
474
+ static ɵprov: i0.ɵɵInjectableDeclaration<OpenSeadragonVisualizerService>;
475
+ }
476
+ export {};
@@ -0,0 +1,17 @@
1
+ import { ICoordinateTransform } from '../../contracts/coordinate-transform.contract';
2
+ /**
3
+ * OpenSeadragon implementation of {@link ICoordinateTransform}. "Data coords"
4
+ * here are image-pixel coordinates (OSD's native shape space), obtained from the
5
+ * viewport API. This is the reason the tools can run over OSD at all: the
6
+ * viewport gives a clean screen<->image mapping that holds across pan/zoom.
7
+ */
8
+ export declare class OsdCoordinateTransform implements ICoordinateTransform {
9
+ private viewer;
10
+ constructor(viewer: any);
11
+ isReady(): boolean;
12
+ clientToData(clientX: number, clientY: number): {
13
+ x: number;
14
+ y: number;
15
+ };
16
+ dataLengthToScreen(dataLength: number): number;
17
+ }
@@ -0,0 +1,16 @@
1
+ /** Viewer-element pixel -> image (data) coordinates. */
2
+ export declare function elementToImage(viewer: any, x: number, y: number): {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ /** Image (data) coordinates -> viewer-element pixel point. */
7
+ export declare function imageToElement(viewer: any, x: number, y: number): {
8
+ x: number;
9
+ y: number;
10
+ };
11
+ /** Image-space rectangle -> viewport rectangle (for fitBounds). */
12
+ export declare function imageRectToViewport(viewer: any, x: number, y: number, w: number, h: number): any;
13
+ /** Viewport rectangle -> image (data) rectangle. Routes through world item 0 so
14
+ * it stays accurate when the world holds multiple images (stack slices /
15
+ * per-channel layers); falls back to the viewport when the world is empty. */
16
+ export declare function viewportRectToImage(viewer: any, vpRect: any): any;
@@ -0,0 +1,19 @@
1
+ import * as OpenSeadragon from 'openseadragon';
2
+ /**
3
+ * The real OpenSeadragon object, normalized for the packaged (FESM) build.
4
+ *
5
+ * OpenSeadragon ships as plain CommonJS (`module.exports = OpenSeadragon`, no
6
+ * `__esModule` flag). Bundled into this library's FESM and re-bundled by a
7
+ * consuming app, `import * as OpenSeadragon` resolves to a synthesized ES
8
+ * namespace whose only reliable slot is `.default` (the real `module.exports`).
9
+ * The factory itself and every static member (Viewer, Point, Rect, TileSource, …)
10
+ * live on that object, NOT on the namespace — so `OpenSeadragon(...)` or
11
+ * `new OpenSeadragon.Point()` against the namespace fail once packaged
12
+ * ("is not a function" / "not a constructor"). Normalize ONCE here and import
13
+ * { OSD } wherever a runtime VALUE is needed; import the `openseadragon` namespace
14
+ * directly only for its TYPES (e.g. `OpenSeadragon.Viewer`).
15
+ *
16
+ * (plotly.js-dist-min needs no equivalent: it sets `__esModule`, so webpack gives
17
+ * it real named exports and plain member access works.)
18
+ */
19
+ export declare const OSD: typeof OpenSeadragon;