@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,37 @@
1
+ /**
2
+ * Plotly implementation of {@link ICoordinateTransform}. Wraps the axis objects
3
+ * on the plot's `_fullLayout`. This is the exact math the wand / vertex-eraser
4
+ * used inline before they were decoupled — lifted here verbatim so Plotly
5
+ * behaviour is unchanged.
6
+ */
7
+ export class PlotlyCoordinateTransform {
8
+ constructor(getGraphDiv, getContainer) {
9
+ this.getGraphDiv = getGraphDiv;
10
+ this.getContainer = getContainer;
11
+ }
12
+ axes() {
13
+ const layout = this.getGraphDiv()?._fullLayout;
14
+ return { xaxis: layout?.xaxis, yaxis: layout?.yaxis };
15
+ }
16
+ isReady() {
17
+ const { xaxis, yaxis } = this.axes();
18
+ return !!(xaxis && yaxis);
19
+ }
20
+ clientToData(clientX, clientY) {
21
+ const { xaxis, yaxis } = this.axes();
22
+ const rect = this.getContainer()?.getBoundingClientRect();
23
+ if (!xaxis || !yaxis || !rect)
24
+ return { x: NaN, y: NaN };
25
+ return {
26
+ x: xaxis.p2d(clientX - rect.left - xaxis._offset),
27
+ y: yaxis.p2d(clientY - rect.top - yaxis._offset),
28
+ };
29
+ }
30
+ dataLengthToScreen(dataLength) {
31
+ const { xaxis } = this.axes();
32
+ if (!xaxis)
33
+ return 0;
34
+ return Math.abs(xaxis.l2p(dataLength) - xaxis.l2p(0));
35
+ }
36
+ }
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LWNvb3JkaW5hdGUtdHJhbnNmb3JtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1jb29yZGluYXRlLXRyYW5zZm9ybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyx5QkFBeUI7SUFFcEMsWUFDVSxXQUFzQixFQUN0QixZQUFzQztRQUR0QyxnQkFBVyxHQUFYLFdBQVcsQ0FBVztRQUN0QixpQkFBWSxHQUFaLFlBQVksQ0FBMEI7SUFDN0MsQ0FBQztJQUVJLElBQUk7UUFDVixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsV0FBVyxDQUFDO1FBQy9DLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3hELENBQUM7SUFFRCxPQUFPO1FBQ0wsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVELFlBQVksQ0FBQyxPQUFlLEVBQUUsT0FBZTtRQUMzQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUscUJBQXFCLEVBQUUsQ0FBQztRQUMxRCxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUN6RCxPQUFPO1lBQ0wsQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztZQUNqRCxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1NBQ2pELENBQUM7SUFDSixDQUFDO0lBRUQsa0JBQWtCLENBQUMsVUFBa0I7UUFDbkMsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsS0FBSztZQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJQ29vcmRpbmF0ZVRyYW5zZm9ybSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9jb29yZGluYXRlLXRyYW5zZm9ybS5jb250cmFjdCc7XG5cbi8qKlxuICogUGxvdGx5IGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJQ29vcmRpbmF0ZVRyYW5zZm9ybX0uIFdyYXBzIHRoZSBheGlzIG9iamVjdHNcbiAqIG9uIHRoZSBwbG90J3MgYF9mdWxsTGF5b3V0YC4gVGhpcyBpcyB0aGUgZXhhY3QgbWF0aCB0aGUgd2FuZCAvIHZlcnRleC1lcmFzZXJcbiAqIHVzZWQgaW5saW5lIGJlZm9yZSB0aGV5IHdlcmUgZGVjb3VwbGVkIOKAlCBsaWZ0ZWQgaGVyZSB2ZXJiYXRpbSBzbyBQbG90bHlcbiAqIGJlaGF2aW91ciBpcyB1bmNoYW5nZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbG90bHlDb29yZGluYXRlVHJhbnNmb3JtIGltcGxlbWVudHMgSUNvb3JkaW5hdGVUcmFuc2Zvcm0ge1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZ2V0R3JhcGhEaXY6ICgpID0+IGFueSxcbiAgICBwcml2YXRlIGdldENvbnRhaW5lcjogKCkgPT4gSFRNTEVsZW1lbnQgfCBudWxsLFxuICApIHt9XG5cbiAgcHJpdmF0ZSBheGVzKCk6IHsgeGF4aXM6IGFueTsgeWF4aXM6IGFueSB9IHtcbiAgICBjb25zdCBsYXlvdXQgPSB0aGlzLmdldEdyYXBoRGl2KCk/Ll9mdWxsTGF5b3V0O1xuICAgIHJldHVybiB7IHhheGlzOiBsYXlvdXQ/LnhheGlzLCB5YXhpczogbGF5b3V0Py55YXhpcyB9O1xuICB9XG5cbiAgaXNSZWFkeSgpOiBib29sZWFuIHtcbiAgICBjb25zdCB7IHhheGlzLCB5YXhpcyB9ID0gdGhpcy5heGVzKCk7XG4gICAgcmV0dXJuICEhKHhheGlzICYmIHlheGlzKTtcbiAgfVxuXG4gIGNsaWVudFRvRGF0YShjbGllbnRYOiBudW1iZXIsIGNsaWVudFk6IG51bWJlcik6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB7XG4gICAgY29uc3QgeyB4YXhpcywgeWF4aXMgfSA9IHRoaXMuYXhlcygpO1xuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmdldENvbnRhaW5lcigpPy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBpZiAoIXhheGlzIHx8ICF5YXhpcyB8fCAhcmVjdCkgcmV0dXJuIHsgeDogTmFOLCB5OiBOYU4gfTtcbiAgICByZXR1cm4ge1xuICAgICAgeDogeGF4aXMucDJkKGNsaWVudFggLSByZWN0LmxlZnQgLSB4YXhpcy5fb2Zmc2V0KSxcbiAgICAgIHk6IHlheGlzLnAyZChjbGllbnRZIC0gcmVjdC50b3AgLSB5YXhpcy5fb2Zmc2V0KSxcbiAgICB9O1xuICB9XG5cbiAgZGF0YUxlbmd0aFRvU2NyZWVuKGRhdGFMZW5ndGg6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgeyB4YXhpcyB9ID0gdGhpcy5heGVzKCk7XG4gICAgaWYgKCF4YXhpcykgcmV0dXJuIDA7XG4gICAgcmV0dXJuIE1hdGguYWJzKHhheGlzLmwycChkYXRhTGVuZ3RoKSAtIHhheGlzLmwycCgwKSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Plotly implementation of {@link IRegionOverlay}.
3
+ *
4
+ * Plotly renders region shapes natively in its plot layout and edits them via
5
+ * its own drag modes, so this adapter is thin: it maps the neutral
6
+ * {@link RegionToolMode} onto Plotly drag modes and lets Plotly draw. `redraw`
7
+ * is a no-op because Plotly re-renders its shapes itself on relayout.
8
+ *
9
+ * It is the symmetric counterpart to {@link OsdRegionOverlay}: both render the
10
+ * same shared `IRegionStore`, each onto its own backend's canvas.
11
+ */
12
+ export class PlotlyRegionOverlay {
13
+ constructor(plotly) {
14
+ this.plotly = plotly;
15
+ }
16
+ setMode(mode) {
17
+ // 'select' is a neutral mode for Plotly (no drag mode); region selection is
18
+ // driven by the table / active-shape sampling, so just clear the drag mode.
19
+ const dragMode = mode === 'drawrect' ? 'drawrect' :
20
+ mode === 'drawclosedpath' ? 'drawclosedpath' :
21
+ mode === 'drawopenpath' ? 'drawopenpath' :
22
+ false;
23
+ this.plotly.setDragMode(dragMode);
24
+ }
25
+ redraw() { }
26
+ /** Bezier regions are an OpenSeadragon-only feature (Plotly has no native
27
+ * curved-shape rendering), so this is a no-op here. */
28
+ setSelectedBezier(_bezier) { }
29
+ destroy() { }
30
+ }
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXJlZ2lvbi1vdmVybGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1yZWdpb24tb3ZlcmxheS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxPQUFPLG1CQUFtQjtJQUU5QixZQUFvQixNQUFxQjtRQUFyQixXQUFNLEdBQU4sTUFBTSxDQUFlO0lBQUcsQ0FBQztJQUU3QyxPQUFPLENBQUMsSUFBb0I7UUFDMUIsNEVBQTRFO1FBQzVFLDRFQUE0RTtRQUM1RSxNQUFNLFFBQVEsR0FDWixJQUFJLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNsQyxJQUFJLEtBQUssZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUM7Z0JBQzlDLElBQUksS0FBSyxjQUFjLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDO29CQUMxQyxLQUFLLENBQUM7UUFDUixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsTUFBTSxLQUFtRSxDQUFDO0lBRTFFOzREQUN3RDtJQUN4RCxpQkFBaUIsQ0FBQyxPQUFnQixJQUF5QixDQUFDO0lBRTVELE9BQU8sS0FBeUUsQ0FBQztDQUNsRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBsb3RseVNlcnZpY2UgfSBmcm9tICcuL3Bsb3RseS5zZXJ2aWNlJztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5LCBSZWdpb25Ub29sTW9kZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9yZWdpb24tb3ZlcmxheS5jb250cmFjdCc7XG5cbi8qKlxuICogUGxvdGx5IGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJUmVnaW9uT3ZlcmxheX0uXG4gKlxuICogUGxvdGx5IHJlbmRlcnMgcmVnaW9uIHNoYXBlcyBuYXRpdmVseSBpbiBpdHMgcGxvdCBsYXlvdXQgYW5kIGVkaXRzIHRoZW0gdmlhXG4gKiBpdHMgb3duIGRyYWcgbW9kZXMsIHNvIHRoaXMgYWRhcHRlciBpcyB0aGluOiBpdCBtYXBzIHRoZSBuZXV0cmFsXG4gKiB7QGxpbmsgUmVnaW9uVG9vbE1vZGV9IG9udG8gUGxvdGx5IGRyYWcgbW9kZXMgYW5kIGxldHMgUGxvdGx5IGRyYXcuIGByZWRyYXdgXG4gKiBpcyBhIG5vLW9wIGJlY2F1c2UgUGxvdGx5IHJlLXJlbmRlcnMgaXRzIHNoYXBlcyBpdHNlbGYgb24gcmVsYXlvdXQuXG4gKlxuICogSXQgaXMgdGhlIHN5bW1ldHJpYyBjb3VudGVycGFydCB0byB7QGxpbmsgT3NkUmVnaW9uT3ZlcmxheX06IGJvdGggcmVuZGVyIHRoZVxuICogc2FtZSBzaGFyZWQgYElSZWdpb25TdG9yZWAsIGVhY2ggb250byBpdHMgb3duIGJhY2tlbmQncyBjYW52YXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbG90bHlSZWdpb25PdmVybGF5IGltcGxlbWVudHMgSVJlZ2lvbk92ZXJsYXkge1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcGxvdGx5OiBQbG90bHlTZXJ2aWNlKSB7fVxuXG4gIHNldE1vZGUobW9kZTogUmVnaW9uVG9vbE1vZGUpOiB2b2lkIHtcbiAgICAvLyAnc2VsZWN0JyBpcyBhIG5ldXRyYWwgbW9kZSBmb3IgUGxvdGx5IChubyBkcmFnIG1vZGUpOyByZWdpb24gc2VsZWN0aW9uIGlzXG4gICAgLy8gZHJpdmVuIGJ5IHRoZSB0YWJsZSAvIGFjdGl2ZS1zaGFwZSBzYW1wbGluZywgc28ganVzdCBjbGVhciB0aGUgZHJhZyBtb2RlLlxuICAgIGNvbnN0IGRyYWdNb2RlID1cbiAgICAgIG1vZGUgPT09ICdkcmF3cmVjdCcgPyAnZHJhd3JlY3QnIDpcbiAgICAgIG1vZGUgPT09ICdkcmF3Y2xvc2VkcGF0aCcgPyAnZHJhd2Nsb3NlZHBhdGgnIDpcbiAgICAgIG1vZGUgPT09ICdkcmF3b3BlbnBhdGgnID8gJ2RyYXdvcGVucGF0aCcgOlxuICAgICAgZmFsc2U7XG4gICAgdGhpcy5wbG90bHkuc2V0RHJhZ01vZGUoZHJhZ01vZGUpO1xuICB9XG5cbiAgcmVkcmF3KCk6IHZvaWQgeyAvKiBQbG90bHkgcmUtcmVuZGVycyBpdHMgc2hhcGVzIG5hdGl2ZWx5IG9uIHJlbGF5b3V0ICovIH1cblxuICAvKiogQmV6aWVyIHJlZ2lvbnMgYXJlIGFuIE9wZW5TZWFkcmFnb24tb25seSBmZWF0dXJlIChQbG90bHkgaGFzIG5vIG5hdGl2ZVxuICAgKiAgY3VydmVkLXNoYXBlIHJlbmRlcmluZyksIHNvIHRoaXMgaXMgYSBuby1vcCBoZXJlLiAqL1xuICBzZXRTZWxlY3RlZEJlemllcihfYmV6aWVyOiBib29sZWFuKTogdm9pZCB7IC8qIE9TRC1vbmx5ICovIH1cblxuICBkZXN0cm95KCk6IHZvaWQgeyAvKiBub3RoaW5nIHRvIHRlYXIgZG93biDigJQgc2hhcGVzIGxpdmUgaW4gdGhlIFBsb3RseSBsYXlvdXQgKi8gfVxufVxuIl19
@@ -0,0 +1,183 @@
1
+ import { PlotType } from '../../contracts/plot-type';
2
+ import { bt601Luminance } from '../../contracts/intensity';
3
+ // ── helpers ──────────────────────────────────────────────────────────────
4
+ /** Scalar value of a frame cell: `[r, g, b]` → BT.601 luminance, scalar as-is. */
5
+ function luminance(cell) {
6
+ if (Array.isArray(cell)) {
7
+ return bt601Luminance(cell[0], cell[1], cell[2]);
8
+ }
9
+ return cell;
10
+ }
11
+ /** Project a frame to a scalar matrix (RGB → luminance, grayscale → as-is). */
12
+ function toScalarFrame(frame, isGrayscale) {
13
+ if (isGrayscale)
14
+ return frame;
15
+ return frame.map((row) => row.map(luminance));
16
+ }
17
+ /** Even stride that keeps an axis under `maxSamples` sample points. */
18
+ function strideFor(length, maxSamples) {
19
+ return Math.max(1, Math.ceil(length / maxSamples));
20
+ }
21
+ // ── builders ─────────────────────────────────────────────────────────────
22
+ /** Max cells per axis the contour grid is downsampled to. The heatmap trace can
23
+ * raster the full preview cheaply, but contour runs CPU marching-squares over
24
+ * every cell, so a full-resolution preview (~1000²) costs seconds. Contours
25
+ * interpolate, so a coarser grid looks the same while rendering near-instantly. */
26
+ const CONTOUR_MAX_SAMPLES = 400;
27
+ /** Every `sx`-th column / `sy`-th row of a scalar matrix. */
28
+ function downsampleMatrix(matrix, sx, sy) {
29
+ if (sx <= 1 && sy <= 1)
30
+ return matrix;
31
+ const out = [];
32
+ for (let r = 0; r < matrix.length; r += sy) {
33
+ const row = matrix[r];
34
+ if (sx <= 1) {
35
+ out.push(row);
36
+ continue;
37
+ }
38
+ const sampled = [];
39
+ for (let c = 0; c < row.length; c += sx)
40
+ sampled.push(row[c]);
41
+ out.push(sampled);
42
+ }
43
+ return out;
44
+ }
45
+ /** CONTOUR — per-frame iso-contours over a downsampled scalar matrix. Mirrors
46
+ * the heatmap trace geometry (x0/dx/y0/dy) so it lines up with the image axes;
47
+ * the stride scales dx/dy so the coarser grid still spans the true extent. */
48
+ function buildContourTraces(input) {
49
+ const [x0, , y0] = [input.trueImageSize[0], input.trueImageSize[1], input.trueImageSize[2]];
50
+ return input.frames.map((frame, index) => {
51
+ const scalar = toScalarFrame(frame, input.isGrayscale);
52
+ const height = scalar.length;
53
+ const width = height > 0 ? scalar[0].length : 0;
54
+ const sx = strideFor(width, CONTOUR_MAX_SAMPLES);
55
+ const sy = strideFor(height, CONTOUR_MAX_SAMPLES);
56
+ return {
57
+ x0,
58
+ dx: input.ratios[0] * sx,
59
+ y0,
60
+ dy: input.ratios[0] * sy,
61
+ z: downsampleMatrix(scalar, sx, sy),
62
+ type: 'contour',
63
+ hoverinfo: 'none',
64
+ colorscale: input.colorscale,
65
+ reversescale: input.reversescale,
66
+ contours: { coloring: 'heatmap' },
67
+ // Cap the level count so it doesn't scale with the (now coarser) grid.
68
+ ncontours: 15,
69
+ name: `Slice ${index + 1}`,
70
+ visible: index === 0,
71
+ };
72
+ });
73
+ }
74
+ /** SCATTER — region centroids as labelled markers (region-sourced). */
75
+ function buildScatterTraces(input) {
76
+ const xs = [];
77
+ const ys = [];
78
+ const text = [];
79
+ input.regions.forEach((poly, i) => {
80
+ const n = poly.xpoints.length;
81
+ if (n === 0)
82
+ return;
83
+ const cx = poly.xpoints.reduce((a, b) => a + b, 0) / n;
84
+ const cy = poly.ypoints.reduce((a, b) => a + b, 0) / n;
85
+ xs.push(cx);
86
+ ys.push(cy);
87
+ text.push(`R${i + 1}`);
88
+ });
89
+ return [{
90
+ x: xs,
91
+ y: ys,
92
+ text,
93
+ type: 'scatter',
94
+ mode: 'markers+text',
95
+ textposition: 'top center',
96
+ marker: { size: 10, color: input.shapeColor, line: { color: '#000', width: 1 } },
97
+ name: 'Region centroids',
98
+ }];
99
+ }
100
+ /**
101
+ * Collect a downsampled regular grid of voxels across the z-stack.
102
+ * Returns parallel flat arrays suitable for both scatter3d and isosurface.
103
+ * A single-frame image is thickened to two z-planes so 3D traces render.
104
+ */
105
+ function sampleVolume(input, maxXY, maxZ) {
106
+ let frames = input.frames.map(f => toScalarFrame(f, input.isGrayscale));
107
+ if (frames.length < 2)
108
+ frames = [frames[0] || [], frames[0] || []];
109
+ const height = frames[0].length;
110
+ const width = height > 0 ? frames[0][0].length : 0;
111
+ const sx = strideFor(width, maxXY);
112
+ const sy = strideFor(height, maxXY);
113
+ const sz = strideFor(frames.length, maxZ);
114
+ const x = [];
115
+ const y = [];
116
+ const z = [];
117
+ const value = [];
118
+ for (let zi = 0; zi < frames.length; zi += sz) {
119
+ for (let yi = 0; yi < height; yi += sy) {
120
+ const rowArr = frames[zi][yi] || [];
121
+ for (let xi = 0; xi < width; xi += sx) {
122
+ x.push(xi * input.ratios[0]);
123
+ y.push(yi * input.ratios[0]);
124
+ z.push(zi);
125
+ value.push(rowArr[xi]);
126
+ }
127
+ }
128
+ }
129
+ return { x, y, z, value };
130
+ }
131
+ /** SCATTER3D — downsampled voxels as intensity-coloured 3D markers. */
132
+ function buildScatter3dTraces(input) {
133
+ const { x, y, z, value } = sampleVolume(input, 48, 40);
134
+ return [{
135
+ type: 'scatter3d',
136
+ mode: 'markers',
137
+ x, y, z,
138
+ marker: {
139
+ size: 2,
140
+ color: value,
141
+ colorscale: input.colorscale,
142
+ reversescale: input.reversescale,
143
+ opacity: 0.8,
144
+ },
145
+ name: 'Voxels',
146
+ }];
147
+ }
148
+ /** ISOSURFACE — iso-intensity surfaces over the downsampled volume grid.
149
+ * isomin/isomax come straight from the toolbar range slider (0–255). */
150
+ function buildIsosurfaceTraces(input) {
151
+ const { x, y, z, value } = sampleVolume(input, 40, 40);
152
+ // The caller (PlotlyService) maps the 0–255 slider onto the volume's real
153
+ // intensity range before this runs, so the band always sits inside the data.
154
+ // We only guard ordering here.
155
+ const isoMin = Math.min(input.isoMin, input.isoMax);
156
+ const isoMax = Math.max(input.isoMin, input.isoMax);
157
+ return [{
158
+ type: 'isosurface',
159
+ x, y, z, value,
160
+ isomin: isoMin,
161
+ isomax: isoMax,
162
+ // A few nested levels (not just the two band extremes): even if an extreme
163
+ // grazes the data edge and draws nothing, an interior level still renders,
164
+ // so the volume is never silently empty.
165
+ surface: { count: 3 },
166
+ colorscale: input.colorscale,
167
+ reversescale: input.reversescale,
168
+ opacity: 0.6,
169
+ caps: { x: { show: false }, y: { show: false }, z: { show: false } },
170
+ name: 'Isosurface',
171
+ }];
172
+ }
173
+ /** Registry of the pluggable (non-original) plot types. */
174
+ export const PLOTLY_PLOT_TYPE_IMPLS = {
175
+ [PlotType.CONTOUR]: { buildTraces: buildContourTraces, layoutKind: '2d-image', threeD: false },
176
+ [PlotType.SCATTER]: { buildTraces: buildScatterTraces, layoutKind: '2d-overlay', threeD: false },
177
+ [PlotType.SCATTER3D]: { buildTraces: buildScatter3dTraces, layoutKind: '3d-volume', threeD: true },
178
+ [PlotType.ISOSURFACE]: { buildTraces: buildIsosurfaceTraces, layoutKind: '3d-volume', threeD: true },
179
+ };
180
+ export function getPlotTypeImpl(type) {
181
+ return PLOTLY_PLOT_TYPE_IMPLS[type];
182
+ }
183
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXRyYWNlLWJ1aWxkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS10cmFjZS1idWlsZGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBNEQzRCw0RUFBNEU7QUFFNUUsa0ZBQWtGO0FBQ2xGLFNBQVMsU0FBUyxDQUFDLElBQVM7SUFDMUIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDeEIsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQ0QsT0FBTyxJQUFjLENBQUM7QUFDeEIsQ0FBQztBQUVELCtFQUErRTtBQUMvRSxTQUFTLGFBQWEsQ0FBQyxLQUFZLEVBQUUsV0FBb0I7SUFDdkQsSUFBSSxXQUFXO1FBQUUsT0FBTyxLQUFtQixDQUFDO0lBQzVDLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQVUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFFRCx1RUFBdUU7QUFDdkUsU0FBUyxTQUFTLENBQUMsTUFBYyxFQUFFLFVBQWtCO0lBQ25ELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBRUQsNEVBQTRFO0FBRTVFOzs7b0ZBR29GO0FBQ3BGLE1BQU0sbUJBQW1CLEdBQUcsR0FB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QUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3BFLElBQUksRUFBRSxZQUFZO1NBQ25CLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCwyREFBMkQ7QUFDM0QsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQWtEO0lBQ25GLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFLLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixFQUFLLFVBQVUsRUFBRSxVQUFVLEVBQUksTUFBTSxFQUFFLEtBQUssRUFBRTtJQUN0RyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBSyxFQUFFLFdBQVcsRUFBRSxrQkFBa0IsRUFBSyxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDdEcsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUcsRUFBRSxXQUFXLEVBQUUsb0JBQW9CLEVBQUcsVUFBVSxFQUFFLFdBQVcsRUFBRyxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3JHLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLHFCQUFxQixFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUcsTUFBTSxFQUFFLElBQUksRUFBRTtDQUN0RyxDQUFDO0FBRUYsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUFjO0lBQzVDLE9BQU8sc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDdEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBsb3RUeXBlIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Bsb3QtdHlwZSc7XG5pbXBvcnQgeyBidDYwMUx1bWluYW5jZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9pbnRlbnNpdHknO1xuXG4vKipcbiAqIFBsdWdnYWJsZSBQbG90bHkgdHJhY2UgYnVpbGRlcnMgZm9yIHRoZSBwbG90IHR5cGVzIGFkZGVkIG9uIHRvcCBvZiB0aGVcbiAqIG9yaWdpbmFsIEhFQVRNQVAgLyBTVVJGQUNFIC8gUkdCLWltYWdlIHJlbmRlcmVycy5cbiAqXG4gKiBERVNJR04gLyBFWFRSQUNUSU9OIEFMSUdOTUVOVFxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEV2ZXJ5IGZ1bmN0aW9uIGhlcmUgaXMgKipwdXJlKiog4oCUIGl0IHRha2VzIGEgYFRyYWNlQnVpbGRJbnB1dGAgYW5kIHJldHVybnNcbiAqIFBsb3RseSB0cmFjZSBkaWN0cy4gVGhlcmUgaXMgbm8gQW5ndWxhciwgbm8gUnhKUywgbm8gaG9zdC1zdGF0ZSBjb3VwbGluZ1xuICogKGBNYWluU3RhdGVgLCBgRmlsZXNTZXJ2aWNlYCwg4oCmKS4gVGhhdCBrZWVwcyB0aGUgbW9kdWxlIHJlbG9jYXRhYmxlIGludG8gdGhlXG4gKiBmdXR1cmUgYEBqYXgtZGF0YS1zY2llbmNlL2ltYWdlLXZpc3VhbGl6YXRpb25gIGxpYnJhcnkgY29yZSAoc2VlIHRoZVxuICogYHNrZXRjaC9qaXQtcGxvdHRpbmctZXh0cmFjdGlvbmAgU09XKSB3aXRob3V0IHBvcnQgc3VyZ2VyeS5cbiAqXG4gKiBMYXlvdXQgYnVpbGRpbmcgc3RheXMgaW4gYFBsb3RseVNlcnZpY2VgIChpdCBuZWVkcyBsaXZlIHNlcnZpY2Ugc3RhdGUgc3VjaFxuICogYXMgc2NyZWVuIGhlaWdodCwgc2NhbGUgcmF0aW8gYW5kIHRoZSBjdXJyZW50IHNoYXBlcyk7IG9ubHkgVFJBQ0UgYnVpbGRpbmdcbiAqIGlzIHBsdWdnYWJsZSBoZXJlLiBUbyBhZGQgYSBuZXcgcGxvdCB0eXBlOiB3cml0ZSBhIGJ1aWxkZXIsIHJlZ2lzdGVyIGl0IGluXG4gKiBgUExPVExZX1BMT1RfVFlQRV9JTVBMU2AsIGFuZCBhZGQgYSBkZXNjcmlwdG9yIGluIGBjb250cmFjdHMvcGxvdC10eXBlLnRzYC5cbiAqXG4gKiBUaGUgb3JpZ2luYWwgSEVBVE1BUC9TVVJGQUNFL1JHQiB0eXBlcyBpbnRlbnRpb25hbGx5IGtlZXAgdGhlaXIgZGVkaWNhdGVkXG4gKiByZW5kZXJlcnMgaW4gYFBsb3RseVNlcnZpY2VgICh0aGV5IGFyZSBhbHNvIHJldXNlZCBieSB0aGUgaGlnaC1kZWYgem9vbVxuICogcmUtZmV0Y2ggcGF0aCksIHNvIHRoZXkgYXJlIE5PVCByZWdpc3RlcmVkIGhlcmUuXG4gKi9cblxuLyoqIE5vcm1hbGlzZWQgaW5wdXQgZm9yIGEgdHJhY2UgYnVpbGRlci4gRnJhbWVzIGFyZSBwZXItei1wbGFuZSBtYXRyaWNlczpcbiAqICBncmF5c2NhbGUgY2VsbHMgYXJlIHNjYWxhcnMsIFJHQiBjZWxscyBhcmUgYFtyLCBnLCBiXWAuICovXG5leHBvcnQgaW50ZXJmYWNlIFRyYWNlQnVpbGRJbnB1dCB7XG4gIGZyYW1lczogYW55W107XG4gIHdpZHRoOiBudW1iZXI7XG4gIGhlaWdodDogbnVtYmVyO1xuICAvKiogW3hSYXRpbywgeVJhdGlvXSDigJQgZGF0YSB1bml0cyBwZXIgcGl4ZWwuICovXG4gIHJhdGlvczogbnVtYmVyW107XG4gIC8qKiBbeDAsIHgxLCB5MCwgeTFdIOKAlCB0cnVlIGltYWdlIGV4dGVudCBpbiBkYXRhIHVuaXRzLiAqL1xuICB0cnVlSW1hZ2VTaXplOiBudW1iZXJbXTtcbiAgaXNHcmF5c2NhbGU6IGJvb2xlYW47XG4gIC8qKiBQbG90bHkgY29sb3JzY2FsZSB2YWx1ZSAoZS5nLiBmcm9tIHRoZSBhY3RpdmUgY29sb3JtYXApLiAqL1xuICBjb2xvcnNjYWxlOiBhbnk7XG4gIHJldmVyc2VzY2FsZTogYm9vbGVhbjtcbiAgLyoqIFJlZ2lvbiBwb2x5Z29ucyBpbiBkYXRhIGNvb3JkcywgZm9yIHJlZ2lvbi1zb3VyY2VkIHBsb3RzIChTQ0FUVEVSKS4gKi9cbiAgcmVnaW9uczogeyB4cG9pbnRzOiBudW1iZXJbXTsgeXBvaW50czogbnVtYmVyW10gfVtdO1xuICAvKiogRGVmYXVsdCBtYXJrZXIvbGluZSBjb2xvdXIgZm9yIGRlcml2ZWQgKG5vbi1pbWFnZS1MVVQpIHRyYWNlcy4gKi9cbiAgc2hhcGVDb2xvcjogc3RyaW5nO1xuICAvKiogSVNPU1VSRkFDRSBpbnRlbnNpdHkgYm91bmRzICgw4oCTMjU1KTogc3VyZmFjZXMgYXJlIGRyYXduIGZvciB2YWx1ZXMgaW5cbiAgICogIFtpc29NaW4sIGlzb01heF0sIG1hcHBlZCBzdHJhaWdodCBvbnRvIFBsb3RseSdzIGlzb21pbi9pc29tYXguICovXG4gIGlzb01pbjogbnVtYmVyO1xuICBpc29NYXg6IG51bWJlcjtcbn1cblxuZXhwb3J0IHR5cGUgVHJhY2VCdWlsZGVyID0gKGlucHV0OiBUcmFjZUJ1aWxkSW5wdXQpID0+IGFueVtdO1xuXG5leHBvcnQgdHlwZSBQbG90TGF5b3V0S2luZCA9ICcyZC1pbWFnZScgfCAnMmQtb3ZlcmxheScgfCAnMmQtY2hhcnQnIHwgJzNkLXZvbHVtZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGxvdGx5UGxvdFR5cGVJbXBsIHtcbiAgYnVpbGRUcmFjZXM6IFRyYWNlQnVpbGRlcjtcbiAgLyoqIFdoaWNoIGxheW91dCBgUGxvdGx5U2VydmljZWAgc2hvdWxkIGJ1aWxkIGZvciB0aGlzIHR5cGUuICovXG4gIGxheW91dEtpbmQ6IFBsb3RMYXlvdXRLaW5kO1xuICAvKiogVHJ1ZSBmb3Igc2NlbmUtYmFzZWQgKDNEKSB0cmFjZXMg4oCUIHBpY2tzIHRoZSAzRCBQbG90bHkgY29uZmlnLiAqL1xuICB0aHJlZUQ6IGJvb2xlYW47XG59XG5cbi8vIOKUgOKUgCBoZWxwZXJzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogU2NhbGFyIHZhbHVlIG9mIGEgZnJhbWUgY2VsbDogYFtyLCBnLCBiXWAg4oaSIEJULjYwMSBsdW1pbmFuY2UsIHNjYWxhciBhcy1pcy4gKi9cbmZ1bmN0aW9uIGx1bWluYW5jZShjZWxsOiBhbnkpOiBudW1iZXIge1xuICBpZiAoQXJyYXkuaXNBcnJheShjZWxsKSkge1xuICAgIHJldHVybiBidDYwMUx1bWluYW5jZShjZWxsWzBdLCBjZWxsWzFdLCBjZWxsWzJdKTtcbiAgfVxuICByZXR1cm4gY2VsbCBhcyBudW1iZXI7XG59XG5cbi8qKiBQcm9qZWN0IGEgZnJhbWUgdG8gYSBzY2FsYXIgbWF0cml4IChSR0Ig4oaSIGx1bWluYW5jZSwgZ3JheXNjYWxlIOKGkiBhcy1pcykuICovXG5mdW5jdGlvbiB0b1NjYWxhckZyYW1lKGZyYW1lOiBhbnlbXSwgaXNHcmF5c2NhbGU6IGJvb2xlYW4pOiBudW1iZXJbXVtdIHtcbiAgaWYgKGlzR3JheXNjYWxlKSByZXR1cm4gZnJhbWUgYXMgbnVtYmVyW11bXTtcbiAgcmV0dXJuIGZyYW1lLm1hcCgocm93OiBhbnlbXSkgPT4gcm93Lm1hcChsdW1pbmFuY2UpKTtcbn1cblxuLyoqIEV2ZW4gc3RyaWRlIHRoYXQga2VlcHMgYW4gYXhpcyB1bmRlciBgbWF4U2FtcGxlc2Agc2FtcGxlIHBvaW50cy4gKi9cbmZ1bmN0aW9uIHN0cmlkZUZvcihsZW5ndGg6IG51bWJlciwgbWF4U2FtcGxlczogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgubWF4KDEsIE1hdGguY2VpbChsZW5ndGggLyBtYXhTYW1wbGVzKSk7XG59XG5cbi8vIOKUgOKUgCBidWlsZGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqIE1heCBjZWxscyBwZXIgYXhpcyB0aGUgY29udG91ciBncmlkIGlzIGRvd25zYW1wbGVkIHRvLiBUaGUgaGVhdG1hcCB0cmFjZSBjYW5cbiAqICByYXN0ZXIgdGhlIGZ1bGwgcHJldmlldyBjaGVhcGx5LCBidXQgY29udG91ciBydW5zIENQVSBtYXJjaGluZy1zcXVhcmVzIG92ZXJcbiAqICBldmVyeSBjZWxsLCBzbyBhIGZ1bGwtcmVzb2x1dGlvbiBwcmV2aWV3ICh+MTAwMMKyKSBjb3N0cyBzZWNvbmRzLiBDb250b3Vyc1xuICogIGludGVycG9sYXRlLCBzbyBhIGNvYXJzZXIgZ3JpZCBsb29rcyB0aGUgc2FtZSB3aGlsZSByZW5kZXJpbmcgbmVhci1pbnN0YW50bHkuICovXG5jb25zdCBDT05UT1VSX01BWF9TQU1QTEVTID0gNDAwO1xuXG4vKiogRXZlcnkgYHN4YC10aCBjb2x1bW4gLyBgc3lgLXRoIHJvdyBvZiBhIHNjYWxhciBtYXRyaXguICovXG5mdW5jdGlvbiBkb3duc2FtcGxlTWF0cml4KG1hdHJpeDogbnVtYmVyW11bXSwgc3g6IG51bWJlciwgc3k6IG51bWJlcik6IG51bWJlcltdW10ge1xuICBpZiAoc3ggPD0gMSAmJiBzeSA8PSAxKSByZXR1cm4gbWF0cml4O1xuICBjb25zdCBvdXQ6IG51bWJlcltdW10gPSBbXTtcbiAgZm9yIChsZXQgciA9IDA7IHIgPCBtYXRyaXgubGVuZ3RoOyByICs9IHN5KSB7XG4gICAgY29uc3Qgcm93ID0gbWF0cml4W3JdO1xuICAgIGlmIChzeCA8PSAxKSB7IG91dC5wdXNoKHJvdyk7IGNvbnRpbnVlOyB9XG4gICAgY29uc3Qgc2FtcGxlZDogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBjID0gMDsgYyA8IHJvdy5sZW5ndGg7IGMgKz0gc3gpIHNhbXBsZWQucHVzaChyb3dbY10pO1xuICAgIG91dC5wdXNoKHNhbXBsZWQpO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBDT05UT1VSIOKAlCBwZXItZnJhbWUgaXNvLWNvbnRvdXJzIG92ZXIgYSBkb3duc2FtcGxlZCBzY2FsYXIgbWF0cml4LiBNaXJyb3JzXG4gKiAgdGhlIGhlYXRtYXAgdHJhY2UgZ2VvbWV0cnkgKHgwL2R4L3kwL2R5KSBzbyBpdCBsaW5lcyB1cCB3aXRoIHRoZSBpbWFnZSBheGVzO1xuICogIHRoZSBzdHJpZGUgc2NhbGVzIGR4L2R5IHNvIHRoZSBjb2Fyc2VyIGdyaWQgc3RpbGwgc3BhbnMgdGhlIHRydWUgZXh0ZW50LiAqL1xuZnVuY3Rpb24gYnVpbGRDb250b3VyVHJhY2VzKGlucHV0OiBUcmFjZUJ1aWxkSW5wdXQpOiBhbnlbXSB7XG4gIGNvbnN0IFt4MCwgLCB5MF0gPSBbaW5wdXQudHJ1ZUltYWdlU2l6ZVswXSwgaW5wdXQudHJ1ZUltYWdlU2l6ZVsxXSwgaW5wdXQudHJ1ZUltYWdlU2l6ZVsyXV07XG4gIHJldHVybiBpbnB1dC5mcmFtZXMubWFwKChmcmFtZSwgaW5kZXgpID0+IHtcbiAgICBjb25zdCBzY2FsYXIgPSB0b1NjYWxhckZyYW1lKGZyYW1lLCBpbnB1dC5pc0dyYXlzY2FsZSk7XG4gICAgY29uc3QgaGVpZ2h0ID0gc2NhbGFyLmxlbmd0aDtcbiAgICBjb25zdCB3aWR0aCA9IGhlaWdodCA+IDAgPyBzY2FsYXJbMF0ubGVuZ3RoIDogMDtcbiAgICBjb25zdCBzeCA9IHN0cmlkZUZvcih3aWR0aCwgQ09OVE9VUl9NQVhfU0FNUExFUyk7XG4gICAgY29uc3Qgc3kgPSBzdHJpZGVGb3IoaGVpZ2h0LCBDT05UT1VSX01BWF9TQU1QTEVTKTtcbiAgICByZXR1cm4ge1xuICAgICAgeDAsXG4gICAgICBkeDogaW5wdXQucmF0aW9zWzBdICogc3gsXG4gICAgICB5MCxcbiAgICAgIGR5OiBpbnB1dC5yYXRpb3NbMF0gKiBzeSxcbiAgICAgIHo6IGRvd25zYW1wbGVNYXRyaXgoc2NhbGFyLCBzeCwgc3kpLFxuICAgICAgdHlwZTogJ2NvbnRvdXInLFxuICAgICAgaG92ZXJpbmZvOiAnbm9uZScsXG4gICAgICBjb2xvcnNjYWxlOiBpbnB1dC5jb2xvcnNjYWxlLFxuICAgICAgcmV2ZXJzZXNjYWxlOiBpbnB1dC5yZXZlcnNlc2NhbGUsXG4gICAgICBjb250b3VyczogeyBjb2xvcmluZzogJ2hlYXRtYXAnIH0sXG4gICAgICAvLyBDYXAgdGhlIGxldmVsIGNvdW50IHNvIGl0IGRvZXNuJ3Qgc2NhbGUgd2l0aCB0aGUgKG5vdyBjb2Fyc2VyKSBncmlkLlxuICAgICAgbmNvbnRvdXJzOiAxNSxcbiAgICAgIG5hbWU6IGBTbGljZSAke2luZGV4ICsgMX1gLFxuICAgICAgdmlzaWJsZTogaW5kZXggPT09IDAsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKiBTQ0FUVEVSIOKAlCByZWdpb24gY2VudHJvaWRzIGFzIGxhYmVsbGVkIG1hcmtlcnMgKHJlZ2lvbi1zb3VyY2VkKS4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2NhdHRlclRyYWNlcyhpbnB1dDogVHJhY2VCdWlsZElucHV0KTogYW55W10ge1xuICBjb25zdCB4czogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgeXM6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHRleHQ6IHN0cmluZ1tdID0gW107XG4gIGlucHV0LnJlZ2lvbnMuZm9yRWFjaCgocG9seSwgaSkgPT4ge1xuICAgIGNvbnN0IG4gPSBwb2x5Lnhwb2ludHMubGVuZ3RoO1xuICAgIGlmIChuID09PSAwKSByZXR1cm47XG4gICAgY29uc3QgY3ggPSBwb2x5Lnhwb2ludHMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgLyBuO1xuICAgIGNvbnN0IGN5ID0gcG9seS55cG9pbnRzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApIC8gbjtcbiAgICB4cy5wdXNoKGN4KTtcbiAgICB5cy5wdXNoKGN5KTtcbiAgICB0ZXh0LnB1c2goYFIke2kgKyAxfWApO1xuICB9KTtcbiAgcmV0dXJuIFt7XG4gICAgeDogeHMsXG4gICAgeTogeXMsXG4gICAgdGV4dCxcbiAgICB0eXBlOiAnc2NhdHRlcicsXG4gICAgbW9kZTogJ21hcmtlcnMrdGV4dCcsXG4gICAgdGV4dHBvc2l0aW9uOiAndG9wIGNlbnRlcicsXG4gICAgbWFya2VyOiB7IHNpemU6IDEwLCBjb2xvcjogaW5wdXQuc2hhcGVDb2xvciwgbGluZTogeyBjb2xvcjogJyMwMDAnLCB3aWR0aDogMSB9IH0sXG4gICAgbmFtZTogJ1JlZ2lvbiBjZW50cm9pZHMnLFxuICB9XTtcbn1cblxuLyoqXG4gKiBDb2xsZWN0IGEgZG93bnNhbXBsZWQgcmVndWxhciBncmlkIG9mIHZveGVscyBhY3Jvc3MgdGhlIHotc3RhY2suXG4gKiBSZXR1cm5zIHBhcmFsbGVsIGZsYXQgYXJyYXlzIHN1aXRhYmxlIGZvciBib3RoIHNjYXR0ZXIzZCBhbmQgaXNvc3VyZmFjZS5cbiAqIEEgc2luZ2xlLWZyYW1lIGltYWdlIGlzIHRoaWNrZW5lZCB0byB0d28gei1wbGFuZXMgc28gM0QgdHJhY2VzIHJlbmRlci5cbiAqL1xuZnVuY3Rpb24gc2FtcGxlVm9sdW1lKGlucHV0OiBUcmFjZUJ1aWxkSW5wdXQsIG1heFhZOiBudW1iZXIsIG1heFo6IG51bWJlcikge1xuICBsZXQgZnJhbWVzID0gaW5wdXQuZnJhbWVzLm1hcChmID0+IHRvU2NhbGFyRnJhbWUoZiwgaW5wdXQuaXNHcmF5c2NhbGUpKTtcbiAgaWYgKGZyYW1lcy5sZW5ndGggPCAyKSBmcmFtZXMgPSBbZnJhbWVzWzBdIHx8IFtdLCBmcmFtZXNbMF0gfHwgW11dO1xuXG4gIGNvbnN0IGhlaWdodCA9IGZyYW1lc1swXS5sZW5ndGg7XG4gIGNvbnN0IHdpZHRoID0gaGVpZ2h0ID4gMCA/IGZyYW1lc1swXVswXS5sZW5ndGggOiAwO1xuICBjb25zdCBzeCA9IHN0cmlkZUZvcih3aWR0aCwgbWF4WFkpO1xuICBjb25zdCBzeSA9IHN0cmlkZUZvcihoZWlnaHQsIG1heFhZKTtcbiAgY29uc3Qgc3ogPSBzdHJpZGVGb3IoZnJhbWVzLmxlbmd0aCwgbWF4Wik7XG5cbiAgY29uc3QgeDogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgeTogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgejogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgdmFsdWU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IHppID0gMDsgemkgPCBmcmFtZXMubGVuZ3RoOyB6aSArPSBzeikge1xuICAgIGZvciAobGV0IHlpID0gMDsgeWkgPCBoZWlnaHQ7IHlpICs9IHN5KSB7XG4gICAgICBjb25zdCByb3dBcnIgPSBmcmFtZXNbemldW3lpXSB8fCBbXTtcbiAgICAgIGZvciAobGV0IHhpID0gMDsgeGkgPCB3aWR0aDsgeGkgKz0gc3gpIHtcbiAgICAgICAgeC5wdXNoKHhpICogaW5wdXQucmF0aW9zWzBdKTtcbiAgICAgICAgeS5wdXNoKHlpICogaW5wdXQucmF0aW9zWzBdKTtcbiAgICAgICAgei5wdXNoKHppKTtcbiAgICAgICAgdmFsdWUucHVzaChyb3dBcnJbeGldKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgeCwgeSwgeiwgdmFsdWUgfTtcbn1cblxuLyoqIFNDQVRURVIzRCDigJQgZG93bnNhbXBsZWQgdm94ZWxzIGFzIGludGVuc2l0eS1jb2xvdXJlZCAzRCBtYXJrZXJzLiAqL1xuZnVuY3Rpb24gYnVpbGRTY2F0dGVyM2RUcmFjZXMoaW5wdXQ6IFRyYWNlQnVpbGRJbnB1dCk6IGFueVtdIHtcbiAgY29uc3QgeyB4LCB5LCB6LCB2YWx1ZSB9ID0gc2FtcGxlVm9sdW1lKGlucHV0LCA0OCwgNDApO1xuICByZXR1cm4gW3tcbiAgICB0eXBlOiAnc2NhdHRlcjNkJyxcbiAgICBtb2RlOiAnbWFya2VycycsXG4gICAgeCwgeSwgeixcbiAgICBtYXJrZXI6IHtcbiAgICAgIHNpemU6IDIsXG4gICAgICBjb2xvcjogdmFsdWUsXG4gICAgICBjb2xvcnNjYWxlOiBpbnB1dC5jb2xvcnNjYWxlLFxuICAgICAgcmV2ZXJzZXNjYWxlOiBpbnB1dC5yZXZlcnNlc2NhbGUsXG4gICAgICBvcGFjaXR5OiAwLjgsXG4gICAgfSxcbiAgICBuYW1lOiAnVm94ZWxzJyxcbiAgfV07XG59XG5cbi8qKiBJU09TVVJGQUNFIOKAlCBpc28taW50ZW5zaXR5IHN1cmZhY2VzIG92ZXIgdGhlIGRvd25zYW1wbGVkIHZvbHVtZSBncmlkLlxuICogIGlzb21pbi9pc29tYXggY29tZSBzdHJhaWdodCBmcm9tIHRoZSB0b29sYmFyIHJhbmdlIHNsaWRlciAoMOKAkzI1NSkuICovXG5mdW5jdGlvbiBidWlsZElzb3N1cmZhY2VUcmFjZXMoaW5wdXQ6IFRyYWNlQnVpbGRJbnB1dCk6IGFueVtdIHtcbiAgY29uc3QgeyB4LCB5LCB6LCB2YWx1ZSB9ID0gc2FtcGxlVm9sdW1lKGlucHV0LCA0MCwgNDApO1xuICAvLyBUaGUgY2FsbGVyIChQbG90bHlTZXJ2aWNlKSBtYXBzIHRoZSAw4oCTMjU1IHNsaWRlciBvbnRvIHRoZSB2b2x1bWUncyByZWFsXG4gIC8vIGludGVuc2l0eSByYW5nZSBiZWZvcmUgdGhpcyBydW5zLCBzbyB0aGUgYmFuZCBhbHdheXMgc2l0cyBpbnNpZGUgdGhlIGRhdGEuXG4gIC8vIFdlIG9ubHkgZ3VhcmQgb3JkZXJpbmcgaGVyZS5cbiAgY29uc3QgaXNvTWluID0gTWF0aC5taW4oaW5wdXQuaXNvTWluLCBpbnB1dC5pc29NYXgpO1xuICBjb25zdCBpc29NYXggPSBNYXRoLm1heChpbnB1dC5pc29NaW4sIGlucHV0Lmlzb01heCk7XG4gIHJldHVybiBbe1xuICAgIHR5cGU6ICdpc29zdXJmYWNlJyxcbiAgICB4LCB5LCB6LCB2YWx1ZSxcbiAgICBpc29taW46IGlzb01pbixcbiAgICBpc29tYXg6IGlzb01heCxcbiAgICAvLyBBIGZldyBuZXN0ZWQgbGV2ZWxzIChub3QganVzdCB0aGUgdHdvIGJhbmQgZXh0cmVtZXMpOiBldmVuIGlmIGFuIGV4dHJlbWVcbiAgICAvLyBncmF6ZXMgdGhlIGRhdGEgZWRnZSBhbmQgZHJhd3Mgbm90aGluZywgYW4gaW50ZXJpb3IgbGV2ZWwgc3RpbGwgcmVuZGVycyxcbiAgICAvLyBzbyB0aGUgdm9sdW1lIGlzIG5ldmVyIHNpbGVudGx5IGVtcHR5LlxuICAgIHN1cmZhY2U6IHsgY291bnQ6IDMgfSxcbiAgICBjb2xvcnNjYWxlOiBpbnB1dC5jb2xvcnNjYWxlLFxuICAgIHJldmVyc2VzY2FsZTogaW5wdXQucmV2ZXJzZXNjYWxlLFxuICAgIG9wYWNpdHk6IDAuNixcbiAgICBjYXBzOiB7IHg6IHsgc2hvdzogZmFsc2UgfSwgeTogeyBzaG93OiBmYWxzZSB9LCB6OiB7IHNob3c6IGZhbHNlIH0gfSxcbiAgICBuYW1lOiAnSXNvc3VyZmFjZScsXG4gIH1dO1xufVxuXG4vKiogUmVnaXN0cnkgb2YgdGhlIHBsdWdnYWJsZSAobm9uLW9yaWdpbmFsKSBwbG90IHR5cGVzLiAqL1xuZXhwb3J0IGNvbnN0IFBMT1RMWV9QTE9UX1RZUEVfSU1QTFM6IFBhcnRpYWw8UmVjb3JkPFBsb3RUeXBlLCBQbG90bHlQbG90VHlwZUltcGw+PiA9IHtcbiAgW1Bsb3RUeXBlLkNPTlRPVVJdOiAgICB7IGJ1aWxkVHJhY2VzOiBidWlsZENvbnRvdXJUcmFjZXMsICAgIGxheW91dEtpbmQ6ICcyZC1pbWFnZScsICAgdGhyZWVEOiBmYWxzZSB9LFxuICBbUGxvdFR5cGUuU0NBVFRFUl06ICAgIHsgYnVpbGRUcmFjZXM6IGJ1aWxkU2NhdHRlclRyYWNlcywgICAgbGF5b3V0S2luZDogJzJkLW92ZXJsYXknLCB0aHJlZUQ6IGZhbHNlIH0sXG4gIFtQbG90VHlwZS5TQ0FUVEVSM0RdOiAgeyBidWlsZFRyYWNlczogYnVpbGRTY2F0dGVyM2RUcmFjZXMsICBsYXlvdXRLaW5kOiAnM2Qtdm9sdW1lJywgIHRocmVlRDogdHJ1ZSB9LFxuICBbUGxvdFR5cGUuSVNPU1VSRkFDRV06IHsgYnVpbGRUcmFjZXM6IGJ1aWxkSXNvc3VyZmFjZVRyYWNlcywgbGF5b3V0S2luZDogJzNkLXZvbHVtZScsICB0aHJlZUQ6IHRydWUgfSxcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQbG90VHlwZUltcGwodHlwZTogUGxvdFR5cGUpOiBQbG90bHlQbG90VHlwZUltcGwgfCB1bmRlZmluZWQge1xuICByZXR1cm4gUExPVExZX1BMT1RfVFlQRV9JTVBMU1t0eXBlXTtcbn1cbiJdfQ==