@jax-data-science/sci-image-visualizer 0.8.3 → 0.10.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 (579) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +34 -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/image.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  13. package/esm2022/lib/contracts/intensity.mjs +48 -5
  14. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  15. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  16. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  17. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  18. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  19. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  20. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  21. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  25. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  26. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  28. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  29. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  30. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  31. package/esm2022/lib/geometry/contour.mjs +63 -0
  32. package/esm2022/lib/geometry/loft.mjs +128 -0
  33. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  34. package/esm2022/lib/geometry/raster.mjs +98 -0
  35. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  36. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  37. package/esm2022/lib/geometry/ring.mjs +201 -0
  38. package/esm2022/lib/geometry/section.mjs +215 -0
  39. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  40. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  41. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  42. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  43. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  45. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +12 -9
  46. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +83 -0
  47. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  48. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +180 -591
  49. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  50. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  51. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  52. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  53. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +270 -0
  54. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  55. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  56. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  57. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  58. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  59. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +347 -0
  60. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +427 -4207
  61. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  62. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +550 -0
  63. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  64. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  65. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  66. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  67. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +194 -0
  68. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  69. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  70. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  71. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  72. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  73. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  74. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  75. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  76. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  77. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  78. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  79. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  80. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  81. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  82. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  83. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  84. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  85. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  86. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +164 -0
  87. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +213 -716
  88. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  89. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  90. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  91. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  92. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  93. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  94. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  95. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  96. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  97. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  98. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  99. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  100. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  101. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  102. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  103. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  104. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  105. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  106. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  107. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  108. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  109. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  110. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  111. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  112. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  113. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  114. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  115. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  116. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  117. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  118. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  119. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  120. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  121. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  122. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  123. package/esm2022/lib/models/bezier.mjs +1 -11
  124. package/esm2022/lib/models/class-preset.mjs +41 -3
  125. package/esm2022/lib/models/geometry.mjs +27 -164
  126. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  127. package/esm2022/lib/models/polygon-factory.mjs +134 -0
  128. package/esm2022/lib/models/region-clone.mjs +68 -0
  129. package/esm2022/lib/models/region-geojson.mjs +411 -0
  130. package/esm2022/lib/models/region.mjs +34 -33
  131. package/esm2022/lib/models/shape.mjs +18 -16
  132. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  133. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  134. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  135. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  136. package/esm2022/lib/plot.utilities.mjs +296 -473
  137. package/esm2022/lib/processing/image-crop.mjs +1 -1
  138. package/esm2022/lib/processing/processing-image.mjs +28 -15
  139. package/esm2022/lib/provide-visualization.mjs +40 -14
  140. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  141. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  142. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +163 -0
  143. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  144. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  145. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  146. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  147. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  148. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  149. package/esm2022/lib/region-editor/region-editor.component.mjs +896 -660
  150. package/esm2022/lib/region-editor/region-metrics.mjs +86 -0
  151. package/esm2022/lib/region-editor/region-persistence.service.mjs +160 -0
  152. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +169 -0
  153. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  154. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  155. package/esm2022/lib/region-ops.service.mjs +28 -70
  156. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  157. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  158. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  159. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  160. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  161. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  162. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  163. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  164. package/esm2022/lib/region-source/region-source.mjs +67 -0
  165. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  166. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  167. package/esm2022/lib/render-orchestrator.mjs +14 -11
  168. package/esm2022/lib/render-session.mjs +207 -0
  169. package/esm2022/lib/routing-visualizer.service.mjs +858 -414
  170. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  171. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  172. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  173. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  174. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  175. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  176. package/esm2022/lib/spatial/lod.mjs +187 -0
  177. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  178. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  179. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  180. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  181. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  182. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  183. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  184. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  185. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  186. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  187. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  188. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  189. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  190. package/esm2022/lib/spatial/stats.mjs +71 -0
  191. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  192. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  193. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  194. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  195. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  196. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  197. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  198. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  199. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  200. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  201. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  202. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  203. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  204. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  205. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  206. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  207. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  208. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  209. package/esm2022/lib/store/class-color.util.mjs +53 -5
  210. package/esm2022/lib/store/class-signatures.mjs +63 -0
  211. package/esm2022/lib/store/region-history.mjs +146 -0
  212. package/esm2022/lib/store/region-scope-cache.mjs +144 -0
  213. package/esm2022/lib/store/region-selection.mjs +82 -0
  214. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  215. package/esm2022/lib/store/region-store.service.mjs +986 -670
  216. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  217. package/esm2022/lib/store/visualizer-store.service.mjs +81 -76
  218. package/esm2022/lib/toast-outlets.mjs +5 -4
  219. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  220. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  221. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  222. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  223. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  224. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +120 -0
  225. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  226. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  227. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  228. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  229. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  230. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  231. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  232. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  233. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  234. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  235. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  236. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  237. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  238. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +121 -0
  239. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  240. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  241. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  242. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  243. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  244. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  245. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  246. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  247. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  248. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  249. package/esm2022/lib/toolbar/toolbar.component.mjs +84 -119
  250. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  251. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  252. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  253. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  254. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  255. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  256. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  257. package/esm2022/lib/util/supersede.mjs +56 -0
  258. package/esm2022/lib/visualization.module.mjs +39 -141
  259. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  260. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  261. package/esm2022/lib/visualizer/region-load.mjs +123 -0
  262. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  263. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  264. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  265. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  266. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  267. package/esm2022/lib/visualizer.component.mjs +602 -1902
  268. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  269. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  270. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  271. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs +47169 -0
  272. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  273. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs +238 -0
  274. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map +1 -0
  275. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  276. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  277. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  278. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  279. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  280. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  281. package/fesm2022/mask.worker.js +36 -917
  282. package/fesm2022/onnx-sam.worker.js +52 -16
  283. package/fesm2022/region-source.worker.js +1067 -0
  284. package/fesm2022/spatial-math.worker.js +471 -0
  285. package/fesm2022/tsne.worker.js +32 -15
  286. package/index.d.ts +19 -10
  287. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  288. package/lib/contracts/capabilities.contract.d.ts +4 -2
  289. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  290. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  291. package/lib/contracts/color.d.ts +27 -0
  292. package/lib/contracts/colormap-lut.d.ts +19 -4
  293. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  294. package/lib/contracts/display-types.d.ts +21 -0
  295. package/lib/contracts/image.contract.d.ts +4 -0
  296. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  297. package/lib/contracts/intensity.d.ts +13 -2
  298. package/lib/contracts/plot-type.d.ts +3 -1
  299. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  300. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  301. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  302. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  303. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  304. package/lib/contracts/region-editor-api.contract.d.ts +85 -1
  305. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  306. package/lib/contracts/region-store.contract.d.ts +22 -0
  307. package/lib/contracts/sam.contract.d.ts +7 -0
  308. package/lib/contracts/section-view.contract.d.ts +44 -0
  309. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  310. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  311. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  312. package/lib/contracts/visualizer.contract.d.ts +231 -54
  313. package/lib/contracts/viz-config.d.ts +9 -0
  314. package/lib/geometry/contour.d.ts +24 -0
  315. package/lib/geometry/loft.d.ts +22 -0
  316. package/lib/geometry/polylabel.d.ts +23 -0
  317. package/lib/geometry/raster.d.ts +42 -0
  318. package/lib/geometry/reconstruct.d.ts +54 -0
  319. package/lib/geometry/reslice-image.d.ts +33 -0
  320. package/lib/geometry/ring.d.ts +67 -0
  321. package/lib/geometry/section.d.ts +52 -0
  322. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  323. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  324. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  325. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  326. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  327. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  328. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -3
  329. package/lib/implementations/napari-js/napari-loading-state.d.ts +37 -0
  330. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  331. package/lib/implementations/napari-js/napari-region-overlay.d.ts +68 -71
  332. package/lib/implementations/napari-js/napari-scene.d.ts +126 -0
  333. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  334. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  335. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  336. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +91 -0
  337. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  338. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  339. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  340. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  341. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  342. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  343. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +169 -883
  344. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  345. package/lib/implementations/napari-js/napari-volume-scene.d.ts +148 -0
  346. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  347. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  348. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  349. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  350. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  351. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  352. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  353. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  354. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  355. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  356. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  357. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  358. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  359. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  360. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  361. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  362. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  363. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  364. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  365. package/lib/implementations/osd/osd-export.d.ts +36 -0
  366. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  367. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  368. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  369. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +38 -0
  370. package/lib/implementations/osd/osd-region-overlay.d.ts +46 -51
  371. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  372. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  373. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  374. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  375. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  376. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  377. package/lib/implementations/osd/simple-source.d.ts +161 -0
  378. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  379. package/lib/implementations/osd/tile-client.d.ts +11 -14
  380. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  381. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  382. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  383. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  384. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  385. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  386. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  387. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  388. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  389. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  390. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  391. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  392. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  393. package/lib/implementations/region-centroids.d.ts +14 -0
  394. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  395. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  396. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  397. package/lib/implementations/tile-server/index.d.ts +5 -0
  398. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  399. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  400. package/lib/implementations/tile-server/tile-protocol.d.ts +83 -0
  401. package/lib/implementations/tile-server/transport.d.ts +62 -0
  402. package/lib/intensity/intensity-profile.d.ts +66 -0
  403. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  404. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  405. package/lib/models/bezier.d.ts +0 -5
  406. package/lib/models/class-preset.d.ts +25 -0
  407. package/lib/models/geometry.d.ts +14 -48
  408. package/lib/models/polygon-edit.d.ts +72 -0
  409. package/lib/models/polygon-factory.d.ts +45 -0
  410. package/lib/models/region-clone.d.ts +20 -0
  411. package/lib/models/region-geojson.d.ts +57 -0
  412. package/lib/models/region.d.ts +59 -4
  413. package/lib/models/shape.d.ts +8 -0
  414. package/lib/plot-mode/contribution-host.d.ts +125 -0
  415. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  416. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  417. package/lib/plot.utilities.d.ts +19 -30
  418. package/lib/processing/processing-image.d.ts +5 -2
  419. package/lib/provide-visualization.d.ts +19 -2
  420. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  421. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  422. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +86 -0
  423. package/lib/region-editor/file-stem.d.ts +7 -0
  424. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  425. package/lib/region-editor/mask-export.service.d.ts +54 -0
  426. package/lib/region-editor/mask-raster.d.ts +2 -8
  427. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  428. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  429. package/lib/region-editor/region-editor.component.d.ts +283 -200
  430. package/lib/region-editor/region-metrics.d.ts +34 -0
  431. package/lib/region-editor/region-persistence.service.d.ts +77 -0
  432. package/lib/region-editor/region-table/region-table.component.d.ts +89 -0
  433. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  434. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  435. package/lib/region-ops.service.d.ts +1 -7
  436. package/lib/region-overlay/region-geometry.d.ts +158 -0
  437. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  438. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  439. package/lib/region-overlay/region-style.d.ts +52 -0
  440. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  441. package/lib/region-source/http-region-source.d.ts +45 -0
  442. package/lib/region-source/region-source-ops.d.ts +89 -0
  443. package/lib/region-source/region-source-worker.d.ts +7 -0
  444. package/lib/region-source/region-source.d.ts +82 -0
  445. package/lib/region-source/region-tiles.d.ts +289 -0
  446. package/lib/region-source/worker-region-source.d.ts +65 -0
  447. package/lib/render-orchestrator.d.ts +6 -2
  448. package/lib/render-session.d.ts +75 -0
  449. package/lib/routing-visualizer.service.d.ts +248 -59
  450. package/lib/section-pane/section-pane.component.d.ts +47 -0
  451. package/lib/spatial/density-raster.d.ts +6 -0
  452. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  453. package/lib/spatial/embedding-compute.d.ts +21 -2
  454. package/lib/spatial/glyphs.d.ts +16 -0
  455. package/lib/spatial/lod.d.ts +94 -0
  456. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  457. package/lib/spatial/spatial-density.d.ts +15 -5
  458. package/lib/spatial/spatial-encoding.d.ts +11 -44
  459. package/lib/spatial/spatial-expression.d.ts +40 -22
  460. package/lib/spatial/spatial-framing.d.ts +1 -0
  461. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  462. package/lib/spatial/spatial-hover.d.ts +4 -16
  463. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  464. package/lib/spatial/spatial-selection.d.ts +21 -26
  465. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  466. package/lib/spatial/spatial-tiles.d.ts +9 -256
  467. package/lib/spatial/stats.d.ts +38 -0
  468. package/lib/spatial/transcript-grouping.d.ts +119 -0
  469. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  470. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  471. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  472. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  473. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  474. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  475. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  476. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  477. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  478. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  479. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  480. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  481. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  482. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  483. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  484. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  485. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  486. package/lib/store/class-color.util.d.ts +39 -2
  487. package/lib/store/class-signatures.d.ts +11 -0
  488. package/lib/store/region-history.d.ts +66 -0
  489. package/lib/store/region-scope-cache.d.ts +65 -0
  490. package/lib/store/region-selection.d.ts +36 -0
  491. package/lib/store/region-source-scope.d.ts +68 -0
  492. package/lib/store/region-store.service.d.ts +312 -116
  493. package/lib/store/visualizer-store.service.d.ts +32 -33
  494. package/lib/toast-outlets.d.ts +4 -3
  495. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  496. package/lib/toolbar/canvas-tools.d.ts +20 -0
  497. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  498. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  499. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  500. package/lib/toolbar/region-tools/region-tools.component.d.ts +62 -0
  501. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  502. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  503. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  504. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  505. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  506. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  507. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  508. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  509. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  510. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  511. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  512. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  513. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  514. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +51 -0
  515. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  516. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  517. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  518. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  519. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  520. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  521. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  522. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  523. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  524. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  525. package/lib/toolbar/toolbar.component.d.ts +55 -84
  526. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  527. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  528. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  529. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  530. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  531. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  532. package/lib/util/mark-for-check.d.ts +11 -0
  533. package/lib/util/supersede.d.ts +53 -0
  534. package/lib/visualization.module.d.ts +18 -39
  535. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  536. package/lib/visualizer/region-actions.d.ts +54 -0
  537. package/lib/visualizer/region-load.d.ts +46 -0
  538. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  539. package/lib/visualizer/tool-modes.d.ts +49 -0
  540. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  541. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  542. package/lib/visualizer/volume-sections.d.ts +64 -0
  543. package/lib/visualizer.component.d.ts +232 -447
  544. package/lib/workers/spatial-math-ops.d.ts +65 -0
  545. package/lib/workers/spatial-math-worker.d.ts +7 -0
  546. package/lib/workers/spatial-math.d.ts +74 -0
  547. package/package.json +12 -3
  548. package/src/lib/assets/slice.svg +23 -0
  549. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  550. package/src/lib/styles/viz-icons.scss +14 -0
  551. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  552. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  553. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  554. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  555. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  556. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  557. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  558. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  559. package/src/lib/assets/cell-detection.svg +0 -37
  560. package/src/lib/assets/click.svg +0 -1
  561. package/src/lib/assets/colormap-luts.json +0 -1
  562. package/src/lib/assets/edit-selection-white.svg +0 -47
  563. package/src/lib/assets/icons/colormap-earth.png +0 -0
  564. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  565. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  566. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  567. package/src/lib/assets/picture-segmentation.svg +0 -43
  568. package/src/lib/assets/test/download-379.svg +0 -1
  569. package/src/lib/assets/test/download-98.svg +0 -1
  570. package/src/lib/assets/test/json-1.svg +0 -1
  571. package/src/lib/assets/test/load-53.svg +0 -1
  572. package/src/lib/assets/test/mask-44.svg +0 -1
  573. package/src/lib/assets/test/mask-download-44.svg +0 -15
  574. package/src/lib/assets/test/mask-save-44.svg +0 -11
  575. package/src/lib/assets/test/overlay-1.svg +0 -1
  576. package/src/lib/assets/test/overlay-4.svg +0 -1
  577. package/src/lib/assets/test/region-26.svg +0 -1
  578. package/src/lib/assets/test/save-56.svg +0 -1
  579. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Level-of-detail planning for tiled spatial geometry — cell outlines and transcripts.
