@jax-data-science/sci-image-visualizer 0.8.2 → 0.9.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 (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +361 -4184
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34430
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -878
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,58 @@
1
+ import { Directive, EventEmitter, HostListener, Input, NgZone, Output } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Drag handle of a floating, `position: fixed` panel (the intensity inset header,
5
+ * the toolbar dock handle). On mousedown it asks {@link origin} where the panel is —
6
+ * the host may detach a docked panel right there — then emits the new position on
7
+ * every move until mouseup.
8
+ *
9
+ * The move/up listeners exist only while a drag is in progress and run outside the
10
+ * Angular zone, re-entering it per emitted position: a permanent window mousemove
11
+ * listener made every pointer move anywhere in the host app run change detection.
12
+ */
13
+ export class FloatingDragDirective {
14
+ constructor(zone) {
15
+ this.zone = zone;
16
+ /** The panel's new position, per pointer move. */
17
+ this.vizFloatingDragMove = new EventEmitter();
18
+ this.end = null;
19
+ }
20
+ onMouseDown(e) {
21
+ e.preventDefault();
22
+ this.end?.();
23
+ const from = this.origin();
24
+ const start = { mx: e.clientX, my: e.clientY, x: from.x, y: from.y };
25
+ const move = (ev) => this.zone.run(() => this.vizFloatingDragMove.emit({
26
+ x: start.x + (ev.clientX - start.mx),
27
+ y: start.y + (ev.clientY - start.my),
28
+ }));
29
+ const up = () => this.end?.();
30
+ this.zone.runOutsideAngular(() => {
31
+ window.addEventListener('mousemove', move);
32
+ window.addEventListener('mouseup', up);
33
+ });
34
+ this.end = () => {
35
+ window.removeEventListener('mousemove', move);
36
+ window.removeEventListener('mouseup', up);
37
+ this.end = null;
38
+ };
39
+ }
40
+ ngOnDestroy() {
41
+ this.end?.();
42
+ }
43
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: FloatingDragDirective, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); }
44
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.9", type: FloatingDragDirective, isStandalone: true, selector: "[vizFloatingDrag]", inputs: { origin: ["vizFloatingDrag", "origin"] }, outputs: { vizFloatingDragMove: "vizFloatingDragMove" }, host: { listeners: { "mousedown": "onMouseDown($event)" } }, ngImport: i0 }); }
45
+ }
46
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: FloatingDragDirective, decorators: [{
47
+ type: Directive,
48
+ args: [{ selector: '[vizFloatingDrag]', standalone: true }]
49
+ }], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { origin: [{
50
+ type: Input,
51
+ args: ['vizFloatingDrag']
52
+ }], vizFloatingDragMove: [{
53
+ type: Output
54
+ }], onMouseDown: [{
55
+ type: HostListener,
56
+ args: ['mousedown', ['$event']]
57
+ }] } });
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvYXRpbmctZHJhZy5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvZmxvYXRpbmctZHJhZy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQWEsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDOztBQVF4Rzs7Ozs7Ozs7O0dBU0c7QUFFSCxNQUFNLE9BQU8scUJBQXFCO0lBUWhDLFlBQTZCLElBQVk7UUFBWixTQUFJLEdBQUosSUFBSSxDQUFRO1FBTHpDLGtEQUFrRDtRQUMvQix3QkFBbUIsR0FBRyxJQUFJLFlBQVksRUFBZSxDQUFDO1FBRWpFLFFBQUcsR0FBd0IsSUFBSSxDQUFDO0lBRUksQ0FBQztJQUc3QyxXQUFXLENBQUMsQ0FBYTtRQUN2QixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7UUFDYixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0IsTUFBTSxLQUFLLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3JFLE1BQU0sSUFBSSxHQUFHLENBQUMsRUFBYyxFQUFFLEVBQUUsQ0FDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQ2pCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUM7WUFDNUIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDcEMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7U0FDckMsQ0FBQyxDQUNILENBQUM7UUFDSixNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsRUFBRTtZQUMvQixNQUFNLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzNDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsRUFBRTtZQUNkLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDOUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMxQyxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQztRQUNsQixDQUFDLENBQUM7SUFDSixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDO0lBQ2YsQ0FBQzs4R0FyQ1UscUJBQXFCO2tHQUFyQixxQkFBcUI7OzJGQUFyQixxQkFBcUI7a0JBRGpDLFNBQVM7bUJBQUMsRUFBRSxRQUFRLEVBQUUsbUJBQW1CLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRTsyRUFHbEMsTUFBTTtzQkFBL0IsS0FBSzt1QkFBQyxpQkFBaUI7Z0JBRUwsbUJBQW1CO3NCQUFyQyxNQUFNO2dCQU9QLFdBQVc7c0JBRFYsWUFBWTt1QkFBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyLCBJbnB1dCwgTmdab25lLCBPbkRlc3Ryb3ksIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKiogQSBzY3JlZW4gcG9zaXRpb24sIGluIENTUyBwaXhlbHMuICovXG5leHBvcnQgaW50ZXJmYWNlIEZsb2F0aW5nUG9zIHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG59XG5cbi8qKlxuICogRHJhZyBoYW5kbGUgb2YgYSBmbG9hdGluZywgYHBvc2l0aW9uOiBmaXhlZGAgcGFuZWwgKHRoZSBpbnRlbnNpdHkgaW5zZXQgaGVhZGVyLFxuICogdGhlIHRvb2xiYXIgZG9jayBoYW5kbGUpLiBPbiBtb3VzZWRvd24gaXQgYXNrcyB7QGxpbmsgb3JpZ2lufSB3aGVyZSB0aGUgcGFuZWwgaXMg4oCUXG4gKiB0aGUgaG9zdCBtYXkgZGV0YWNoIGEgZG9ja2VkIHBhbmVsIHJpZ2h0IHRoZXJlIOKAlCB0aGVuIGVtaXRzIHRoZSBuZXcgcG9zaXRpb24gb25cbiAqIGV2ZXJ5IG1vdmUgdW50aWwgbW91c2V1cC5cbiAqXG4gKiBUaGUgbW92ZS91cCBsaXN0ZW5lcnMgZXhpc3Qgb25seSB3aGlsZSBhIGRyYWcgaXMgaW4gcHJvZ3Jlc3MgYW5kIHJ1biBvdXRzaWRlIHRoZVxuICogQW5ndWxhciB6b25lLCByZS1lbnRlcmluZyBpdCBwZXIgZW1pdHRlZCBwb3NpdGlvbjogYSBwZXJtYW5lbnQgd2luZG93IG1vdXNlbW92ZVxuICogbGlzdGVuZXIgbWFkZSBldmVyeSBwb2ludGVyIG1vdmUgYW55d2hlcmUgaW4gdGhlIGhvc3QgYXBwIHJ1biBjaGFuZ2UgZGV0ZWN0aW9uLlxuICovXG5ARGlyZWN0aXZlKHsgc2VsZWN0b3I6ICdbdml6RmxvYXRpbmdEcmFnXScsIHN0YW5kYWxvbmU6IHRydWUgfSlcbmV4cG9ydCBjbGFzcyBGbG9hdGluZ0RyYWdEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAvKiogQ2FsbGVkIG9uIG1vdXNlZG93bjogdGhlIHBhbmVsJ3MgcG9zaXRpb24gdGhlIGRyYWcgc3RhcnRzIGZyb20uICovXG4gIEBJbnB1dCgndml6RmxvYXRpbmdEcmFnJykgb3JpZ2luITogKCkgPT4gRmxvYXRpbmdQb3M7XG4gIC8qKiBUaGUgcGFuZWwncyBuZXcgcG9zaXRpb24sIHBlciBwb2ludGVyIG1vdmUuICovXG4gIEBPdXRwdXQoKSByZWFkb25seSB2aXpGbG9hdGluZ0RyYWdNb3ZlID0gbmV3IEV2ZW50RW1pdHRlcjxGbG9hdGluZ1Bvcz4oKTtcblxuICBwcml2YXRlIGVuZDogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSB6b25lOiBOZ1pvbmUpIHt9XG5cbiAgQEhvc3RMaXN0ZW5lcignbW91c2Vkb3duJywgWyckZXZlbnQnXSlcbiAgb25Nb3VzZURvd24oZTogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmVuZD8uKCk7XG4gICAgY29uc3QgZnJvbSA9IHRoaXMub3JpZ2luKCk7XG4gICAgY29uc3Qgc3RhcnQgPSB7IG14OiBlLmNsaWVudFgsIG15OiBlLmNsaWVudFksIHg6IGZyb20ueCwgeTogZnJvbS55IH07XG4gICAgY29uc3QgbW92ZSA9IChldjogTW91c2VFdmVudCkgPT5cbiAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT5cbiAgICAgICAgdGhpcy52aXpGbG9hdGluZ0RyYWdNb3ZlLmVtaXQoe1xuICAgICAgICAgIHg6IHN0YXJ0LnggKyAoZXYuY2xpZW50WCAtIHN0YXJ0Lm14KSxcbiAgICAgICAgICB5OiBzdGFydC55ICsgKGV2LmNsaWVudFkgLSBzdGFydC5teSksXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICBjb25zdCB1cCA9ICgpID0+IHRoaXMuZW5kPy4oKTtcbiAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG1vdmUpO1xuICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB1cCk7XG4gICAgfSk7XG4gICAgdGhpcy5lbmQgPSAoKSA9PiB7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW92ZSk7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHVwKTtcbiAgICAgIHRoaXMuZW5kID0gbnVsbDtcbiAgICB9O1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5lbmQ/LigpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,149 @@
1
+ import { takeUntil } from 'rxjs/operators';
2
+ import { MultiPolygon, Polygon, Rectangle } from '../models/region';
3
+ import { opEligible, regionsAt } from './visualizer-context-menu';
4
+ /**
5
+ * Region set-operations on the current selection (jit-ui#85) — select all, merge,
6
+ * ungroup, inverse, simplify — plus the store mirrors the toolbar and the context
7
+ * menu read synchronously: the selection and the undo/redo availability.
8
+ *
9
+ * Every operation commits through `setRegions`, so it is undo-tracked and the
10
+ * backend on screen re-renders; profile lines and unselected regions are kept.
11
+ */
12
+ export class RegionActions {
13
+ constructor(target, ops,
14
+ /** `[width, height]` of the image, when known — the frame inverse and merge rasterize in. */
15
+ imageSize, notify) {
16
+ this.target = target;
17
+ this.ops = ops;
18
+ this.imageSize = imageSize;
19
+ this.notify = notify;
20
+ /** Current selection (array indices), mirrored from the store. */
21
+ this.selectedIndices = [];
22
+ /** Whether a region action is available to undo / redo; drive the toolbar buttons. */
23
+ this.canUndo = false;
24
+ this.canRedo = false;
25
+ /** Custom-threshold Simplify dialog. */
26
+ this.displaySimplifyDialog = false;
27
+ this.simplifyThreshold = 3;
28
+ }
29
+ /** Mirror the store's selection and undo/redo depth until `until$` emits.
30
+ * `changed` runs after an undo/redo flip (the toolbar binds those). */
31
+ bind(until$, changed) {
32
+ this.target
33
+ .getCanUndo$()
34
+ .pipe(takeUntil(until$))
35
+ .subscribe((v) => {
36
+ this.canUndo = v;
37
+ changed();
38
+ });
39
+ this.target
40
+ .getCanRedo$()
41
+ .pipe(takeUntil(until$))
42
+ .subscribe((v) => {
43
+ this.canRedo = v;
44
+ changed();
45
+ });
46
+ this.target
47
+ .getSelectedShapeIndices$()
48
+ .pipe(takeUntil(until$))
49
+ .subscribe((indices) => {
50
+ this.selectedIndices = indices || [];
51
+ });
52
+ }
53
+ /** The currently-selected regions (live store instances). */
54
+ get selected() {
55
+ return regionsAt(this.target.getRegions(), this.selectedIndices);
56
+ }
57
+ /** Select every region on the image (excludes intensity-profile lines). */
58
+ selectAll() {
59
+ const indices = [];
60
+ this.target.getRegions().forEach((r, i) => {
61
+ if (r.kind !== 'profile')
62
+ indices.push(i);
63
+ });
64
+ this.target.setSelectedShapeIndices(indices);
65
+ }
66
+ /** Merge the selected regions into a single (possibly multi-part) region. */
67
+ merge() {
68
+ const sel = opEligible(this.selected);
69
+ if (sel.length < 2)
70
+ return;
71
+ const { w, h } = this.frame(sel);
72
+ const merged = this.ops.merge(sel, w, h);
73
+ if (merged)
74
+ this.replace(sel, [merged]);
75
+ }
76
+ /** Split each selected multi-part region into one region per part. */
77
+ ungroup() {
78
+ const sel = this.selected.filter((r) => this.ops.canUngroup(r));
79
+ if (sel.length === 0)
80
+ return;
81
+ this.replace(sel, sel.flatMap((r) => this.ops.ungroup(r)));
82
+ }
83
+ /** Replace the selection with its inverse inside the image rectangle. */
84
+ inverse() {
85
+ const sel = opEligible(this.selected);
86
+ if (sel.length === 0)
87
+ return;
88
+ const { w, h } = this.frame(sel);
89
+ const inv = this.ops.inverse(sel, w, h);
90
+ if (!inv) {
91
+ this.notify({
92
+ severity: 'warn',
93
+ summary: 'Inverse',
94
+ detail: 'Nothing to invert — select one or more closed regions first.',
95
+ });
96
+ return;
97
+ }
98
+ this.replace(sel, [inv]);
99
+ }
100
+ /** Douglas–Peucker simplify each selected region by `thresholdPx`, closing the dialog. */
101
+ simplify(thresholdPx) {
102
+ const sel = opEligible(this.selected);
103
+ if (sel.length === 0)
104
+ return;
105
+ this.replace(sel, sel.map((r) => this.ops.simplify(r, thresholdPx)));
106
+ this.displaySimplifyDialog = false;
107
+ }
108
+ openSimplifyDialog() {
109
+ this.displaySimplifyDialog = true;
110
+ }
111
+ /** Commit a set-op: drop `remove`, append `add`, and select the results. */
112
+ replace(remove, add) {
113
+ if (add.length === 0)
114
+ return;
115
+ const removeSet = new Set(remove);
116
+ const kept = this.target.getRegions().filter((r) => !removeSet.has(r));
117
+ this.target.setRegions([...kept, ...add]); // mints ids on `add`, records undo
118
+ const stored = this.target.getRegions();
119
+ this.target.setSelectedShapeIndices(add.map((r) => stored.indexOf(r)).filter((i) => i >= 0));
120
+ }
121
+ /** Image pixel dimensions for the raster ops; falls back to the selection's extent
122
+ * when the image size isn't known (keeps clamping sane). */
123
+ frame(regions) {
124
+ let [w, h] = this.imageSize() ?? [0, 0];
125
+ if (!(w > 0) || !(h > 0)) {
126
+ let maxX = 0, maxY = 0;
127
+ const scan = (xs, ys) => {
128
+ for (const x of xs)
129
+ maxX = Math.max(maxX, x);
130
+ for (const y of ys)
131
+ maxY = Math.max(maxY, y);
132
+ };
133
+ for (const r of regions) {
134
+ const b = r.bounds;
135
+ if (b instanceof Rectangle)
136
+ scan([b.x + b.width], [b.y + b.height]);
137
+ else if (b instanceof Polygon)
138
+ scan(b.xpoints, b.ypoints);
139
+ else if (b instanceof MultiPolygon)
140
+ for (const p of b.polygons)
141
+ scan(p.xpoints, p.ypoints);
142
+ }
143
+ w = Math.max(w, Math.ceil(maxX) + 2);
144
+ h = Math.max(h, Math.ceil(maxY) + 2);
145
+ }
146
+ return { w, h };
147
+ }
148
+ }
149
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLWFjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvcmVnaW9uLWFjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSTNDLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBVSxNQUFNLGtCQUFrQixDQUFDO0FBRTVFLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFhbEU7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBVXhCLFlBQ21CLE1BQTJCLEVBQzNCLEdBQXFCO0lBQ3RDLDZGQUE2RjtJQUM1RSxTQUFxQyxFQUNyQyxNQUFrQztRQUpsQyxXQUFNLEdBQU4sTUFBTSxDQUFxQjtRQUMzQixRQUFHLEdBQUgsR0FBRyxDQUFrQjtRQUVyQixjQUFTLEdBQVQsU0FBUyxDQUE0QjtRQUNyQyxXQUFNLEdBQU4sTUFBTSxDQUE0QjtRQWRyRCxrRUFBa0U7UUFDbEUsb0JBQWUsR0FBYSxFQUFFLENBQUM7UUFDL0Isc0ZBQXNGO1FBQ3RGLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFDaEIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQix3Q0FBd0M7UUFDeEMsMEJBQXFCLEdBQUcsS0FBSyxDQUFDO1FBQzlCLHNCQUFpQixHQUFHLENBQUMsQ0FBQztJQVFuQixDQUFDO0lBRUo7NEVBQ3dFO0lBQ3hFLElBQUksQ0FBQyxNQUEyQixFQUFFLE9BQW1CO1FBQ25ELElBQUksQ0FBQyxNQUFNO2FBQ1IsV0FBVyxFQUFFO2FBQ2IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUN2QixTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUNmLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1lBQ2pCLE9BQU8s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QU0sQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUN4QixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO2dCQUNuQixJQUFJLENBQUMsWUFBWSxTQUFTO29CQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztxQkFDL0QsSUFBSSxDQUFDLFlBQVksT0FBTztvQkFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7cUJBQ3JELElBQUksQ0FBQyxZQUFZLFlBQVk7b0JBQUUsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUTt3QkFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDN0YsQ0FBQztZQUNELENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFDRCxPQUFPLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ2xCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IE1lc3NhZ2UgfSBmcm9tICdwcmltZW5nL2FwaSc7XG5cbmltcG9ydCB7IElSZWdpb25TdG9yZSB9IGZyb20gJy4uL2NvbnRyYWN0cy92aXN1YWxpemVyLmNvbnRyYWN0JztcbmltcG9ydCB7IE11bHRpUG9seWdvbiwgUG9seWdvbiwgUmVjdGFuZ2xlLCBSZWdpb24gfSBmcm9tICcuLi9tb2RlbHMvcmVnaW9uJztcbmltcG9ydCB7IFJlZ2lvbk9wc1NlcnZpY2UgfSBmcm9tICcuLi9yZWdpb24tb3BzLnNlcnZpY2UnO1xuaW1wb3J0IHsgb3BFbGlnaWJsZSwgcmVnaW9uc0F0IH0gZnJvbSAnLi92aXN1YWxpemVyLWNvbnRleHQtbWVudSc7XG5cbi8qKiBUaGUgcmVnaW9uLXN0b3JlIG1lbWJlcnMgdGhlIHNldC1vcGVyYXRpb25zIHJlYWQgYW5kIHdyaXRlIHRocm91Z2guICovXG5leHBvcnQgdHlwZSBSZWdpb25BY3Rpb25zVGFyZ2V0ID0gUGljazxcbiAgSVJlZ2lvblN0b3JlLFxuICB8ICdnZXRSZWdpb25zJ1xuICB8ICdzZXRSZWdpb25zJ1xuICB8ICdzZXRTZWxlY3RlZFNoYXBlSW5kaWNlcydcbiAgfCAnZ2V0U2VsZWN0ZWRTaGFwZUluZGljZXMkJ1xuICB8ICdnZXRDYW5VbmRvJCdcbiAgfCAnZ2V0Q2FuUmVkbyQnXG4+O1xuXG4vKipcbiAqIFJlZ2lvbiBzZXQtb3BlcmF0aW9ucyBvbiB0aGUgY3VycmVudCBzZWxlY3Rpb24gKGppdC11aSM4NSkg4oCUIHNlbGVjdCBhbGwsIG1lcmdlLFxuICogdW5ncm91cCwgaW52ZXJzZSwgc2ltcGxpZnkg4oCUIHBsdXMgdGhlIHN0b3JlIG1pcnJvcnMgdGhlIHRvb2xiYXIgYW5kIHRoZSBjb250ZXh0XG4gKiBtZW51IHJlYWQgc3luY2hyb25vdXNseTogdGhlIHNlbGVjdGlvbiBhbmQgdGhlIHVuZG8vcmVkbyBhdmFpbGFiaWxpdHkuXG4gKlxuICogRXZlcnkgb3BlcmF0aW9uIGNvbW1pdHMgdGhyb3VnaCBgc2V0UmVnaW9uc2AsIHNvIGl0IGlzIHVuZG8tdHJhY2tlZCBhbmQgdGhlXG4gKiBiYWNrZW5kIG9uIHNjcmVlbiByZS1yZW5kZXJzOyBwcm9maWxlIGxpbmVzIGFuZCB1bnNlbGVjdGVkIHJlZ2lvbnMgYXJlIGtlcHQuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZWdpb25BY3Rpb25zIHtcbiAgLyoqIEN1cnJlbnQgc2VsZWN0aW9uIChhcnJheSBpbmRpY2VzKSwgbWlycm9yZWQgZnJvbSB0aGUgc3RvcmUuICovXG4gIHNlbGVjdGVkSW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgLyoqIFdoZXRoZXIgYSByZWdpb24gYWN0aW9uIGlzIGF2YWlsYWJsZSB0byB1bmRvIC8gcmVkbzsgZHJpdmUgdGhlIHRvb2xiYXIgYnV0dG9ucy4gKi9cbiAgY2FuVW5kbyA9IGZhbHNlO1xuICBjYW5SZWRvID0gZmFsc2U7XG4gIC8qKiBDdXN0b20tdGhyZXNob2xkIFNpbXBsaWZ5IGRpYWxvZy4gKi9cbiAgZGlzcGxheVNpbXBsaWZ5RGlhbG9nID0gZmFsc2U7XG4gIHNpbXBsaWZ5VGhyZXNob2xkID0gMztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRhcmdldDogUmVnaW9uQWN0aW9uc1RhcmdldCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wczogUmVnaW9uT3BzU2VydmljZSxcbiAgICAvKiogYFt3aWR0aCwgaGVpZ2h0XWAgb2YgdGhlIGltYWdlLCB3aGVuIGtub3duIOKAlCB0aGUgZnJhbWUgaW52ZXJzZSBhbmQgbWVyZ2UgcmFzdGVyaXplIGluLiAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaW1hZ2VTaXplOiAoKSA9PiBudW1iZXJbXSB8IHVuZGVmaW5lZCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IG5vdGlmeTogKG1lc3NhZ2U6IE1lc3NhZ2UpID0+IHZvaWQsXG4gICkge31cblxuICAvKiogTWlycm9yIHRoZSBzdG9yZSdzIHNlbGVjdGlvbiBhbmQgdW5kby9yZWRvIGRlcHRoIHVudGlsIGB1bnRpbCRgIGVtaXRzLlxuICAgKiAgYGNoYW5nZWRgIHJ1bnMgYWZ0ZXIgYW4gdW5kby9yZWRvIGZsaXAgKHRoZSB0b29sYmFyIGJpbmRzIHRob3NlKS4gKi9cbiAgYmluZCh1bnRpbCQ6IE9ic2VydmFibGU8dW5rbm93bj4sIGNoYW5nZWQ6ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLnRhcmdldFxuICAgICAgLmdldENhblVuZG8kKClcbiAgICAgIC5waXBlKHRha2VVbnRpbCh1bnRpbCQpKVxuICAgICAgLnN1YnNjcmliZSgodikgPT4ge1xuICAgICAgICB0aGlzLmNhblVuZG8gPSB2O1xuICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICB9KTtcbiAgICB0aGlzLnRhcmdldFxuICAgICAgLmdldENhblJlZG8kKClcbiAgICAgIC5waXBlKHRha2VVbnRpbCh1bnRpbCQpKVxuICAgICAgLnN1YnNjcmliZSgodikgPT4ge1xuICAgICAgICB0aGlzLmNhblJlZG8gPSB2O1xuICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICB9KTtcbiAgICB0aGlzLnRhcmdldFxuICAgICAgLmdldFNlbGVjdGVkU2hhcGVJbmRpY2VzJCgpXG4gICAgICAucGlwZSh0YWtlVW50aWwodW50aWwkKSlcbiAgICAgIC5zdWJzY3JpYmUoKGluZGljZXMpID0+IHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZEluZGljZXMgPSBpbmRpY2VzIHx8IFtdO1xuICAgICAgfSk7XG4gIH1cblxuICAvKiogVGhlIGN1cnJlbnRseS1zZWxlY3RlZCByZWdpb25zIChsaXZlIHN0b3JlIGluc3RhbmNlcykuICovXG4gIGdldCBzZWxlY3RlZCgpOiBSZWdpb25bXSB7XG4gICAgcmV0dXJuIHJlZ2lvbnNBdCh0aGlzLnRhcmdldC5nZXRSZWdpb25zKCksIHRoaXMuc2VsZWN0ZWRJbmRpY2VzKTtcbiAgfVxuXG4gIC8qKiBTZWxlY3QgZXZlcnkgcmVnaW9uIG9uIHRoZSBpbWFnZSAoZXhjbHVkZXMgaW50ZW5zaXR5LXByb2ZpbGUgbGluZXMpLiAqL1xuICBzZWxlY3RBbGwoKTogdm9pZCB7XG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgICB0aGlzLnRhcmdldC5nZXRSZWdpb25zKCkuZm9yRWFjaCgociwgaSkgPT4ge1xuICAgICAgaWYgKHIua2luZCAhPT0gJ3Byb2ZpbGUnKSBpbmRpY2VzLnB1c2goaSk7XG4gICAgfSk7XG4gICAgdGhpcy50YXJnZXQuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoaW5kaWNlcyk7XG4gIH1cblxuICAvKiogTWVyZ2UgdGhlIHNlbGVjdGVkIHJlZ2lvbnMgaW50byBhIHNpbmdsZSAocG9zc2libHkgbXVsdGktcGFydCkgcmVnaW9uLiAqL1xuICBtZXJnZSgpOiB2b2lkIHtcbiAgICBjb25zdCBzZWwgPSBvcEVsaWdpYmxlKHRoaXMuc2VsZWN0ZWQpO1xuICAgIGlmIChzZWwubGVuZ3RoIDwgMikgcmV0dXJuO1xuICAgIGNvbnN0IHsgdywgaCB9ID0gdGhpcy5mcmFtZShzZWwpO1xuICAgIGNvbnN0IG1lcmdlZCA9IHRoaXMub3BzLm1lcmdlKHNlbCwgdywgaCk7XG4gICAgaWYgKG1lcmdlZCkgdGhpcy5yZXBsYWNlKHNlbCwgW21lcmdlZF0pO1xuICB9XG5cbiAgLyoqIFNwbGl0IGVhY2ggc2VsZWN0ZWQgbXVsdGktcGFydCByZWdpb24gaW50byBvbmUgcmVnaW9uIHBlciBwYXJ0LiAqL1xuICB1bmdyb3VwKCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbCA9IHRoaXMuc2VsZWN0ZWQuZmlsdGVyKChyKSA9PiB0aGlzLm9wcy5jYW5Vbmdyb3VwKHIpKTtcbiAgICBpZiAoc2VsLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIHRoaXMucmVwbGFjZShcbiAgICAgIHNlbCxcbiAgICAgIHNlbC5mbGF0TWFwKChyKSA9PiB0aGlzLm9wcy51bmdyb3VwKHIpKSxcbiAgICApO1xuICB9XG5cbiAgLyoqIFJlcGxhY2UgdGhlIHNlbGVjdGlvbiB3aXRoIGl0cyBpbnZlcnNlIGluc2lkZSB0aGUgaW1hZ2UgcmVjdGFuZ2xlLiAqL1xuICBpbnZlcnNlKCk6IHZvaWQge1xuICAgIGNvbnN0IHNlbCA9IG9wRWxpZ2libGUodGhpcy5zZWxlY3RlZCk7XG4gICAgaWYgKHNlbC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICBjb25zdCB7IHcsIGggfSA9IHRoaXMuZnJhbWUoc2VsKTtcbiAgICBjb25zdCBpbnYgPSB0aGlzLm9wcy5pbnZlcnNlKHNlbCwgdywgaCk7XG4gICAgaWYgKCFpbnYpIHtcbiAgICAgIHRoaXMubm90aWZ5KHtcbiAgICAgICAgc2V2ZXJpdHk6ICd3YXJuJyxcbiAgICAgICAgc3VtbWFyeTogJ0ludmVyc2UnLFxuICAgICAgICBkZXRhaWw6ICdOb3RoaW5nIHRvIGludmVydCDigJQgc2VsZWN0IG9uZSBvciBtb3JlIGNsb3NlZCByZWdpb25zIGZpcnN0LicsXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yZXBsYWNlKHNlbCwgW2ludl0pO1xuICB9XG5cbiAgLyoqIERvdWdsYXPigJNQZXVja2VyIHNpbXBsaWZ5IGVhY2ggc2VsZWN0ZWQgcmVnaW9uIGJ5IGB0aHJlc2hvbGRQeGAsIGNsb3NpbmcgdGhlIGRpYWxvZy4gKi9cbiAgc2ltcGxpZnkodGhyZXNob2xkUHg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHNlbCA9IG9wRWxpZ2libGUodGhpcy5zZWxlY3RlZCk7XG4gICAgaWYgKHNlbC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnJlcGxhY2UoXG4gICAgICBzZWwsXG4gICAgICBzZWwubWFwKChyKSA9PiB0aGlzLm9wcy5zaW1wbGlmeShyLCB0aHJlc2hvbGRQeCkpLFxuICAgICk7XG4gICAgdGhpcy5kaXNwbGF5U2ltcGxpZnlEaWFsb2cgPSBmYWxzZTtcbiAgfVxuXG4gIG9wZW5TaW1wbGlmeURpYWxvZygpOiB2b2lkIHtcbiAgICB0aGlzLmRpc3BsYXlTaW1wbGlmeURpYWxvZyA9IHRydWU7XG4gIH1cblxuICAvKiogQ29tbWl0IGEgc2V0LW9wOiBkcm9wIGByZW1vdmVgLCBhcHBlbmQgYGFkZGAsIGFuZCBzZWxlY3QgdGhlIHJlc3VsdHMuICovXG4gIHByaXZhdGUgcmVwbGFjZShyZW1vdmU6IFJlZ2lvbltdLCBhZGQ6IFJlZ2lvbltdKTogdm9pZCB7XG4gICAgaWYgKGFkZC5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICBjb25zdCByZW1vdmVTZXQgPSBuZXcgU2V0KHJlbW92ZSk7XG4gICAgY29uc3Qga2VwdCA9IHRoaXMudGFyZ2V0LmdldFJlZ2lvbnMoKS5maWx0ZXIoKHIpID0+ICFyZW1vdmVTZXQuaGFzKHIpKTtcbiAgICB0aGlzLnRhcmdldC5zZXRSZWdpb25zKFsuLi5rZXB0LCAuLi5hZGRdKTsgLy8gbWludHMgaWRzIG9uIGBhZGRgLCByZWNvcmRzIHVuZG9cbiAgICBjb25zdCBzdG9yZWQgPSB0aGlzLnRhcmdldC5nZXRSZWdpb25zKCk7XG4gICAgdGhpcy50YXJnZXQuc2V0U2VsZWN0ZWRTaGFwZUluZGljZXMoYWRkLm1hcCgocikgPT4gc3RvcmVkLmluZGV4T2YocikpLmZpbHRlcigoaSkgPT4gaSA+PSAwKSk7XG4gIH1cblxuICAvKiogSW1hZ2UgcGl4ZWwgZGltZW5zaW9ucyBmb3IgdGhlIHJhc3RlciBvcHM7IGZhbGxzIGJhY2sgdG8gdGhlIHNlbGVjdGlvbidzIGV4dGVudFxuICAgKiAgd2hlbiB0aGUgaW1hZ2Ugc2l6ZSBpc24ndCBrbm93biAoa2VlcHMgY2xhbXBpbmcgc2FuZSkuICovXG4gIHByaXZhdGUgZnJhbWUocmVnaW9uczogUmVnaW9uW10pOiB7IHc6IG51bWJlcjsgaDogbnVtYmVyIH0ge1xuICAgIGxldCBbdywgaF0gPSB0aGlzLmltYWdlU2l6ZSgpID8/IFswLCAwXTtcbiAgICBpZiAoISh3ID4gMCkgfHwgIShoID4gMCkpIHtcbiAgICAgIGxldCBtYXhYID0gMCxcbiAgICAgICAgbWF4WSA9IDA7XG4gICAgICBjb25zdCBzY2FuID0gKHhzOiBudW1iZXJbXSwgeXM6IG51bWJlcltdKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgeCBvZiB4cykgbWF4WCA9IE1hdGgubWF4KG1heFgsIHgpO1xuICAgICAgICBmb3IgKGNvbnN0IHkgb2YgeXMpIG1heFkgPSBNYXRoLm1heChtYXhZLCB5KTtcbiAgICAgIH07XG4gICAgICBmb3IgKGNvbnN0IHIgb2YgcmVnaW9ucykge1xuICAgICAgICBjb25zdCBiID0gci5ib3VuZHM7XG4gICAgICAgIGlmIChiIGluc3RhbmNlb2YgUmVjdGFuZ2xlKSBzY2FuKFtiLnggKyBiLndpZHRoXSwgW2IueSArIGIuaGVpZ2h0XSk7XG4gICAgICAgIGVsc2UgaWYgKGIgaW5zdGFuY2VvZiBQb2x5Z29uKSBzY2FuKGIueHBvaW50cywgYi55cG9pbnRzKTtcbiAgICAgICAgZWxzZSBpZiAoYiBpbnN0YW5jZW9mIE11bHRpUG9seWdvbikgZm9yIChjb25zdCBwIG9mIGIucG9seWdvbnMpIHNjYW4ocC54cG9pbnRzLCBwLnlwb2ludHMpO1xuICAgICAgfVxuICAgICAgdyA9IE1hdGgubWF4KHcsIE1hdGguY2VpbChtYXhYKSArIDIpO1xuICAgICAgaCA9IE1hdGgubWF4KGgsIE1hdGguY2VpbChtYXhZKSArIDIpO1xuICAgIH1cbiAgICByZXR1cm4geyB3LCBoIH07XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Apply an image's saved ROIs once its render has landed, choosing the region
3
+ * layout from the image's shape:
4
+ *
5
+ * - **Folder stack** (`isStack && tiled === false`, see loadSeriesAsStack): a stack
6
+ * of self-contained per-slice files. Each slice-file may carry its own sibling
7
+ * `<stem>.geojson` (`roiJsonStrs[z]`), but a fresh folder with none yet leaves
8
+ * `roiJsonStrs` undefined — so this keys off `tiled === false`, NOT `roiJsonStrs`,
9
+ * and an unannotated folder stack still enters the per-slice-file layout (saving
10
+ * back one geojson per slice-file) rather than the combined one (jit-ui#93).
11
+ * - **Single-file z-stack**: one sibling geojson holding every slice's regions,
12
+ * indexed by QuPath's `geometry.plane.z`. Per-slice (combined) mode is entered when
13
+ * the geojson actually carries slice indices, or when there is nothing yet to
14
+ * author against. A legacy geojson whose regions are all on the default plane
15
+ * stays global (shown on every slice), so existing single-plane annotations are
16
+ * not confined to slice 0.
17
+ * - **Single plane** (or that legacy global stack): one region set for the image.
18
+ * Loading saved ROIs is not a user edit, so the undo history starts fresh and the
19
+ * first undo cannot wipe them (jit-ui#85).
20
+ *
21
+ * `z` is the slice shown now; entering stack mode makes it live and resets undo.
22
+ */
23
+ export function applyImageRois(info, target, z) {
24
+ if (info.isStack && info.tiled === false) {
25
+ const perSlice = info.roiJsonStrs;
26
+ const sliceCount = info.urls?.length ?? perSlice?.length ?? 0;
27
+ const slices = new Map();
28
+ for (let s = 0; s < sliceCount; s++) {
29
+ const json = perSlice?.[s] ?? null;
30
+ slices.set(s, json ? target.importRegions(json) : []);
31
+ }
32
+ target.enterStackMode(slices, z, 'per-slice-file');
33
+ return;
34
+ }
35
+ const roiJson = info.roiJsonStr;
36
+ if (info.isStack) {
37
+ const regions = roiJson ? target.importRegions(roiJson) : [];
38
+ if (!roiJson || regions.some((r) => (r.z ?? 0) !== 0)) {
39
+ target.enterStackMode(bySlice(regions), z, 'combined');
40
+ return;
41
+ }
42
+ }
43
+ if (roiJson)
44
+ target.setRegions(target.importRegions(roiJson));
45
+ target.resetUndoHistory();
46
+ }
47
+ /** Bucket regions by their zero-based {@link Region.z} (unset = slice 0). */
48
+ function bySlice(regions) {
49
+ const slices = new Map();
50
+ for (const r of regions) {
51
+ const z = r.z ?? 0;
52
+ const bucket = slices.get(z);
53
+ if (bucket)
54
+ bucket.push(r);
55
+ else
56
+ slices.set(z, [r]);
57
+ }
58
+ return slices;
59
+ }
60
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLWxvYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Zpc3VhbGl6ZXIvcmVnaW9uLWxvYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBVUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBZ0IsRUFBRSxNQUF3QixFQUFFLENBQVM7SUFDbEYsSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDekMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNsQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLE1BQU0sSUFBSSxRQUFRLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUM5RCxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBb0IsQ0FBQztRQUMzQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDcEMsTUFBTSxJQUFJLEdBQUcsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO1lBQ25DLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDeEQsQ0FBQztRQUNELE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25ELE9BQU87SUFDVCxDQUFDO0lBQ0QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUNoQyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUM3RCxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3RELE1BQU0sQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUN2RCxPQUFPO1FBQ1QsQ0FBQztJQUNILENBQUM7SUFDRCxJQUFJLE9BQU87UUFBRSxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUM5RCxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztBQUM1QixDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLFNBQVMsT0FBTyxDQUFDLE9BQWlCO0lBQ2hDLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO0lBQzNDLEtBQUssTUFBTSxDQUFDLElBQUksT0FBTyxFQUFFLENBQUM7UUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkIsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixJQUFJLE1BQU07WUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDOztZQUN0QixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJSW1hZ2VJbmZvIH0gZnJvbSAnLi4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IElSZWdpb25TdG9yZSB9IGZyb20gJy4uL2NvbnRyYWN0cy92aXN1YWxpemVyLmNvbnRyYWN0JztcbmltcG9ydCB7IFJlZ2lvbiB9IGZyb20gJy4uL21vZGVscy9yZWdpb24nO1xuXG4vKiogVGhlIHJlZ2lvbi1zdG9yZSBtZW1iZXJzIHtAbGluayBhcHBseUltYWdlUm9pc30gd3JpdGVzIHRocm91Z2guICovXG5leHBvcnQgdHlwZSBSZWdpb25Mb2FkVGFyZ2V0ID0gUGljazxcbiAgSVJlZ2lvblN0b3JlLFxuICAnaW1wb3J0UmVnaW9ucycgfCAnZW50ZXJTdGFja01vZGUnIHwgJ3NldFJlZ2lvbnMnIHwgJ3Jlc2V0VW5kb0hpc3RvcnknXG4+O1xuXG4vKipcbiAqIEFwcGx5IGFuIGltYWdlJ3Mgc2F2ZWQgUk9JcyBvbmNlIGl0cyByZW5kZXIgaGFzIGxhbmRlZCwgY2hvb3NpbmcgdGhlIHJlZ2lvblxuICogbGF5b3V0IGZyb20gdGhlIGltYWdlJ3Mgc2hhcGU6XG4gKlxuICogIC0gKipGb2xkZXIgc3RhY2sqKiAoYGlzU3RhY2sgJiYgdGlsZWQgPT09IGZhbHNlYCwgc2VlIGxvYWRTZXJpZXNBc1N0YWNrKTogYSBzdGFja1xuICogICAgb2Ygc2VsZi1jb250YWluZWQgcGVyLXNsaWNlIGZpbGVzLiBFYWNoIHNsaWNlLWZpbGUgbWF5IGNhcnJ5IGl0cyBvd24gc2libGluZ1xuICogICAgYDxzdGVtPi5nZW9qc29uYCAoYHJvaUpzb25TdHJzW3pdYCksIGJ1dCBhIGZyZXNoIGZvbGRlciB3aXRoIG5vbmUgeWV0IGxlYXZlc1xuICogICAgYHJvaUpzb25TdHJzYCB1bmRlZmluZWQg4oCUIHNvIHRoaXMga2V5cyBvZmYgYHRpbGVkID09PSBmYWxzZWAsIE5PVCBgcm9pSnNvblN0cnNgLFxuICogICAgYW5kIGFuIHVuYW5ub3RhdGVkIGZvbGRlciBzdGFjayBzdGlsbCBlbnRlcnMgdGhlIHBlci1zbGljZS1maWxlIGxheW91dCAoc2F2aW5nXG4gKiAgICBiYWNrIG9uZSBnZW9qc29uIHBlciBzbGljZS1maWxlKSByYXRoZXIgdGhhbiB0aGUgY29tYmluZWQgb25lIChqaXQtdWkjOTMpLlxuICogIC0gKipTaW5nbGUtZmlsZSB6LXN0YWNrKio6IG9uZSBzaWJsaW5nIGdlb2pzb24gaG9sZGluZyBldmVyeSBzbGljZSdzIHJlZ2lvbnMsXG4gKiAgICBpbmRleGVkIGJ5IFF1UGF0aCdzIGBnZW9tZXRyeS5wbGFuZS56YC4gUGVyLXNsaWNlIChjb21iaW5lZCkgbW9kZSBpcyBlbnRlcmVkIHdoZW5cbiAqICAgIHRoZSBnZW9qc29uIGFjdHVhbGx5IGNhcnJpZXMgc2xpY2UgaW5kaWNlcywgb3Igd2hlbiB0aGVyZSBpcyBub3RoaW5nIHlldCB0b1xuICogICAgYXV0aG9yIGFnYWluc3QuIEEgbGVnYWN5IGdlb2pzb24gd2hvc2UgcmVnaW9ucyBhcmUgYWxsIG9uIHRoZSBkZWZhdWx0IHBsYW5lXG4gKiAgICBzdGF5cyBnbG9iYWwgKHNob3duIG9uIGV2ZXJ5IHNsaWNlKSwgc28gZXhpc3Rpbmcgc2luZ2xlLXBsYW5lIGFubm90YXRpb25zIGFyZVxuICogICAgbm90IGNvbmZpbmVkIHRvIHNsaWNlIDAuXG4gKiAgLSAqKlNpbmdsZSBwbGFuZSoqIChvciB0aGF0IGxlZ2FjeSBnbG9iYWwgc3RhY2spOiBvbmUgcmVnaW9uIHNldCBmb3IgdGhlIGltYWdlLlxuICogICAgTG9hZGluZyBzYXZlZCBST0lzIGlzIG5vdCBhIHVzZXIgZWRpdCwgc28gdGhlIHVuZG8gaGlzdG9yeSBzdGFydHMgZnJlc2ggYW5kIHRoZVxuICogICAgZmlyc3QgdW5kbyBjYW5ub3Qgd2lwZSB0aGVtIChqaXQtdWkjODUpLlxuICpcbiAqIGB6YCBpcyB0aGUgc2xpY2Ugc2hvd24gbm93OyBlbnRlcmluZyBzdGFjayBtb2RlIG1ha2VzIGl0IGxpdmUgYW5kIHJlc2V0cyB1bmRvLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlJbWFnZVJvaXMoaW5mbzogSUltYWdlSW5mbywgdGFyZ2V0OiBSZWdpb25Mb2FkVGFyZ2V0LCB6OiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKGluZm8uaXNTdGFjayAmJiBpbmZvLnRpbGVkID09PSBmYWxzZSkge1xuICAgIGNvbnN0IHBlclNsaWNlID0gaW5mby5yb2lKc29uU3RycztcbiAgICBjb25zdCBzbGljZUNvdW50ID0gaW5mby51cmxzPy5sZW5ndGggPz8gcGVyU2xpY2U/Lmxlbmd0aCA/PyAwO1xuICAgIGNvbnN0IHNsaWNlcyA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgICBmb3IgKGxldCBzID0gMDsgcyA8IHNsaWNlQ291bnQ7IHMrKykge1xuICAgICAgY29uc3QganNvbiA9IHBlclNsaWNlPy5bc10gPz8gbnVsbDtcbiAgICAgIHNsaWNlcy5zZXQocywganNvbiA/IHRhcmdldC5pbXBvcnRSZWdpb25zKGpzb24pIDogW10pO1xuICAgIH1cbiAgICB0YXJnZXQuZW50ZXJTdGFja01vZGUoc2xpY2VzLCB6LCAncGVyLXNsaWNlLWZpbGUnKTtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgcm9pSnNvbiA9IGluZm8ucm9pSnNvblN0cjtcbiAgaWYgKGluZm8uaXNTdGFjaykge1xuICAgIGNvbnN0IHJlZ2lvbnMgPSByb2lKc29uID8gdGFyZ2V0LmltcG9ydFJlZ2lvbnMocm9pSnNvbikgOiBbXTtcbiAgICBpZiAoIXJvaUpzb24gfHwgcmVnaW9ucy5zb21lKChyKSA9PiAoci56ID8/IDApICE9PSAwKSkge1xuICAgICAgdGFyZ2V0LmVudGVyU3RhY2tNb2RlKGJ5U2xpY2UocmVnaW9ucyksIHosICdjb21iaW5lZCcpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuICBpZiAocm9pSnNvbikgdGFyZ2V0LnNldFJlZ2lvbnModGFyZ2V0LmltcG9ydFJlZ2lvbnMocm9pSnNvbikpO1xuICB0YXJnZXQucmVzZXRVbmRvSGlzdG9yeSgpO1xufVxuXG4vKiogQnVja2V0IHJlZ2lvbnMgYnkgdGhlaXIgemVyby1iYXNlZCB7QGxpbmsgUmVnaW9uLnp9ICh1bnNldCA9IHNsaWNlIDApLiAqL1xuZnVuY3Rpb24gYnlTbGljZShyZWdpb25zOiBSZWdpb25bXSk6IE1hcDxudW1iZXIsIFJlZ2lvbltdPiB7XG4gIGNvbnN0IHNsaWNlcyA9IG5ldyBNYXA8bnVtYmVyLCBSZWdpb25bXT4oKTtcbiAgZm9yIChjb25zdCByIG9mIHJlZ2lvbnMpIHtcbiAgICBjb25zdCB6ID0gci56ID8/IDA7XG4gICAgY29uc3QgYnVja2V0ID0gc2xpY2VzLmdldCh6KTtcbiAgICBpZiAoYnVja2V0KSBidWNrZXQucHVzaChyKTtcbiAgICBlbHNlIHNsaWNlcy5zZXQoeiwgW3JdKTtcbiAgfVxuICByZXR1cm4gc2xpY2VzO1xufVxuIl19
@@ -0,0 +1,163 @@
1
+ import { takeUntil } from 'rxjs/operators';
2
+ import { PlotType, isSpatialOmics3d } from '../contracts/plot-type';
3
+ import { buildVolumeStackImage } from '../spatial/spatial-volume-image';
4
+ /**
5
+ * Binds the viewer to the spatial-omics dataset on `SPATIAL_DATA_PORT`: the gates it
6
+ * puts on the plot-type selector ({@link gates}), the mode an image-less dataset opens
7
+ * on, and publishing a dataset's registered volume AS the image.
8
+ *
9
+ * No-op when the host provides no port — the spatial types then stay hidden.
10
+ */
11
+ export class SpatialDatasetBinder {
12
+ constructor(port, host) {
13
+ this.port = port;
14
+ this.host = host;
15
+ /** The dataset on offer, for drawing one that brings no image. */
16
+ this.dataset = null;
17
+ /** A dataset is published — gates the spatial plot types; the toolbar binds it too. */
18
+ this.hasDataset = false;
19
+ /** Its observations carry a z, gating the 3D spatial mode. */
20
+ this.has3d = false;
21
+ /** It brings pixels of its own (see {@link SpatialGates.hasPixels}). */
22
+ this.hasPixels = false;
23
+ /** Dataset identity + capability shape the last emission was handled at, so a
24
+ * switch between two datasets of the same shape is not mistaken for a repeat. */
25
+ this.key = null;
26
+ /** Dataset + geometry the published volume image was built from, so a re-emitted
27
+ * dataset doesn't re-fetch megabytes or reset the user's scrub. */
28
+ this.volumeImageKey = null;
29
+ /** Blob URLs backing that image — ours to revoke. */
30
+ this.volumeImageUrls = [];
31
+ }
32
+ /** Follow the port's dataset until `until$` emits. */
33
+ bind(until$) {
34
+ this.port
35
+ ?.getDataset$()
36
+ .pipe(takeUntil(until$))
37
+ .subscribe((dataset) => this.onDataset(dataset ?? null));
38
+ }
39
+ /** Revoke the published volume image's blob URLs (teardown). */
40
+ dispose() {
41
+ this.revokeVolumeImageUrls();
42
+ }
43
+ onDataset(dataset) {
44
+ this.dataset = dataset;
45
+ // Only a dataset whose observations carry a z can be drawn as a cloud, so the 3D
46
+ // mode is gated on the coordinates, not merely on a dataset being present.
47
+ const has3d = !!dataset?.observations.z;
48
+ const hasVolume = !!dataset?.volume;
49
+ // The port publishes its current value on subscribe, so the initial `null` would
50
+ // otherwise recompute the selector for no change. Keyed by dataset IDENTITY as well
51
+ // as capability shape: two 3D datasets that both carry a volume have the same
52
+ // shape, and comparing only that skipped the switch — leaving the previous
53
+ // dataset's volume image on screen underneath the new one's observations.
54
+ const key = dataset
55
+ ? `${dataset.id}|${has3d}|${hasVolume}|${dataset.volume ? `${dataset.volume.width}x${dataset.volume.height}x${dataset.volume.depth}` : ''}`
56
+ : null;
57
+ if (key === this.key)
58
+ return;
59
+ this.key = key;
60
+ this.hasDataset = !!dataset;
61
+ this.has3d = has3d;
62
+ // Whether the dataset brings pixels: it registers onto a tissue image (which may
63
+ // still be on its way — the pixel modes must not flicker out while it arrives), or
64
+ // its volume is published AS a grayscale z-stack image. Either way the pixel modes
65
+ // stay on offer — Volume and Isosurface are exactly how a 3D omics dataset is read.
66
+ this.hasPixels = !!dataset?.imageRef || hasVolume;
67
+ this.host.gatesChanged();
68
+ if (dataset && !dataset.imageRef && hasVolume) {
69
+ // No section to draw observations over (a cloud registered into a common frame,
70
+ // the Allen CCF), but a registered VOLUME: make that the image and open on it,
71
+ // slice bar and all. Ordered after the gates so the type is on offer first.
72
+ void this.showVolumeAsImage(dataset);
73
+ }
74
+ else {
75
+ // Anything else means a published volume image is no longer what is on screen.
76
+ // Forget it, or coming BACK to the volume dataset would short-circuit on a
77
+ // matching key and leave the other dataset's slide up.
78
+ this.dropVolumeImage();
79
+ if (dataset && !dataset.imageRef) {
80
+ // No reference image and no volume: the observations are all there is, so open
81
+ // on whichever spatial mode their coordinates support — leaving the type alone
82
+ // strands the host on the previous slide. A one-plane assay has no z and
83
+ // cannot be a cloud.
84
+ const target = has3d ? PlotType.SPATIAL_OMICS_3D : PlotType.SPATIAL_OMICS;
85
+ if (this.host.selectedId() !== target)
86
+ this.host.selectPlotType(target);
87
+ // Same mode, another image-less dataset, nothing loaded: re-plot so its
88
+ // placeholder image info (and with it the regions' key) is this dataset's.
89
+ else if (!this.host.hasImage())
90
+ this.host.replot();
91
+ }
92
+ }
93
+ // Clearing the dataset while a spatial mode is active leaves a type that is no
94
+ // longer offered — the host falls back, as turning test mode off does.
95
+ this.host.settled();
96
+ }
97
+ /**
98
+ * Publish a dataset's reference volume AS the image, and open the 2D Image view on it:
99
+ * the slice bar scrubs z, and the contrast window, colormaps and region tools all work
100
+ * because the volume genuinely is the image now. The 3D cloud stays one pick away.
101
+ *
102
+ * Keyed by dataset + geometry: the dataset stream re-emits on things like a
103
+ * colour-column change, and rebuilding then would re-fetch the voxels and throw the
104
+ * user back to the middle slice.
105
+ */
106
+ async showVolumeAsImage(dataset) {
107
+ const meta = dataset.volume;
108
+ if (!meta || !this.port?.getVolume)
109
+ return;
110
+ const key = `${dataset.id}:${meta.width}x${meta.height}x${meta.depth}`;
111
+ if (key === this.volumeImageKey)
112
+ return;
113
+ // Claim the key BEFORE awaiting: the stream can emit again while the voxels are in
114
+ // flight, and two builds of the same volume would race to publish.
115
+ this.volumeImageKey = key;
116
+ this.host.setImageLoading(true);
117
+ try {
118
+ const built = await buildVolumeStackImage(dataset, await this.port.getVolume());
119
+ // A different dataset was selected while this one encoded: drop what we built.
120
+ if (this.volumeImageKey !== key) {
121
+ built?.urls.forEach((u) => URL.revokeObjectURL(u));
122
+ return;
123
+ }
124
+ if (!built) {
125
+ this.volumeImageKey = null;
126
+ return;
127
+ }
128
+ // Pick the mode first so the image lands in the view that will show it.
129
+ if (this.host.selectedId() !== PlotType.IMAGE)
130
+ this.host.selectPlotType(PlotType.IMAGE);
131
+ this.revokeVolumeImageUrls();
132
+ this.volumeImageUrls = built.urls;
133
+ this.host.publishImage(built.info);
134
+ }
135
+ catch (err) {
136
+ // No volume served after all: the cloud is still renderable, so fall back to it.
137
+ console.warn('[visualizer] reference volume unavailable — falling back to the 3D cloud', err);
138
+ this.volumeImageKey = null;
139
+ if (this.has3d && !isSpatialOmics3d(this.host.basePlotType())) {
140
+ this.host.selectPlotType(PlotType.SPATIAL_OMICS_3D);
141
+ }
142
+ }
143
+ finally {
144
+ // Only the build still on screen (or one that failed and released its key) may
145
+ // drop the overlay: a newer volume build that superseded this one is still encoding.
146
+ if (this.volumeImageKey === key || this.volumeImageKey === null)
147
+ this.host.setImageLoading(false);
148
+ this.host.detectChanges();
149
+ }
150
+ }
151
+ /** Forget the published volume image so re-selecting the dataset rebuilds it. The
152
+ * URLs deliberately stay alive: the host may still be displaying that image, and
153
+ * revoking under it would break every later tile read. They are freed when the next
154
+ * volume replaces them, or on {@link dispose}. */
155
+ dropVolumeImage() {
156
+ this.volumeImageKey = null;
157
+ }
158
+ revokeVolumeImageUrls() {
159
+ this.volumeImageUrls.forEach((u) => URL.revokeObjectURL(u));
160
+ this.volumeImageUrls = [];
161
+ }
162
+ }
163
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1kYXRhc2V0LWJpbmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdmlzdWFsaXplci9zcGF0aWFsLWRhdGFzZXQtYmluZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUczQyxPQUFPLEVBQUUsUUFBUSxFQUFjLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFJaEYsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFzQnhFOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFrQi9CLFlBQ21CLElBQWlDLEVBQ2pDLElBQXVCO1FBRHZCLFNBQUksR0FBSixJQUFJLENBQTZCO1FBQ2pDLFNBQUksR0FBSixJQUFJLENBQW1CO1FBbkIxQyxrRUFBa0U7UUFDbEUsWUFBTyxHQUEwQixJQUFJLENBQUM7UUFDdEMsdUZBQXVGO1FBQ3ZGLGVBQVUsR0FBRyxLQUFLLENBQUM7UUFDbkIsOERBQThEO1FBQzlELFVBQUssR0FBRyxLQUFLLENBQUM7UUFDZCx3RUFBd0U7UUFDeEUsY0FBUyxHQUFHLEtBQUssQ0FBQztRQUNsQjswRkFDa0Y7UUFDMUUsUUFBRyxHQUFrQixJQUFJLENBQUM7UUFDbEM7NEVBQ29FO1FBQzVELG1CQUFjLEdBQWtCLElBQUksQ0FBQztRQUM3QyxxREFBcUQ7UUFDN0Msb0JBQWUsR0FBYSxFQUFFLENBQUM7SUFLcEMsQ0FBQztJQUVKLHNEQUFzRDtJQUN0RCxJQUFJLENBQUMsTUFBMkI7UUFDOUIsSUFBSSxDQUFDLElBQUk7WUFDUCxFQUFFLFdBQVcsRUFBRTthQUNkLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDdkIsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sSUFBSSxJ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aW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBJSW1hZ2VJbmZvIH0gZnJvbSAnLi4vY29udHJhY3RzL2ltYWdlLmNvbnRyYWN0JztcbmltcG9ydCB7IFBsb3RUeXBlLCBQbG90VHlwZUlkLCBpc1NwYXRpYWxPbWljczNkIH0gZnJvbSAnLi4vY29udHJhY3RzL3Bsb3QtdHlwZSc7XG5pbXBvcnQgeyBTcGF0aWFsRGF0YVBvcnQgfSBmcm9tICcuLi9jb250cmFjdHMvcG9ydHMvc3BhdGlhbC1kYXRhLnBvcnQnO1xuaW1wb3J0IHsgU3BhdGlhbERhdGFzZXQgfSBmcm9tICcuLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB7IFNwYXRpYWxHYXRlcyB9IGZyb20gJy4uL3Bsb3QtbW9kZS9wbG90LXR5cGUtbWVudSc7XG5pbXBvcnQgeyBidWlsZFZvbHVtZVN0YWNrSW1hZ2UgfSBmcm9tICcuLi9zcGF0aWFsL3NwYXRpYWwtdm9sdW1lLWltYWdlJztcblxuLyoqIFdoYXQgYSBkYXRhc2V0IHN3aXRjaCBhc2tzIG9mIHRoZSB2aWV3ZXIuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwYXRpYWxCaW5kZXJIb3N0IHtcbiAgLyoqIFRoZSBwbG90LXR5cGUgZ2F0ZXMgY2hhbmdlZDogcmVjb21wdXRlIHRoZSBzZWxlY3Rvci4gKi9cbiAgZ2F0ZXNDaGFuZ2VkKCk6IHZvaWQ7XG4gIC8qKiBUaGUgc2VsZWN0b3IncyBjdXJyZW50IGlkLCBhbmQgdGhlIGJ1aWx0LWluIHR5cGUgcmVuZGVyZWQgZm9yIGl0LiAqL1xuICBzZWxlY3RlZElkKCk6IFBsb3RUeXBlSWQ7XG4gIGJhc2VQbG90VHlwZSgpOiBQbG90VHlwZTtcbiAgLyoqIFdoZXRoZXIgYW4gaW1hZ2UgaXMgbG9hZGVkLiAqL1xuICBoYXNJbWFnZSgpOiBib29sZWFuO1xuICBzZWxlY3RQbG90VHlwZSh0eXBlOiBQbG90VHlwZSk6IHZvaWQ7XG4gIC8qKiBSZS1wbG90IHRoZSBjdXJyZW50IG1vZGUuICovXG4gIHJlcGxvdCgpOiB2b2lkO1xuICAvKiogUHVibGlzaCBhbiBpbWFnZSBhcyB0aGUgaG9zdCdzIGN1cnJlbnQgb25lLiAqL1xuICBwdWJsaXNoSW1hZ2UoaW5mbzogSUltYWdlSW5mbyk6IHZvaWQ7XG4gIHNldEltYWdlTG9hZGluZyhsb2FkaW5nOiBib29sZWFuKTogdm9pZDtcbiAgLyoqIFRoZSBzd2l0Y2ggaXMgaGFuZGxlZDogcmVjb25jaWxlIHRoZSBzZWxlY3Rpb24gd2l0aCB0aGUgbmV3IGdhdGVzIGFuZCByZS1yZW5kZXIuICovXG4gIHNldHRsZWQoKTogdm9pZDtcbiAgZGV0ZWN0Q2hhbmdlcygpOiB2b2lkO1xufVxuXG4vKipcbiAqIEJpbmRzIHRoZSB2aWV3ZXIgdG8gdGhlIHNwYXRpYWwtb21pY3MgZGF0YXNldCBvbiBgU1BBVElBTF9EQVRBX1BPUlRgOiB0aGUgZ2F0ZXMgaXRcbiAqIHB1dHMgb24gdGhlIHBsb3QtdHlwZSBzZWxlY3RvciAoe0BsaW5rIGdhdGVzfSksIHRoZSBtb2RlIGFuIGltYWdlLWxlc3MgZGF0YXNldCBvcGVuc1xuICogb24sIGFuZCBwdWJsaXNoaW5nIGEgZGF0YXNldCdzIHJlZ2lzdGVyZWQgdm9sdW1lIEFTIHRoZSBpbWFnZS5cbiAqXG4gKiBOby1vcCB3aGVuIHRoZSBob3N0IHByb3ZpZGVzIG5vIHBvcnQg4oCUIHRoZSBzcGF0aWFsIHR5cGVzIHRoZW4gc3RheSBoaWRkZW4uXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGF0aWFsRGF0YXNldEJpbmRlciBpbXBsZW1lbnRzIFNwYXRpYWxHYXRlcyB7XG4gIC8qKiBUaGUgZGF0YXNldCBvbiBvZmZlciwgZm9yIGRyYXdpbmcgb25lIHRoYXQgYnJpbmdzIG5vIGltYWdlLiAqL1xuICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwgPSBudWxsO1xuICAvKiogQSBkYXRhc2V0IGlzIHB1Ymxpc2hlZCDigJQgZ2F0ZXMgdGhlIHNwYXRpYWwgcGxvdCB0eXBlczsgdGhlIHRvb2xiYXIgYmluZHMgaXQgdG9vLiAqL1xuICBoYXNEYXRhc2V0ID0gZmFsc2U7XG4gIC8qKiBJdHMgb2JzZXJ2YXRpb25zIGNhcnJ5IGEgeiwgZ2F0aW5nIHRoZSAzRCBzcGF0aWFsIG1vZGUuICovXG4gIGhhczNkID0gZmFsc2U7XG4gIC8qKiBJdCBicmluZ3MgcGl4ZWxzIG9mIGl0cyBvd24gKHNlZSB7QGxpbmsgU3BhdGlhbEdhdGVzLmhhc1BpeGVsc30pLiAqL1xuICBoYXNQaXhlbHMgPSBmYWxzZTtcbiAgLyoqIERhdGFzZXQgaWRlbnRpdHkgKyBjYXBhYmlsaXR5IHNoYXBlIHRoZSBsYXN0IGVtaXNzaW9uIHdhcyBoYW5kbGVkIGF0LCBzbyBhXG4gICAqICBzd2l0Y2ggYmV0d2VlbiB0d28gZGF0YXNldHMgb2YgdGhlIHNhbWUgc2hhcGUgaXMgbm90IG1pc3Rha2VuIGZvciBhIHJlcGVhdC4gKi9cbiAgcHJpdmF0ZSBrZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogRGF0YXNldCArIGdlb21ldHJ5IHRoZSBwdWJsaXNoZWQgdm9sdW1lIGltYWdlIHdhcyBidWlsdCBmcm9tLCBzbyBhIHJlLWVtaXR0ZWRcbiAgICogIGRhdGFzZXQgZG9lc24ndCByZS1mZXRjaCBtZWdhYnl0ZXMgb3IgcmVzZXQgdGhlIHVzZXIncyBzY3J1Yi4gKi9cbiAgcHJpdmF0ZSB2b2x1bWVJbWFnZUtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBCbG9iIFVSTHMgYmFja2luZyB0aGF0IGltYWdlIOKAlCBvdXJzIHRvIHJldm9rZS4gKi9cbiAgcHJpdmF0ZSB2b2x1bWVJbWFnZVVybHM6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwb3J0OiBTcGF0aWFsRGF0YVBvcnQgfCB1bmRlZmluZWQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBTcGF0aWFsQmluZGVySG9zdCxcbiAgKSB7fVxuXG4gIC8qKiBGb2xsb3cgdGhlIHBvcnQncyBkYXRhc2V0IHVudGlsIGB1bnRpbCRgIGVtaXRzLiAqL1xuICBiaW5kKHVudGlsJDogT2JzZXJ2YWJsZTx1bmtub3duPik6IHZvaWQge1xuICAgIHRoaXMucG9ydFxuICAgICAgPy5nZXREYXRhc2V0JCgpXG4gICAgICAucGlwZSh0YWtlVW50aWwodW50aWwkKSlcbiAgICAgIC5zdWJzY3JpYmUoKGRhdGFzZXQpID0+IHRoaXMub25EYXRhc2V0KGRhdGFzZXQgPz8gbnVsbCkpO1xuICB9XG5cbiAgLyoqIFJldm9rZSB0aGUgcHVibGlzaGVkIHZvbHVtZSBpbWFnZSdzIGJsb2IgVVJMcyAodGVhcmRvd24pLiAqL1xuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMucmV2b2tlVm9sdW1lSW1hZ2VVcmxzKCk7XG4gIH1cblxuICBwcml2YXRlIG9uRGF0YXNldChkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGFzZXQgPSBkYXRhc2V0O1xuICAgIC8vIE9ubHkgYSBkYXRhc2V0IHdob3NlIG9ic2VydmF0aW9ucyBjYXJyeSBhIHogY2FuIGJlIGRyYXduIGFzIGEgY2xvdWQsIHNvIHRoZSAzRFxuICAgIC8vIG1vZGUgaXMgZ2F0ZWQgb24gdGhlIGNvb3JkaW5hdGVzLCBub3QgbWVyZWx5IG9uIGEgZGF0YXNldCBiZWluZyBwcmVzZW50LlxuICAgIGNvbnN0IGhhczNkID0gISFkYXRhc2V0Py5vYnNlcnZhdGlvbnMuejtcbiAgICBjb25zdCBoYXNWb2x1bWUgPSAhIWRhdGFzZXQ/LnZvbHVtZTtcbiAgICAvLyBUaGUgcG9ydCBwdWJsaXNoZXMgaXRzIGN1cnJlbnQgdmFsdWUgb24gc3Vic2NyaWJlLCBzbyB0aGUgaW5pdGlhbCBgbnVsbGAgd291bGRcbiAgICAvLyBvdGhlcndpc2UgcmVjb21wdXRlIHRoZSBzZWxlY3RvciBmb3Igbm8gY2hhbmdlLiBLZXllZCBieSBkYXRhc2V0IElERU5USVRZIGFzIHdlbGxcbiAgICAvLyBhcyBjYXBhYmlsaXR5IHNoYXBlOiB0d28gM0QgZGF0YXNldHMgdGhhdCBib3RoIGNhcnJ5IGEgdm9sdW1lIGhhdmUgdGhlIHNhbWVcbiAgICAvLyBzaGFwZSwgYW5kIGNvbXBhcmluZyBvbmx5IHRoYXQgc2tpcHBlZCB0aGUgc3dpdGNoIOKAlCBsZWF2aW5nIHRoZSBwcmV2aW91c1xuICAgIC8vIGRhdGFzZXQncyB2b2x1bWUgaW1hZ2Ugb24gc2NyZWVuIHVuZGVybmVhdGggdGhlIG5ldyBvbmUncyBvYnNlcnZhdGlvbnMuXG4gICAgY29uc3Qga2V5ID0gZGF0YXNldFxuICAgICAgPyBgJHtkYXRhc2V0LmlkfXwke2hhczNkfXwke2hhc1ZvbHVtZX18JHtcbiAgICAgICAgICBkYXRhc2V0LnZvbHVtZSA/IGAke2RhdGFzZXQudm9sdW1lLndpZHRofXgke2RhdGFzZXQudm9sdW1lLmhlaWdodH14JHtkYXRhc2V0LnZvbHVtZS5kZXB0aH1gIDogJydcbiAgICAgICAgfWBcbiAgICAgIDogbnVsbDtcbiAgICBpZiAoa2V5ID09PSB0aGlzLmtleSkgcmV0dXJuO1xuICAgIHRoaXMua2V5ID0ga2V5O1xuICAgIHRoaXMuaGFzRGF0YXNldCA9ICEhZGF0YXNldDtcbiAgICB0aGlzLmhhczNkID0gaGFzM2Q7XG4gICAgLy8gV2hldGhlciB0aGUgZGF0YXNldCBicmluZ3MgcGl4ZWxzOiBpdCByZWdpc3RlcnMgb250byBhIHRpc3N1ZSBpbWFnZSAod2hpY2ggbWF5XG4gICAgLy8gc3RpbGwgYmUgb24gaXRzIHdheSDigJQgdGhlIHBpeGVsIG1vZGVzIG11c3Qgbm90IGZsaWNrZXIgb3V0IHdoaWxlIGl0IGFycml2ZXMpLCBvclxuICAgIC8vIGl0cyB2b2x1bWUgaXMgcHVibGlzaGVkIEFTIGEgZ3JheXNjYWxlIHotc3RhY2sgaW1hZ2UuIEVpdGhlciB3YXkgdGhlIHBpeGVsIG1vZGVzXG4gICAgLy8gc3RheSBvbiBvZmZlciDigJQgVm9sdW1lIGFuZCBJc29zdXJmYWNlIGFyZSBleGFjdGx5IGhvdyBhIDNEIG9taWNzIGRhdGFzZXQgaXMgcmVhZC5cbiAgICB0aGlzLmhhc1BpeGVscyA9ICEhZGF0YXNldD8uaW1hZ2VSZWYgfHwgaGFzVm9sdW1lO1xuICAgIHRoaXMuaG9zdC5nYXRlc0NoYW5nZWQoKTtcbiAgICBpZiAoZGF0YXNldCAmJiAhZGF0YXNldC5pbWFnZVJlZiAmJiBoYXNWb2x1bWUpIHtcbiAgICAgIC8vIE5vIHNlY3Rpb24gdG8gZHJhdyBvYnNlcnZhdGlvbnMgb3ZlciAoYSBjbG91ZCByZWdpc3RlcmVkIGludG8gYSBjb21tb24gZnJhbWUsXG4gICAgICAvLyB0aGUgQWxsZW4gQ0NGKSwgYnV0IGEgcmVnaXN0ZXJlZCBWT0xVTUU6IG1ha2UgdGhhdCB0aGUgaW1hZ2UgYW5kIG9wZW4gb24gaXQsXG4gICAgICAvLyBzbGljZSBiYXIgYW5kIGFsbC4gT3JkZXJlZCBhZnRlciB0aGUgZ2F0ZXMgc28gdGhlIHR5cGUgaXMgb24gb2ZmZXIgZmlyc3QuXG4gICAgICB2b2lkIHRoaXMuc2hvd1ZvbHVtZUFzSW1hZ2UoZGF0YXNldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEFueXRoaW5nIGVsc2UgbWVhbnMgYSBwdWJsaXNoZWQgdm9sdW1lIGltYWdlIGlzIG5vIGxvbmdlciB3aGF0IGlzIG9uIHNjcmVlbi5cbiAgICAgIC8vIEZvcmdldCBpdCwgb3IgY29taW5nIEJBQ0sgdG8gdGhlIHZvbHVtZSBkYXRhc2V0IHdvdWxkIHNob3J0LWNpcmN1aXQgb24gYVxuICAgICAgLy8gbWF0Y2hpbmcga2V5IGFuZCBsZWF2ZSB0aGUgb3RoZXIgZGF0YXNldCdzIHNsaWRlIHVwLlxuICAgICAgdGhpcy5kcm9wVm9sdW1lSW1hZ2UoKTtcbiAgICAgIGlmIChkYXRhc2V0ICYmICFkYXRhc2V0LmltYWdlUmVmKSB7XG4gICAgICAgIC8vIE5vIHJlZmVyZW5jZSBpbWFnZSBhbmQgbm8gdm9sdW1lOiB0aGUgb2JzZXJ2YXRpb25zIGFyZSBhbGwgdGhlcmUgaXMsIHNvIG9wZW5cbiAgICAgICAgLy8gb24gd2hpY2hldmVyIHNwYXRpYWwgbW9kZSB0aGVpciBjb29yZGluYXRlcyBzdXBwb3J0IOKAlCBsZWF2aW5nIHRoZSB0eXBlIGFsb25lXG4gICAgICAgIC8vIHN0cmFuZHMgdGhlIGhvc3Qgb24gdGhlIHByZXZpb3VzIHNsaWRlLiBBIG9uZS1wbGFuZSBhc3NheSBoYXMgbm8geiBhbmRcbiAgICAgICAgLy8gY2Fubm90IGJlIGEgY2xvdWQuXG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGhhczNkID8gUGxvdFR5cGUuU1BBVElBTF9PTUlDU18zRCA6IFBsb3RUeXBlLlNQQVRJQUxfT01JQ1M7XG4gICAgICAgIGlmICh0aGlzLmhvc3Quc2VsZWN0ZWRJZCgpICE9PSB0YXJnZXQpIHRoaXMuaG9zdC5zZWxlY3RQbG90VHlwZSh0YXJnZXQpO1xuICAgICAgICAvLyBTYW1lIG1vZGUsIGFub3RoZXIgaW1hZ2UtbGVzcyBkYXRhc2V0LCBub3RoaW5nIGxvYWRlZDogcmUtcGxvdCBzbyBpdHNcbiAgICAgICAgLy8gcGxhY2Vob2xkZXIgaW1hZ2UgaW5mbyAoYW5kIHdpdGggaXQgdGhlIHJlZ2lvbnMnIGtleSkgaXMgdGhpcyBkYXRhc2V0J3MuXG4gICAgICAgIGVsc2UgaWYgKCF0aGlzLmhvc3QuaGFzSW1hZ2UoKSkgdGhpcy5ob3N0LnJlcGxvdCgpO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBDbGVhcmluZyB0aGUgZGF0YXNldCB3aGlsZSBhIHNwYXRpYWwgbW9kZSBpcyBhY3RpdmUgbGVhdmVzIGEgdHlwZSB0aGF0IGlzIG5vXG4gICAgLy8gbG9uZ2VyIG9mZmVyZWQg4oCUIHRoZSBob3N0IGZhbGxzIGJhY2ssIGFzIHR1cm5pbmcgdGVzdCBtb2RlIG9mZiBkb2VzLlxuICAgIHRoaXMuaG9zdC5zZXR0bGVkKCk7XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaCBhIGRhdGFzZXQncyByZWZlcmVuY2Ugdm9sdW1lIEFTIHRoZSBpbWFnZSwgYW5kIG9wZW4gdGhlIDJEIEltYWdlIHZpZXcgb24gaXQ6XG4gICAqIHRoZSBzbGljZSBiYXIgc2NydWJzIHosIGFuZCB0aGUgY29udHJhc3Qgd2luZG93LCBjb2xvcm1hcHMgYW5kIHJlZ2lvbiB0b29scyBhbGwgd29ya1xuICAgKiBiZWNhdXNlIHRoZSB2b2x1bWUgZ2VudWluZWx5IGlzIHRoZSBpbWFnZSBub3cuIFRoZSAzRCBjbG91ZCBzdGF5cyBvbmUgcGljayBhd2F5LlxuICAgKlxuICAgKiBLZXllZCBieSBkYXRhc2V0ICsgZ2VvbWV0cnk6IHRoZSBkYXRhc2V0IHN0cmVhbSByZS1lbWl0cyBvbiB0aGluZ3MgbGlrZSBhXG4gICAqIGNvbG91ci1jb2x1bW4gY2hhbmdlLCBhbmQgcmVidWlsZGluZyB0aGVuIHdvdWxkIHJlLWZldGNoIHRoZSB2b3hlbHMgYW5kIHRocm93IHRoZVxuICAgKiB1c2VyIGJhY2sgdG8gdGhlIG1pZGRsZSBzbGljZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc2hvd1ZvbHVtZUFzSW1hZ2UoZGF0YXNldDogU3BhdGlhbERhdGFzZXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBtZXRhID0gZGF0YXNldC52b2x1bWU7XG4gICAgaWYgKCFtZXRhIHx8ICF0aGlzLnBvcnQ/LmdldFZvbHVtZSkgcmV0dXJuO1xuICAgIGNvbnN0IGtleSA9IGAke2RhdGFzZXQuaWR9OiR7bWV0YS53aWR0aH14JHttZXRhLmhlaWdodH14JHttZXRhLmRlcHRofWA7XG4gICAgaWYgKGtleSA9PT0gdGhpcy52b2x1bWVJbWFnZUtleSkgcmV0dXJuO1xuICAgIC8vIENsYWltIHRoZSBrZXkgQkVGT1JFIGF3YWl0aW5nOiB0aGUgc3RyZWFtIGNhbiBlbWl0IGFnYWluIHdoaWxlIHRoZSB2b3hlbHMgYXJlIGluXG4gICAgLy8gZmxpZ2h0LCBhbmQgdHdvIGJ1aWxkcyBvZiB0aGUgc2FtZSB2b2x1bWUgd291bGQgcmFjZSB0byBwdWJsaXNoLlxuICAgIHRoaXMudm9sdW1lSW1hZ2VLZXkgPSBrZXk7XG4gICAgdGhpcy5ob3N0LnNldEltYWdlTG9hZGluZyh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYnVpbHQgPSBhd2FpdCBidWlsZFZvbHVtZVN0YWNrSW1hZ2UoZGF0YXNldCwgYXdhaXQgdGhpcy5wb3J0LmdldFZvbHVtZSgpKTtcbiAgICAgIC8vIEEgZGlmZmVyZW50IGRhdGFzZXQgd2FzIHNlbGVjdGVkIHdoaWxlIHRoaXMgb25lIGVuY29kZWQ6IGRyb3Agd2hhdCB3ZSBidWlsdC5cbiAgICAgIGlmICh0aGlzLnZvbHVtZUltYWdlS2V5ICE9PSBrZXkpIHtcbiAgICAgICAgYnVpbHQ/LnVybHMuZm9yRWFjaCgodSkgPT4gVVJMLnJldm9rZU9iamVjdFVSTCh1KSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmICghYnVpbHQpIHtcbiAgICAgICAgdGhpcy52b2x1bWVJbWFnZUtleSA9IG51bGw7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIFBpY2sgdGhlIG1vZGUgZmlyc3Qgc28gdGhlIGltYWdlIGxhbmRzIGluIHRoZSB2aWV3IHRoYXQgd2lsbCBzaG93IGl0LlxuICAgICAgaWYgKHRoaXMuaG9zdC5zZWxlY3RlZElkKCkgIT09IFBsb3RUeXBlLklNQUdFKSB0aGlzLmhvc3Quc2VsZWN0UGxvdFR5cGUoUGxvdFR5cGUuSU1BR0UpO1xuICAgICAgdGhpcy5yZXZva2VWb2x1bWVJbWFnZVVybHMoKTtcbiAgICAgIHRoaXMudm9sdW1lSW1hZ2VVcmxzID0gYnVpbHQudXJscztcbiAgICAgIHRoaXMuaG9zdC5wdWJsaXNoSW1hZ2UoYnVpbHQuaW5mbyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBObyB2b2x1bWUgc2VydmVkIGFmdGVyIGFsbDogdGhlIGNsb3VkIGlzIHN0aWxsIHJlbmRlcmFibGUsIHNvIGZhbGwgYmFjayB0byBpdC5cbiAgICAgIGNvbnNvbGUud2FybignW3Zpc3VhbGl6ZXJdIHJlZmVyZW5jZSB2b2x1bWUgdW5hdmFpbGFibGUg4oCUIGZhbGxpbmcgYmFjayB0byB0aGUgM0QgY2xvdWQnLCBlcnIpO1xuICAgICAgdGhpcy52b2x1bWVJbWFnZUtleSA9IG51bGw7XG4gICAgICBpZiAodGhpcy5oYXMzZCAmJiAhaXNTcGF0aWFsT21pY3MzZCh0aGlzLmhvc3QuYmFzZVBsb3RUeXBlKCkpKSB7XG4gICAgICAgIHRoaXMuaG9zdC5zZWxlY3RQbG90VHlwZShQbG90VHlwZS5TUEFUSUFMX09NSUNTXzNEKTtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gT25seSB0aGUgYnVpbGQgc3RpbGwgb24gc2NyZWVuIChvciBvbmUgdGhhdCBmYWlsZWQgYW5kIHJlbGVhc2VkIGl0cyBrZXkpIG1heVxuICAgICAgLy8gZHJvcCB0aGUgb3ZlcmxheTogYSBuZXdlciB2b2x1bWUgYnVpbGQgdGhhdCBzdXBlcnNlZGVkIHRoaXMgb25lIGlzIHN0aWxsIGVuY29kaW5nLlxuICAgICAgaWYgKHRoaXMudm9sdW1lSW1hZ2VLZXkgPT09IGtleSB8fCB0aGlzLnZvbHVtZUltYWdlS2V5ID09PSBudWxsKSB0aGlzLmhvc3Quc2V0SW1hZ2VMb2FkaW5nKGZhbHNlKTtcbiAgICAgIHRoaXMuaG9zdC5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEZvcmdldCB0aGUgcHVibGlzaGVkIHZvbHVtZSBpbWFnZSBzbyByZS1zZWxlY3RpbmcgdGhlIGRhdGFzZXQgcmVidWlsZHMgaXQuIFRoZVxuICAgKiAgVVJMcyBkZWxpYmVyYXRlbHkgc3RheSBhbGl2ZTogdGhlIGhvc3QgbWF5IHN0aWxsIGJlIGRpc3BsYXlpbmcgdGhhdCBpbWFnZSwgYW5kXG4gICAqICByZXZva2luZyB1bmRlciBpdCB3b3VsZCBicmVhayBldmVyeSBsYXRlciB0aWxlIHJlYWQuIFRoZXkgYXJlIGZyZWVkIHdoZW4gdGhlIG5leHRcbiAgICogIHZvbHVtZSByZXBsYWNlcyB0aGVtLCBvciBvbiB7QGxpbmsgZGlzcG9zZX0uICovXG4gIHByaXZhdGUgZHJvcFZvbHVtZUltYWdlKCk6IHZvaWQge1xuICAgIHRoaXMudm9sdW1lSW1hZ2VLZXkgPSBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSByZXZva2VWb2x1bWVJbWFnZVVybHMoKTogdm9pZCB7XG4gICAgdGhpcy52b2x1bWVJbWFnZVVybHMuZm9yRWFjaCgodSkgPT4gVVJMLnJldm9rZU9iamVjdFVSTCh1KSk7XG4gICAgdGhpcy52b2x1bWVJbWFnZVVybHMgPSBbXTtcbiAgfVxufVxuIl19