@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,121 @@
1
+ /**
2
+ * Plotly layout builders for every plot type the Plotly backend renders. Pure:
3
+ * the live service state they need (screen height, aspect lock, drag mode, the
4
+ * current region shapes and colours) comes in through {@link ImageLayoutContext}.
5
+ */
6
+ /** One slider step per z-plane, each showing only its own trace. */
7
+ export function sliderSteps(sliceCount) {
8
+ const steps = [];
9
+ for (let i = 0; i < sliceCount; i++) {
10
+ steps.push({
11
+ label: i + 1,
12
+ method: 'restyle',
13
+ args: [
14
+ 'visible',
15
+ Array(sliceCount)
16
+ .fill(false)
17
+ .fill(true, i, i + 1),
18
+ ],
19
+ });
20
+ }
21
+ return steps;
22
+ }
23
+ /** Image axes over `xRange`/`yRange` (pass the y range reversed for an image). */
24
+ function imageAxes(ctx, xRange, yRange) {
25
+ return {
26
+ xaxis: { constrain: 'range', constraintoward: 'center', side: 'top', ticks: '', range: xRange },
27
+ yaxis: {
28
+ constrain: 'range',
29
+ constraintoward: 'center',
30
+ range: yRange,
31
+ ticks: '',
32
+ ticksuffix: ' ',
33
+ // autorange off so that Plotly does not overwrite the range for the y axis
34
+ autorange: false,
35
+ scaleanchor: ctx.scaleratio ? 'x' : false,
36
+ },
37
+ };
38
+ }
39
+ /** The heatmap / RGB image layout: image axes, the z-plane slider, the region shapes. */
40
+ export function heatmapLayout(ctx, xRange, yRange, sliceCount) {
41
+ return {
42
+ ...imageAxes(ctx, xRange, yRange),
43
+ margin: { t: 30, b: 5, l: 55, r: 5 },
44
+ height: ctx.screenHeight,
45
+ sliders: [
46
+ {
47
+ pad: { t: 50 },
48
+ currentvalue: { visible: true, prefix: 'Z-plane:', xanchor: 'right' },
49
+ steps: sliderSteps(sliceCount),
50
+ },
51
+ ],
52
+ autosize: true,
53
+ shapes: ctx.shapes,
54
+ activeshape: { fillcolor: ctx.fillColor },
55
+ dragmode: ctx.dragMode ? ctx.dragMode : false,
56
+ newshape: { line: { color: ctx.shapeColor, width: 3 } },
57
+ };
58
+ }
59
+ /** Image-aligned 2D axes without the z-plane slider (region scatter). */
60
+ export function overlayLayout(ctx, xRange, yRange) {
61
+ return {
62
+ ...imageAxes(ctx, xRange, yRange),
63
+ margin: { t: 30, b: 5, l: 55, r: 5 },
64
+ height: ctx.screenHeight,
65
+ autosize: true,
66
+ shapes: ctx.shapes,
67
+ dragmode: ctx.dragMode ? ctx.dragMode : false,
68
+ };
69
+ }
70
+ /** Plain 2D chart axes (intensity profile / line plots). */
71
+ export function chartLayout(screenHeight) {
72
+ return {
73
+ margin: { t: 30, b: 45, l: 60, r: 20 },
74
+ height: screenHeight,
75
+ autosize: true,
76
+ xaxis: { title: 'Position (px)' },
77
+ yaxis: { title: 'Intensity' },
78
+ dragmode: false,
79
+ };
80
+ }
81
+ /** 3D scene for volumetric plot types (scatter3d, isosurface). */
82
+ export function volumeLayout(screenHeight) {
83
+ return {
84
+ margin: { t: 0, b: 0, l: 0, r: 0 },
85
+ height: screenHeight,
86
+ autosize: true,
87
+ scene: {
88
+ xaxis: { title: 'X' },
89
+ yaxis: { title: 'Y' },
90
+ zaxis: { title: 'Z-plane' },
91
+ // 'cube' (not 'data'): a z-stack has far fewer planes than X/Y pixels,
92
+ // so 'data' squashes the volume into a near-flat slab that reads as
93
+ // empty edge-on. A cube gives the z dimension real height so the
94
+ // isosurface/voxels are actually visible.
95
+ aspectmode: 'cube',
96
+ },
97
+ };
98
+ }
99
+ /**
100
+ * Scene layout for the surface plot: light-grey axis planes and a manual
101
+ * aspect ratio whose z extent is `zRatio` of the x/y extent.
102
+ */
103
+ export function surfaceLayout(zRatio) {
104
+ const plane = {
105
+ gridcolor: 'rgb(255, 255, 255)',
106
+ zerolinecolor: 'rgb(255, 255, 255)',
107
+ showbackground: true,
108
+ backgroundcolor: 'rgb(230, 230,230)',
109
+ };
110
+ return {
111
+ margin: { t: 0, b: 0, l: 0, r: 0 },
112
+ scene: {
113
+ xaxis: { ...plane },
114
+ yaxis: { ...plane, backgroundcolor: 'rgb(230, 230, 230)' },
115
+ zaxis: { ...plane },
116
+ aspectratio: { x: 1, y: 1, z: zRatio },
117
+ aspectmode: 'manual',
118
+ },
119
+ };
120
+ }
121
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LWxheW91dHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9wbG90bHkvcGxvdGx5LWxheW91dHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQW9CSCxvRUFBb0U7QUFDcEUsTUFBTSxVQUFVLFdBQVcsQ0FBQyxVQUFrQjtJQUM1QyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDakIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3BDLEtBQUssQ0FBQyxJQUFJLENBQUM7WUFDVCxLQUFLLEVBQUUsQ0FBQyxHQUFHLENBQUM7WUFDWixNQUFNLEVBQUUsU0FBUztZQUNqQixJQUFJLEVBQUU7Z0JBQ0osU0FBUztnQkFDVCxLQUFLLENBQUMsVUFBVSxDQUFDO3FCQUNkLElBQUksQ0FBQyxLQUFLLENBQUM7cUJBQ1gsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUN4QjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRCxrRkFBa0Y7QUFDbEYsU0FBUyxTQUFTLENBQUMsR0FBdUIsRUFBRSxNQUFnQixFQUFFLE1BQWdCO0lBQzVFLE9BQU87UUFDTCxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7UUFDL0YsS0FBSyxFQUFFO1lBQ0wsU0FBUyxFQUFFLE9BQU87WUFDbEIsZUFBZSxFQUFFLFFBQVE7WUFDekIsS0FBSyxFQUFFLE1BQU07WUFDYixLQUFLLEVBQUUsRUFBRTtZQUNULFVBQVUsRUFBRSxJ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Q3BCLFFBQVEsRUFBRSxJQUFJO1FBQ2QsS0FBSyxFQUFFO1lBQ0wsS0FBSyxFQUFFLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUNyQixLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFO1lBQ3JCLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7WUFDM0IsdUVBQXVFO1lBQ3ZFLG9FQUFvRTtZQUNwRSxpRUFBaUU7WUFDakUsMENBQTBDO1lBQzFDLFVBQVUsRUFBRSxNQUFNO1NBQ25CO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLE1BQWM7SUFDMUMsTUFBTSxLQUFLLEdBQUc7UUFDWixTQUFTLEVBQUUsb0JBQW9CO1FBQy9CLGFBQWEsRUFBRSxvQkFBb0I7UUFDbkMsY0FBYyxFQUFFLElBQUk7UUFDcEIsZUFBZSxFQUFFLG1CQUFtQjtLQUNyQyxDQUFDO0lBQ0YsT0FBTztRQUNMLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUU7UUFDbEMsS0FBSyxFQUFFO1lBQ0wsS0FBSyxFQUFFLEVBQUUsR0FBRyxLQUFLLEVBQUU7WUFDbkIsS0FBSyxFQUFFLEVBQUUsR0FBRyxLQUFLLEVBQUUsZUFBZSxFQUFFLG9CQUFvQixFQUFFO1lBQzFELEtBQUssRUFBRSxFQUFFLEdBQUcsS0FBSyxFQUFFO1lBQ25CLFdBQVcsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFO1lBQ3RDLFVBQVUsRUFBRSxRQUFRO1NBQ3JCO0tBQ0YsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBsb3RseSBsYXlvdXQgYnVpbGRlcnMgZm9yIGV2ZXJ5IHBsb3QgdHlwZSB0aGUgUGxvdGx5IGJhY2tlbmQgcmVuZGVycy4gUHVyZTpcbiAqIHRoZSBsaXZlIHNlcnZpY2Ugc3RhdGUgdGhleSBuZWVkIChzY3JlZW4gaGVpZ2h0LCBhc3BlY3QgbG9jaywgZHJhZyBtb2RlLCB0aGVcbiAqIGN1cnJlbnQgcmVnaW9uIHNoYXBlcyBhbmQgY29sb3VycykgY29tZXMgaW4gdGhyb3VnaCB7QGxpbmsgSW1hZ2VMYXlvdXRDb250ZXh0fS5cbiAqL1xuXG4vKiogUGxvdGx5IHNoYXBlIGRpY3RzLCBhcyBgbGF5b3V0LnNoYXBlc2AgdGFrZXMgdGhlbS4gKi9cbmV4cG9ydCB0eXBlIFBsb3RseVNoYXBlRGljdCA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuXG4vKiogVGhlIHNlcnZpY2Ugc3RhdGUgYW4gaW1hZ2UtYWxpZ25lZCBsYXlvdXQgZGVwZW5kcyBvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW1hZ2VMYXlvdXRDb250ZXh0IHtcbiAgc2NyZWVuSGVpZ2h0OiBudW1iZXI7XG4gIC8qKiBMb2NrIHRoZSB5IGF4aXMgdG8geCAoc3F1YXJlIGltYWdlIHBpeGVscykuICovXG4gIHNjYWxlcmF0aW86IGJvb2xlYW47XG4gIC8qKiBUaGUgYWN0aXZlIFBsb3RseSBkcmFnIG1vZGUsIG9yICcnIGZvciBub25lLiAqL1xuICBkcmFnTW9kZTogc3RyaW5nO1xuICAvKiogVGhlIHJlZ2lvbiBzaGFwZXMgdG8gZHJhdyBvdmVyIHRoZSBpbWFnZS4gKi9cbiAgc2hhcGVzOiBQbG90bHlTaGFwZURpY3RbXTtcbiAgLyoqIFRoZSBhY3RpdmUgKHNlbGVjdGVkKSBzaGFwZSdzIGZpbGwgY29sb3VyLiAqL1xuICBmaWxsQ29sb3I6IHN0cmluZztcbiAgLyoqIFRoZSBvdXRsaW5lIGNvbG91ciBvZiBhIG5ld2x5IGRyYXduIHNoYXBlLiAqL1xuICBzaGFwZUNvbG9yOiBzdHJpbmc7XG59XG5cbi8qKiBPbmUgc2xpZGVyIHN0ZXAgcGVyIHotcGxhbmUsIGVhY2ggc2hvd2luZyBvbmx5IGl0cyBvd24gdHJhY2UuICovXG5leHBvcnQgZnVuY3Rpb24gc2xpZGVyU3RlcHMoc2xpY2VDb3VudDogbnVtYmVyKTogQXJyYXk8eyBsYWJlbDogbnVtYmVyOyBtZXRob2Q6IHN0cmluZzsgYXJnczogdW5rbm93bltdIH0+IHtcbiAgY29uc3Qgc3RlcHMgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbGljZUNvdW50OyBpKyspIHtcbiAgICBzdGVwcy5wdXNoKHtcbiAgICAgIGxhYmVsOiBpICsgMSxcbiAgICAgIG1ldGhvZDogJ3Jlc3R5bGUnLFxuICAgICAgYXJnczogW1xuICAgICAgICAndmlzaWJsZScsXG4gICAgICAgIEFycmF5KHNsaWNlQ291bnQpXG4gICAgICAgICAgLmZpbGwoZmFsc2UpXG4gICAgICAgICAgLmZpbGwodHJ1ZSwgaSwgaSArIDEpLFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gc3RlcHM7XG59XG5cbi8qKiBJbWFnZSBheGVzIG92ZXIgYHhSYW5nZWAvYHlSYW5nZWAgKHBhc3MgdGhlIHkgcmFuZ2UgcmV2ZXJzZWQgZm9yIGFuIGltYWdlKS4gKi9cbmZ1bmN0aW9uIGltYWdlQXhlcyhjdHg6IEltYWdlTGF5b3V0Q29udGV4dCwgeFJhbmdlOiBudW1iZXJbXSwgeVJhbmdlOiBudW1iZXJbXSkge1xuICByZXR1cm4ge1xuICAgIHhheGlzOiB7IGNvbnN0cmFpbjogJ3JhbmdlJywgY29uc3RyYWludG93YXJkOiAnY2VudGVyJywgc2lkZTogJ3RvcCcsIHRpY2tzOiAnJywgcmFuZ2U6IHhSYW5nZSB9LFxuICAgIHlheGlzOiB7XG4gICAgICBjb25zdHJhaW46ICdyYW5nZScsXG4gICAgICBjb25zdHJhaW50b3dhcmQ6ICdjZW50ZXInLFxuICAgICAgcmFuZ2U6IHlSYW5nZSxcbiAgICAgIHRpY2tzOiAnJyxcbiAgICAgIHRpY2tzdWZmaXg6ICcgICcsXG4gICAgICAvLyBhdXRvcmFuZ2Ugb2ZmIHNvIHRoYXQgUGxvdGx5IGRvZXMgbm90IG92ZXJ3cml0ZSB0aGUgcmFuZ2UgZm9yIHRoZSB5IGF4aXNcbiAgICAgIGF1dG9yYW5nZTogZmFsc2UsXG4gICAgICBzY2FsZWFuY2hvcjogY3R4LnNjYWxlcmF0aW8gPyAneCcgOiBmYWxzZSxcbiAgICB9LFxuICB9O1xufVxuXG4vKiogVGhlIGhlYXRtYXAgLyBSR0IgaW1hZ2UgbGF5b3V0OiBpbWFnZSBheGVzLCB0aGUgei1wbGFuZSBzbGlkZXIsIHRoZSByZWdpb24gc2hhcGVzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhlYXRtYXBMYXlvdXQoY3R4OiBJbWFnZUxheW91dENvbnRleHQsIHhSYW5nZTogbnVtYmVyW10sIHlSYW5nZTogbnVtYmVyW10sIHNsaWNlQ291bnQ6IG51bWJlcikge1xuICByZXR1cm4ge1xuICAgIC4uLmltYWdlQXhlcyhjdHgsIHhSYW5nZSwgeVJhbmdlKSxcbiAgICBtYXJnaW46IHsgdDogMzAsIGI6IDUsIGw6IDU1LCByOiA1IH0sXG4gICAgaGVpZ2h0OiBjdHguc2NyZWVuSGVpZ2h0LFxuICAgIHNsaWRlcnM6IFtcbiAgICAgIHtcbiAgICAgICAgcGFkOiB7IHQ6IDUwIH0sXG4gICAgICAgIGN1cnJlbnR2YWx1ZTogeyB2aXNpYmxlOiB0cnVlLCBwcmVmaXg6ICdaLXBsYW5lOicsIHhhbmNob3I6ICdyaWdodCcgfSxcbiAgICAgICAgc3RlcHM6IHNsaWRlclN0ZXBzKHNsaWNlQ291bnQpLFxuICAgICAgfSxcbiAgICBdLFxuICAgIGF1dG9zaXplOiB0cnVlLFxuICAgIHNoYXBlczogY3R4LnNoYXBlcyxcbiAgICBhY3RpdmVzaGFwZTogeyBmaWxsY29sb3I6IGN0eC5maWxsQ29sb3IgfSxcbiAgICBkcmFnbW9kZTogY3R4LmRyYWdNb2RlID8gY3R4LmRyYWdNb2RlIDogZmFsc2UsXG4gICAgbmV3c2hhcGU6IHsgbGluZTogeyBjb2xvcjogY3R4LnNoYXBlQ29sb3IsIHdpZHRoOiAzIH0gfSxcbiAgfTtcbn1cblxuLyoqIEltYWdlLWFsaWduZWQgMkQgYXhlcyB3aXRob3V0IHRoZSB6LXBsYW5lIHNsaWRlciAocmVnaW9uIHNjYXR0ZXIpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG92ZXJsYXlMYXlvdXQoY3R4OiBJbWFnZUxheW91dENvbnRleHQsIHhSYW5nZTogbnVtYmVyW10sIHlSYW5nZTogbnVtYmVyW10pIHtcbiAgcmV0dXJuIHtcbiAgICAuLi5pbWFnZUF4ZXMoY3R4LCB4UmFuZ2UsIHlSYW5nZSksXG4gICAgbWFyZ2luOiB7IHQ6IDMwLCBiOiA1LCBsOiA1NSwgcjogNSB9LFxuICAgIGhlaWdodDogY3R4LnNjcmVlbkhlaWdodCxcbiAgICBhdXRvc2l6ZTogdHJ1ZSxcbiAgICBzaGFwZXM6IGN0eC5zaGFwZXMsXG4gICAgZHJhZ21vZGU6IGN0eC5kcmFnTW9kZSA/IGN0eC5kcmFnTW9kZSA6IGZhbHNlLFxuICB9O1xufVxuXG4vKiogUGxhaW4gMkQgY2hhcnQgYXhlcyAoaW50ZW5zaXR5IHByb2ZpbGUgLyBsaW5lIHBsb3RzKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGFydExheW91dChzY3JlZW5IZWlnaHQ6IG51bWJlcikge1xuICByZXR1cm4ge1xuICAgIG1hcmdpbjogeyB0OiAzMCwgYjogNDUsIGw6IDYwLCByOiAyMCB9LFxuICAgIGhlaWdodDogc2NyZWVuSGVpZ2h0LFxuICAgIGF1dG9zaXplOiB0cnVlLFxuICAgIHhheGlzOiB7IHRpdGxlOiAnUG9zaXRpb24gKHB4KScgfSxcbiAgICB5YXhpczogeyB0aXRsZTogJ0ludGVuc2l0eScgfSxcbiAgICBkcmFnbW9kZTogZmFsc2UsXG4gIH07XG59XG5cbi8qKiAzRCBzY2VuZSBmb3Igdm9sdW1ldHJpYyBwbG90IHR5cGVzIChzY2F0dGVyM2QsIGlzb3N1cmZhY2UpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZvbHVtZUxheW91dChzY3JlZW5IZWlnaHQ6IG51bWJlcikge1xuICByZXR1cm4ge1xuICAgIG1hcmdpbjogeyB0OiAwLCBiOiAwLCBsOiAwLCByOiAwIH0sXG4gICAgaGVpZ2h0OiBzY3JlZW5IZWlnaHQsXG4gICAgYXV0b3NpemU6IHRydWUsXG4gICAgc2NlbmU6IHtcbiAgICAgIHhheGlzOiB7IHRpdGxlOiAnWCcgfSxcbiAgICAgIHlheGlzOiB7IHRpdGxlOiAnWScgfSxcbiAgICAgIHpheGlzOiB7IHRpdGxlOiAnWi1wbGFuZScgfSxcbiAgICAgIC8vICdjdWJlJyAobm90ICdkYXRhJyk6IGEgei1zdGFjayBoYXMgZmFyIGZld2VyIHBsYW5lcyB0aGFuIFgvWSBwaXhlbHMsXG4gICAgICAvLyBzbyAnZGF0YScgc3F1YXNoZXMgdGhlIHZvbHVtZSBpbnRvIGEgbmVhci1mbGF0IHNsYWIgdGhhdCByZWFkcyBhc1xuICAgICAgLy8gZW1wdHkgZWRnZS1vbi4gQSBjdWJlIGdpdmVzIHRoZSB6IGRpbWVuc2lvbiByZWFsIGhlaWdodCBzbyB0aGVcbiAgICAgIC8vIGlzb3N1cmZhY2Uvdm94ZWxzIGFyZSBhY3R1YWxseSB2aXNpYmxlLlxuICAgICAgYXNwZWN0bW9kZTogJ2N1YmUnLFxuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogU2NlbmUgbGF5b3V0IGZvciB0aGUgc3VyZmFjZSBwbG90OiBsaWdodC1ncmV5IGF4aXMgcGxhbmVzIGFuZCBhIG1hbnVhbFxuICogYXNwZWN0IHJhdGlvIHdob3NlIHogZXh0ZW50IGlzIGB6UmF0aW9gIG9mIHRoZSB4L3kgZXh0ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3VyZmFjZUxheW91dCh6UmF0aW86IG51bWJlcikge1xuICBjb25zdCBwbGFuZSA9IHtcbiAgICBncmlkY29sb3I6ICdyZ2IoMjU1LCAyNTUsIDI1NSknLFxuICAgIHplcm9saW5lY29sb3I6ICdyZ2IoMjU1LCAyNTUsIDI1NSknLFxuICAgIHNob3diYWNrZ3JvdW5kOiB0cnVlLFxuICAgIGJhY2tncm91bmRjb2xvcjogJ3JnYigyMzAsIDIzMCwyMzApJyxcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBtYXJnaW46IHsgdDogMCwgYjogMCwgbDogMCwgcjogMCB9LFxuICAgIHNjZW5lOiB7XG4gICAgICB4YXhpczogeyAuLi5wbGFuZSB9LFxuICAgICAgeWF4aXM6IHsgLi4ucGxhbmUsIGJhY2tncm91bmRjb2xvcjogJ3JnYigyMzAsIDIzMCwgMjMwKScgfSxcbiAgICAgIHpheGlzOiB7IC4uLnBsYW5lIH0sXG4gICAgICBhc3BlY3RyYXRpbzogeyB4OiAxLCB5OiAxLCB6OiB6UmF0aW8gfSxcbiAgICAgIGFzcGVjdG1vZGU6ICdtYW51YWwnLFxuICAgIH0sXG4gIH07XG59XG4iXX0=
@@ -0,0 +1,117 @@
1
+ import { bt601Luminance, histogram256 } from '../../contracts/intensity';
2
+ import { PlotType } from '../../contracts/plot-type';
3
+ /**
4
+ * Pure reads of what the Plotly backend has on screen or in memory: a trace's
5
+ * pixels, a frame's histogram, the image rect the axes show, and the restyle
6
+ * that applies the channel display state.
7
+ */
8
+ /** A plotted trace's `z` grid as flat pixels: an RGB `image` trace keeps its
9
+ * channels (3 or 4), a heatmap is one rounded channel. Null when empty. */
10
+ export function tracePixels(trace) {
11
+ const zData = trace?.z;
12
+ if (!zData)
13
+ return null;
14
+ const height = zData.length;
15
+ if (height === 0)
16
+ return null;
17
+ const width = zData[0].length;
18
+ if (trace.type === 'image') {
19
+ // RGB image: z[row][col] = [r, g, b] or [r, g, b, a]
20
+ const sample = zData[0][0];
21
+ const channels = Array.isArray(sample) ? sample.length : 3;
22
+ const data = new Uint8ClampedArray(width * height * channels);
23
+ for (let y = 0; y < height; y++) {
24
+ for (let x = 0; x < width; x++) {
25
+ const pixel = zData[y][x];
26
+ const offset = (y * width + x) * channels;
27
+ for (let c = 0; c < channels; c++)
28
+ data[offset + c] = pixel[c];
29
+ }
30
+ }
31
+ return { width, height, channels, data };
32
+ }
33
+ // Heatmap (grayscale): z[row][col] = scalar value
34
+ const data = new Uint8ClampedArray(width * height);
35
+ for (let y = 0; y < height; y++) {
36
+ for (let x = 0; x < width; x++)
37
+ data[y * width + x] = Math.round(zData[y][x]);
38
+ }
39
+ return { width, height, channels: 1, data };
40
+ }
41
+ /** 256-bin histogram of one channel of a frame (raw, pre-LUT). Grayscale cells
42
+ * are numbers; RGB cells `[r,g,b]` give channel `channelIndex`, or the BT.601
43
+ * luminance for an index past their channels. */
44
+ export function frameHistogram(frame, channelIndex) {
45
+ const counts = new Array(256).fill(0);
46
+ for (const row of frame) {
47
+ if (!row)
48
+ continue;
49
+ for (const cell of row) {
50
+ let v;
51
+ if (Array.isArray(cell)) {
52
+ v =
53
+ channelIndex >= 0 && channelIndex < cell.length
54
+ ? cell[channelIndex]
55
+ : Math.round(bt601Luminance(cell[0], cell[1], cell[2]));
56
+ }
57
+ else {
58
+ v = cell;
59
+ }
60
+ v = v | 0;
61
+ if (v < 0)
62
+ v = 0;
63
+ else if (v > 255)
64
+ v = 255;
65
+ counts[v]++;
66
+ }
67
+ }
68
+ return histogram256(counts);
69
+ }
70
+ /** 256-bin histogram of a one-byte-per-pixel plane (a channel's raw pixels). */
71
+ export function planeHistogram(plane) {
72
+ const counts = new Array(256).fill(0);
73
+ for (let i = 0; i < plane.length; i++)
74
+ counts[plane[i]]++;
75
+ return histogram256(counts);
76
+ }
77
+ /**
78
+ * The image rect the plot shows, from the live axis ranges — after a high-def
79
+ * zoom the axes are relaid out to the crop's bounds, so the ranges ARE the
80
+ * crop — else the whole image `[x0, x1, y0, y1]`, else null.
81
+ */
82
+ export function axesSourceRect(xr, yr, trueImgSize) {
83
+ if (xr && yr) {
84
+ const x0 = Math.min(xr[0], xr[1]);
85
+ const y0 = Math.min(yr[0], yr[1]); // y axis is reversed for image layouts
86
+ return { x: x0, y: y0, width: Math.abs(xr[1] - xr[0]), height: Math.abs(yr[1] - yr[0]) };
87
+ }
88
+ if (!trueImgSize)
89
+ return null;
90
+ return {
91
+ x: trueImgSize[0],
92
+ y: trueImgSize[2],
93
+ width: trueImgSize[1] - trueImgSize[0],
94
+ height: trueImgSize[3] - trueImgSize[2],
95
+ };
96
+ }
97
+ /**
98
+ * The restyle that live-applies the channel display: the colour scale, reverse
99
+ * (reverse-scale and invert each flip the ramp; both together cancel) and the
100
+ * Intensity channel's window — cmin/cmax for the 3D plot types, zmin/zmax for
101
+ * heatmap/contour. A trace without a colour scale ignores these attributes.
102
+ */
103
+ export function channelDisplayRestyle(channels, reverse, invert, colorscale, plotType) {
104
+ const update = { reversescale: reverse !== invert };
105
+ if (colorscale != null)
106
+ update['colorscale'] = colorscale;
107
+ const ch = channels?.[0];
108
+ if (ch) {
109
+ const threeD = plotType === PlotType.ISOSURFACE || plotType === PlotType.SURFACE || plotType === PlotType.SCATTER3D;
110
+ if (threeD)
111
+ Object.assign(update, { cmin: ch.min, cmax: ch.max, cauto: false });
112
+ else
113
+ Object.assign(update, { zmin: ch.min, zmax: ch.max, zauto: false });
114
+ }
115
+ return update;
116
+ }
117
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXJlYWRiYWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1yZWFkYmFjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBR3pFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUdyRDs7OztHQUlHO0FBRUg7NEVBQzRFO0FBQzVFLE1BQU0sVUFBVSxXQUFXLENBQUMsS0FBaUQ7SUFDM0UsTUFBTSxLQUFLLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUN2QixJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3hCLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDNUIsSUFBSSxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDOUIsSUFBSSxLQUFNLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQzVCLHFEQUFxRDtRQUNyRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0IsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNELE1BQU0sSUFBSSxHQUFHLElBQUksaUJBQWlCLENBQUMsS0FBSyxHQUFHLE1BQU0sR0FBRyxRQUFRLENBQUMsQ0FBQztRQUM5RCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDaEMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUMvQixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFCLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUMsR0FBRyxRQUFRLENBQUM7Z0JBQzFDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxRQUFRLEVBQUUsQ0FBQyxFQUFFO29CQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pFLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFDRCxrREFBa0Q7SUFDbEQsTUFBTSxJQUFJLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLENBQUM7SUFDbkQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2hDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFO1lBQUUsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNoRixDQUFDO0lBQ0QsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQztBQUM5QyxDQUFDO0FBRUQ7O2tEQUVrRDtBQUNsRCxNQUFNLFVBQVUsY0FBYyxDQUFDLEtBQVksRUFBRSxZQUFvQjtJQUMvRCxNQUFNLE1BQU0sR0FBRyxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsS0FBSyxNQUFNLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsR0FBRztZQUFFLFNBQVM7UUFDbkIsS0FBSyxNQUFNLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQVMsQ0FBQztZQUNkLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUN4QixDQUFDO29CQUNDLFlBQVksSUFBSSxDQUFDLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNO3dCQUM3QyxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQzt3QkFDcEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5RCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sQ0FBQyxHQUFHLElBQUksQ0FBQztZQUNYLENBQUM7WUFDRCxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNWLElBQUksQ0FBQyxHQUFHLENBQUM7Z0JBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDWixJQUFJLENBQUMsR0FBRyxHQUFHO2dCQUFFLENBQUMsR0FBRyxHQUFHLENBQUM7WUFDMUIsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzlCLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUF3QjtJQUNyRCxNQUFNLE1BQU0sR0FBRyxJQUFJLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdEMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFO1FBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDMUQsT0FBTyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUlEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUM1QixFQUF3QixFQUN4QixFQUF3QixFQUN4QixXQUFpQztJQUVqQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUNiLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsdUNBQXVDO1FBQzFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzNGLENBQUM7SUFDRCxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLE9BQU87UUFDTCxDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNqQixDQUFDLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUNqQixLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUM7UUFDdEMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDO0tBQ3hDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLFFBQXlCLEVBQ3pCLE9BQWdCLEVBQ2hCLE1BQWUsRUFDZixVQUFtQixFQUNuQixRQUFrQjtJQUVsQixNQUFNLE1BQU0sR0FBNEIsRUFBRSxZQUFZLEVBQUUsT0FBTyxLQUFLLE1BQU0sRUFBRSxDQUFDO0lBQzdFLElBQUksVUFBVSxJQUFJLElBQUk7UUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsVUFBVSxDQUFDO0lBQzFELE1BQU0sRUFBRSxHQUFHLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3pCLElBQUksRUFBRSxFQUFFLENBQUM7UUFDUCxNQUFNLE1BQU0sR0FDVixRQUFRLEtBQUssUUFBUSxDQUFDLFVBQVUsSUFBSSxRQUFRLEtBQUssUUFBUSxDQUFDLE9BQU8sSUFBSSxRQUFRLEtBQUssUUFBUSxDQUFDLFNBQVMsQ0FBQztRQUN2RyxJQUFJLE1BQU07WUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDOztZQUMzRSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzNFLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgYnQ2MDFMdW1pbmFuY2UsIGhpc3RvZ3JhbTI1NiB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9pbnRlbnNpdHknO1xuaW1wb3J0IHsgSUhpc3RvZ3JhbSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9jaGFubmVsLWhpc3RvZ3JhbS1hcGkuY29udHJhY3QnO1xuaW1wb3J0IHsgUGl4ZWxEYXRhIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Zpc3VhbGl6ZXIuY29udHJhY3QnO1xuaW1wb3J0IHsgUGxvdFR5cGUgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvcGxvdC10eXBlJztcbmltcG9ydCB7IElDaGFubmVsU3RhdGUgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvY2hhbm5lbC1oaXN0b2dyYW0tYXBpLmNvbnRyYWN0JztcblxuLyoqXG4gKiBQdXJlIHJlYWRzIG9mIHdoYXQgdGhlIFBsb3RseSBiYWNrZW5kIGhhcyBvbiBzY3JlZW4gb3IgaW4gbWVtb3J5OiBhIHRyYWNlJ3NcbiAqIHBpeGVscywgYSBmcmFtZSdzIGhpc3RvZ3JhbSwgdGhlIGltYWdlIHJlY3QgdGhlIGF4ZXMgc2hvdywgYW5kIHRoZSByZXN0eWxlXG4gKiB0aGF0IGFwcGxpZXMgdGhlIGNoYW5uZWwgZGlzcGxheSBzdGF0ZS5cbiAqL1xuXG4vKiogQSBwbG90dGVkIHRyYWNlJ3MgYHpgIGdyaWQgYXMgZmxhdCBwaXhlbHM6IGFuIFJHQiBgaW1hZ2VgIHRyYWNlIGtlZXBzIGl0c1xuICogIGNoYW5uZWxzICgzIG9yIDQpLCBhIGhlYXRtYXAgaXMgb25lIHJvdW5kZWQgY2hhbm5lbC4gTnVsbCB3aGVuIGVtcHR5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYWNlUGl4ZWxzKHRyYWNlOiB7IHR5cGU/OiBzdHJpbmc7IHo/OiBhbnlbXVtdIH0gfCB1bmRlZmluZWQpOiBQaXhlbERhdGEgfCBudWxsIHtcbiAgY29uc3QgekRhdGEgPSB0cmFjZT8uejtcbiAgaWYgKCF6RGF0YSkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IGhlaWdodCA9IHpEYXRhLmxlbmd0aDtcbiAgaWYgKGhlaWdodCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gIGNvbnN0IHdpZHRoID0gekRhdGFbMF0ubGVuZ3RoO1xuICBpZiAodHJhY2UhLnR5cGUgPT09ICdpbWFnZScpIHtcbiAgICAvLyBSR0IgaW1hZ2U6IHpbcm93XVtjb2xdID0gW3IsIGcsIGJdIG9yIFtyLCBnLCBiLCBhXVxuICAgIGNvbnN0IHNhbXBsZSA9IHpEYXRhWzBdWzBdO1xuICAgIGNvbnN0IGNoYW5uZWxzID0gQXJyYXkuaXNBcnJheShzYW1wbGUpID8gc2FtcGxlLmxlbmd0aCA6IDM7XG4gICAgY29uc3QgZGF0YSA9IG5ldyBVaW50OENsYW1wZWRBcnJheSh3aWR0aCAqIGhlaWdodCAqIGNoYW5uZWxzKTtcbiAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHtcbiAgICAgICAgY29uc3QgcGl4ZWwgPSB6RGF0YVt5XVt4XTtcbiAgICAgICAgY29uc3Qgb2Zmc2V0ID0gKHkgKiB3aWR0aCArIHgpICogY2hhbm5lbHM7XG4gICAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY2hhbm5lbHM7IGMrKykgZGF0YVtvZmZzZXQgKyBjXSA9IHBpeGVsW2NdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyB3aWR0aCwgaGVpZ2h0LCBjaGFubmVscywgZGF0YSB9O1xuICB9XG4gIC8vIEhlYXRtYXAgKGdyYXlzY2FsZSk6IHpbcm93XVtjb2xdID0gc2NhbGFyIHZhbHVlXG4gIGNvbnN0IGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkod2lkdGggKiBoZWlnaHQpO1xuICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7XG4gICAgZm9yIChsZXQgeCA9IDA7IHggPCB3aWR0aDsgeCsrKSBkYXRhW3kgKiB3aWR0aCArIHhdID0gTWF0aC5yb3VuZCh6RGF0YVt5XVt4XSk7XG4gIH1cbiAgcmV0dXJuIHsgd2lkdGgsIGhlaWdodCwgY2hhbm5lbHM6IDEsIGRhdGEgfTtcbn1cblxuLyoqIDI1Ni1iaW4gaGlzdG9ncmFtIG9mIG9uZSBjaGFubmVsIG9mIGEgZnJhbWUgKHJhdywgcHJlLUxVVCkuIEdyYXlzY2FsZSBjZWxsc1xuICogIGFyZSBudW1iZXJzOyBSR0IgY2VsbHMgYFtyLGcsYl1gIGdpdmUgY2hhbm5lbCBgY2hhbm5lbEluZGV4YCwgb3IgdGhlIEJULjYwMVxuICogIGx1bWluYW5jZSBmb3IgYW4gaW5kZXggcGFzdCB0aGVpciBjaGFubmVscy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcmFtZUhpc3RvZ3JhbShmcmFtZTogYW55W10sIGNoYW5uZWxJbmRleDogbnVtYmVyKTogSUhpc3RvZ3JhbSB7XG4gIGNvbnN0IGNvdW50cyA9IG5ldyBBcnJheSgyNTYpLmZpbGwoMCk7XG4gIGZvciAoY29uc3Qgcm93IG9mIGZyYW1lKSB7XG4gICAgaWYgKCFyb3cpIGNvbnRpbnVlO1xuICAgIGZvciAoY29uc3QgY2VsbCBvZiByb3cpIHtcbiAgICAgIGxldCB2OiBudW1iZXI7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShjZWxsKSkge1xuICAgICAgICB2ID1cbiAgICAgICAgICBjaGFubmVsSW5kZXggPj0gMCAmJiBjaGFubmVsSW5kZXggPCBjZWxsLmxlbmd0aFxuICAgICAgICAgICAgPyBjZWxsW2NoYW5uZWxJbmRleF1cbiAgICAgICAgICAgIDogTWF0aC5yb3VuZChidDYwMUx1bWluYW5jZShjZWxsWzBdLCBjZWxsWzFdLCBjZWxsWzJdKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2ID0gY2VsbDtcbiAgICAgIH1cbiAgICAgIHYgPSB2IHwgMDtcbiAgICAgIGlmICh2IDwgMCkgdiA9IDA7XG4gICAgICBlbHNlIGlmICh2ID4gMjU1KSB2ID0gMjU1O1xuICAgICAgY291bnRzW3ZdKys7XG4gICAgfVxuICB9XG4gIHJldHVybiBoaXN0b2dyYW0yNTYoY291bnRzKTtcbn1cblxuLyoqIDI1Ni1iaW4gaGlzdG9ncmFtIG9mIGEgb25lLWJ5dGUtcGVyLXBpeGVsIHBsYW5lIChhIGNoYW5uZWwncyByYXcgcGl4ZWxzKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwbGFuZUhpc3RvZ3JhbShwbGFuZTogQXJyYXlMaWtlPG51bWJlcj4pOiBJSGlzdG9ncmFtIHtcbiAgY29uc3QgY291bnRzID0gbmV3IEFycmF5KDI1NikuZmlsbCgwKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwbGFuZS5sZW5ndGg7IGkrKykgY291bnRzW3BsYW5lW2ldXSsrO1xuICByZXR1cm4gaGlzdG9ncmFtMjU2KGNvdW50cyk7XG59XG5cbnR5cGUgUmVjdCA9IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH07XG5cbi8qKlxuICogVGhlIGltYWdlIHJlY3QgdGhlIHBsb3Qgc2hvd3MsIGZyb20gdGhlIGxpdmUgYXhpcyByYW5nZXMg4oCUIGFmdGVyIGEgaGlnaC1kZWZcbiAqIHpvb20gdGhlIGF4ZXMgYXJlIHJlbGFpZCBvdXQgdG8gdGhlIGNyb3AncyBib3VuZHMsIHNvIHRoZSByYW5nZXMgQVJFIHRoZVxuICogY3JvcCDigJQgZWxzZSB0aGUgd2hvbGUgaW1hZ2UgYFt4MCwgeDEsIHkwLCB5MV1gLCBlbHNlIG51bGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBheGVzU291cmNlUmVjdChcbiAgeHI6IG51bWJlcltdIHwgdW5kZWZpbmVkLFxuICB5cjogbnVtYmVyW10gfCB1bmRlZmluZWQsXG4gIHRydWVJbWdTaXplOiBudW1iZXJbXSB8IHVuZGVmaW5lZCxcbik6IFJlY3QgfCBudWxsIHtcbiAgaWYgKHhyICYmIHlyKSB7XG4gICAgY29uc3QgeDAgPSBNYXRoLm1pbih4clswXSwgeHJbMV0pO1xuICAgIGNvbnN0IHkwID0gTWF0aC5taW4oeXJbMF0sIHlyWzFdKTsgLy8geSBheGlzIGlzIHJldmVyc2VkIGZvciBpbWFnZSBsYXlvdXRzXG4gICAgcmV0dXJuIHsgeDogeDAsIHk6IHkwLCB3aWR0aDogTWF0aC5hYnMoeHJbMV0gLSB4clswXSksIGhlaWdodDogTWF0aC5hYnMoeXJbMV0gLSB5clswXSkgfTtcbiAgfVxuICBpZiAoIXRydWVJbWdTaXplKSByZXR1cm4gbnVsbDtcbiAgcmV0dXJuIHtcbiAgICB4OiB0cnVlSW1nU2l6ZVswXSxcbiAgICB5OiB0cnVlSW1nU2l6ZVsyXSxcbiAgICB3aWR0aDogdHJ1ZUltZ1NpemVbMV0gLSB0cnVlSW1nU2l6ZVswXSxcbiAgICBoZWlnaHQ6IHRydWVJbWdTaXplWzNdIC0gdHJ1ZUltZ1NpemVbMl0sXG4gIH07XG59XG5cbi8qKlxuICogVGhlIHJlc3R5bGUgdGhhdCBsaXZlLWFwcGxpZXMgdGhlIGNoYW5uZWwgZGlzcGxheTogdGhlIGNvbG91ciBzY2FsZSwgcmV2ZXJzZVxuICogKHJldmVyc2Utc2NhbGUgYW5kIGludmVydCBlYWNoIGZsaXAgdGhlIHJhbXA7IGJvdGggdG9nZXRoZXIgY2FuY2VsKSBhbmQgdGhlXG4gKiBJbnRlbnNpdHkgY2hhbm5lbCdzIHdpbmRvdyDigJQgY21pbi9jbWF4IGZvciB0aGUgM0QgcGxvdCB0eXBlcywgem1pbi96bWF4IGZvclxuICogaGVhdG1hcC9jb250b3VyLiBBIHRyYWNlIHdpdGhvdXQgYSBjb2xvdXIgc2NhbGUgaWdub3JlcyB0aGVzZSBhdHRyaWJ1dGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2hhbm5lbERpc3BsYXlSZXN0eWxlKFxuICBjaGFubmVsczogSUNoYW5uZWxTdGF0ZVtdLFxuICByZXZlcnNlOiBib29sZWFuLFxuICBpbnZlcnQ6IGJvb2xlYW4sXG4gIGNvbG9yc2NhbGU6IHVua25vd24sXG4gIHBsb3RUeXBlOiBQbG90VHlwZSxcbik6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgY29uc3QgdXBkYXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHsgcmV2ZXJzZXNjYWxlOiByZXZlcnNlICE9PSBpbnZlcnQgfTtcbiAgaWYgKGNvbG9yc2NhbGUgIT0gbnVsbCkgdXBkYXRlWydjb2xvcnNjYWxlJ10gPSBjb2xvcnNjYWxlO1xuICBjb25zdCBjaCA9IGNoYW5uZWxzPy5bMF07XG4gIGlmIChjaCkge1xuICAgIGNvbnN0IHRocmVlRCA9XG4gICAgICBwbG90VHlwZSA9PT0gUGxvdFR5cGUuSVNPU1VSRkFDRSB8fCBwbG90VHlwZSA9PT0gUGxvdFR5cGUuU1VSRkFDRSB8fCBwbG90VHlwZSA9PT0gUGxvdFR5cGUuU0NBVFRFUjNEO1xuICAgIGlmICh0aHJlZUQpIE9iamVjdC5hc3NpZ24odXBkYXRlLCB7IGNtaW46IGNoLm1pbiwgY21heDogY2gubWF4LCBjYXV0bzogZmFsc2UgfSk7XG4gICAgZWxzZSBPYmplY3QuYXNzaWduKHVwZGF0ZSwgeyB6bWluOiBjaC5taW4sIHptYXg6IGNoLm1heCwgemF1dG86IGZhbHNlIH0pO1xuICB9XG4gIHJldHVybiB1cGRhdGU7XG59XG4iXX0=
@@ -16,16 +16,25 @@ export class PlotlyRegionOverlay {
16
16
  setMode(mode) {
17
17
  // 'select' is a neutral mode for Plotly (no drag mode); region selection is
18
18
  // driven by the table / active-shape sampling, so just clear the drag mode.
19
- const dragMode = mode === 'drawrect' ? 'drawrect' :
20
- mode === 'drawclosedpath' ? 'drawclosedpath' :
21
- mode === 'drawopenpath' ? 'drawopenpath' :
22
- false;
19
+ const dragMode = mode === 'drawrect'
20
+ ? 'drawrect'
21
+ : mode === 'drawclosedpath'
22
+ ? 'drawclosedpath'
23
+ : mode === 'drawopenpath'
24
+ ? 'drawopenpath'
25
+ : false;
23
26
  this.plotly.setDragMode(dragMode);
24
27
  }
25
- redraw() { }
26
- /** Bezier regions are an OpenSeadragon-only feature (Plotly has no native
27
- * curved-shape rendering), so this is a no-op here. */
28
- setSelectedBezier(_bezier) { }
29
- destroy() { }
28
+ redraw() {
29
+ /* Plotly re-renders its shapes natively on relayout */
30
+ }
31
+ /** Bezier regions are drawn by the SVG overlays (OpenSeadragon, napari-js);
32
+ * Plotly has no native curved-shape rendering, so this is a no-op here. */
33
+ setSelectedBezier(_bezier) {
34
+ /* not rendered by Plotly */
35
+ }
36
+ destroy() {
37
+ /* nothing to tear down — shapes live in the Plotly layout */
38
+ }
30
39
  }
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXJlZ2lvbi1vdmVybGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1yZWdpb24tb3ZlcmxheS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxPQUFPLG1CQUFtQjtJQUU5QixZQUFvQixNQUFxQjtRQUFyQixXQUFNLEdBQU4sTUFBTSxDQUFlO0lBQUcsQ0FBQztJQUU3QyxPQUFPLENBQUMsSUFBb0I7UUFDMUIsNEVBQTRFO1FBQzVFLDRFQUE0RTtRQUM1RSxNQUFNLFFBQVEsR0FDWixJQUFJLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNsQyxJQUFJLEtBQUssZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUM7Z0JBQzlDLElBQUksS0FBSyxjQUFjLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDO29CQUMxQyxLQUFLLENBQUM7UUFDUixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsTUFBTSxLQUFtRSxDQUFDO0lBRTFFOzREQUN3RDtJQUN4RCxpQkFBaUIsQ0FBQyxPQUFnQixJQUF5QixDQUFDO0lBRTVELE9BQU8sS0FBeUUsQ0FBQztDQUNsRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBsb3RseVNlcnZpY2UgfSBmcm9tICcuL3Bsb3RseS5zZXJ2aWNlJztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5LCBSZWdpb25Ub29sTW9kZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9yZWdpb24tb3ZlcmxheS5jb250cmFjdCc7XG5cbi8qKlxuICogUGxvdGx5IGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJUmVnaW9uT3ZlcmxheX0uXG4gKlxuICogUGxvdGx5IHJlbmRlcnMgcmVnaW9uIHNoYXBlcyBuYXRpdmVseSBpbiBpdHMgcGxvdCBsYXlvdXQgYW5kIGVkaXRzIHRoZW0gdmlhXG4gKiBpdHMgb3duIGRyYWcgbW9kZXMsIHNvIHRoaXMgYWRhcHRlciBpcyB0aGluOiBpdCBtYXBzIHRoZSBuZXV0cmFsXG4gKiB7QGxpbmsgUmVnaW9uVG9vbE1vZGV9IG9udG8gUGxvdGx5IGRyYWcgbW9kZXMgYW5kIGxldHMgUGxvdGx5IGRyYXcuIGByZWRyYXdgXG4gKiBpcyBhIG5vLW9wIGJlY2F1c2UgUGxvdGx5IHJlLXJlbmRlcnMgaXRzIHNoYXBlcyBpdHNlbGYgb24gcmVsYXlvdXQuXG4gKlxuICogSXQgaXMgdGhlIHN5bW1ldHJpYyBjb3VudGVycGFydCB0byB7QGxpbmsgT3NkUmVnaW9uT3ZlcmxheX06IGJvdGggcmVuZGVyIHRoZVxuICogc2FtZSBzaGFyZWQgYElSZWdpb25TdG9yZWAsIGVhY2ggb250byBpdHMgb3duIGJhY2tlbmQncyBjYW52YXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbG90bHlSZWdpb25PdmVybGF5IGltcGxlbWVudHMgSVJlZ2lvbk92ZXJsYXkge1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcGxvdGx5OiBQbG90bHlTZXJ2aWNlKSB7fVxuXG4gIHNldE1vZGUobW9kZTogUmVnaW9uVG9vbE1vZGUpOiB2b2lkIHtcbiAgICAvLyAnc2VsZWN0JyBpcyBhIG5ldXRyYWwgbW9kZSBmb3IgUGxvdGx5IChubyBkcmFnIG1vZGUpOyByZWdpb24gc2VsZWN0aW9uIGlzXG4gICAgLy8gZHJpdmVuIGJ5IHRoZSB0YWJsZSAvIGFjdGl2ZS1zaGFwZSBzYW1wbGluZywgc28ganVzdCBjbGVhciB0aGUgZHJhZyBtb2RlLlxuICAgIGNvbnN0IGRyYWdNb2RlID1cbiAgICAgIG1vZGUgPT09ICdkcmF3cmVjdCcgPyAnZHJhd3JlY3QnIDpcbiAgICAgIG1vZGUgPT09ICdkcmF3Y2xvc2VkcGF0aCcgPyAnZHJhd2Nsb3NlZHBhdGgnIDpcbiAgICAgIG1vZGUgPT09ICdkcmF3b3BlbnBhdGgnID8gJ2RyYXdvcGVucGF0aCcgOlxuICAgICAgZmFsc2U7XG4gICAgdGhpcy5wbG90bHkuc2V0RHJhZ01vZGUoZHJhZ01vZGUpO1xuICB9XG5cbiAgcmVkcmF3KCk6IHZvaWQgeyAvKiBQbG90bHkgcmUtcmVuZGVycyBpdHMgc2hhcGVzIG5hdGl2ZWx5IG9uIHJlbGF5b3V0ICovIH1cblxuICAvKiogQmV6aWVyIHJlZ2lvbnMgYXJlIGFuIE9wZW5TZWFkcmFnb24tb25seSBmZWF0dXJlIChQbG90bHkgaGFzIG5vIG5hdGl2ZVxuICAgKiAgY3VydmVkLXNoYXBlIHJlbmRlcmluZyksIHNvIHRoaXMgaXMgYSBuby1vcCBoZXJlLiAqL1xuICBzZXRTZWxlY3RlZEJlemllcihfYmV6aWVyOiBib29sZWFuKTogdm9pZCB7IC8qIE9TRC1vbmx5ICovIH1cblxuICBkZXN0cm95KCk6IHZvaWQgeyAvKiBub3RoaW5nIHRvIHRlYXIgZG93biDigJQgc2hhcGVzIGxpdmUgaW4gdGhlIFBsb3RseSBsYXlvdXQgKi8gfVxufVxuIl19
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXJlZ2lvbi1vdmVybGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1yZWdpb24tb3ZlcmxheS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxPQUFPLG1CQUFtQjtJQUM5QixZQUFvQixNQUFxQjtRQUFyQixXQUFNLEdBQU4sTUFBTSxDQUFlO0lBQUcsQ0FBQztJQUU3QyxPQUFPLENBQUMsSUFBb0I7UUFDMUIsNEVBQTRFO1FBQzVFLDRFQUE0RTtRQUM1RSxNQUFNLFFBQVEsR0FDWixJQUFJLEtBQUssVUFBVTtZQUNqQixDQUFDLENBQUMsVUFBVTtZQUNaLENBQUMsQ0FBQyxJQUFJLEtBQUssZ0JBQWdCO2dCQUN6QixDQUFDLENBQUMsZ0JBQWdCO2dCQUNsQixDQUFDLENBQUMsSUFBSSxLQUFLLGNBQWM7b0JBQ3ZCLENBQUMsQ0FBQyxjQUFjO29CQUNoQixDQUFDLENBQUMsS0FBSyxDQUFDO1FBQ2hCLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNO1FBQ0osdURBQXVEO0lBQ3pELENBQUM7SUFFRDtnRkFDNEU7SUFDNUUsaUJBQWlCLENBQUMsT0FBZ0I7UUFDaEMsNEJBQTRCO0lBQzlCLENBQUM7SUFFRCxPQUFPO1FBQ0wsNkRBQTZEO0lBQy9ELENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBsb3RseVNlcnZpY2UgfSBmcm9tICcuL3Bsb3RseS5zZXJ2aWNlJztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5LCBSZWdpb25Ub29sTW9kZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9yZWdpb24tb3ZlcmxheS5jb250cmFjdCc7XG5cbi8qKlxuICogUGxvdGx5IGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJUmVnaW9uT3ZlcmxheX0uXG4gKlxuICogUGxvdGx5IHJlbmRlcnMgcmVnaW9uIHNoYXBlcyBuYXRpdmVseSBpbiBpdHMgcGxvdCBsYXlvdXQgYW5kIGVkaXRzIHRoZW0gdmlhXG4gKiBpdHMgb3duIGRyYWcgbW9kZXMsIHNvIHRoaXMgYWRhcHRlciBpcyB0aGluOiBpdCBtYXBzIHRoZSBuZXV0cmFsXG4gKiB7QGxpbmsgUmVnaW9uVG9vbE1vZGV9IG9udG8gUGxvdGx5IGRyYWcgbW9kZXMgYW5kIGxldHMgUGxvdGx5IGRyYXcuIGByZWRyYXdgXG4gKiBpcyBhIG5vLW9wIGJlY2F1c2UgUGxvdGx5IHJlLXJlbmRlcnMgaXRzIHNoYXBlcyBpdHNlbGYgb24gcmVsYXlvdXQuXG4gKlxuICogSXQgaXMgdGhlIHN5bW1ldHJpYyBjb3VudGVycGFydCB0byB7QGxpbmsgT3NkUmVnaW9uT3ZlcmxheX06IGJvdGggcmVuZGVyIHRoZVxuICogc2FtZSBzaGFyZWQgYElSZWdpb25TdG9yZWAsIGVhY2ggb250byBpdHMgb3duIGJhY2tlbmQncyBjYW52YXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbG90bHlSZWdpb25PdmVybGF5IGltcGxlbWVudHMgSVJlZ2lvbk92ZXJsYXkge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHBsb3RseTogUGxvdGx5U2VydmljZSkge31cblxuICBzZXRNb2RlKG1vZGU6IFJlZ2lvblRvb2xNb2RlKTogdm9pZCB7XG4gICAgLy8gJ3NlbGVjdCcgaXMgYSBuZXV0cmFsIG1vZGUgZm9yIFBsb3RseSAobm8gZHJhZyBtb2RlKTsgcmVnaW9uIHNlbGVjdGlvbiBpc1xuICAgIC8vIGRyaXZlbiBieSB0aGUgdGFibGUgLyBhY3RpdmUtc2hhcGUgc2FtcGxpbmcsIHNvIGp1c3QgY2xlYXIgdGhlIGRyYWcgbW9kZS5cbiAgICBjb25zdCBkcmFnTW9kZSA9XG4gICAgICBtb2RlID09PSAnZHJhd3JlY3QnXG4gICAgICAgID8gJ2RyYXdyZWN0J1xuICAgICAgICA6IG1vZGUgPT09ICdkcmF3Y2xvc2VkcGF0aCdcbiAgICAgICAgICA/ICdkcmF3Y2xvc2VkcGF0aCdcbiAgICAgICAgICA6IG1vZGUgPT09ICdkcmF3b3BlbnBhdGgnXG4gICAgICAgICAgICA/ICdkcmF3b3BlbnBhdGgnXG4gICAgICAgICAgICA6IGZhbHNlO1xuICAgIHRoaXMucGxvdGx5LnNldERyYWdNb2RlKGRyYWdNb2RlKTtcbiAgfVxuXG4gIHJlZHJhdygpOiB2b2lkIHtcbiAgICAvKiBQbG90bHkgcmUtcmVuZGVycyBpdHMgc2hhcGVzIG5hdGl2ZWx5IG9uIHJlbGF5b3V0ICovXG4gIH1cblxuICAvKiogQmV6aWVyIHJlZ2lvbnMgYXJlIGRyYXduIGJ5IHRoZSBTVkcgb3ZlcmxheXMgKE9wZW5TZWFkcmFnb24sIG5hcGFyaS1qcyk7XG4gICAqICBQbG90bHkgaGFzIG5vIG5hdGl2ZSBjdXJ2ZWQtc2hhcGUgcmVuZGVyaW5nLCBzbyB0aGlzIGlzIGEgbm8tb3AgaGVyZS4gKi9cbiAgc2V0U2VsZWN0ZWRCZXppZXIoX2JlemllcjogYm9vbGVhbik6IHZvaWQge1xuICAgIC8qIG5vdCByZW5kZXJlZCBieSBQbG90bHkgKi9cbiAgfVxuXG4gIGRlc3Ryb3koKTogdm9pZCB7XG4gICAgLyogbm90aGluZyB0byB0ZWFyIGRvd24g4oCUIHNoYXBlcyBsaXZlIGluIHRoZSBQbG90bHkgbGF5b3V0ICovXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,223 @@
1
+ import * as Plotly from 'plotly.js-dist-min';
2
+ import { Subscription } from 'rxjs';
3
+ import { ShapeSelection } from '../../models/shape';
4
+ import { PlotUtilities } from '../../plot.utilities';
5
+ /**
6
+ * Plotly's render projection of the shared RegionStore: `shapes` is the dict
7
+ * array `Plotly.relayout` consumes, kept beside the store. Shapes edited or
8
+ * drawn on the Plotly canvas are mirrored INTO the store ({@link commitToStore});
9
+ * every other change — wherever it was made — arrives as a store update event
10
+ * and is projected back OUT and redrawn ({@link connect}). Also maps the store's
11
+ * selection onto Plotly's `_activeShapeIndex` (the shape with the edit handles)
12
+ * and back.
13
+ */
14
+ export class PlotlyShapeProjection {
15
+ constructor(host, regionStore) {
16
+ this.host = host;
17
+ this.regionStore = regionStore;
18
+ /** The render projection: one Plotly shape dict per store region. */
19
+ this.shapes = [];
20
+ /** Nesting depth of {@link quietly}: region updates are not redrawn while > 0. */
21
+ this.muted = 0;
22
+ this.utils = new PlotUtilities();
23
+ }
24
+ /** The plot div, live Plotly graph or not (null when none is set). */
25
+ gd() {
26
+ const id = this.host.plotDiv();
27
+ return id ? document.getElementById(id) : null;
28
+ }
29
+ /** The plot div while it hosts a live Plotly graph, else null: the div stays
30
+ * set after it was handed to another backend, and Plotly throws on it then. */
31
+ liveGd() {
32
+ const gd = this.gd();
33
+ return gd?._fullLayout ? gd : null;
34
+ }
35
+ /** Rebuild the dict working-set from the store (after an image switch, or when
36
+ * regions changed while another backend was rendering). */
37
+ syncFromStore() {
38
+ const showLabel = this.regionStore.getShowShapeLabel();
39
+ this.shapes = this.regionStore.getRegions().map((r) => {
40
+ r.filename = this.host.fileName();
41
+ return { ...r.getShape(showLabel) };
42
+ });
43
+ }
44
+ /**
45
+ * Make the shared store authoritative for the current dict working-set: convert
46
+ * the dicts to neutral regions and replace the store's list (the store mints
47
+ * ids, applies class colours, syncs its per-image cache and emits the
48
+ * region-update event). Store-minted ids are written back onto the dicts so the
49
+ * two representations stay aligned. Profile-line ROIs are ordinary regions
50
+ * (tagged `kind: 'profile'`) and round-trip through here too.
51
+ */
52
+ commitToStore() {
53
+ const regions = this.shapes.map((s) => Object.assign(new ShapeSelection(), s).getRegion());
54
+ // The canvas already shows these shapes: don't redraw them from the update.
55
+ this.quietly(() => this.regionStore.setRegions(regions, this.regionStore.getShowShapeLabel(), true, this.regionStore.getFillColor(), false));
56
+ const stored = this.regionStore.getRegions();
57
+ for (let i = 0; i < this.shapes.length && i < stored.length; i++) {
58
+ if (this.shapes[i].id == null)
59
+ this.shapes[i].id = stored[i].id;
60
+ if (this.shapes[i].name == null)
61
+ this.shapes[i].name = stored[i].name;
62
+ }
63
+ }
64
+ /**
65
+ * Apply a `plotly_relayout` event's shape part: in-place edits
66
+ * (`shapes[i].x0`, `shapes[i].path`, …, rounded to whole pixels) and a shape
67
+ * drawn natively on the canvas (a lone `shapes` key — snapped, tagged with
68
+ * the file and, when labels are on, a label object), mirrored into the store.
69
+ */
70
+ applyRelayout(event) {
71
+ let shapesModified = false;
72
+ for (const key of Object.keys(event)) {
73
+ if (!key.startsWith('shapes['))
74
+ continue;
75
+ const shapeNumber = +key.split('[')[1].split(']')[0];
76
+ const shapeChange = key.split('.')[1];
77
+ if (this.shapes && this.shapes[shapeNumber]) {
78
+ this.shapes[shapeNumber][shapeChange] =
79
+ shapeChange === 'path' ? this.utils.roundPathCoordinates(event[key]) : Math.round(+event[key]);
80
+ shapesModified = true;
81
+ }
82
+ }
83
+ if (shapesModified)
84
+ this.commitToStore();
85
+ if (Object.keys(event).length === 1 && 'shapes' in event) {
86
+ this.shapes = event['shapes'];
87
+ for (let i = 0; i < this.shapes.length; i++) {
88
+ // A freshly Plotly-drawn shape has no id yet — give it a label object
89
+ // (when labels are on) before the store mints id + default name.
90
+ const isNew = this.shapes[i].id == null;
91
+ this.shapes[i].fileName = this.host.fileName();
92
+ this.shapes[i] = this.utils.snapRegion(this.shapes[i]);
93
+ if (isNew && this.regionStore.getShowShapeLabel()) {
94
+ this.shapes[i].label = {
95
+ text: this.shapes[i].label,
96
+ texttemplate: this.shapes[i].label,
97
+ font: { color: this.regionStore.getShapeColor() },
98
+ textposition: 'top left',
99
+ };
100
+ }
101
+ }
102
+ // Mint ids/names in the store, write them back onto the dicts, and emit.
103
+ this.commitToStore();
104
+ }
105
+ }
106
+ /** Push the dict working-set to Plotly (a no-op when another backend owns the div). */
107
+ render() {
108
+ const gd = this.liveGd();
109
+ if (!gd)
110
+ return;
111
+ void Plotly.relayout(gd, this.relayoutPayload(this.shapes.map((s) => ({ ...s }))));
112
+ }
113
+ /** The shapes of the image on screen, labelled (or not) for display, as fresh dicts. */
114
+ shapesToRedraw(showLabel = this.regionStore.getShowShapeLabel()) {
115
+ const shapesToRedraw = [];
116
+ for (const shape of this.shapes) {
117
+ if (JSON.stringify(shape.fileName) === JSON.stringify(this.host.fileName())) {
118
+ shape.label = showLabel
119
+ ? {
120
+ text: `${shape.legend}`,
121
+ texttemplate: `${shape.legend}`,
122
+ textposition: 'top left',
123
+ font: { color: `${shape.line.color}` },
124
+ }
125
+ : {};
126
+ shapesToRedraw.push(shape);
127
+ }
128
+ }
129
+ // convert to dict so that plotly recognises the shapes
130
+ return shapesToRedraw.map((s) => ({ ...s }));
131
+ }
132
+ /**
133
+ * Follow the shared store: redraw the shapes on every region update and move
134
+ * the edit handles on every selection change, whoever made the change (the
135
+ * router, an undo, the Region Editor, another backend's overlay, a canvas
136
+ * tool). Plotly is not on the store's write path any more — it listens, like
137
+ * the OpenSeadragon and napari-js overlays do. Service-lifetime: both
138
+ * callbacks no-op while no live Plotly graph holds the div.
139
+ */
140
+ connect() {
141
+ const subs = new Subscription();
142
+ subs.add(this.regionStore.getRegionUpdateEvent().subscribe((regions) => this.onRegionUpdate(regions)));
143
+ subs.add(this.regionStore.getSelectedShapeIndices$().subscribe((indices) => this.onSelection(indices)));
144
+ return subs;
145
+ }
146
+ /**
147
+ * Run `write` — a store write this projection already reflects (a shape edited
148
+ * on the canvas, an image switch the next plot draws) — without redrawing from
149
+ * the update event it causes.
150
+ */
151
+ quietly(write) {
152
+ this.muted++;
153
+ try {
154
+ write();
155
+ }
156
+ finally {
157
+ this.muted--;
158
+ }
159
+ }
160
+ /**
161
+ * A region update. The stored set re-projects and redraws; a transient set
162
+ * (`setRegions(…, isRegionSaveOn = false)`, which the store emits without
163
+ * storing) is drawn as-is and leaves the working-set alone.
164
+ */
165
+ onRegionUpdate(regions) {
166
+ if (this.muted > 0)
167
+ return;
168
+ const stored = this.regionStore.getRegions();
169
+ const isStored = regions.length === stored.length && regions.every((r, i) => r === stored[i]);
170
+ if (isStored) {
171
+ this.syncFromStore();
172
+ this.render();
173
+ return;
174
+ }
175
+ const gd = this.liveGd();
176
+ if (!gd)
177
+ return;
178
+ const showLabel = this.regionStore.getShowShapeLabel();
179
+ const dicts = regions.map((r) => {
180
+ r.filename = this.host.fileName();
181
+ return { ...r.getShape(showLabel) };
182
+ });
183
+ void Plotly.relayout(gd, this.relayoutPayload(dicts));
184
+ }
185
+ /**
186
+ * A selection change: Plotly's `_activeShapeIndex` points at the last selected
187
+ * shape so it gets the edit handles (Plotly's own active-shape rendering is the
188
+ * only highlight). Skipped when the plot already shows it — the change came
189
+ * from a click on the plot ({@link syncSelectionFromPlot}).
190
+ */
191
+ onSelection(indices) {
192
+ const gd = this.liveGd();
193
+ if (!gd)
194
+ return;
195
+ const active = indices.length > 0 ? indices[indices.length - 1] : -1;
196
+ if ((gd._fullLayout._activeShapeIndex ?? -1) === active)
197
+ return;
198
+ gd._fullLayout._activeShapeIndex = active;
199
+ try {
200
+ void Plotly.redraw(gd);
201
+ }
202
+ catch {
203
+ /* noop in tests */
204
+ }
205
+ }
206
+ /**
207
+ * Read Plotly's `_activeShapeIndex` and push it as the selection. Plotly fires
208
+ * no dedicated active-shape event for clicks, so this is sampled after a
209
+ * relayout and a click. The store no-ops when the selection is unchanged.
210
+ */
211
+ syncSelectionFromPlot() {
212
+ if (!this.host.plotDiv())
213
+ return;
214
+ const raw = this.gd()?._fullLayout?._activeShapeIndex;
215
+ const idx = typeof raw === 'number' && raw >= 0 && raw < this.shapes.length ? raw : -1;
216
+ this.regionStore.setSelectedShapeIndices(idx >= 0 ? [idx] : []);
217
+ }
218
+ /** The shapes-relayout payload: the shapes plus the active-shape fill colour. */
219
+ relayoutPayload(shapeDicts) {
220
+ return { shapes: shapeDicts, activeshape: { fillcolor: this.regionStore.getFillColor() } };
221
+ }
222
+ }
223
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXNoYXBlLXByb2plY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9wbG90bHkvcGxvdGx5LXNoYXBlLXByb2plY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE1BQU0sTUFBTSxvQkFBb0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBR3BDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVwRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFhckQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLE9BQU8scUJBQXFCO0lBT2hDLFlBQ21CLElBQXlCLEVBQ3pCLFdBQXdCO1FBRHhCLFNBQUksR0FBSixJQUFJLENBQXFCO1FBQ3pCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBUjNDLHFFQUFxRTtRQUNyRSxXQUFNLEdBQVUsRUFBRSxDQUFDO1FBQ25CLGtGQUFrRjtRQUMxRSxVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ0QsVUFBSyxHQUFHLElBQUksYUFBYSxFQUFFLENBQUM7SUFLMUMsQ0FBQztJQUVKLHNFQUFzRTtJQUM5RCxFQUFFO1FBQ1IsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUMvQixPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUUsUUFBUSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQXFCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN0RSxDQUFDO0lBRUQ7b0ZBQ2dGO0lBQ3hFLE1BQU07UUFDWixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDckIsT0FBTyxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FB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U0FBUyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQzdGLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFBsb3RseSBmcm9tICdwbG90bHkuanMtZGlzdC1taW4nO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFJlZ2lvbiB9IGZyb20gJy4uLy4uL21vZGVscy9yZWdpb24nO1xuaW1wb3J0IHsgU2hhcGVTZWxlY3Rpb24gfSBmcm9tICcuLi8uLi9tb2RlbHMvc2hhcGUnO1xuaW1wb3J0IHsgUmVnaW9uU3RvcmUgfSBmcm9tICcuLi8uLi9zdG9yZS9yZWdpb24tc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBQbG90VXRpbGl0aWVzIH0gZnJvbSAnLi4vLi4vcGxvdC51dGlsaXRpZXMnO1xuXG4vKiogQSBQbG90bHkgZ3JhcGggZGl2LCBhcyBmYXIgYXMgdGhlIHByb2plY3Rpb24gcmVhZHMgaXQuICovXG50eXBlIEdyYXBoRGl2ID0gSFRNTEVsZW1lbnQgJiB7IF9mdWxsTGF5b3V0PzogeyBfYWN0aXZlU2hhcGVJbmRleD86IG51bWJlciB9IH07XG5cbi8qKiBUaGUgc2VydmljZSBzdGF0ZSB0aGUgcHJvamVjdGlvbiByZWFkcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhcGVQcm9qZWN0aW9uSG9zdCB7XG4gIC8qKiBUaGUgcGxvdCBkaXYncyBpZCAoJycgYmVmb3JlIHRoZSBmaXJzdCBwbG90KTsgaXQgbWF5IGJlIGFub3RoZXIgYmFja2VuZCdzIG5vdy4gKi9cbiAgcGxvdERpdigpOiBzdHJpbmc7XG4gIC8qKiBUaGUgaW1hZ2Ugb24gc2NyZWVuIChzaGFwZXMgYXJlIHRhZ2dlZCB3aXRoIGl0KS4gKi9cbiAgZmlsZU5hbWUoKTogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFBsb3RseSdzIHJlbmRlciBwcm9qZWN0aW9uIG9mIHRoZSBzaGFyZWQgUmVnaW9uU3RvcmU6IGBzaGFwZXNgIGlzIHRoZSBkaWN0XG4gKiBhcnJheSBgUGxvdGx5LnJlbGF5b3V0YCBjb25zdW1lcywga2VwdCBiZXNpZGUgdGhlIHN0b3JlLiBTaGFwZXMgZWRpdGVkIG9yXG4gKiBkcmF3biBvbiB0aGUgUGxvdGx5IGNhbnZhcyBhcmUgbWlycm9yZWQgSU5UTyB0aGUgc3RvcmUgKHtAbGluayBjb21taXRUb1N0b3JlfSk7XG4gKiBldmVyeSBvdGhlciBjaGFuZ2Ug4oCUIHdoZXJldmVyIGl0IHdhcyBtYWRlIOKAlCBhcnJpdmVzIGFzIGEgc3RvcmUgdXBkYXRlIGV2ZW50XG4gKiBhbmQgaXMgcHJvamVjdGVkIGJhY2sgT1VUIGFuZCByZWRyYXduICh7QGxpbmsgY29ubmVjdH0pLiBBbHNvIG1hcHMgdGhlIHN0b3JlJ3NcbiAqIHNlbGVjdGlvbiBvbnRvIFBsb3RseSdzIGBfYWN0aXZlU2hhcGVJbmRleGAgKHRoZSBzaGFwZSB3aXRoIHRoZSBlZGl0IGhhbmRsZXMpXG4gKiBhbmQgYmFjay5cbiAqL1xuZXhwb3J0IGNsYXNzIFBsb3RseVNoYXBlUHJvamVjdGlvbiB7XG4gIC8qKiBUaGUgcmVuZGVyIHByb2plY3Rpb246IG9uZSBQbG90bHkgc2hhcGUgZGljdCBwZXIgc3RvcmUgcmVnaW9uLiAqL1xuICBzaGFwZXM6IGFueVtdID0gW107XG4gIC8qKiBOZXN0aW5nIGRlcHRoIG9mIHtAbGluayBxdWlldGx5fTogcmVnaW9uIHVwZGF0ZXMgYXJlIG5vdCByZWRyYXduIHdoaWxlID4gMC4gKi9cbiAgcHJpdmF0ZSBtdXRlZCA9IDA7XG4gIHByaXZhdGUgcmVhZG9ubHkgdXRpbHMgPSBuZXcgUGxvdFV0aWxpdGllcygpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaG9zdDogU2hhcGVQcm9qZWN0aW9uSG9zdCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lvblN0b3JlOiBSZWdpb25TdG9yZSxcbiAgKSB7fVxuXG4gIC8qKiBUaGUgcGxvdCBkaXYsIGxpdmUgUGxvdGx5IGdyYXBoIG9yIG5vdCAobnVsbCB3aGVuIG5vbmUgaXMgc2V0KS4gKi9cbiAgcHJpdmF0ZSBnZCgpOiBHcmFwaERpdiB8IG51bGwge1xuICAgIGNvbnN0IGlkID0gdGhpcy5ob3N0LnBsb3REaXYoKTtcbiAgICByZXR1cm4gaWQgPyAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpIGFzIEdyYXBoRGl2IHwgbnVsbCkgOiBudWxsO1xuICB9XG5cbiAgLyoqIFRoZSBwbG90IGRpdiB3aGlsZSBpdCBob3N0cyBhIGxpdmUgUGxvdGx5IGdyYXBoLCBlbHNlIG51bGw6IHRoZSBkaXYgc3RheXNcbiAgICogIHNldCBhZnRlciBpdCB3YXMgaGFuZGVkIHRvIGFub3RoZXIgYmFja2VuZCwgYW5kIFBsb3RseSB0aHJvd3Mgb24gaXQgdGhlbi4gKi9cbiAgcHJpdmF0ZSBsaXZlR2QoKTogR3JhcGhEaXYgfCBudWxsIHtcbiAgICBjb25zdCBnZCA9IHRoaXMuZ2QoKTtcbiAgICByZXR1cm4gZ2Q/Ll9mdWxsTGF5b3V0ID8gZ2QgOiBudWxsO1xuICB9XG5cbiAgLyoqIFJlYnVpbGQgdGhlIGRpY3Qgd29ya2luZy1zZXQgZnJvbSB0aGUgc3RvcmUgKGFmdGVyIGFuIGltYWdlIHN3aXRjaCwgb3Igd2hlblxuICAgKiAgcmVnaW9ucyBjaGFuZ2VkIHdoaWxlIGFub3RoZXIgYmFja2VuZCB3YXMgcmVuZGVyaW5nKS4gKi9cbiAgc3luY0Zyb21TdG9yZSgpOiB2b2lkIHtcbiAgICBjb25zdCBzaG93TGFiZWwgPSB0aGlzLnJlZ2lvblN0b3JlLmdldFNob3dTaGFwZUxhYmVsKCk7XG4gICAgdGhpcy5zaGFwZXMgPSB0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKS5tYXAoKHIpID0+IHtcbiAgICAgIHIuZmlsZW5hbWUgPSB0aGlzLmhvc3QuZmlsZU5hbWUoKTtcbiAgICAgIHJldHVybiB7IC4uLnIuZ2V0U2hhcGUoc2hvd0xhYmVsKSB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgdGhlIHNoYXJlZCBzdG9yZSBhdXRob3JpdGF0aXZlIGZvciB0aGUgY3VycmVudCBkaWN0IHdvcmtpbmctc2V0OiBjb252ZXJ0XG4gICAqIHRoZSBkaWN0cyB0byBuZXV0cmFsIHJlZ2lvbnMgYW5kIHJlcGxhY2UgdGhlIHN0b3JlJ3MgbGlzdCAodGhlIHN0b3JlIG1pbnRzXG4gICAqIGlkcywgYXBwbGllcyBjbGFzcyBjb2xvdXJzLCBzeW5jcyBpdHMgcGVyLWltYWdlIGNhY2hlIGFuZCBlbWl0cyB0aGVcbiAgICogcmVnaW9uLXVwZGF0ZSBldmVudCkuIFN0b3JlLW1pbnRlZCBpZHMgYXJlIHdyaXR0ZW4gYmFjayBvbnRvIHRoZSBkaWN0cyBzbyB0aGVcbiAgICogdHdvIHJlcHJlc2VudGF0aW9ucyBzdGF5IGFsaWduZWQuIFByb2ZpbGUtbGluZSBST0lzIGFyZSBvcmRpbmFyeSByZWdpb25zXG4gICAqICh0YWdnZWQgYGtpbmQ6ICdwcm9maWxlJ2ApIGFuZCByb3VuZC10cmlwIHRocm91Z2ggaGVyZSB0b28uXG4gICAqL1xuICBjb21taXRUb1N0b3JlKCk6IHZvaWQge1xuICAgIGNvbnN0IHJlZ2lvbnMgPSB0aGlzLnNoYXBlcy5tYXAoKHMpID0+IE9iamVjdC5hc3NpZ24obmV3IFNoYXBlU2VsZWN0aW9uKCksIHMpLmdldFJlZ2lvbigpKTtcbiAgICAvLyBUaGUgY2FudmFzIGFscmVhZHkgc2hvd3MgdGhlc2Ugc2hhcGVzOiBkb24ndCByZWRyYXcgdGhlbSBmcm9tIHRoZSB1cGRhdGUuXG4gICAgdGhpcy5xdWlldGx5KCgpID0+XG4gICAgICB0aGlzLnJlZ2lvblN0b3JlLnNldFJlZ2lvbnMoXG4gICAgICAgIHJlZ2lvbnMsXG4gICAgICAgIHRoaXMucmVnaW9uU3RvcmUuZ2V0U2hvd1NoYXBlTGFiZWwoKSxcbiAgICAgICAgdHJ1ZSxcbiAgICAgICAgdGhpcy5yZWdpb25TdG9yZS5nZXRGaWxsQ29sb3IoKSxcbiAgICAgICAgZmFsc2UsXG4gICAgICApLFxuICAgICk7XG4gICAgY29uc3Qgc3RvcmVkID0gdGhpcy5yZWdpb25TdG9yZS5nZXRSZWdpb25zKCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnNoYXBlcy5sZW5ndGggJiYgaSA8IHN0b3JlZC5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHRoaXMuc2hhcGVzW2ldLmlkID09IG51bGwpIHRoaXMuc2hhcGVzW2ldLmlkID0gc3RvcmVkW2ldLmlkO1xuICAgICAgaWYgKHRoaXMuc2hhcGVzW2ldLm5hbWUgPT0gbnVsbCkgdGhpcy5zaGFwZXNbaV0ubmFtZSA9IHN0b3JlZFtpXS5uYW1lO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBseSBhIGBwbG90bHlfcmVsYXlvdXRgIGV2ZW50J3Mgc2hhcGUgcGFydDogaW4tcGxhY2UgZWRpdHNcbiAgICogKGBzaGFwZXNbaV0ueDBgLCBgc2hhcGVzW2ldLnBhdGhgLCDigKYsIHJvdW5kZWQgdG8gd2hvbGUgcGl4ZWxzKSBhbmQgYSBzaGFwZVxuICAgKiBkcmF3biBuYXRpdmVseSBvbiB0aGUgY2FudmFzIChhIGxvbmUgYHNoYXBlc2Aga2V5IOKAlCBzbmFwcGVkLCB0YWdnZWQgd2l0aFxuICAgKiB0aGUgZmlsZSBhbmQsIHdoZW4gbGFiZWxzIGFyZSBvbiwgYSBsYWJlbCBvYmplY3QpLCBtaXJyb3JlZCBpbnRvIHRoZSBzdG9yZS5cbiAgICovXG4gIGFwcGx5UmVsYXlvdXQoZXZlbnQ6IFJlY29yZDxzdHJpbmcsIGFueT4pOiB2b2lkIHtcbiAgICBsZXQgc2hhcGVzTW9kaWZpZWQgPSBmYWxzZTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhldmVudCkpIHtcbiAgICAgIGlmICgha2V5LnN0YXJ0c1dpdGgoJ3NoYXBlc1snKSkgY29udGludWU7XG4gICAgICBjb25zdCBzaGFwZU51bWJlciA9ICtrZXkuc3BsaXQoJ1snKVsxXS5zcGxpdCgnXScpWzBdO1xuICAgICAgY29uc3Qgc2hhcGVDaGFuZ2UgPSBrZXkuc3BsaXQoJy4nKVsxXTtcbiAgICAgIGlmICh0aGlzLnNoYXBlcyAmJiB0aGlzLnNoYXBlc1tzaGFwZU51bWJlcl0pIHtcbiAgICAgICAgdGhpcy5zaGFwZXNbc2hhcGVOdW1iZXJdW3NoYXBlQ2hhbmdlXSA9XG4gICAgICAgICAgc2hhcGVDaGFuZ2UgPT09ICdwYXRoJyA/IHRoaXMudXRpbHMucm91bmRQYXRoQ29vcmRpbmF0ZXMoZXZlbnRba2V5XSkgOiBNYXRoLnJvdW5kKCtldmVudFtrZXldKTtcbiAgICAgICAgc2hhcGVzTW9kaWZpZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoc2hhcGVzTW9kaWZpZWQpIHRoaXMuY29tbWl0VG9TdG9yZSgpO1xuICAgIGlmIChPYmplY3Qua2V5cyhldmVudCkubGVuZ3RoID09PSAxICYmICdzaGFwZXMnIGluIGV2ZW50KSB7XG4gICAgICB0aGlzLnNoYXBlcyA9IGV2ZW50WydzaGFwZXMnXSBhcyBhbnlbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zaGFwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgLy8gQSBmcmVzaGx5IFBsb3RseS1kcmF3biBzaGFwZSBoYXMgbm8gaWQgeWV0IOKAlCBnaXZlIGl0IGEgbGFiZWwgb2JqZWN0XG4gICAgICAgIC8vICh3aGVuIGxhYmVscyBhcmUgb24pIGJlZm9yZSB0aGUgc3RvcmUgbWludHMgaWQgKyBkZWZhdWx0IG5hbWUuXG4gICAgICAgIGNvbnN0IGlzTmV3ID0gdGhpcy5zaGFwZXNbaV0uaWQgPT0gbnVsbDtcbiAgICAgICAgdGhpcy5zaGFwZXNbaV0uZmlsZU5hbWUgPSB0aGlzLmhvc3QuZmlsZU5hbWUoKTtcbiAgICAgICAgdGhpcy5zaGFwZXNbaV0gPSB0aGlzLnV0aWxzLnNuYXBSZWdpb24odGhpcy5zaGFwZXNbaV0pO1xuICAgICAgICBpZiAoaXNOZXcgJiYgdGhpcy5yZWdpb25TdG9yZS5nZXRTaG93U2hhcGVMYWJlbCgpKSB7XG4gICAgICAgICAgdGhpcy5zaGFwZXNbaV0ubGFiZWwgPSB7XG4gICAgICAgICAgICB0ZXh0OiB0aGlzLnNoYXBlc1tpXS5sYWJlbCxcbiAgICAgICAgICAgIHRleHR0ZW1wbGF0ZTogdGhpcy5zaGFwZXNbaV0ubGFiZWwsXG4gICAgICAgICAgICBmb250OiB7IGNvbG9yOiB0aGlzLnJlZ2lvblN0b3JlLmdldFNoYXBlQ29sb3IoKSB9LFxuICAgICAgICAgICAgdGV4dHBvc2l0aW9uOiAndG9wIGxlZnQnLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIE1pbnQgaWRzL25hbWVzIGluIHRoZSBzdG9yZSwgd3JpdGUgdGhlbSBiYWNrIG9udG8gdGhlIGRpY3RzLCBhbmQgZW1pdC5cbiAgICAgIHRoaXMuY29tbWl0VG9TdG9yZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBQdXNoIHRoZSBkaWN0IHdvcmtpbmctc2V0IHRvIFBsb3RseSAoYSBuby1vcCB3aGVuIGFub3RoZXIgYmFja2VuZCBvd25zIHRoZSBkaXYpLiAqL1xuICByZW5kZXIoKTogdm9pZCB7XG4gICAgY29uc3QgZ2QgPSB0aGlzLmxpdmVHZCgpO1xuICAgIGlmICghZ2QpIHJldHVybjtcbiAgICB2b2lkIFBsb3RseS5yZWxheW91dChnZCwgdGhpcy5yZWxheW91dFBheWxvYWQodGhpcy5zaGFwZXMubWFwKChzKSA9PiAoeyAuLi5zIH0pKSkgYXMgUGxvdGx5LkxheW91dCk7XG4gIH1cblxuICAvKiogVGhlIHNoYXBlcyBvZiB0aGUgaW1hZ2Ugb24gc2NyZWVuLCBsYWJlbGxlZCAob3Igbm90KSBmb3IgZGlzcGxheSwgYXMgZnJlc2ggZGljdHMuICovXG4gIHNoYXBlc1RvUmVkcmF3KHNob3dMYWJlbCA9IHRoaXMucmVnaW9uU3RvcmUuZ2V0U2hvd1NoYXBlTGFiZWwoKSk6IGFueVtdIHtcbiAgICBjb25zdCBzaGFwZXNUb1JlZHJhdzogU2hhcGVTZWxlY3Rpb25bXSA9IFtdO1xuICAgIGZvciAoY29uc3Qgc2hhcGUgb2YgdGhpcy5zaGFwZXMpIHtcbiAgICAgIGlmIChKU09OLnN0cmluZ2lmeShzaGFwZS5maWxlTmFtZSkgPT09IEpTT04uc3RyaW5naWZ5KHRoaXMuaG9zdC5maWxlTmFtZSgpKSkge1xuICAgICAgICBzaGFwZS5sYWJlbCA9IHNob3dMYWJlbFxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICB0ZXh0OiBgJHtzaGFwZS5sZWdlbmR9YCxcbiAgICAgICAgICAgICAgdGV4dHRlbXBsYXRlOiBgJHtzaGFwZS5sZWdlbmR9YCxcbiAgICAgICAgICAgICAgdGV4dHBvc2l0aW9uOiAndG9wIGxlZnQnLFxuICAgICAgICAgICAgICBmb250OiB7IGNvbG9yOiBgJHtzaGFwZS5saW5lLmNvbG9yfWAgfSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICA6IHt9O1xuICAgICAgICBzaGFwZXNUb1JlZHJhdy5wdXNoKHNoYXBlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gY29udmVydCB0byBkaWN0IHNvIHRoYXQgcGxvdGx5IHJlY29nbmlzZXMgdGhlIHNoYXBlc1xuICAgIHJldHVybiBzaGFwZXNUb1JlZHJhdy5tYXAoKHMpID0+ICh7IC4uLnMgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZvbGxvdyB0aGUgc2hhcmVkIHN0b3JlOiByZWRyYXcgdGhlIHNoYXBlcyBvbiBldmVyeSByZWdpb24gdXBkYXRlIGFuZCBtb3ZlXG4gICAqIHRoZSBlZGl0IGhhbmRsZXMgb24gZXZlcnkgc2VsZWN0aW9uIGNoYW5nZSwgd2hvZXZlciBtYWRlIHRoZSBjaGFuZ2UgKHRoZVxuICAgKiByb3V0ZXIsIGFuIHVuZG8sIHRoZSBSZWdpb24gRWRpdG9yLCBhbm90aGVyIGJhY2tlbmQncyBvdmVybGF5LCBhIGNhbnZhc1xuICAgKiB0b29sKS4gUGxvdGx5IGlzIG5vdCBvbiB0aGUgc3RvcmUncyB3cml0ZSBwYXRoIGFueSBtb3JlIOKAlCBpdCBsaXN0ZW5zLCBsaWtlXG4gICAqIHRoZSBPcGVuU2VhZHJhZ29uIGFuZCBuYXBhcmktanMgb3ZlcmxheXMgZG8uIFNlcnZpY2UtbGlmZXRpbWU6IGJvdGhcbiAgICogY2FsbGJhY2tzIG5vLW9wIHdoaWxlIG5vIGxpdmUgUGxvdGx5IGdyYXBoIGhvbGRzIHRoZSBkaXYuXG4gICAqL1xuICBjb25uZWN0KCk6IFN1YnNjcmlwdGlvbiB7XG4gICAgY29uc3Qgc3VicyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgICBzdWJzLmFkZCh0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvblVwZGF0ZUV2ZW50KCkuc3Vic2NyaWJlKChyZWdpb25zKSA9PiB0aGlzLm9uUmVnaW9uVXBkYXRlKHJlZ2lvbnMpKSk7XG4gICAgc3Vicy5hZGQodGhpcy5yZWdpb25TdG9yZS5nZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyQoKS5zdWJzY3JpYmUoKGluZGljZXMpID0+IHRoaXMub25TZWxlY3Rpb24oaW5kaWNlcykpKTtcbiAgICByZXR1cm4gc3VicztcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gYHdyaXRlYCDigJQgYSBzdG9yZSB3cml0ZSB0aGlzIHByb2plY3Rpb24gYWxyZWFkeSByZWZsZWN0cyAoYSBzaGFwZSBlZGl0ZWRcbiAgICogb24gdGhlIGNhbnZhcywgYW4gaW1hZ2Ugc3dpdGNoIHRoZSBuZXh0IHBsb3QgZHJhd3MpIOKAlCB3aXRob3V0IHJlZHJhd2luZyBmcm9tXG4gICAqIHRoZSB1cGRhdGUgZXZlbnQgaXQgY2F1c2VzLlxuICAgKi9cbiAgcXVpZXRseSh3cml0ZTogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMubXV0ZWQrKztcbiAgICB0cnkge1xuICAgICAgd3JpdGUoKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5tdXRlZC0tO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBIHJlZ2lvbiB1cGRhdGUuIFRoZSBzdG9yZWQgc2V0IHJlLXByb2plY3RzIGFuZCByZWRyYXdzOyBhIHRyYW5zaWVudCBzZXRcbiAgICogKGBzZXRSZWdpb25zKOKApiwgaXNSZWdpb25TYXZlT24gPSBmYWxzZSlgLCB3aGljaCB0aGUgc3RvcmUgZW1pdHMgd2l0aG91dFxuICAgKiBzdG9yaW5nKSBpcyBkcmF3biBhcy1pcyBhbmQgbGVhdmVzIHRoZSB3b3JraW5nLXNldCBhbG9uZS5cbiAgICovXG4gIHByaXZhdGUgb25SZWdpb25VcGRhdGUocmVnaW9uczogUmVnaW9uW10pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5tdXRlZCA+IDApIHJldHVybjtcbiAgICBjb25zdCBzdG9yZWQgPSB0aGlzLnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKTtcbiAgICBjb25zdCBpc1N0b3JlZCA9IHJlZ2lvbnMubGVuZ3RoID09PSBzdG9yZWQubGVuZ3RoICYmIHJlZ2lvbnMuZXZlcnkoKHIsIGkpID0+IHIgPT09IHN0b3JlZFtpXSk7XG4gICAgaWYgKGlzU3RvcmVkKSB7XG4gICAgICB0aGlzLnN5bmNGcm9tU3RvcmUoKTtcbiAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGdkID0gdGhpcy5saXZlR2QoKTtcbiAgICBpZiAoIWdkKSByZXR1cm47XG4gICAgY29uc3Qgc2hvd0xhYmVsID0gdGhpcy5yZWdpb25TdG9yZS5nZXRTaG93U2hhcGVMYWJlbCgpO1xuICAgIGNvbnN0IGRpY3RzID0gcmVnaW9ucy5tYXAoKHIpID0+IHtcbiAgICAgIHIuZmlsZW5hbWUgPSB0aGlzLmhvc3QuZmlsZU5hbWUoKTtcbiAgICAgIHJldHVybiB7IC4uLnIuZ2V0U2hhcGUoc2hvd0xhYmVsKSB9O1xuICAgIH0pO1xuICAgIHZvaWQgUGxvdGx5LnJlbGF5b3V0KGdkLCB0aGlzLnJlbGF5b3V0UGF5bG9hZChkaWN0cykgYXMgUGxvdGx5LkxheW91dCk7XG4gIH1cblxuICAvKipcbiAgICogQSBzZWxlY3Rpb24gY2hhbmdlOiBQbG90bHkncyBgX2FjdGl2ZVNoYXBlSW5kZXhgIHBvaW50cyBhdCB0aGUgbGFzdCBzZWxlY3RlZFxuICAgKiBzaGFwZSBzbyBpdCBnZXRzIHRoZSBlZGl0IGhhbmRsZXMgKFBsb3RseSdzIG93biBhY3RpdmUtc2hhcGUgcmVuZGVyaW5nIGlzIHRoZVxuICAgKiBvbmx5IGhpZ2hsaWdodCkuIFNraXBwZWQgd2hlbiB0aGUgcGxvdCBhbHJlYWR5IHNob3dzIGl0IOKAlCB0aGUgY2hhbmdlIGNhbWVcbiAgICogZnJvbSBhIGNsaWNrIG9uIHRoZSBwbG90ICh7QGxpbmsgc3luY1NlbGVjdGlvbkZyb21QbG90fSkuXG4gICAqL1xuICBwcml2YXRlIG9uU2VsZWN0aW9uKGluZGljZXM6IG51bWJlcltdKTogdm9pZCB7XG4gICAgY29uc3QgZ2QgPSB0aGlzLmxpdmVHZCgpO1xuICAgIGlmICghZ2QpIHJldHVybjtcbiAgICBjb25zdCBhY3RpdmUgPSBpbmRpY2VzLmxlbmd0aCA+IDAgPyBpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV0gOiAtMTtcbiAgICBpZiAoKGdkLl9mdWxsTGF5b3V0IS5fYWN0aXZlU2hhcGVJbmRleCA/PyAtMSkgPT09IGFjdGl2ZSkgcmV0dXJuO1xuICAgIGdkLl9mdWxsTGF5b3V0IS5fYWN0aXZlU2hhcGVJbmRleCA9IGFjdGl2ZTtcbiAgICB0cnkge1xuICAgICAgdm9pZCBQbG90bHkucmVkcmF3KGdkKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8qIG5vb3AgaW4gdGVzdHMgKi9cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVhZCBQbG90bHkncyBgX2FjdGl2ZVNoYXBlSW5kZXhgIGFuZCBwdXNoIGl0IGFzIHRoZSBzZWxlY3Rpb24uIFBsb3RseSBmaXJlc1xuICAgKiBubyBkZWRpY2F0ZWQgYWN0aXZlLXNoYXBlIGV2ZW50IGZvciBjbGlja3MsIHNvIHRoaXMgaXMgc2FtcGxlZCBhZnRlciBhXG4gICAqIHJlbGF5b3V0IGFuZCBhIGNsaWNrLiBUaGUgc3RvcmUgbm8tb3BzIHdoZW4gdGhlIHNlbGVjdGlvbiBpcyB1bmNoYW5nZWQuXG4gICAqL1xuICBzeW5jU2VsZWN0aW9uRnJvbVBsb3QoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmhvc3QucGxvdERpdigpKSByZXR1cm47XG4gICAgY29uc3QgcmF3ID0gdGhpcy5nZCgpPy5fZnVsbExheW91dD8uX2FjdGl2ZVNoYXBlSW5kZXg7XG4gICAgY29uc3QgaWR4ID0gdHlwZW9mIHJhdyA9PT0gJ251bWJlcicgJiYgcmF3ID49IDAgJiYgcmF3IDwgdGhpcy5zaGFwZXMubGVuZ3RoID8gcmF3IDogLTE7XG4gICAgdGhpcy5yZWdpb25TdG9yZS5zZXRTZWxlY3RlZFNoYXBlSW5kaWNlcyhpZHggPj0gMCA/IFtpZHhdIDogW10pO1xuICB9XG5cbiAgLyoqIFRoZSBzaGFwZXMtcmVsYXlvdXQgcGF5bG9hZDogdGhlIHNoYXBlcyBwbHVzIHRoZSBhY3RpdmUtc2hhcGUgZmlsbCBjb2xvdXIuICovXG4gIHByaXZhdGUgcmVsYXlvdXRQYXlsb2FkKHNoYXBlRGljdHM6IGFueVtdKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICAgIHJldHVybiB7IHNoYXBlczogc2hhcGVEaWN0cywgYWN0aXZlc2hhcGU6IHsgZmlsbGNvbG9yOiB0aGlzLnJlZ2lvblN0b3JlLmdldEZpbGxDb2xvcigpIH0gfTtcbiAgfVxufVxuIl19