3
+ *
4
+ * The renderer knows its camera (a world-space centre, a zoom in canvas pixels per world
5
+ * unit, a canvas size); a tiled dataset knows its grids (one per level, in observation
6
+ * units). This module is the bridge: which level the zoom calls for and which tiles are on
7
+ * screen. Everything here is pure, so the policy — the part that decides whether the view
8
+ * is fast and legible — is testable without a GPU.
9
+ *
10
+ * Observation units map onto world units through the dataset's `imageRef` affine
11
+ * (`world = data · scale + translate`), so "pixels per observation unit" is
12
+ * `zoom · scale`. For a Xenium bundle the data unit is the micron and the world unit the
13
+ * morphology pixel.
14
+ */
15
+ import { worldViewport } from 'napari-js';
16
+ import { quantile } from './stats';
17
+ // ── What the view draws ───────────────────────────────────────────────────────────────
18
+ /** Whether cell outlines are drawn: the user's choice, else on when the dataset has any. */
19
+ export function cellsShown(dataset, view) {
20
+ const available = !!(dataset?.polygonTiles || dataset?.polygons);
21
+ return available && (view.showCells ?? true);
22
+ }
23
+ /** A column holding a hand-curated cell-type annotation, by naming convention. */
24
+ export function isCuratedColumn(name) {
25
+ return /curated/i.test(name);
26
+ }
27
+ /**
28
+ * The categorical column that names each cell's type: the view's choice when it is a
29
+ * column of this dataset, else the first categorical column that is not a curated
30
+ * annotation (a pipeline's clustering is the default; curation is opted into), else
31
+ * any categorical column.
32
+ */
33
+ export function cellTypeColumnFor(dataset, view) {
34
+ const categorical = dataset.columns.filter((c) => c.kind === 'categorical');
35
+ if (view.cellTypeColumn && categorical.some((c) => c.name === view.cellTypeColumn)) {
36
+ return view.cellTypeColumn;
37
+ }
38
+ return (categorical.find((c) => !isCuratedColumn(c.name)) ?? categorical[0])?.name ?? null;
39
+ }
40
+ // ── Tiles in view ─────────────────────────────────────────────────────────────────────
41
+ /** A stable string id for a tile key, `level/gx/gy` — usable as a Map key. */
42
+ export function tileId(k) {
43
+ return `${k.level}/${k.gx}/${k.gy}`;
44
+ }
45
+ /** Canvas pixels per observation unit along x, for a camera zoom and a data→world affine. */
46
+ export function pixelsPerDataUnit(zoom, ref) {
47
+ return zoom * Math.abs(ref?.scale?.[0] ?? 1);
48
+ }
49
+ /**
50
+ * The part of observation space the camera shows, padded by `margin` (a fraction of the
51
+ * viewport) so tiles just off screen are already there when a pan brings them in: napari-js's
52
+ * `worldViewport`, mapped back through the inverse of the data→world affine.
53
+ */
54
+ export function visibleDataRect(center, zoom, canvasW, canvasH, ref, margin = 0.15) {
55
+ if (!(zoom > 0) || !(canvasW > 0) || !(canvasH > 0))
56
+ return null;
57
+ const sx = ref?.scale?.[0] ?? 1;
58
+ const sy = ref?.scale?.[1] ?? 1;
59
+ const tx = ref?.translate?.[0] ?? 0;
60
+ const ty = ref?.translate?.[1] ?? 0;
61
+ // The world rect of a canvas grown by the margin on each side (napari-js's worldViewport).
62
+ const v = worldViewport(center[0], center[1], zoom, canvasW * (1 + 2 * margin), canvasH * (1 + 2 * margin));
63
+ const wx0 = v.x;
64
+ const wx1 = v.x + v.width;
65
+ const wy0 = v.y;
66
+ const wy1 = v.y + v.height;
67
+ const ax = (wx0 - tx) / sx;
68
+ const bx = (wx1 - tx) / sx;
69
+ const ay = (wy0 - ty) / sy;
70
+ const by = (wy1 - ty) / sy;
71
+ return { x0: Math.min(ax, bx), y0: Math.min(ay, by), x1: Math.max(ax, bx), y1: Math.max(ay, by) };
72
+ }
73
+ /**
74
+ * Tiles of one level intersecting `rect`, clipped to the dataset's `bounds` (so zooming
75
+ * out over empty canvas does not ask for tiles that cannot exist). Ordered from the
76
+ * rectangle's centre outward, so the middle of the screen fills in first.
77
+ *
78
+ * Tile `g` covers `[g·s, (g+1)·s)`. The view's far edge is open — a tile starting exactly
79
+ * at `rect.x1` shows nothing — but the bounds' far edge is closed: the bounds are the
80
+ * extreme observations' coordinates, so one sits exactly on `bounds[2]`, in the tile
81
+ * starting there.
82
+ */
83
+ export function tilesInRect(rect, level, levels, bounds, limit = Infinity) {
84
+ const size = levels[level]?.tileSize;
85
+ if (!(size > 0))
86
+ return [];
87
+ let { x0, y0 } = rect;
88
+ // Last tile along an axis: the one before the open view edge, at most the closed bound's.
89
+ let gx1 = Math.ceil(rect.x1 / size) - 1;
90
+ let gy1 = Math.ceil(rect.y1 / size) - 1;
91
+ if (bounds) {
92
+ x0 = Math.max(x0, bounds[0]);
93
+ y0 = Math.max(y0, bounds[1]);
94
+ if (Math.min(rect.x1, bounds[2]) < x0 || Math.min(rect.y1, bounds[3]) < y0)
95
+ return [];
96
+ gx1 = Math.min(gx1, Math.floor(bounds[2] / size));
97
+ gy1 = Math.min(gy1, Math.floor(bounds[3] / size));
98
+ }
99
+ const gx0 = Math.floor(x0 / size);
100
+ const gy0 = Math.floor(y0 / size);
101
+ const cx = (rect.x0 + rect.x1) / 2 / size;
102
+ const cy = (rect.y0 + rect.y1) / 2 / size;
103
+ const out = [];
104
+ for (let gy = gy0; gy <= gy1; gy++) {
105
+ for (let gx = gx0; gx <= gx1; gx++)
106
+ out.push({ level, gx, gy });
107
+ }
108
+ out.sort((a, b) => (a.gx + 0.5 - cx) ** 2 + (a.gy + 0.5 - cy) ** 2 - ((b.gx + 0.5 - cx) ** 2 + (b.gy + 0.5 - cy) ** 2));
109
+ return out.length > limit ? out.slice(0, limit) : out;
110
+ }
111
+ /** {@link tilesInRect} for a grid whose tile (0, 0) starts at `origin`. */
112
+ export function tilesInRectFrom(origin, rect, level, levels, bounds, limit = Infinity) {
113
+ const [ox, oy] = origin;
114
+ const shifted = { x0: rect.x0 - ox, y0: rect.y0 - oy, x1: rect.x1 - ox, y1: rect.y1 - oy };
115
+ const b = bounds ? [bounds[0] - ox, bounds[1] - oy, bounds[2] - ox, bounds[3] - oy] : null;
116
+ return tilesInRect(shifted, level, levels, b, limit);
117
+ }
118
+ /** Area of `rect` inside `bounds` (the whole rect when there are none). */
119
+ export function visibleArea(rect, bounds) {
120
+ const x0 = bounds ? Math.max(rect.x0, bounds[0]) : rect.x0;
121
+ const y0 = bounds ? Math.max(rect.y0, bounds[1]) : rect.y0;
122
+ const x1 = bounds ? Math.min(rect.x1, bounds[2]) : rect.x1;
123
+ const y1 = bounds ? Math.min(rect.y1, bounds[3]) : rect.y1;
124
+ return Math.max(0, x1 - x0) * Math.max(0, y1 - y0);
125
+ }
126
+ // ── Levels ────────────────────────────────────────────────────────────────────────────
127
+ /**
128
+ * Typical cell diameter, in observation units, used to judge how large cells appear.
129
+ * Derived from the per-observation radius when there is one; 12 µm otherwise.
130
+ */
131
+ export function typicalCellDiameter(radius, fallback = 12) {
132
+ if (typeof radius === 'number')
133
+ return radius > 0 ? radius * 2 : fallback;
134
+ if (!radius?.length)
135
+ return fallback;
136
+ // The median of a sample is plenty — this sets a threshold, not a measurement.
137
+ const median = quantile(radius, 0.5, { filter: 'positive', sampleSize: 2048 });
138
+ return median === null ? fallback : median * 2;
139
+ }
140
+ /**
141
+ * On-screen cell diameter (px) at or above which each polygon level is used. A level
142
+ * halves the vertices of the one below, so each should take over when the cell is about
143
+ * half as large on screen. Below the last finite threshold outlines are not drawn at
144
+ * all — a cell a few pixels wide is a dot, and the observation markers already draw it
145
+ * as one.
146
+ *
147
+ * Xenium's fourth level (3 vertices per cell) is deliberately never used: seen on
148
+ * screen it is a field of triangles, which reads as an artefact rather than as cells.
149
+ * The dots below 8 px say the same thing more honestly.
150
+ */
151
+ export const POLYGON_LEVEL_MIN_CELL_PX = [36, 18, 8, Infinity];
152
+ /**
153
+ * Which polygon level suits this zoom, or -1 for "too small to outline".
154
+ * `detail` > 1 prefers finer levels (sharper, slower); < 1 coarser.
155
+ */
156
+ export function polygonLevelFor(pxPerUnit, cellDiameter, levelCount, detail = 1) {
157
+ const cellPx = pxPerUnit * cellDiameter * detail;
158
+ const table = POLYGON_LEVEL_MIN_CELL_PX;
159
+ for (let l = 0; l < levelCount; l++) {
160
+ // Past the table, keep halving: each level still halves the vertices.
161
+ const min = table[l] ?? table[table.length - 1] / 2 ** (l - table.length + 1);
162
+ if (cellPx >= min)
163
+ return l;
164
+ }
165
+ return -1;
166
+ }
167
+ /**
168
+ * Which transcript level suits this zoom: the one whose tiles come out closest to
169
+ * `targetTilePx` on screen. Coarser levels aggregate more, so this keeps the number of
170
+ * markers per screen roughly constant however far out the camera is — the property that
171
+ * keeps the view fast.
172
+ */
173
+ export function transcriptLevelFor(pxPerUnit, levels, targetTilePx = 512) {
174
+ if (!levels.length || !(pxPerUnit > 0))
175
+ return 0;
176
+ let best = 0;
177
+ let bestErr = Infinity;
178
+ for (let l = 0; l < levels.length; l++) {
179
+ const err = Math.abs(Math.log2((levels[l].tileSize * pxPerUnit) / targetTilePx));
180
+ if (err < bestErr) {
181
+ bestErr = err;
182
+ best = l;
183
+ }
184
+ }
185
+ return best;
186
+ }
187
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9zcGF0aWFsL2xvZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7OztHQWFHO0FBRUgsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVMxQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBaUJuQyx5RkFBeUY7QUFFekYsNEZBQTRGO0FBQzVGLE1BQU0sVUFBVSxVQUFVLENBQ3hCLE9BQWlFLEVBQ2pFLElBQXlDO0lBRXpDLE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxZQUFZLElBQUksT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2pFLE9BQU8sU0FBUyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsQ0FBQztBQUMvQyxDQUFDO0FBRUQsa0ZBQWtGO0FBQ2xGLE1BQU0sVUFBVSxlQUFlLENBQUMsSUFBWTtJQUMxQyxPQUFPLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDL0IsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixPQUF1QixFQUN2QixJQUE4QztJQUU5QyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxhQUFhLENBQUMsQ0FBQztJQUM1RSxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUNuRixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU8sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLElBQUksSUFBSSxDQUFDO0FBQzdGLENBQUM7QUFFRCx5RkFBeUY7QUFFekYsOEVBQThFO0FBQzlFLE1BQU0sVUFBVSxNQUFNLENBQUMsQ0FBVTtJQUMvQixPQUFPLEdBQUcsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRUQsNkZBQTZGO0FBQzdGLE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxJQUFZLEVBQUUsR0FBNEI7SUFDMUUsT0FBTyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUM3QixNQUFpQyxFQUNqQyxJQUFZLEVBQ1osT0FBZSxFQUNmLE9BQWUsRUFDZixHQUE0QixFQUM1QixNQUFNLEdBQUcsSUFBSTtJQUViLElBQUksQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDakUsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQywyRkFBMkY7SUFDM0YsTUFBTSxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLEVBQUUsT0FBTyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzVHLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDO0lBQzFCLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzNCLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUMzQixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzNCLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUMzQixPQUFPLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDcEcsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQ3pCLElBQWMsRUFDZCxLQUFhLEVBQ2IsTUFBbUMsRUFDbkMsTUFBNkIsRUFDN0IsS0FBSyxHQUFHLFFBQVE7SUFFaEIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLFFBQVEsQ0FBQztJQUNyQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDM0IsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDdEIsMEZBQTBGO0lBQzFGLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDeEMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4QyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ1gsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUU7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN0RixHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNsRCxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQzFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUMxQyxNQUFNLEdBQUcsR0FBYyxFQUFFLENBQUM7SUFDMUIsS0FBSyxJQUFJLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ25DLEtBQUssSUFBSSxFQUFFLEdBQUcsR0FBRyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFBRSxFQUFFO1lBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsR0FBRyxDQUFDLElBQUksQ0FDTixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FDOUcsQ0FBQztJQUNGLE9BQU8sR0FBRyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7QUFDeEQsQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxNQUFNLFVBQVUsZUFBZSxDQUM3QixNQUFpQyxFQUNqQyxJQUFjLEVBQ2QsS0FBYSxFQUNiLE1BQW1DLEVBQ25DLE1BQTZCLEVBQzdCLEtBQUssR0FBRyxRQUFRO0lBRWhCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDO0lBQ3hCLE1BQU0sT0FBTyxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUM7SUFDM0YsTUFBTSxDQUFDLEdBQXlCLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNqSCxPQUFPLFdBQVcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDdkQsQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxNQUFNLFVBQVUsV0FBVyxDQUFDLElBQWMsRUFBRSxNQUE2QjtJQUN2RSxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUMzRCxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUMzRCxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUMzRCxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUMzRCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7QUFDckQsQ0FBQztBQUVELHlGQUF5RjtBQUV6Rjs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsTUFBeUMsRUFBRSxRQUFRLEdBQUcsRUFBRTtJQUMxRixJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVE7UUFBRSxPQUFPLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztJQUMxRSxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU07UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUNyQywrRUFBK0U7SUFDL0UsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQy9FLE9BQU8sTUFBTSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBQ2pELENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztBQUUvRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUFDLFNBQWlCLEVBQUUsWUFBb0IsRUFBRSxVQUFrQixFQUFFLE1BQU0sR0FBRyxDQUFDO0lBQ3JHLE1BQU0sTUFBTSxHQUFHLFNBQVMsR0FBRyxZQUFZLEdBQUcsTUFBTSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLHlCQUF5QixDQUFDO0lBQ3hDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNwQyxzRUFBc0U7UUFDdEUsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlFLElBQUksTUFBTSxJQUFJLEdBQUc7WUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBQ0QsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNaLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FDaEMsU0FBaUIsRUFDakIsTUFBbUMsRUFDbkMsWUFBWSxHQUFHLEdBQUc7SUFFbEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUNqRCxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFDYixJQUFJLE9BQU8sR0FBRyxRQUFRLENBQUM7SUFDdkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUN2QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDakYsSUFBSSxHQUFHLEdBQUcsT0FBTyxFQUFFLENBQUM7WUFDbEIsT0FBTyxHQUFHLEdBQUcsQ0FBQztZQUNkLElBQUksR0FBRyxDQUFDLENBQUM7UUFDWCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGV2ZWwtb2YtZGV0YWlsIHBsYW5uaW5nIGZvciB0aWxlZCBzcGF0aWFsIGdlb21ldHJ5IOKAlCBjZWxsIG91dGxpbmVzIGFuZCB0cmFuc2NyaXB0cy5cbiAqXG4gKiBUaGUgcmVuZGVyZXIga25vd3MgaXRzIGNhbWVyYSAoYSB3b3JsZC1zcGFjZSBjZW50cmUsIGEgem9vbSBpbiBjYW52YXMgcGl4ZWxzIHBlciB3b3JsZFxuICogdW5pdCwgYSBjYW52YXMgc2l6ZSk7IGEgdGlsZWQgZGF0YXNldCBrbm93cyBpdHMgZ3JpZHMgKG9uZSBwZXIgbGV2ZWwsIGluIG9ic2VydmF0aW9uXG4gKiB1bml0cykuIFRoaXMgbW9kdWxlIGlzIHRoZSBicmlkZ2U6IHdoaWNoIGxldmVsIHRoZSB6b29tIGNhbGxzIGZvciBhbmQgd2hpY2ggdGlsZXMgYXJlIG9uXG4gKiBzY3JlZW4uIEV2ZXJ5dGhpbmcgaGVyZSBpcyBwdXJlLCBzbyB0aGUgcG9saWN5IOKAlCB0aGUgcGFydCB0aGF0IGRlY2lkZXMgd2hldGhlciB0aGUgdmlld1xuICogaXMgZmFzdCBhbmQgbGVnaWJsZSDigJQgaXMgdGVzdGFibGUgd2l0aG91dCBhIEdQVS5cbiAqXG4gKiBPYnNlcnZhdGlvbiB1bml0cyBtYXAgb250byB3b3JsZCB1bml0cyB0aHJvdWdoIHRoZSBkYXRhc2V0J3MgYGltYWdlUmVmYCBhZmZpbmVcbiAqIChgd29ybGQgPSBkYXRhIMK3IHNjYWxlICsgdHJhbnNsYXRlYCksIHNvIFwicGl4ZWxzIHBlciBvYnNlcnZhdGlvbiB1bml0XCIgaXNcbiAqIGB6b29tIMK3IHNjYWxlYC4gRm9yIGEgWGVuaXVtIGJ1bmRsZSB0aGUgZGF0YSB1bml0IGlzIHRoZSBtaWNyb24gYW5kIHRoZSB3b3JsZCB1bml0IHRoZVxuICogbW9ycGhvbG9neSBwaXhlbC5cbiAqL1xuXG5pbXBvcnQgeyB3b3JsZFZpZXdwb3J0IH0gZnJvbSAnbmFwYXJpLWpzJztcblxuaW1wb3J0IHR5cGUge1xuICBTcGF0aWFsQm91bmRzLFxuICBTcGF0aWFsRGF0YXNldCxcbiAgU3BhdGlhbEltYWdlUmVmLFxuICBTcGF0aWFsVGlsZUxldmVsLFxufSBmcm9tICcuLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB0eXBlIHsgU3BhdGlhbFZpZXdTdGF0ZSB9IGZyb20gJy4uL2NvbnRyYWN0cy9kaXNwbGF5LXR5cGVzJztcbmltcG9ydCB7IHF1YW50aWxlIH0gZnJvbSAnLi9zdGF0cyc7XG5cbi8qKiBBIHJlY3RhbmdsZSBpbiBvYnNlcnZhdGlvbiBjb29yZGluYXRlcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YVJlY3Qge1xuICB4MDogbnVtYmVyO1xuICB5MDogbnVtYmVyO1xuICB4MTogbnVtYmVyO1xuICB5MTogbnVtYmVyO1xufVxuXG4vKiogVGlsZSBhZGRyZXNzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUaWxlS2V5IHtcbiAgbGV2ZWw6IG51bWJlcjtcbiAgZ3g6IG51bWJlcjtcbiAgZ3k6IG51bWJlcjtcbn1cblxuLy8g4pSA4pSAIFdoYXQgdGhlIHZpZXcgZHJhd3Mg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKiBXaGV0aGVyIGNlbGwgb3V0bGluZXMgYXJlIGRyYXduOiB0aGUgdXNlcidzIGNob2ljZSwgZWxzZSBvbiB3aGVuIHRoZSBkYXRhc2V0IGhhcyBhbnkuICovXG5leHBvcnQgZnVuY3Rpb24gY2VsbHNTaG93bihcbiAgZGF0YXNldDogUGljazxTcGF0aWFsRGF0YXNldCwgJ3BvbHlnb25UaWxlcycgfCAncG9seWdvbnMnPiB8IG51bGwsXG4gIHZpZXc6IFBpY2s8U3BhdGlhbFZpZXdTdGF0ZSwgJ3Nob3dDZWxscyc+LFxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGF2YWlsYWJsZSA9ICEhKGRhdGFzZXQ/LnBvbHlnb25UaWxlcyB8fCBkYXRhc2V0Py5wb2x5Z29ucyk7XG4gIHJldHVybiBhdmFpbGFibGUgJiYgKHZpZXcuc2hvd0NlbGxzID8/IHRydWUpO1xufVxuXG4vKiogQSBjb2x1bW4gaG9sZGluZyBhIGhhbmQtY3VyYXRlZCBjZWxsLXR5cGUgYW5ub3RhdGlvbiwgYnkgbmFtaW5nIGNvbnZlbnRpb24uICovXG5leHBvcnQgZnVuY3Rpb24gaXNDdXJhdGVkQ29sdW1uKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gL2N1cmF0ZWQvaS50ZXN0KG5hbWUpO1xufVxuXG4vKipcbiAqIFRoZSBjYXRlZ29yaWNhbCBjb2x1bW4gdGhhdCBuYW1lcyBlYWNoIGNlbGwncyB0eXBlOiB0aGUgdmlldydzIGNob2ljZSB3aGVuIGl0IGlzIGFcbiAqIGNvbHVtbiBvZiB0aGlzIGRhdGFzZXQsIGVsc2UgdGhlIGZpcnN0IGNhdGVnb3JpY2FsIGNvbHVtbiB0aGF0IGlzIG5vdCBhIGN1cmF0ZWRcbiAqIGFubm90YXRpb24gKGEgcGlwZWxpbmUncyBjbHVzdGVyaW5nIGlzIHRoZSBkZWZhdWx0OyBjdXJhdGlvbiBpcyBvcHRlZCBpbnRvKSwgZWxzZVxuICogYW55IGNhdGVnb3JpY2FsIGNvbHVtbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNlbGxUeXBlQ29sdW1uRm9yKFxuICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCxcbiAgdmlldzogUGljazxTcGF0aWFsVmlld1N0YXRlLCAnY2VsbFR5cGVDb2x1bW4nPixcbik6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBjYXRlZ29yaWNhbCA9IGRhdGFzZXQuY29sdW1ucy5maWx0ZXIoKGMpID0+IGMua2luZCA9PT0gJ2NhdGVnb3JpY2FsJyk7XG4gIGlmICh2aWV3LmNlbGxUeXBlQ29sdW1uICYmIGNhdGVnb3JpY2FsLnNvbWUoKGMpID0+IGMubmFtZSA9PT0gdmlldy5jZWxsVHlwZUNvbHVtbikpIHtcbiAgICByZXR1cm4gdmlldy5jZWxsVHlwZUNvbHVtbjtcbiAgfVxuICByZXR1cm4gKGNhdGVnb3JpY2FsLmZpbmQoKGMpID0+ICFpc0N1cmF0ZWRDb2x1bW4oYy5uYW1lKSkgPz8gY2F0ZWdvcmljYWxbMF0pPy5uYW1lID8/IG51bGw7XG59XG5cbi8vIOKUgOKUgCBUaWxlcyBpbiB2aWV3IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogQSBzdGFibGUgc3RyaW5nIGlkIGZvciBhIHRpbGUga2V5LCBgbGV2ZWwvZ3gvZ3lgIOKAlCB1c2FibGUgYXMgYSBNYXAga2V5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbGVJZChrOiBUaWxlS2V5KTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2subGV2ZWx9LyR7ay5neH0vJHtrLmd5fWA7XG59XG5cbi8qKiBDYW52YXMgcGl4ZWxzIHBlciBvYnNlcnZhdGlvbiB1bml0IGFsb25nIHgsIGZvciBhIGNhbWVyYSB6b29tIGFuZCBhIGRhdGHihpJ3b3JsZCBhZmZpbmUuICovXG5leHBvcnQgZnVuY3Rpb24gcGl4ZWxzUGVyRGF0YVVuaXQoem9vbTogbnVtYmVyLCByZWY/OiBTcGF0aWFsSW1hZ2VSZWYgfCBudWxsKTogbnVtYmVyIHtcbiAgcmV0dXJuIHpvb20gKiBNYXRoLmFicyhyZWY/LnNjYWxlPy5bMF0gPz8gMSk7XG59XG5cbi8qKlxuICogVGhlIHBhcnQgb2Ygb2JzZXJ2YXRpb24gc3BhY2UgdGhlIGNhbWVyYSBzaG93cywgcGFkZGVkIGJ5IGBtYXJnaW5gIChhIGZyYWN0aW9uIG9mIHRoZVxuICogdmlld3BvcnQpIHNvIHRpbGVzIGp1c3Qgb2ZmIHNjcmVlbiBhcmUgYWxyZWFkeSB0aGVyZSB3aGVuIGEgcGFuIGJyaW5ncyB0aGVtIGluOiBuYXBhcmktanMnc1xuICogYHdvcmxkVmlld3BvcnRgLCBtYXBwZWQgYmFjayB0aHJvdWdoIHRoZSBpbnZlcnNlIG9mIHRoZSBkYXRh4oaSd29ybGQgYWZmaW5lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlzaWJsZURhdGFSZWN0KFxuICBjZW50ZXI6IHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0sXG4gIHpvb206IG51bWJlcixcbiAgY2FudmFzVzogbnVtYmVyLFxuICBjYW52YXNIOiBudW1iZXIsXG4gIHJlZj86IFNwYXRpYWxJbWFnZVJlZiB8IG51bGwsXG4gIG1hcmdpbiA9IDAuMTUsXG4pOiBEYXRhUmVjdCB8IG51bGwge1xuICBpZiAoISh6b29tID4gMCkgfHwgIShjYW52YXNXID4gMCkgfHwgIShjYW52YXNIID4gMCkpIHJldHVybiBudWxsO1xuICBjb25zdCBzeCA9IHJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICBjb25zdCBzeSA9IHJlZj8uc2NhbGU/LlsxXSA/PyAxO1xuICBjb25zdCB0eCA9IHJlZj8udHJhbnNsYXRlPy5bMF0gPz8gMDtcbiAgY29uc3QgdHkgPSByZWY/LnRyYW5zbGF0ZT8uWzFdID8/IDA7XG4gIC8vIFRoZSB3b3JsZCByZWN0IG9mIGEgY2FudmFzIGdyb3duIGJ5IHRoZSBtYXJnaW4gb24gZWFjaCBzaWRlIChuYXBhcmktanMncyB3b3JsZFZpZXdwb3J0KS5cbiAgY29uc3QgdiA9IHdvcmxkVmlld3BvcnQoY2VudGVyWzBdLCBjZW50ZXJbMV0sIHpvb20sIGNhbnZhc1cgKiAoMSArIDIgKiBtYXJnaW4pLCBjYW52YXNIICogKDEgKyAyICogbWFyZ2luKSk7XG4gIGNvbnN0IHd4MCA9IHYueDtcbiAgY29uc3Qgd3gxID0gdi54ICsgdi53aWR0aDtcbiAgY29uc3Qgd3kwID0gdi55O1xuICBjb25zdCB3eTEgPSB2LnkgKyB2LmhlaWdodDtcbiAgY29uc3QgYXggPSAod3gwIC0gdHgpIC8gc3g7XG4gIGNvbnN0IGJ4ID0gKHd4MSAtIHR4KSAvIHN4O1xuICBjb25zdCBheSA9ICh3eTAgLSB0eSkgLyBzeTtcbiAgY29uc3QgYnkgPSAod3kxIC0gdHkpIC8gc3k7XG4gIHJldHVybiB7IHgwOiBNYXRoLm1pbihheCwgYngpLCB5MDogTWF0aC5taW4oYXksIGJ5KSwgeDE6IE1hdGgubWF4KGF4LCBieCksIHkxOiBNYXRoLm1heChheSwgYnkpIH07XG59XG5cbi8qKlxuICogVGlsZXMgb2Ygb25lIGxldmVsIGludGVyc2VjdGluZyBgcmVjdGAsIGNsaXBwZWQgdG8gdGhlIGRhdGFzZXQncyBgYm91bmRzYCAoc28gem9vbWluZ1xuICogb3V0IG92ZXIgZW1wdHkgY2FudmFzIGRvZXMgbm90IGFzayBmb3IgdGlsZXMgdGhhdCBjYW5ub3QgZXhpc3QpLiBPcmRlcmVkIGZyb20gdGhlXG4gKiByZWN0YW5nbGUncyBjZW50cmUgb3V0d2FyZCwgc28gdGhlIG1pZGRsZSBvZiB0aGUgc2NyZWVuIGZpbGxzIGluIGZpcnN0LlxuICpcbiAqIFRpbGUgYGdgIGNvdmVycyBgW2fCt3MsIChnKzEpwrdzKWAuIFRoZSB2aWV3J3MgZmFyIGVkZ2UgaXMgb3BlbiDigJQgYSB0aWxlIHN0YXJ0aW5nIGV4YWN0bHlcbiAqIGF0IGByZWN0LngxYCBzaG93cyBub3RoaW5nIOKAlCBidXQgdGhlIGJvdW5kcycgZmFyIGVkZ2UgaXMgY2xvc2VkOiB0aGUgYm91bmRzIGFyZSB0aGVcbiAqIGV4dHJlbWUgb2JzZXJ2YXRpb25zJyBjb29yZGluYXRlcywgc28gb25lIHNpdHMgZXhhY3RseSBvbiBgYm91bmRzWzJdYCwgaW4gdGhlIHRpbGVcbiAqIHN0YXJ0aW5nIHRoZXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdGlsZXNJblJlY3QoXG4gIHJlY3Q6IERhdGFSZWN0LFxuICBsZXZlbDogbnVtYmVyLFxuICBsZXZlbHM6IHJlYWRvbmx5IFNwYXRpYWxUaWxlTGV2ZWxbXSxcbiAgYm91bmRzPzogU3BhdGlhbEJvdW5kcyB8IG51bGwsXG4gIGxpbWl0ID0gSW5maW5pdHksXG4pOiBUaWxlS2V5W10ge1xuICBjb25zdCBzaXplID0gbGV2ZWxzW2xldmVsXT8udGlsZVNpemU7XG4gIGlmICghKHNpemUgPiAwKSkgcmV0dXJuIFtdO1xuICBsZXQgeyB4MCwgeTAgfSA9IHJlY3Q7XG4gIC8vIExhc3QgdGlsZSBhbG9uZyBhbiBheGlzOiB0aGUgb25lIGJlZm9yZSB0aGUgb3BlbiB2aWV3IGVkZ2UsIGF0IG1vc3QgdGhlIGNsb3NlZCBib3VuZCdzLlxuICBsZXQgZ3gxID0gTWF0aC5jZWlsKHJlY3QueDEgLyBzaXplKSAtIDE7XG4gIGxldCBneTEgPSBNYXRoLmNlaWwocmVjdC55MSAvIHNpemUpIC0gMTtcbiAgaWYgKGJvdW5kcykge1xuICAgIHgwID0gTWF0aC5tYXgoeDAsIGJvdW5kc1swXSk7XG4gICAgeTAgPSBNYXRoLm1heCh5MCwgYm91bmRzWzFdKTtcbiAgICBpZiAoTWF0aC5taW4ocmVjdC54MSwgYm91bmRzWzJdKSA8IHgwIHx8IE1hdGgubWluKHJlY3QueTEsIGJvdW5kc1szXSkgPCB5MCkgcmV0dXJuIFtdO1xuICAgIGd4MSA9IE1hdGgubWluKGd4MSwgTWF0aC5mbG9vcihib3VuZHNbMl0gLyBzaXplKSk7XG4gICAgZ3kxID0gTWF0aC5taW4oZ3kxLCBNYXRoLmZsb29yKGJvdW5kc1szXSAvIHNpemUpKTtcbiAgfVxuICBjb25zdCBneDAgPSBNYXRoLmZsb29yKHgwIC8gc2l6ZSk7XG4gIGNvbnN0IGd5MCA9IE1hdGguZmxvb3IoeTAgLyBzaXplKTtcbiAgY29uc3QgY3ggPSAocmVjdC54MCArIHJlY3QueDEpIC8gMiAvIHNpemU7XG4gIGNvbnN0IGN5ID0gKHJlY3QueTAgKyByZWN0LnkxKSAvIDIgLyBzaXplO1xuICBjb25zdCBvdXQ6IFRpbGVLZXlbXSA9IFtdO1xuICBmb3IgKGxldCBneSA9IGd5MDsgZ3kgPD0gZ3kxOyBneSsrKSB7XG4gICAgZm9yIChsZXQgZ3ggPSBneDA7IGd4IDw9IGd4MTsgZ3grKykgb3V0LnB1c2goeyBsZXZlbCwgZ3gsIGd5IH0pO1xuICB9XG4gIG91dC5zb3J0KFxuICAgIChhLCBiKSA9PiAoYS5neCArIDAuNSAtIGN4KSAqKiAyICsgKGEuZ3kgKyAwLjUgLSBjeSkgKiogMiAtICgoYi5neCArIDAuNSAtIGN4KSAqKiAyICsgKGIuZ3kgKyAwLjUgLSBjeSkgKiogMiksXG4gICk7XG4gIHJldHVybiBvdXQubGVuZ3RoID4gbGltaXQgPyBvdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0O1xufVxuXG4vKioge0BsaW5rIHRpbGVzSW5SZWN0fSBmb3IgYSBncmlkIHdob3NlIHRpbGUgKDAsIDApIHN0YXJ0cyBhdCBgb3JpZ2luYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWxlc0luUmVjdEZyb20oXG4gIG9yaWdpbjogcmVhZG9ubHkgW251bWJlciwgbnVtYmVyXSxcbiAgcmVjdDogRGF0YVJlY3QsXG4gIGxldmVsOiBudW1iZXIsXG4gIGxldmVsczogcmVhZG9ubHkgU3BhdGlhbFRpbGVMZXZlbFtdLFxuICBib3VuZHM/OiBTcGF0aWFsQm91bmRzIHwgbnVsbCxcbiAgbGltaXQgPSBJbmZpbml0eSxcbik6IFRpbGVLZXlbXSB7XG4gIGNvbnN0IFtveCwgb3ldID0gb3JpZ2luO1xuICBjb25zdCBzaGlmdGVkID0geyB4MDogcmVjdC54MCAtIG94LCB5MDogcmVjdC55MCAtIG95LCB4MTogcmVjdC54MSAtIG94LCB5MTogcmVjdC55MSAtIG95IH07XG4gIGNvbnN0IGI6IFNwYXRpYWxCb3VuZHMgfCBudWxsID0gYm91bmRzID8gW2JvdW5kc1swXSAtIG94LCBib3VuZHNbMV0gLSBveSwgYm91bmRzWzJdIC0gb3gsIGJvdW5kc1szXSAtIG95XSA6IG51bGw7XG4gIHJldHVybiB0aWxlc0luUmVjdChzaGlmdGVkLCBsZXZlbCwgbGV2ZWxzLCBiLCBsaW1pdCk7XG59XG5cbi8qKiBBcmVhIG9mIGByZWN0YCBpbnNpZGUgYGJvdW5kc2AgKHRoZSB3aG9sZSByZWN0IHdoZW4gdGhlcmUgYXJlIG5vbmUpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZpc2libGVBcmVhKHJlY3Q6IERhdGFSZWN0LCBib3VuZHM/OiBTcGF0aWFsQm91bmRzIHwgbnVsbCk6IG51bWJlciB7XG4gIGNvbnN0IHgwID0gYm91bmRzID8gTWF0aC5tYXgocmVjdC54MCwgYm91bmRzWzBdKSA6IHJlY3QueDA7XG4gIGNvbnN0IHkwID0gYm91bmRzID8gTWF0aC5tYXgocmVjdC55MCwgYm91bmRzWzFdKSA6IHJlY3QueTA7XG4gIGNvbnN0IHgxID0gYm91bmRzID8gTWF0aC5taW4ocmVjdC54MSwgYm91bmRzWzJdKSA6IHJlY3QueDE7XG4gIGNvbnN0IHkxID0gYm91bmRzID8gTWF0aC5taW4ocmVjdC55MSwgYm91bmRzWzNdKSA6IHJlY3QueTE7XG4gIHJldHVybiBNYXRoLm1heCgwLCB4MSAtIHgwKSAqIE1hdGgubWF4KDAsIHkxIC0geTApO1xufVxuXG4vLyDilIDilIAgTGV2ZWxzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKipcbiAqIFR5cGljYWwgY2VsbCBkaWFtZXRlciwgaW4gb2JzZXJ2YXRpb24gdW5pdHMsIHVzZWQgdG8ganVkZ2UgaG93IGxhcmdlIGNlbGxzIGFwcGVhci5cbiAqIERlcml2ZWQgZnJvbSB0aGUgcGVyLW9ic2VydmF0aW9uIHJhZGl1cyB3aGVuIHRoZXJlIGlzIG9uZTsgMTIgwrVtIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGljYWxDZWxsRGlhbWV0ZXIocmFkaXVzOiBGbG9hdDMyQXJyYXkgfCBudW1iZXIgfCB1bmRlZmluZWQsIGZhbGxiYWNrID0gMTIpOiBudW1iZXIge1xuICBpZiAodHlwZW9mIHJhZGl1cyA9PT0gJ251bWJlcicpIHJldHVybiByYWRpdXMgPiAwID8gcmFkaXVzICogMiA6IGZhbGxiYWNrO1xuICBpZiAoIXJhZGl1cz8ubGVuZ3RoKSByZXR1cm4gZmFsbGJhY2s7XG4gIC8vIFRoZSBtZWRpYW4gb2YgYSBzYW1wbGUgaXMgcGxlbnR5IOKAlCB0aGlzIHNldHMgYSB0aHJlc2hvbGQsIG5vdCBhIG1lYXN1cmVtZW50LlxuICBjb25zdCBtZWRpYW4gPSBxdWFudGlsZShyYWRpdXMsIDAuNSwgeyBmaWx0ZXI6ICdwb3NpdGl2ZScsIHNhbXBsZVNpemU6IDIwNDggfSk7XG4gIHJldHVybiBtZWRpYW4gPT09IG51bGwgPyBmYWxsYmFjayA6IG1lZGlhbiAqIDI7XG59XG5cbi8qKlxuICogT24tc2NyZWVuIGNlbGwgZGlhbWV0ZXIgKHB4KSBhdCBvciBhYm92ZSB3aGljaCBlYWNoIHBvbHlnb24gbGV2ZWwgaXMgdXNlZC4gQSBsZXZlbFxuICogaGFsdmVzIHRoZSB2ZXJ0aWNlcyBvZiB0aGUgb25lIGJlbG93LCBzbyBlYWNoIHNob3VsZCB0YWtlIG92ZXIgd2hlbiB0aGUgY2VsbCBpcyBhYm91dFxuICogaGFsZiBhcyBsYXJnZSBvbiBzY3JlZW4uIEJlbG93IHRoZSBsYXN0IGZpbml0ZSB0aHJlc2hvbGQgb3V0bGluZXMgYXJlIG5vdCBkcmF3biBhdFxuICogYWxsIOKAlCBhIGNlbGwgYSBmZXcgcGl4ZWxzIHdpZGUgaXMgYSBkb3QsIGFuZCB0aGUgb2JzZXJ2YXRpb24gbWFya2VycyBhbHJlYWR5IGRyYXcgaXRcbiAqIGFzIG9uZS5cbiAqXG4gKiBYZW5pdW0ncyBmb3VydGggbGV2ZWwgKDMgdmVydGljZXMgcGVyIGNlbGwpIGlzIGRlbGliZXJhdGVseSBuZXZlciB1c2VkOiBzZWVuIG9uXG4gKiBzY3JlZW4gaXQgaXMgYSBmaWVsZCBvZiB0cmlhbmdsZXMsIHdoaWNoIHJlYWRzIGFzIGFuIGFydGVmYWN0IHJhdGhlciB0aGFuIGFzIGNlbGxzLlxuICogVGhlIGRvdHMgYmVsb3cgOCBweCBzYXkgdGhlIHNhbWUgdGhpbmcgbW9yZSBob25lc3RseS5cbiAqL1xuZXhwb3J0IGNvbnN0IFBPTFlHT05fTEVWRUxfTUlOX0NFTExfUFggPSBbMzYsIDE4LCA4LCBJbmZpbml0eV07XG5cbi8qKlxuICogV2hpY2ggcG9seWdvbiBsZXZlbCBzdWl0cyB0aGlzIHpvb20sIG9yIC0xIGZvciBcInRvbyBzbWFsbCB0byBvdXRsaW5lXCIuXG4gKiBgZGV0YWlsYCA+IDEgcHJlZmVycyBmaW5lciBsZXZlbHMgKHNoYXJwZXIsIHNsb3dlcik7IDwgMSBjb2Fyc2VyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcG9seWdvbkxldmVsRm9yKHB4UGVyVW5pdDogbnVtYmVyLCBjZWxsRGlhbWV0ZXI6IG51bWJlciwgbGV2ZWxDb3VudDogbnVtYmVyLCBkZXRhaWwgPSAxKTogbnVtYmVyIHtcbiAgY29uc3QgY2VsbFB4ID0gcHhQZXJVbml0ICogY2VsbERpYW1ldGVyICogZGV0YWlsO1xuICBjb25zdCB0YWJsZSA9IFBPTFlHT05fTEVWRUxfTUlOX0NFTExfUFg7XG4gIGZvciAobGV0IGwgPSAwOyBsIDwgbGV2ZWxDb3VudDsgbCsrKSB7XG4gICAgLy8gUGFzdCB0aGUgdGFibGUsIGtlZXAgaGFsdmluZzogZWFjaCBsZXZlbCBzdGlsbCBoYWx2ZXMgdGhlIHZlcnRpY2VzLlxuICAgIGNvbnN0IG1pbiA9IHRhYmxlW2xdID8/IHRhYmxlW3RhYmxlLmxlbmd0aCAtIDFdIC8gMiAqKiAobCAtIHRhYmxlLmxlbmd0aCArIDEpO1xuICAgIGlmIChjZWxsUHggPj0gbWluKSByZXR1cm4gbDtcbiAgfVxuICByZXR1cm4gLTE7XG59XG5cbi8qKlxuICogV2hpY2ggdHJhbnNjcmlwdCBsZXZlbCBzdWl0cyB0aGlzIHpvb206IHRoZSBvbmUgd2hvc2UgdGlsZXMgY29tZSBvdXQgY2xvc2VzdCB0b1xuICogYHRhcmdldFRpbGVQeGAgb24gc2NyZWVuLiBDb2Fyc2VyIGxldmVscyBhZ2dyZWdhdGUgbW9yZSwgc28gdGhpcyBrZWVwcyB0aGUgbnVtYmVyIG9mXG4gKiBtYXJrZXJzIHBlciBzY3JlZW4gcm91Z2hseSBjb25zdGFudCBob3dldmVyIGZhciBvdXQgdGhlIGNhbWVyYSBpcyDigJQgdGhlIHByb3BlcnR5IHRoYXRcbiAqIGtlZXBzIHRoZSB2aWV3IGZhc3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2NyaXB0TGV2ZWxGb3IoXG4gIHB4UGVyVW5pdDogbnVtYmVyLFxuICBsZXZlbHM6IHJlYWRvbmx5IFNwYXRpYWxUaWxlTGV2ZWxbXSxcbiAgdGFyZ2V0VGlsZVB4ID0gNTEyLFxuKTogbnVtYmVyIHtcbiAgaWYgKCFsZXZlbHMubGVuZ3RoIHx8ICEocHhQZXJVbml0ID4gMCkpIHJldHVybiAwO1xuICBsZXQgYmVzdCA9IDA7XG4gIGxldCBiZXN0RXJyID0gSW5maW5pdHk7XG4gIGZvciAobGV0IGwgPSAwOyBsIDwgbGV2ZWxzLmxlbmd0aDsgbCsrKSB7XG4gICAgY29uc3QgZXJyID0gTWF0aC5hYnMoTWF0aC5sb2cyKChsZXZlbHNbbF0udGlsZVNpemUgKiBweFBlclVuaXQpIC8gdGFyZ2V0VGlsZVB4KSk7XG4gICAgaWYgKGVyciA8IGJlc3RFcnIpIHtcbiAgICAgIGJlc3RFcnIgPSBlcnI7XG4gICAgICBiZXN0ID0gbDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJlc3Q7XG59XG4iXX0=
@@ -0,0 +1,200 @@
1
+ import { firstValueFrom } from 'rxjs';
2
+ import { isSpatialOmics3d } from '../contracts/plot-type';
3
+ import { isCategoricalColumn } from '../contracts/spatial-dataset.contract';
4
+ import { resolveCategoryColors } from './spatial-encoding';
5
+ import { sectionsOf } from './spatial-sections';
6
+ import { observationsInSlice, volumeImageRef } from './spatial-volume-image';
7
+ import { emptySelection, selectByCategory, selectByIndices, selectInRegions, selectInRegionsProjected, } from './spatial-selection';
8
+ /**
9
+ * The spatial-omics controls (`ISpatialControls`) over a host's `SPATIAL_DATA_PORT`.
10
+ *
11
+ * Backend-neutral: the view state lives in the shared `VisualizerStore` (like the
12
+ * colormap) and the selection in the `SpatialSelectionStore`, so the controls keep
13
+ * working across a plot-type switch and a host can drive them before any backend has
14
+ * mounted. Owns its mirror of the port's dataset — dropping a stale selection and an
15
+ * unsatisfiable colour source when the dataset changes — and the subscription behind
16
+ * it, released by {@link dispose} (review CORE-30).
17
+ */
18
+ export class SpatialControlsFacade {
19
+ constructor(port, ctx) {
20
+ this.port = port;
21
+ this.ctx = ctx;
22
+ /** Latest dataset, mirrored so `selectFromRegions()` can answer synchronously — it
23
+ * runs from a button click and must not await a round-trip. */
24
+ this.dataset = null;
25
+ // Mirror the dataset (and drop a stale selection when it changes — the masks are
26
+ // index-based, so they are meaningless against different observations).
27
+ this.sub = port.getDataset$().subscribe((dataset) => {
28
+ const changed = dataset?.id !== this.dataset?.id;
29
+ this.dataset = dataset;
30
+ if (!changed)
31
+ return;
32
+ ctx.selectionStore.set(emptySelection(dataset?.observations.count ?? 0));
33
+ // A colour source the new dataset cannot satisfy would leave the map flat while
34
+ // the panel and the charts kept naming the old column — so drop it, and only it:
35
+ // point size, opacity and the rest are the user's preferences.
36
+ const by = ctx.store.currentSpatialView().colorBy;
37
+ if (by && !canColorBy(dataset, by))
38
+ ctx.store.setSpatialView({ colorBy: null });
39
+ });
40
+ this.controls = this.build();
41
+ }
42
+ /** Release the port subscription (the router's injector is being destroyed). */
43
+ dispose() {
44
+ this.sub.unsubscribe();
45
+ }
46
+ build() {
47
+ const port = this.port;
48
+ return {
49
+ getDataset$: () => port.getDataset$(),
50
+ getViewState$: () => this.ctx.store.getSpatialView$(),
51
+ viewState: () => this.ctx.store.currentSpatialView(),
52
+ setViewState: (partial) => this.ctx.store.setSpatialView(partial),
53
+ // The hint SEEDS the toggle when the source changes, and nothing consults it
54
+ // afterwards. It used to be ORed in at render time, which meant an unchecked
55
+ // box could not turn log scaling off for a hinted column — and the linked
56
+ // chart, which reads `logScale` alone, disagreed with the map about what it
57
+ // was showing. One authority, set once per source.
58
+ colorByColumn: (name) => {
59
+ const meta = this.dataset?.columns.find((c) => c.name === name);
60
+ const hint = meta?.kind === 'continuous' ? !!meta.logScaleHint : false;
61
+ this.ctx.store.setSpatialView({ colorBy: { kind: 'column', name }, logScale: hint });
62
+ },
63
+ colorByFeature: (name) => this.ctx.store.setSpatialView({
64
+ colorBy: { kind: 'feature', name },
65
+ logScale: !!this.dataset?.features?.logScaleHint,
66
+ }),
67
+ clearColorBy: () => this.ctx.store.setSpatialView({ colorBy: null }),
68
+ searchFeatures: async (query, limit = 50) => {
69
+ // Prefer the port's search (a 31k-gene dataset does not ship its names);
70
+ // otherwise filter whatever the manifest inlined.
71
+ if (port.searchFeatures)
72
+ return port.searchFeatures(query, limit);
73
+ const dataset = await firstValueFrom(port.getDataset$());
74
+ const names = dataset?.features?.names ?? [];
75
+ const q = query.toLowerCase();
76
+ return names.filter((n) => n.toLowerCase().includes(q)).slice(0, limit);
77
+ },
78
+ ...(port.importGroups
79
+ ? {
80
+ importGroups: (label, table) => port.importGroups(label, table),
81
+ }
82
+ : {}),
83
+ ...(port.getTranscriptCounts
84
+ ? {
85
+ transcriptCounts: (genes) => port.getTranscriptCounts(genes),
86
+ }
87
+ : {}),
88
+ ...(port.getMarkerGenes
89
+ ? {
90
+ markerGenes: (column, perGroup) => port.getMarkerGenes(column, perGroup),
91
+ }
92
+ : {}),
93
+ getTranscriptEstimate$: () => this.ctx.napari.transcriptEstimate$.asObservable(),
94
+ getGeneCountsInView$: () => this.ctx.napari.geneCountsInView$.asObservable(),
95
+ getDensityStats$: () => this.ctx.napari.densityStats$.asObservable(),
96
+ categoryColors: async (name) => {
97
+ const column = await port.getColumn(name);
98
+ if (!isCategoricalColumn(column)) {
99
+ throw new Error(`[spatial] column "${name}" is continuous — it has no categories`);
100
+ }
101
+ // Resolved by the SAME function the renderer uses, so a legend swatch
102
+ // can never disagree with the colour on screen.
103
+ return resolveCategoryColors(column.meta);
104
+ },
105
+ continuousValues: async (source) => {
106
+ if (source.kind === 'feature')
107
+ return port.getFeatureVector(source.name);
108
+ const column = await port.getColumn(source.name);
109
+ if (isCategoricalColumn(column)) {
110
+ throw new Error(`[spatial] column "${source.name}" is categorical — it has no values to chart`);
111
+ }
112
+ return column.values;
113
+ },
114
+ categoricalView: async (name) => {
115
+ const column = await port.getColumn(name);
116
+ if (!isCategoricalColumn(column)) {
117
+ throw new Error(`[spatial] column "${name}" is continuous — it has no categories`);
118
+ }
119
+ return {
120
+ name,
121
+ categories: column.meta.categories,
122
+ colors: resolveCategoryColors(column.meta),
123
+ codes: column.codes,
124
+ };
125
+ },
126
+ // Spread rather than always defined: `getEmbedding` is optional on both the port
127
+ // and this facade, and a panel checks for its presence to decide whether the view
128
+ // is offered at all. Defining it as a function that rejects would make an
129
+ // embedding-less source look like a broken one.
130
+ ...(port.getEmbedding ? { getEmbedding: (name) => port.getEmbedding(name) } : {}),
131
+ categoricalColumns: () => (this.dataset?.columns ?? []).filter((c) => c.kind === 'categorical').map((c) => c.name),
132
+ // Memoized on the observations object, so the renderer's own lookup and
133
+ // this one are the same single scan of up to 3.7M z values.
134
+ sampledSections: () => {
135
+ const obs = this.dataset?.observations;
136
+ return obs ? sectionsOf(obs) : null;
137
+ },
138
+ getSelection$: () => this.ctx.selectionStore.getSelection$(),
139
+ selectFromRegions: () => {
140
+ const dataset = this.dataset;
141
+ if (!dataset)
142
+ return 0;
143
+ const regions = this.ctx.regionStore.getRegions();
144
+ // The union of every drawn region — so every ROI tool the library
145
+ // already has doubles as a spatial selection tool.
146
+ //
147
+ // In the 3D cloud there is no data-space affine to push a drawn shape
148
+ // through, so the observations are projected to canvas pixels by the
149
+ // renderer (which owns the camera) and tested in screen space instead.
150
+ // Falls back to the 2D path whenever the cloud is not mounted.
151
+ const projected = isSpatialOmics3d(this.ctx.plotType())
152
+ ? this.ctx.napari.getSpatialScreenProjection(dataset.observations)
153
+ : null;
154
+ // In the 2D view of a volume-backed dataset the shape was drawn over ONE
155
+ // section, in the volume's pixel grid: it selects the cells of that
156
+ // section, not the whole depth of brain standing behind them.
157
+ const volume = !dataset.imageRef ? dataset.volume : undefined;
158
+ const selection = projected
159
+ ? selectInRegionsProjected(projected, dataset.observations.count, regions)
160
+ : selectInRegions(dataset.observations, volume ? volumeImageRef(volume, dataset.micronsPerUnit) : dataset.imageRef, regions, volume ? observationsInSlice(dataset.observations, volume, this.ctx.zIndex()) : undefined);
161
+ this.ctx.selectionStore.set(selection);
162
+ return selection.count;
163
+ },
164
+ selectCategory: async (column, categoryIndex) => {
165
+ const loaded = await port.getColumn(column);
166
+ if (!isCategoricalColumn(loaded)) {
167
+ throw new Error(`[spatial] column "${column}" is continuous — it has no categories`);
168
+ }
169
+ const selection = selectByCategory(loaded.codes, categoryIndex);
170
+ this.ctx.selectionStore.set(selection);
171
+ return selection.count;
172
+ },
173
+ selectIndices: (indices) => {
174
+ const count = this.dataset?.observations.count ?? 0;
175
+ if (count === 0)
176
+ return 0;
177
+ const selection = selectByIndices(indices, count);
178
+ this.ctx.selectionStore.set(selection);
179
+ return selection.count;
180
+ },
181
+ clearSelection: () => this.ctx.selectionStore.clear(),
182
+ };
183
+ }
184
+ }
185
+ /**
186
+ * Whether `dataset` can answer this colour source. A column is checkable against the
187
+ * declared list. A gene is checkable only when the dataset inlines its feature names —
188
+ * a dataset too wide to inline them (typeahead-only) keeps the source, and a name that
189
+ * turns out not to exist surfaces as the chart's "could not be charted" rather than as
190
+ * a silent reset.
191
+ */
192
+ function canColorBy(dataset, by) {
193
+ if (!dataset)
194
+ return false;
195
+ if (by.kind === 'column')
196
+ return dataset.columns.some((c) => c.name === by.name);
197
+ const names = dataset.features?.names;
198
+ return !!dataset.features && (!names || names.includes(by.name));
199
+ }
200
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC1jb250cm9scy5mYWNhZGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NwYXRpYWwvc3BhdGlhbC1jb250cm9scy5mYWNhZGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUE0QixjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFaEUsT0FBTyxFQUFZLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFHcEUsT0FBTyxFQUF1QyxtQkFBbUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBS2pILE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzNELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0UsT0FBTyxFQUNMLGNBQWMsRUFDZCxnQkFBZ0IsRUFDaEIsZUFBZSxFQUNmLGVBQWUsRUFDZix3QkFBd0IsR0FDekIsTUFBTSxxQkFBcUIsQ0FBQztBQXVCN0I7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxPQUFPLHFCQUFxQjtJQVFoQyxZQUNtQixJQUFxQixFQUNyQixHQUEyQjtRQUQzQixTQUFJLEdBQUosSUFBSSxDQUFpQjtRQUNyQixRQUFHLEdBQUgsR0FBRyxDQUF3QjtRQVA5Qzt3RUFDZ0U7UUFDeEQsWUFBTyxHQUEwQixJQUFJLENBQUM7UUFPNUMsaUZBQWlGO1FBQ2pGLHdFQUF3RTtRQUN4RSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNsRCxNQUFNLE9BQU8sR0FBRyxPQUFPLEVBQUUsRUFBRSxLQUFLLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQ2pELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFD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LGVBQWUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ2xELElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDdkMsT0FBTyxTQUFTLENBQUMsS0FBSyxDQUFDO1lBQ3pCLENBQUM7WUFFRCxjQUFjLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFO1NBQ3RELENBQUM7SUFDSixDQUFDO0NBQ0Y7QUFFRDs7Ozs7O0dBTUc7QUFDSCxTQUFTLFVBQVUsQ0FBQyxPQUE4QixFQUFFLEVBQWtCO0lBQ3BFLElBQUksQ0FBQyxPQUFPO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDM0IsSUFBSSxFQUFFLENBQUMsSUFBSSxLQUFLLFFBQVE7UUFBRSxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqRixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQztJQUN0QyxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLENBQUMsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUNuRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uLCBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBQbG90VHlwZSwgaXNTcGF0aWFsT21pY3MzZCB9IGZyb20gJy4uL2NvbnRyYWN0cy9wbG90LXR5cGUnO1xuaW1wb3J0IHsgU3BhdGlhbERhdGFQb3J0IH0gZnJvbSAnLi4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB7IFNwYXRpYWxDb2xvckJ5IH0gZnJvbSAnLi4vY29udHJhY3RzL2Rpc3BsYXktdHlwZXMnO1xuaW1wb3J0IHsgU3BhdGlhbERhdGFzZXQsIFNwYXRpYWxPYnNlcnZhdGlvbnMsIGlzQ2F0ZWdvcmljYWxDb2x1bW4gfSBmcm9tICcuLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB7IElTcGF0aWFsQ29udHJvbHMgfSBmcm9tICcuLi9jb250cmFjdHMvdmlzdWFsaXplci5jb250cmFjdCc7XG5pbXBvcnQgeyBSZWdpb25TdG9yZSB9IGZyb20gJy4uL3N0b3JlL3JlZ2lvbi1zdG9yZS5zZXJ2aWNlJztcbmltcG9ydCB7IFNwYXRpYWxTZWxlY3Rpb25TdG9yZSB9IGZyb20gJy4uL3N0b3JlL3NwYXRpYWwtc2VsZWN0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgVmlzdWFsaXplclN0b3JlIH0gZnJvbSAnLi4vc3RvcmUvdmlzdWFsaXplci1zdG9yZS5zZXJ2aWNlJztcbmltcG9ydCB7IHJlc29sdmVDYXRlZ29yeUNvbG9ycyB9IGZyb20gJy4vc3BhdGlhbC1lbmNvZGluZyc7XG5pbXBvcnQgeyBzZWN0aW9uc09mIH0gZnJvbSAnLi9zcGF0aWFsLXNlY3Rpb25zJztcbmltcG9ydCB7IG9ic2VydmF0aW9uc0luU2xpY2UsIHZvbHVtZUltYWdlUmVmIH0gZnJvbSAnLi9zcGF0aWFsLXZvbHVtZS1pbWFnZSc7XG5pbXBvcnQge1xuICBlbXB0eVNlbGVjdGlvbixcbiAgc2VsZWN0QnlDYXRlZ29yeSxcbiAgc2VsZWN0QnlJbmRpY2VzLFxuICBzZWxlY3RJblJlZ2lvbnMsXG4gIHNlbGVjdEluUmVnaW9uc1Byb2plY3RlZCxcbn0gZnJvbSAnLi9zcGF0aWFsLXNlbGVjdGlvbic7XG5cbi8qKiBUaGUgcmVuZGVyZXItc2lkZSBzcGF0aWFsIHJlYWRvdXRzIHRoZSBjb250cm9scyBzdXJmYWNlICh0aGUgbmFwYXJpLWpzIGJhY2tlbmQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTcGF0aWFsUmVuZGVyZXJGZWVkcyB7XG4gIHJlYWRvbmx5IHRyYW5zY3JpcHRFc3RpbWF0ZSQ6IHsgYXNPYnNlcnZhYmxlKCk6IE9ic2VydmFibGU8eyBwb2ludHM6IG51bWJlcjsgbWF4OiBudW1iZXIgfSB8IG51bGw+IH07XG4gIHJlYWRvbmx5IGdlbmVDb3VudHNJblZpZXckOiB7IGFzT2JzZXJ2YWJsZSgpOiBPYnNlcnZhYmxlPFJlY29yZDxzdHJpbmcsIG51bWJlcj4gfCBudWxsPiB9O1xuICByZWFkb25seSBkZW5zaXR5U3RhdHMkOiB7IGFzT2JzZXJ2YWJsZSgpOiBPYnNlcnZhYmxlPHsgbG86IG51bWJlcjsgaGk6IG51bWJlcjsgbWF4OiBudW1iZXIgfSB8IG51bGw+IH07XG4gIC8qKiBPYnNlcnZhdGlvbnMgcHJvamVjdGVkIHRvIGNhbnZhcyBwaXhlbHMgYnkgdGhlIDNEIGNhbWVyYSwgb3IgbnVsbCB3aGVuIHRoZSBjbG91ZCBpcyBub3QgbW91bnRlZC4gKi9cbiAgZ2V0U3BhdGlhbFNjcmVlblByb2plY3Rpb24ob2JzOiBTcGF0aWFsT2JzZXJ2YXRpb25zKTogRmxvYXQzMkFycmF5IHwgbnVsbDtcbn1cblxuLyoqIFdoYXQgdGhlIGZhY2FkZSB3b3JrcyBvdmVyOiB0aGUgc2hhcmVkIHN0b3JlcywgdGhlIHJlbmRlcmVyIGZlZWRzIGFuZCB0aGUgcm91dGVyJ3MgdmlldyBzdGF0ZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3BhdGlhbENvbnRyb2xzQ29udGV4dCB7XG4gIHJlYWRvbmx5IHN0b3JlOiBWaXN1YWxpemVyU3RvcmU7XG4gIHJlYWRvbmx5IHJlZ2lvblN0b3JlOiBSZWdpb25TdG9yZTtcbiAgcmVhZG9ubHkgc2VsZWN0aW9uU3RvcmU6IFNwYXRpYWxTZWxlY3Rpb25TdG9yZTtcbiAgcmVhZG9ubHkgbmFwYXJpOiBTcGF0aWFsUmVuZGVyZXJGZWVkcztcbiAgLyoqIFRoZSBwbG90IHR5cGUgb24gc2NyZWVuICh0aGUgM0QgY2xvdWQgc2VsZWN0cyBpbiBzY3JlZW4gc3BhY2UpLiAqL1xuICBwbG90VHlwZSgpOiBQbG90VHlwZTtcbiAgLyoqIFRoZSBkaXNwbGF5ZWQgc2xpY2UgKGEgdm9sdW1lLWJhY2tlZCBkYXRhc2V0IHNlbGVjdHMgd2l0aGluIG9uZSBzZWN0aW9uKS4gKi9cbiAgekluZGV4KCk6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgc3BhdGlhbC1vbWljcyBjb250cm9scyAoYElTcGF0aWFsQ29udHJvbHNgKSBvdmVyIGEgaG9zdCdzIGBTUEFUSUFMX0RBVEFfUE9SVGAuXG4gKlxuICogQmFja2VuZC1uZXV0cmFsOiB0aGUgdmlldyBzdGF0ZSBsaXZlcyBpbiB0aGUgc2hhcmVkIGBWaXN1YWxpemVyU3RvcmVgIChsaWtlIHRoZVxuICogY29sb3JtYXApIGFuZCB0aGUgc2VsZWN0aW9uIGluIHRoZSBgU3BhdGlhbFNlbGVjdGlvblN0b3JlYCwgc28gdGhlIGNvbnRyb2xzIGtlZXBcbiAqIHdvcmtpbmcgYWNyb3NzIGEgcGxvdC10eXBlIHN3aXRjaCBhbmQgYSBob3N0IGNhbiBkcml2ZSB0aGVtIGJlZm9yZSBhbnkgYmFja2VuZCBoYXNcbiAqIG1vdW50ZWQuIE93bnMgaXRzIG1pcnJvciBvZiB0aGUgcG9ydCdzIGRhdGFzZXQg4oCUIGRyb3BwaW5nIGEgc3RhbGUgc2VsZWN0aW9uIGFuZCBhblxuICogdW5zYXRpc2ZpYWJsZSBjb2xvdXIgc291cmNlIHdoZW4gdGhlIGRhdGFzZXQgY2hhbmdlcyDigJQgYW5kIHRoZSBzdWJzY3JpcHRpb24gYmVoaW5kXG4gKiBpdCwgcmVsZWFzZWQgYnkge0BsaW5rIGRpc3Bvc2V9IChyZXZpZXcgQ09SRS0zMCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGF0aWFsQ29udHJvbHNGYWNhZGUge1xuICAvKiogVGhlIGNvbnRyb2xzOyBvbmUgb2JqZWN0IGZvciB0aGUgZmFjYWRlJ3MgbGlmZSwgc28gY29uc3VtZXJzIGNhbiBob2xkIGl0LiAqL1xuICByZWFkb25seSBjb250cm9sczogSVNwYXRpYWxDb250cm9scztcbiAgLyoqIExhdGVzdCBkYXRhc2V0LCBtaXJyb3JlZCBzbyBgc2VsZWN0RnJvbVJlZ2lvbnMoKWAgY2FuIGFuc3dlciBzeW5jaHJvbm91c2x5IOKAlCBpdFxuICAgKiAgcnVucyBmcm9tIGEgYnV0dG9uIGNsaWNrIGFuZCBtdXN0IG5vdCBhd2FpdCBhIHJvdW5kLXRyaXAuICovXG4gIHByaXZhdGUgZGF0YXNldDogU3BhdGlhbERhdGFzZXQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBzdWI6IFN1YnNjcmlwdGlvbjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBvcnQ6IFNwYXRpYWxEYXRhUG9ydCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGN0eDogU3BhdGlhbENvbnRyb2xzQ29udGV4dCxcbiAgKSB7XG4gICAgLy8gTWlycm9yIHRoZSBkYXRhc2V0IChhbmQgZHJvcCBhIHN0YWxlIHNlbGVjdGlvbiB3aGVuIGl0IGNoYW5nZXMg4oCUIHRoZSBtYXNrcyBhcmVcbiAgICAvLyBpbmRleC1iYXNlZCwgc28gdGhleSBhcmUgbWVhbmluZ2xlc3MgYWdhaW5zdCBkaWZmZXJlbnQgb2JzZXJ2YXRpb25zKS5cbiAgICB0aGlzLnN1YiA9IHBvcnQuZ2V0RGF0YXNldCQoKS5zdWJzY3JpYmUoKGRhdGFzZXQpID0+IHtcbiAgICAgIGNvbnN0IGNoYW5nZWQgPSBkYXRhc2V0Py5pZCAhPT0gdGhpcy5kYXRhc2V0Py5pZDtcbiAgICAgIHRoaXMuZGF0YXNldCA9IGRhdGFzZXQ7XG4gICAgICBpZiAoIWNoYW5nZWQpIHJldHVybjtcbiAgICAgIGN0eC5zZWxlY3Rpb25TdG9yZS5zZXQoZW1wdHlTZWxlY3Rpb24oZGF0YXNldD8ub2JzZXJ2YXRpb25zLmNvdW50ID8/IDApKTtcbiAgICAgIC8vIEEgY29sb3VyIHNvdXJjZSB0aGUgbmV3IGRhdGFzZXQgY2Fubm90IHNhdGlzZnkgd291bGQgbGVhdmUgdGhlIG1hcCBmbGF0IHdoaWxlXG4gICAgICAvLyB0aGUgcGFuZWwgYW5kIHRoZSBjaGFydHMga2VwdCBuYW1pbmcgdGhlIG9sZCBjb2x1bW4g4oCUIHNvIGRyb3AgaXQsIGFuZCBvbmx5IGl0OlxuICAgICAgLy8gcG9pbnQgc2l6ZSwgb3BhY2l0eSBhbmQgdGhlIHJlc3QgYXJlIHRoZSB1c2VyJ3MgcHJlZmVyZW5jZXMuXG4gICAgICBjb25zdCBieSA9IGN0eC5zdG9yZS5jdXJyZW50U3BhdGlhbFZpZXcoKS5jb2xvckJ5O1xuICAgICAgaWYgKGJ5ICYmICFjYW5Db2xvckJ5KGRhdGFzZXQsIGJ5KSkgY3R4LnN0b3JlLnNldFNwYXRpYWxWaWV3KHsgY29sb3JCeTogbnVsbCB9KTtcbiAgICB9KTtcbiAgICB0aGlzLmNvbnRyb2xzID0gdGhpcy5idWlsZCgpO1xuICB9XG5cbiAgLyoqIFJlbGVhc2UgdGhlIHBvcnQgc3Vic2NyaXB0aW9uICh0aGUgcm91dGVyJ3MgaW5qZWN0b3IgaXMgYmVpbmcgZGVzdHJveWVkKS4gKi9cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yi51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZCgpOiBJU3BhdGlhbENvbnRyb2xzIHtcbiAgICBjb25zdCBwb3J0ID0gdGhpcy5wb3J0O1xuICAgIHJldHVybiB7XG4gICAgICBnZXREYXRhc2V0JDogKCkgPT4gcG9ydC5nZXREYXRhc2V0JCgpLFxuICAgICAgZ2V0Vmlld1N0YXRlJDogKCkgPT4gdGhpcy5jdHguc3RvcmUuZ2V0U3BhdGlhbFZpZXckKCksXG4gICAgICB2aWV3U3RhdGU6ICgpID0+IHRoaXMuY3R4LnN0b3JlLmN1cnJlbnRTcGF0aWFsVmlldygpLFxuICAgICAgc2V0Vmlld1N0YXRlOiAocGFydGlhbCkgPT4gdGhpcy5jdHguc3RvcmUuc2V0U3BhdGlhbFZpZXcocGFydGlhbCksXG4gICAgICAvLyBUaGUgaGludCBTRUVEUyB0aGUgdG9nZ2xlIHdoZW4gdGhlIHNvdXJjZSBjaGFuZ2VzLCBhbmQgbm90aGluZyBjb25zdWx0cyBpdFxuICAgICAgLy8gYWZ0ZXJ3YXJkcy4gSXQgdXNlZCB0byBiZSBPUmVkIGluIGF0IHJlbmRlciB0aW1lLCB3aGljaCBtZWFudCBhbiB1bmNoZWNrZWRcbiAgICAgIC8vIGJveCBjb3VsZCBub3QgdHVybiBsb2cgc2NhbGluZyBvZmYgZm9yIGEgaGludGVkIGNvbHVtbiDigJQgYW5kIHRoZSBsaW5rZWRcbiAgICAgIC8vIGNoYXJ0LCB3aGljaCByZWFkcyBgbG9nU2NhbGVgIGFsb25lLCBkaXNhZ3JlZWQgd2l0aCB0aGUgbWFwIGFib3V0IHdoYXQgaXRcbiAgICAgIC8vIHdhcyBzaG93aW5nLiBPbmUgYXV0aG9yaXR5LCBzZXQgb25jZSBwZXIgc291cmNlLlxuICAgICAgY29sb3JCeUNvbHVtbjogKG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBtZXRhID0gdGhpcy5kYXRhc2V0Py5jb2x1bW5zLmZpbmQoKGMpID0+IGMubmFtZSA9PT0gbmFtZSk7XG4gICAgICAgIGNvbnN0IGhpbnQgPSBtZXRhPy5raW5kID09PSAnY29udGludW91cycgPyAhIW1ldGEubG9nU2NhbGVIaW50IDogZmFsc2U7XG4gICAgICAgIHRoaXMuY3R4LnN0b3JlLnNldFNwYXRpYWxWaWV3KHsgY29sb3JCeTogeyBraW5kOiAnY29sdW1uJywgbmFtZSB9LCBsb2dTY2FsZTogaGludCB9KTtcbiAgICAgIH0sXG4gICAgICBjb2xvckJ5RmVhdHVyZTogKG5hbWU6IHN0cmluZykgPT5cbiAgICAgICAgdGhpcy5jdHguc3RvcmUuc2V0U3BhdGlhbFZpZXcoe1xuICAgICAgICAgIGNvbG9yQnk6IHsga2luZDogJ2ZlYXR1cmUnLCBuYW1lIH0sXG4gICAgICAgICAgbG9nU2NhbGU6ICEhdGhpcy5kYXRhc2V0Py5mZWF0dXJlcz8ubG9nU2NhbGVIaW50LFxuICAgICAgICB9KSxcbiAgICAgIGNsZWFyQ29sb3JCeTogKCkgPT4gdGhpcy5jdHguc3RvcmUuc2V0U3BhdGlhbFZpZXcoeyBjb2xvckJ5OiBudWxsIH0pLFxuICAgICAgc2VhcmNoRmVhdHVyZXM6IGFzeW5jIChxdWVyeTogc3RyaW5nLCBsaW1pdCA9IDUwKSA9PiB7XG4gICAgICAgIC8vIFByZWZlciB0aGUgcG9ydCdzIHNlYXJjaCAoYSAzMWstZ2VuZSBkYXRhc2V0IGRvZXMgbm90IHNoaXAgaXRzIG5hbWVzKTtcbiAgICAgICAgLy8gb3RoZXJ3aXNlIGZpbHRlciB3aGF0ZXZlciB0aGUgbWFuaWZlc3QgaW5saW5lZC5cbiAgICAgICAgaWYgKHBvcnQuc2VhcmNoRmVhdHVyZXMpIHJldHVybiBwb3J0LnNlYXJjaEZlYXR1cmVzKHF1ZXJ5LCBsaW1pdCk7XG4gICAgICAgIGNvbnN0IGRhdGFzZXQgPSBhd2FpdCBmaXJzdFZhbHVlRnJvbShwb3J0LmdldERhdGFzZXQkKCkpO1xuICAgICAgICBjb25zdCBuYW1lcyA9IGRhdGFzZXQ/LmZlYXR1cmVzPy5uYW1lcyA/PyBbXTtcbiAgICAgICAgY29uc3QgcSA9IHF1ZXJ5LnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHJldHVybiBuYW1lcy5maWx0ZXIoKG4pID0+IG4udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhxKSkuc2xpY2UoMCwgbGltaXQpO1xuICAgICAgfSxcbiAgICAgIC4uLihwb3J0LmltcG9ydEdyb3Vwc1xuICAgICAgICA/IHtcbiAgICAgICAgICAgIGltcG9ydEdyb3VwczogKGxhYmVsOiBzdHJpbmcsIHRhYmxlOiBzdHJpbmcpID0+IHBvcnQuaW1wb3J0R3JvdXBzIShsYWJlbCwgdGFibGUpLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgICAuLi4ocG9ydC5nZXRUcmFuc2NyaXB0Q291bnRzXG4gICAgICAgID8ge1xuICAgICAgICAgICAgdHJhbnNjcmlwdENvdW50czogKGdlbmVzOiBzdHJpbmdbXSkgPT4gcG9ydC5nZXRUcmFuc2NyaXB0Q291bnRzIShnZW5lcyksXG4gICAgICAgICAgfVxuICAgICAgICA6IHt9KSxcbiAgICAgIC4uLihwb3J0LmdldE1hcmtlckdlbmVzXG4gICAgICAgID8ge1xuICAgICAgICAgICAgbWFya2VyR2VuZXM6IChjb2x1bW46IHN0cmluZywgcGVyR3JvdXA/OiBudW1iZXIpID0+IHBvcnQuZ2V0TWFya2VyR2VuZXMhKGNvbHVtbiwgcGVyR3JvdXApLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgICBnZXRUcmFuc2NyaXB0RXN0aW1hdGUkOiAoKSA9PiB0aGlzLmN0eC5uYXBhcmkudHJhbnNjcmlwdEVzdGltYXRlJC5hc09ic2VydmFibGUoKSxcbiAgICAgIGdldEdlbmVDb3VudHNJblZpZXckOiAoKSA9PiB0aGlzLmN0eC5uYXBhcmkuZ2VuZUNvdW50c0luVmlldyQuYXNPYnNlcnZhYmxlKCksXG4gICAgICBnZXREZW5zaXR5U3RhdHMkOiAoKSA9PiB0aGlzLmN0eC5uYXBhcmkuZGVuc2l0eVN0YXRzJC5hc09ic2VydmFibGUoKSxcbiAgICAgIGNhdGVnb3J5Q29sb3JzOiBhc3luYyAobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbHVtbiA9IGF3YWl0IHBvcnQuZ2V0Q29sdW1uKG5hbWUpO1xuICAgICAgICBpZiAoIWlzQ2F0ZWdvcmljYWxDb2x1bW4oY29sdW1uKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgW3NwYXRpYWxdIGNvbHVtbiBcIiR7bmFtZX1cIiBpcyBjb250aW51b3VzIOKAlCBpdCBoYXMgbm8gY2F0ZWdvcmllc2ApO1xuICAgICAgICB9XG4gICAgICAgIC8vIFJlc29sdmVkIGJ5IHRoZSBTQU1FIGZ1bmN0aW9uIHRoZSByZW5kZXJlciB1c2VzLCBzbyBhIGxlZ2VuZCBzd2F0Y2hcbiAgICAgICAgLy8gY2FuIG5ldmVyIGRpc2FncmVlIHdpdGggdGhlIGNvbG91ciBvbiBzY3JlZW4uXG4gICAgICAgIHJldHVybiByZXNvbHZlQ2F0ZWdvcnlDb2xvcnMoY29sdW1uLm1ldGEpO1xuICAgICAgfSxcblxuICAgICAgY29udGludW91c1ZhbHVlczogYXN5bmMgKHNvdXJjZSkgPT4ge1xuICAgICAgICBpZiAoc291cmNlLmtpbmQgPT09ICdmZWF0dXJlJykgcmV0dXJuIHBvcnQuZ2V0RmVhdHVyZVZlY3Rvcihzb3VyY2UubmFtZSk7XG4gICAgICAgIGNvbnN0IGNvbHVtbiA9IGF3YWl0IHBvcnQuZ2V0Q29sdW1uKHNvdXJjZS5uYW1lKTtcbiAgICAgICAgaWYgKGlzQ2F0ZWdvcmljYWxDb2x1bW4oY29sdW1uKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgW3NwYXRpYWxdIGNvbHVtbiBcIiR7c291cmNlLm5hbWV9XCIgaXMgY2F0ZWdvcmljYWwg4oCUIGl0IGhhcyBubyB2YWx1ZXMgdG8gY2hhcnRgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29sdW1uLnZhbHVlcztcbiAgICAgIH0sXG5cbiAgICAgIGNhdGVnb3JpY2FsVmlldzogYXN5bmMgKG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBhd2FpdCBwb3J0LmdldENvbHVtbihuYW1lKTtcbiAgICAgICAgaWYgKCFpc0NhdGVnb3JpY2FsQ29sdW1uKGNvbHVtbikpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFtzcGF0aWFsXSBjb2x1bW4gXCIke25hbWV9XCIgaXMgY29udGludW91cyDigJQgaXQgaGFzIG5vIGNhdGVnb3JpZXNgKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgY2F0ZWdvcmllczogY29sdW1uLm1ldGEuY2F0ZWdvcmllcyxcbiAgICAgICAgICBjb2xvcnM6IHJlc29sdmVDYXRlZ29yeUNvbG9ycyhjb2x1bW4ubWV0YSksXG4gICAgICAgICAgY29kZXM6IGNvbHVtbi5jb2RlcyxcbiAgICAgICAgfTtcbiAgICAgIH0sXG5cbiAgICAgIC8vIFNwcmVhZCByYXRoZXIgdGhhbiBhbHdheXMgZGVmaW5lZDogYGdldEVtYmVkZGluZ2AgaXMgb3B0aW9uYWwgb24gYm90aCB0aGUgcG9ydFxuICAgICAgLy8gYW5kIHRoaXMgZmFjYWRlLCBhbmQgYSBwYW5lbCBjaGVja3MgZm9yIGl0cyBwcmVzZW5jZSB0byBkZWNpZGUgd2hldGhlciB0aGUgdmlld1xuICAgICAgLy8gaXMgb2ZmZXJlZCBhdCBhbGwuIERlZmluaW5nIGl0IGFzIGEgZnVuY3Rpb24gdGhhdCByZWplY3RzIHdvdWxkIG1ha2UgYW5cbiAgICAgIC8vIGVtYmVkZGluZy1sZXNzIHNvdXJjZSBsb29rIGxpa2UgYSBicm9rZW4gb25lLlxuICAgICAgLi4uKHBvcnQuZ2V0RW1iZWRkaW5nID8geyBnZXRFbWJlZGRpbmc6IChuYW1lOiBzdHJpbmcpID0+IHBvcnQuZ2V0RW1iZWRkaW5nIShuYW1lKSB9IDoge30pLFxuXG4gICAgICBjYXRlZ29yaWNhbENvbHVtbnM6ICgpID0+XG4gICAgICAgICh0aGlzLmRhdGFzZXQ/LmNvbHVtbnMgPz8gW10pLmZpbHRlcigoYykgPT4gYy5raW5kID09PSAnY2F0ZWdvcmljYWwnKS5tYXAoKGMpID0+IGMubmFtZSksXG5cbiAgICAgIC8vIE1lbW9pemVkIG9uIHRoZSBvYnNlcnZhdGlvbnMgb2JqZWN0LCBzbyB0aGUgcmVuZGVyZXIncyBvd24gbG9va3VwIGFuZFxuICAgICAgLy8gdGhpcyBvbmUgYXJlIHRoZSBzYW1lIHNpbmdsZSBzY2FuIG9mIHVwIHRvIDMuN00geiB2YWx1ZXMuXG4gICAgICBzYW1wbGVkU2VjdGlvbnM6ICgpID0+IHtcbiAgICAgICAgY29uc3Qgb2JzID0gdGhpcy5kYXRhc2V0Py5vYnNlcnZhdGlvbnM7XG4gICAgICAgIHJldHVybiBvYnMgPyBzZWN0aW9uc09mKG9icykgOiBudWxsO1xuICAgICAgfSxcblxuICAgICAgZ2V0U2VsZWN0aW9uJDogKCkgPT4gdGhpcy5jdHguc2VsZWN0aW9uU3RvcmUuZ2V0U2VsZWN0aW9uJCgpLFxuXG4gICAgICBzZWxlY3RGcm9tUmVnaW9uczogKCkgPT4ge1xuICAgICAgICBjb25zdCBkYXRhc2V0ID0gdGhpcy5kYXRhc2V0O1xuICAgICAgICBpZiAoIWRhdGFzZXQpIHJldHVybiAwO1xuICAgICAgICBjb25zdCByZWdpb25zID0gdGhpcy5jdHgucmVnaW9uU3RvcmUuZ2V0UmVnaW9ucygpO1xuICAgICAgICAvLyBUaGUgdW5pb24gb2YgZXZlcnkgZHJhd24gcmVnaW9uIOKAlCBzbyBldmVyeSBST0kgdG9vbCB0aGUgbGlicmFyeVxuICAgICAgICAvLyBhbHJlYWR5IGhhcyBkb3VibGVzIGFzIGEgc3BhdGlhbCBzZWxlY3Rpb24gdG9vbC5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gSW4gdGhlIDNEIGNsb3VkIHRoZXJlIGlzIG5vIGRhdGEtc3BhY2UgYWZmaW5lIHRvIHB1c2ggYSBkcmF3biBzaGFwZVxuICAgICAgICAvLyB0aHJvdWdoLCBzbyB0aGUgb2JzZXJ2YXRpb25zIGFyZSBwcm9qZWN0ZWQgdG8gY2FudmFzIHBpeGVscyBieSB0aGVcbiAgICAgICAgLy8gcmVuZGVyZXIgKHdoaWNoIG93bnMgdGhlIGNhbWVyYSkgYW5kIHRlc3RlZCBpbiBzY3JlZW4gc3BhY2UgaW5zdGVhZC5cbiAgICAgICAgLy8gRmFsbHMgYmFjayB0byB0aGUgMkQgcGF0aCB3aGVuZXZlciB0aGUgY2xvdWQgaXMgbm90IG1vdW50ZWQuXG4gICAgICAgIGNvbnN0IHByb2plY3RlZCA9IGlzU3BhdGlhbE9taWNzM2QodGhpcy5jdHgucGxvdFR5cGUoKSlcbiAgICAgICAgICA/IHRoaXMuY3R4Lm5hcGFyaS5nZXRTcGF0aWFsU2NyZWVuUHJvamVjdGlvbihkYXRhc2V0Lm9ic2VydmF0aW9ucylcbiAgICAgICAgICA6IG51bGw7XG4gICAgICAgIC8vIEluIHRoZSAyRCB2aWV3IG9mIGEgdm9sdW1lLWJhY2tlZCBkYXRhc2V0IHRoZSBzaGFwZSB3YXMgZHJhd24gb3ZlciBPTkVcbiAgICAgICAgLy8gc2VjdGlvbiwgaW4gdGhlIHZvbHVtZSdzIHBpeGVsIGdyaWQ6IGl0IHNlbGVjdHMgdGhlIGNlbGxzIG9mIHRoYXRcbiAgICAgICAgLy8gc2VjdGlvbiwgbm90IHRoZSB3aG9sZSBkZXB0aCBvZiBicmFpbiBzdGFuZGluZyBiZWhpbmQgdGhlbS5cbiAgICAgICAgY29uc3Qgdm9sdW1lID0gIWRhdGFzZXQuaW1hZ2VSZWYgPyBkYXRhc2V0LnZvbHVtZSA6IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gcHJvamVjdGVkXG4gICAgICAgICAgPyBzZWxlY3RJblJlZ2lvbnNQcm9qZWN0ZWQocHJvamVjdGVkLCBkYXRhc2V0Lm9ic2VydmF0aW9ucy5jb3VudCwgcmVnaW9ucylcbiAgICAgICAgICA6IHNlbGVjdEluUmVnaW9ucyhcbiAgICAgICAgICAgICAgZGF0YXNldC5vYnNlcnZhdGlvbnMsXG4gICAgICAgICAgICAgIHZvbHVtZSA/IHZvbHVtZUltYWdlUmVmKHZvbHVtZSwgZGF0YXNldC5taWNyb25zUGVyVW5pdCkgOiBkYXRhc2V0LmltYWdlUmVmLFxuICAgICAgICAgICAgICByZWdpb25zLFxuICAgICAgICAgICAgICB2b2x1bWUgPyBvYnNlcnZhdGlvbnNJblNsaWNlKGRhdGFzZXQub2JzZXJ2YXRpb25zLCB2b2x1bWUsIHRoaXMuY3R4LnpJbmRleCgpKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuY3R4LnNlbGVjdGlvblN0b3JlLnNldChzZWxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gc2VsZWN0aW9uLmNvdW50O1xuICAgICAgfSxcblxuICAgICAgc2VsZWN0Q2F0ZWdvcnk6IGFzeW5jIChjb2x1bW46IHN0cmluZywgY2F0ZWdvcnlJbmRleDogbnVtYmVyKSA9PiB7XG4gICAgICAgIGNvbnN0IGxvYWRlZCA9IGF3YWl0IHBvcnQuZ2V0Q29sdW1uKGNvbHVtbik7XG4gICAgICAgIGlmICghaXNDYXRlZ29yaWNhbENvbHVtbihsb2FkZWQpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbc3BhdGlhbF0gY29sdW1uIFwiJHtjb2x1bW59XCIgaXMgY29udGludW91cyDigJQgaXQgaGFzIG5vIGNhdGVnb3JpZXNgKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBzZWxlY3RCeUNhdGVnb3J5KGxvYWRlZC5jb2RlcywgY2F0ZWdvcnlJbmRleCk7XG4gICAgICAgIHRoaXMuY3R4LnNlbGVjdGlvblN0b3JlLnNldChzZWxlY3Rpb24pO1xuICAgICAgICByZXR1cm4gc2VsZWN0aW9uLmNvdW50O1xuICAgICAgfSxcblxuICAgICAgc2VsZWN0SW5kaWNlczogKGluZGljZXM6IEl0ZXJhYmxlPG51bWJlcj4pID0+IHtcbiAgICAgICAgY29uc3QgY291bnQgPSB0aGlzLmRhdGFzZXQ/Lm9ic2VydmF0aW9ucy5jb3VudCA/PyAwO1xuICAgICAgICBpZiAoY291bnQgPT09IDApIHJldHVybiAwO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBzZWxlY3RCeUluZGljZXMoaW5kaWNlcywgY291bnQpO1xuICAgICAgICB0aGlzLmN0eC5zZWxlY3Rpb25TdG9yZS5zZXQoc2VsZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuIHNlbGVjdGlvbi5jb3VudDtcbiAgICAgIH0sXG5cbiAgICAgIGNsZWFyU2VsZWN0aW9uOiAoKSA9PiB0aGlzLmN0eC5zZWxlY3Rpb25TdG9yZS5jbGVhcigpLFxuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBXaGV0aGVyIGBkYXRhc2V0YCBjYW4gYW5zd2VyIHRoaXMgY29sb3VyIHNvdXJjZS4gQSBjb2x1bW4gaXMgY2hlY2thYmxlIGFnYWluc3QgdGhlXG4gKiBkZWNsYXJlZCBsaXN0LiBBIGdlbmUgaXMgY2hlY2thYmxlIG9ubHkgd2hlbiB0aGUgZGF0YXNldCBpbmxpbmVzIGl0cyBmZWF0dXJlIG5hbWVzIOKAlFxuICogYSBkYXRhc2V0IHRvbyB3aWRlIHRvIGlubGluZSB0aGVtICh0eXBlYWhlYWQtb25seSkga2VlcHMgdGhlIHNvdXJjZSwgYW5kIGEgbmFtZSB0aGF0XG4gKiB0dXJucyBvdXQgbm90IHRvIGV4aXN0IHN1cmZhY2VzIGFzIHRoZSBjaGFydCdzIFwiY291bGQgbm90IGJlIGNoYXJ0ZWRcIiByYXRoZXIgdGhhbiBhc1xuICogYSBzaWxlbnQgcmVzZXQuXG4gKi9cbmZ1bmN0aW9uIGNhbkNvbG9yQnkoZGF0YXNldDogU3BhdGlhbERhdGFzZXQgfCBudWxsLCBieTogU3BhdGlhbENvbG9yQnkpOiBib29sZWFuIHtcbiAgaWYgKCFkYXRhc2V0KSByZXR1cm4gZmFsc2U7XG4gIGlmIChieS5raW5kID09PSAnY29sdW1uJykgcmV0dXJuIGRhdGFzZXQuY29sdW1ucy5zb21lKChjKSA9PiBjLm5hbWUgPT09IGJ5Lm5hbWUpO1xuICBjb25zdCBuYW1lcyA9IGRhdGFzZXQuZmVhdHVyZXM/Lm5hbWVzO1xuICByZXR1cm4gISFkYXRhc2V0LmZlYXR1cmVzICYmICghbmFtZXMgfHwgbmFtZXMuaW5jbHVkZXMoYnkubmFtZSkpO1xufVxuIl19