@jax-data-science/sci-image-visualizer 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +361 -4184
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34430
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -878
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,274 @@
1
+ import { colormapFromLut } from 'napari-js';
2
+ import { NO_CATEGORY, isCategoricalColumn, } from '../../../contracts/spatial-dataset.contract';
3
+ import { DEFAULT_CATEGORICAL_PALETTE, MISSING_COLOR, contrastWindow, parseHex, resolveCategoryColors, } from '../../../spatial/spatial-encoding';
4
+ import { POLYGON_LEVEL_MIN_CELL_PX, cellTypeColumnFor, cellsShown, polygonLevelFor, tileId, tilesInRect, typicalCellDiameter, } from '../../../spatial/lod';
5
+ import { filterRings, mergePolygonTiles } from '../../../spatial/spatial-tile-merge';
6
+ import { ContrastWindowCache } from '../napari-spatial-encoding';
7
+ const MAX_CELL_TILES = 48;
8
+ /**
9
+ * The cell outlines of the 2D spatial view, at the polygon level the zoom calls for: a fill,
10
+ * an outline or both (plus nucleus outlines for the "both" cell set), coloured by the view's
11
+ * cell-colour mode, with switched-off groups left out of the geometry.
12
+ *
13
+ * Geometry and style are keyed apart, so a recolour (a new cell-type column, a selection)
14
+ * rewrites the per-shape values of the existing layers and never re-expands the rings.
15
+ */
16
+ export class CellLayers {
17
+ constructor(port, groups, lookup, host) {
18
+ this.port = port;
19
+ this.groups = groups;
20
+ this.lookup = lookup;
21
+ this.host = host;
22
+ this.polygonsShown = false;
23
+ /** Rings currently drawn and the (dataset, set, tiles) they came from. */
24
+ this.currentRings = null;
25
+ this.cellGeometryKey = null;
26
+ this.currentNuclei = null;
27
+ this.cellStyleKey = null;
28
+ /** Selection identity → revision, so a change key can name a selection cheaply. */
29
+ this.lastSelection = null;
30
+ this.selectionRevision = 0;
31
+ /** Continuous colourings' windows, per (vector, clip, log): `contrastWindow` sorts every
32
+ * value, and a selection or opacity change recolours with the vector unchanged (SPATIAL-12). */
33
+ this.contrastWindows = new ContrastWindowCache();
34
+ }
35
+ /** True while outlines are on screen — the service hides its dots then. */
36
+ get outlinesShown() {
37
+ return this.polygonsShown;
38
+ }
39
+ /** The viewer went away (its layers with it): the outlines are no longer shown. */
40
+ detached() {
41
+ this.setPolygonsShown(false);
42
+ }
43
+ /** Draw the cells covering `rect` at the level `pxPerUnit` calls for, or drop them. */
44
+ async plan(dataset, view, selection, rect, pxPerUnit, ctx) {
45
+ const tiled = dataset.polygonTiles;
46
+ const whole = !tiled && dataset.polygons && this.port.getPolygons;
47
+ if (!cellsShown(dataset, view) || (!tiled && !whole)) {
48
+ this.drop();
49
+ return;
50
+ }
51
+ const diameter = typicalCellDiameter(dataset.observations.radius);
52
+ // Whole-dataset rings have one level and no coarser fallback, so they are drawn as
53
+ // soon as a cell is big enough to read as a shape rather than a dot.
54
+ const level = tiled
55
+ ? polygonLevelFor(pxPerUnit, diameter, tiled.levels.length)
56
+ : pxPerUnit * diameter >= POLYGON_LEVEL_MIN_CELL_PX[2]
57
+ ? 0
58
+ : -1;
59
+ if (level < 0) {
60
+ this.drop();
61
+ return;
62
+ }
63
+ // Groups switched off in the list: their cells are left out of the geometry.
64
+ const hidden = await this.lookup.hiddenCodes(dataset, view);
65
+ if (ctx.stale())
66
+ return;
67
+ const label = view.cellSet === 'both' ? 'Cells and nuclei' : view.cellSet === 'nucleus' ? 'Nuclei' : 'Cells';
68
+ const geometry = await ctx.track(label, this.cellGeometry(dataset, view, rect, level, hidden, ctx));
69
+ if (!geometry)
70
+ return;
71
+ const { rings, nuclei, geometryKey } = geometry;
72
+ const geometryChanged = geometryKey !== this.cellGeometryKey;
73
+ const styleKey = [
74
+ geometryKey,
75
+ view.cellColorMode,
76
+ view.cellColorGene,
77
+ view.cellSingleColor,
78
+ cellTypeColumnFor(dataset, view),
79
+ this.selectionRev(selection),
80
+ view.logScale,
81
+ view.percentileClip.join(),
82
+ JSON.stringify(view.continuousColormap),
83
+ view.cellDraw,
84
+ view.cellOpacity,
85
+ ].join('|');
86
+ const present = ['cellFill', 'cellOutline', 'nucleusOutline'].some((g) => this.groups.shown(g));
87
+ if (!geometryChanged && styleKey === this.cellStyleKey && present) {
88
+ this.setPolygonsShown(true);
89
+ return;
90
+ }
91
+ const colors = await this.cellColors(dataset, view, selection, rings.observation);
92
+ if (ctx.stale())
93
+ return;
94
+ this.currentRings = rings;
95
+ this.currentNuclei = nuclei;
96
+ // A geometry missing a failed tile is drawn but not remembered, so the retry refetches it.
97
+ this.cellGeometryKey = ctx.incomplete ? null : geometryKey;
98
+ this.cellStyleKey = styleKey;
99
+ this.drawCells(dataset, view, geometry, colors, geometryChanged);
100
+ this.setPolygonsShown(true);
101
+ }
102
+ /**
103
+ * The cell layers: the fill and the outline the view's draw mode asks for, and with "both" the
104
+ * nucleus outlines over them. A geometry change builds new layers; a style change restyles them.
105
+ */
106
+ drawCells(dataset, view, { rings, nuclei }, colors, geometryChanged) {
107
+ const ref = dataset.imageRef;
108
+ const common = { scale: ref?.scale ?? [1, 1], translate: ref?.translate ?? [0, 0] };
109
+ const fill = view.cellDraw !== 'outline';
110
+ const outline = view.cellDraw !== 'fill';
111
+ this.groups.upsertShapes('cellFill', fill, geometryChanged, rings, {
112
+ name: 'cells',
113
+ draw: 'fill',
114
+ opacity: view.cellOpacity,
115
+ ...colors,
116
+ ...common,
117
+ });
118
+ this.groups.upsertShapes('cellOutline', outline, geometryChanged, rings, fill
119
+ ? // Over a fill, a dark outline separates neighbours of the same type.
120
+ { name: 'cell outlines', draw: 'outline', color: [0.08, 0.08, 0.1, 1], opacity: 0.7, ...common }
121
+ : { name: 'cell outlines', draw: 'outline', opacity: 1, ...colors, ...common });
122
+ // "Both": nuclei outlined over the cells, light so they read against any fill.
123
+ if (nuclei) {
124
+ this.groups.upsertShapes('nucleusOutline', true, geometryChanged, nuclei, {
125
+ name: 'nucleus outlines',
126
+ draw: 'outline',
127
+ color: [0.95, 0.95, 0.98, 1],
128
+ opacity: 0.8,
129
+ ...common,
130
+ });
131
+ }
132
+ else {
133
+ this.groups.drop('nucleusOutline');
134
+ }
135
+ }
136
+ selectionRev(selection) {
137
+ if (selection !== this.lastSelection) {
138
+ this.lastSelection = selection;
139
+ this.selectionRevision++;
140
+ }
141
+ return this.selectionRevision;
142
+ }
143
+ /**
144
+ * The rings' colours by their owners, by the view's cell-colour mode (Xenium Explorer's "Cell
145
+ * Color"): one RGBA per shape for a grouping, values + colormap for a measurement, one colour
146
+ * for "single". A selection mutes what it leaves out.
147
+ */
148
+ async cellColors(dataset, view, selection, owners) {
149
+ const muted = selection.count > 0 ? selection.mask : null;
150
+ const mode = view.cellColorMode;
151
+ if (mode === 'single') {
152
+ const [r, g, b] = parseHex(view.cellSingleColor);
153
+ return { color: [r / 255, g / 255, b / 255, 1] };
154
+ }
155
+ const continuous = async (raw, log) => {
156
+ const values = new Float32Array(owners.length);
157
+ for (let i = 0; i < owners.length; i++) {
158
+ const v = raw[owners[i]] ?? NaN;
159
+ values[i] = log ? Math.log1p(Math.max(0, v)) : v;
160
+ }
161
+ const [clipLo, clipHi] = view.percentileClip;
162
+ // Keyed by the SOURCE vector (the log copy would be new on every call), as the 3D cloud's.
163
+ const [lo, hi] = this.contrastWindows.get(raw, clipLo, clipHi, log, () => contrastWindow(log ? raw.map((v) => Math.log1p(Math.max(0, v))) : raw, clipLo, clipHi));
164
+ return {
165
+ values,
166
+ colormap: colormapFromLut('spatial-continuous', this.host.continuousLut(view)),
167
+ contrastLimits: [lo, hi],
168
+ };
169
+ };
170
+ if (mode === 'gene' && view.cellColorGene) {
171
+ return continuous(await this.port.getFeatureVector(view.cellColorGene), true);
172
+ }
173
+ if (mode === 'transcriptDensity' && dataset.columns.some((c) => c.name === 'transcript_density')) {
174
+ const column = await this.port.getColumn('transcript_density');
175
+ if (!isCategoricalColumn(column))
176
+ return continuous(column.values, false);
177
+ }
178
+ const name = mode === 'segmentation' && dataset.columns.some((c) => c.name === 'segmentation_method')
179
+ ? 'segmentation_method'
180
+ : cellTypeColumnFor(dataset, view);
181
+ const codes = name ? await this.lookup.codes(name) : null;
182
+ const palette = categoryRgba(codes?.meta ?? null);
183
+ const missing = rgba01(MISSING_COLOR);
184
+ // One RGBA per shape (napari Shapes' `face_color`): any number of categories keeps its own
185
+ // colour, where a colormap band per category ran out of LUT entries past ~127.
186
+ const faceColor = new Float32Array(owners.length * 4);
187
+ for (let i = 0; i < owners.length; i++) {
188
+ const o = owners[i];
189
+ const code = !codes || (muted && !muted[o]) ? NO_CATEGORY : codes.codes[o];
190
+ faceColor.set(palette[code] ?? missing, i * 4);
191
+ }
192
+ return { faceColor };
193
+ }
194
+ /**
195
+ * The cell rings (and, for "both", the nucleus rings) covering `rect` at `level`, minus
196
+ * the hidden groups — reused when nothing that decides them changed. Null when the
197
+ * view went stale or the dataset has no set to draw.
198
+ */
199
+ async cellGeometry(dataset, view, rect, level, hidden, ctx) {
200
+ const tiled = dataset.polygonTiles;
201
+ const hiddenKey = view.hiddenGroups.join('\u0001');
202
+ let rings;
203
+ let nuclei = null;
204
+ let geometryKey;
205
+ if (tiled) {
206
+ const both = view.cellSet === 'both';
207
+ const set = !both && view.cellSet && tiled.sets.some((s) => s.name === view.cellSet)
208
+ ? view.cellSet
209
+ : (tiled.defaultSet ?? tiled.sets[0]?.name);
210
+ if (!set)
211
+ return null;
212
+ const nucleusSet = both ? tiled.sets.find((s) => s.name !== set)?.name : undefined;
213
+ const keys = tilesInRect(rect, level, tiled.levels, tiled.bounds, MAX_CELL_TILES);
214
+ geometryKey = `${dataset.id}|${set}|${nucleusSet ?? ''}|${hiddenKey}|${keys.map(tileId).join(',')}`;
215
+ if (geometryKey === this.cellGeometryKey && this.currentRings) {
216
+ rings = this.currentRings;
217
+ nuclei = this.currentNuclei;
218
+ }
219
+ else {
220
+ const [tiles, nucleusTiles] = await Promise.all([
221
+ ctx.fetchAll(keys, (k) => this.port.getPolygonTile(set, k.level, k.gx, k.gy)),
222
+ nucleusSet
223
+ ? ctx.fetchAll(keys, (k) => this.port.getPolygonTile(nucleusSet, k.level, k.gx, k.gy))
224
+ : Promise.resolve(null),
225
+ ]);
226
+ if (ctx.stale())
227
+ return null;
228
+ rings = filterRings(mergePolygonTiles(tiles), hidden);
229
+ nuclei = nucleusTiles ? filterRings(mergePolygonTiles(nucleusTiles), hidden) : null;
230
+ }
231
+ }
232
+ else {
233
+ geometryKey = `${dataset.id}|whole|${hiddenKey}`;
234
+ if (geometryKey === this.cellGeometryKey && this.currentRings) {
235
+ rings = this.currentRings;
236
+ }
237
+ else {
238
+ const polys = await this.port.getPolygons();
239
+ if (ctx.stale())
240
+ return null;
241
+ // Whole-dataset rings are index-aligned with the observations.
242
+ rings = filterRings({ ...polys, observation: Uint32Array.from({ length: polys.count }, (_v, i) => i) }, hidden);
243
+ }
244
+ }
245
+ return { rings, nuclei, geometryKey };
246
+ }
247
+ /** Remove the cell layers and forget what they showed. */
248
+ drop() {
249
+ this.groups.drop('cellFill');
250
+ this.groups.drop('cellOutline');
251
+ this.groups.drop('nucleusOutline');
252
+ this.currentNuclei = null;
253
+ this.cellGeometryKey = null;
254
+ this.cellStyleKey = null;
255
+ this.currentRings = null;
256
+ this.setPolygonsShown(false);
257
+ }
258
+ setPolygonsShown(shown) {
259
+ if (shown === this.polygonsShown)
260
+ return;
261
+ this.polygonsShown = shown;
262
+ this.host.polygonsShownChanged(shown);
263
+ }
264
+ }
265
+ /** An 8-bit RGB as an opaque 0..1 RGBA. */
266
+ function rgba01([r, g, b]) {
267
+ return [r / 255, g / 255, b / 255, 1];
268
+ }
269
+ /** A grouping's category colours, as 0..1 RGBA by category code (one default without a grouping). */
270
+ function categoryRgba(meta) {
271
+ const hex = meta && meta.kind === 'categorical' ? resolveCategoryColors(meta) : [DEFAULT_CATEGORICAL_PALETTE[0]];
272
+ return hex.map((h) => rgba01(parseHex(h)));
273
+ }
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbC1sYXllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9uYXBhcmktanMvc3BhdGlhbC10aWxlcy9jZWxsLWxheWVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBTTVDLE9BQU8sRUFDTCxXQUFXLEVBS1gsbUJBQW1CLEdBQ3BCLE1BQU0sNkNBQTZDLENBQUM7QUFDckQsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixhQUFhLEVBQ2IsY0FBYyxFQUNkLFFBQVEsRUFDUixxQkFBcUIsR0FDdEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUUzQyxPQUFPLEVBRUwseUJBQXlCLEVBQ3pCLGlCQUFpQixFQUNqQixVQUFVLEVBQ1YsZUFBZSxFQUNmLE1BQU0sRUFDTixXQUFXLEVBQ1gsbUJBQW1CLEdBQ3BCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3JGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBS2pFLE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQztBQW9CMUI7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBY3JCLFlBQ21CLElBQXFCLEVBQ3JCLE1BQXFDLEVBQ3JDLE1BQXlCLEVBQ3pCLElBQW9CO1FBSHBCLFNBQUksR0FBSixJQUFJLENBQWlCO1FBQ3JCLFdBQU0sR0FBTixNQUFNLENBQStCO1FBQ3JDLFdBQU0sR0FBTixNQUFNLENBQW1CO1FBQ3pCLFNBQUksR0FBSixJQUFJLENBQWdCO1FBakIvQixrQkFBYSxHQUFHLEtBQUssQ0FBQztRQUM5QiwwRUFBMEU7UUFDbEUsaUJBQVksR0FBOEIsSUFBSSxDQUFDO1FBQy9DLG9CQUFlLEdBQWtCLElBQUksQ0FBQztRQUN0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cG9ydCB7IGNvbG9ybWFwRnJvbUx1dCB9IGZyb20gJ25hcGFyaS1qcyc7XG5pbXBvcnQgdHlwZSB7IENvbG9ybWFwLCBSR0JBIH0gZnJvbSAnbmFwYXJpLWpzJztcblxuaW1wb3J0IHR5cGUgeyBSZ2IgfSBmcm9tICcuLi8uLi8uLi9jb250cmFjdHMvY29sb3JtYXAtbHV0JztcbmltcG9ydCB0eXBlIHsgU3BhdGlhbERhdGFQb3J0IH0gZnJvbSAnLi4vLi4vLi4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB0eXBlIHsgU3BhdGlhbFZpZXdTdGF0ZSB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9kaXNwbGF5LXR5cGVzJztcbmltcG9ydCB7XG4gIE5PX0NBVEVHT1JZLFxuICBTcGF0aWFsQ29sdW1uLFxuICBTcGF0aWFsRGF0YXNldCxcbiAgU3BhdGlhbFBvbHlnb25UaWxlLFxuICBTcGF0aWFsUG9seWdvbnMsXG4gIGlzQ2F0ZWdvcmljYWxDb2x1bW4sXG59IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9zcGF0aWFsLWRhdGFzZXQuY29udHJhY3QnO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFLFxuICBNSVNTSU5HX0NPTE9SLFxuICBjb250cmFzdFdpbmRvdyxcbiAgcGFyc2VIZXgsXG4gIHJlc29sdmVDYXRlZ29yeUNvbG9ycyxcbn0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB7IFNwYXRpYWxTZWxlY3Rpb25NYXNrIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXNlbGVjdGlvbic7XG5pbXBvcnQge1xuICBEYXRhUmVjdCxcbiAgUE9MWUdPTl9MRVZFTF9NSU5fQ0VMTF9QWCxcbiAgY2VsbFR5cGVDb2x1bW5Gb3IsXG4gIGNlbGxzU2hvd24sXG4gIHBvbHlnb25MZXZlbEZvcixcbiAgdGlsZUlkLFxuICB0aWxlc0luUmVjdCxcbiAgdHlwaWNhbENlbGxEaWFtZXRlcixcbn0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9sb2QnO1xuaW1wb3J0IHsgZmlsdGVyUmluZ3MsIG1lcmdlUG9seWdvblRpbGVzIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXRpbGUtbWVyZ2UnO1xuaW1wb3J0IHsgQ29udHJhc3RXaW5kb3dDYWNoZSB9IGZyb20gJy4uL25hcGFyaS1zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB0eXBlIHsgQ2F0ZWdvcmljYWxMb29rdXAsIEhpZGRlbkNvZGVzIH0gZnJvbSAnLi9jYXRlZ29yaWNhbC1sb29rdXAnO1xuaW1wb3J0IHR5cGUgeyBPcmRlcmVkTGF5ZXJHcm91cHMsIFRpbGVHcm91cCB9IGZyb20gJy4vbGF5ZXItZ3JvdXBzJztcbmltcG9ydCB0eXBlIHsgUGxhbkNvbnRleHQgfSBmcm9tICcuL3BsYW4tY29udGV4dCc7XG5cbmNvbnN0IE1BWF9DRUxMX1RJTEVTID0gNDg7XG5cbi8qKiBUaGUgY2VsbHMnIGNvbG91cnMgYXMgYSBzaGFwZXMgbGF5ZXIgdGFrZXMgdGhlbTogcGVyLXNoYXBlIFJHQkEsIHZhbHVlcyBvdmVyIGEgY29sb3JtYXAsIG9yXG4gKiAgb25lIGNvbG91ci4gKi9cbmludGVyZmFjZSBDZWxsQ29sb3JzIHtcbiAgdmFsdWVzPzogRmxvYXQzMkFycmF5O1xuICBjb2xvcm1hcD86IENvbG9ybWFwO1xuICBjb250cmFzdExpbWl0cz86IFtudW1iZXIsIG51bWJlcl07XG4gIGNvbG9yPzogUkdCQTtcbiAgZmFjZUNvbG9yPzogRmxvYXQzMkFycmF5O1xufVxuXG4vKiogV2hhdCB0aGUgY2VsbCBsYXllcnMgbmVlZCBmcm9tIHRoZSBzZXJ2aWNlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDZWxsTGF5ZXJzSG9zdCB7XG4gIC8qKiBUaGUgY29udGludW91cyBMVVQgdGhlIHZpZXcgaXMgdXNpbmcgKHNvIGNlbGxzIGNvbG91cmVkIGJ5IGEgZ2VuZSBtYXRjaCB0aGUgbWFya2VycykuICovXG4gIGNvbnRpbnVvdXNMdXQodmlldzogU3BhdGlhbFZpZXdTdGF0ZSk6IFJnYltdO1xuICAvKiogT3V0bGluZXMgYXBwZWFyZWQgb3IgZGlzYXBwZWFyZWQ6IHRoZSBtYXJrZXJzJyB2aXNpYmlsaXR5IGZvbGxvd3MuICovXG4gIHBvbHlnb25zU2hvd25DaGFuZ2VkKHNob3duOiBib29sZWFuKTogdm9pZDtcbn1cblxuLyoqXG4gKiBUaGUgY2VsbCBvdXRsaW5lcyBvZiB0aGUgMkQgc3BhdGlhbCB2aWV3LCBhdCB0aGUgcG9seWdvbiBsZXZlbCB0aGUgem9vbSBjYWxscyBmb3I6IGEgZmlsbCxcbiAqIGFuIG91dGxpbmUgb3IgYm90aCAocGx1cyBudWNsZXVzIG91dGxpbmVzIGZvciB0aGUgXCJib3RoXCIgY2VsbCBzZXQpLCBjb2xvdXJlZCBieSB0aGUgdmlldydzXG4gKiBjZWxsLWNvbG91ciBtb2RlLCB3aXRoIHN3aXRjaGVkLW9mZiBncm91cHMgbGVmdCBvdXQgb2YgdGhlIGdlb21ldHJ5LlxuICpcbiAqIEdlb21ldHJ5IGFuZCBzdHlsZSBhcmUga2V5ZWQgYXBhcnQsIHNvIGEgcmVjb2xvdXIgKGEgbmV3IGNlbGwtdHlwZSBjb2x1bW4sIGEgc2VsZWN0aW9uKVxuICogcmV3cml0ZXMgdGhlIHBlci1zaGFwZSB2YWx1ZXMgb2YgdGhlIGV4aXN0aW5nIGxheWVycyBhbmQgbmV2ZXIgcmUtZXhwYW5kcyB0aGUgcmluZ3MuXG4gKi9cbmV4cG9ydCBjbGFzcyBDZWxsTGF5ZXJzIHtcbiAgcHJpdmF0ZSBwb2x5Z29uc1Nob3duID0gZmFsc2U7XG4gIC8qKiBSaW5ncyBjdXJyZW50bHkgZHJhd24gYW5kIHRoZSAoZGF0YXNldCwgc2V0LCB0aWxlcykgdGhleSBjYW1lIGZyb20uICovXG4gIHByaXZhdGUgY3VycmVudFJpbmdzOiBTcGF0aWFsUG9seWdvblRpbGUgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjZWxsR2VvbWV0cnlLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGN1cnJlbnROdWNsZWk6IFNwYXRpYWxQb2x5Z29uVGlsZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGNlbGxTdHlsZUtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBTZWxlY3Rpb24gaWRlbnRpdHkg4oaSIHJldmlzaW9uLCBzbyBhIGNoYW5nZSBrZXkgY2FuIG5hbWUgYSBzZWxlY3Rpb24gY2hlYXBseS4gKi9cbiAgcHJpdmF0ZSBsYXN0U2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNlbGVjdGlvblJldmlzaW9uID0gMDtcbiAgLyoqIENvbnRpbnVvdXMgY29sb3VyaW5ncycgd2luZG93cywgcGVyICh2ZWN0b3IsIGNsaXAsIGxvZyk6IGBjb250cmFzdFdpbmRvd2Agc29ydHMgZXZlcnlcbiAgICogIHZhbHVlLCBhbmQgYSBzZWxlY3Rpb24gb3Igb3BhY2l0eSBjaGFuZ2UgcmVjb2xvdXJzIHdpdGggdGhlIHZlY3RvciB1bmNoYW5nZWQgKFNQQVRJQUwtMTIpLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbnRyYXN0V2luZG93cyA9IG5ldyBDb250cmFzdFdpbmRvd0NhY2hlKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwb3J0OiBTcGF0aWFsRGF0YVBvcnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBncm91cHM6IE9yZGVyZWRMYXllckdyb3VwczxUaWxlR3JvdXA+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9va3VwOiBDYXRlZ29yaWNhbExvb2t1cCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhvc3Q6IENlbGxMYXllcnNIb3N0LFxuICApIHt9XG5cbiAgLyoqIFRydWUgd2hpbGUgb3V0bGluZXMgYXJlIG9uIHNjcmVlbiDigJQgdGhlIHNlcnZpY2UgaGlkZXMgaXRzIGRvdHMgdGhlbi4gKi9cbiAgZ2V0IG91dGxpbmVzU2hvd24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucG9seWdvbnNTaG93bjtcbiAgfVxuXG4gIC8qKiBUaGUgdmlld2VyIHdlbnQgYXdheSAoaXRzIGxheWVycyB3aXRoIGl0KTogdGhlIG91dGxpbmVzIGFyZSBubyBsb25nZXIgc2hvd24uICovXG4gIGRldGFjaGVkKCk6IHZvaWQge1xuICAgIHRoaXMuc2V0UG9seWdvbnNTaG93bihmYWxzZSk7XG4gIH1cblxuICAvKiogRHJhdyB0aGUgY2VsbHMgY292ZXJpbmcgYHJlY3RgIGF0IHRoZSBsZXZlbCBgcHhQZXJVbml0YCBjYWxscyBmb3IsIG9yIGRyb3AgdGhlbS4gKi9cbiAgYXN5bmMgcGxhbihcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCxcbiAgICB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLFxuICAgIHNlbGVjdGlvbjogU3BhdGlhbFNlbGVjdGlvbk1hc2ssXG4gICAgcmVjdDogRGF0YVJlY3QsXG4gICAgcHhQZXJVbml0OiBudW1iZXIsXG4gICAgY3R4OiBQbGFuQ29udGV4dCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdGlsZWQgPSBkYXRhc2V0LnBvbHlnb25UaWxlcztcbiAgICBjb25zdCB3aG9sZSA9ICF0aWxlZCAmJiBkYXRhc2V0LnBvbHlnb25zICYmIHRoaXMucG9ydC5nZXRQb2x5Z29ucztcbiAgICBpZiAoIWNlbGxzU2hvd24oZGF0YXNldCwgdmlldykgfHwgKCF0aWxlZCAmJiAhd2hvbGUpKSB7XG4gICAgICB0aGlzLmRyb3AoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZGlhbWV0ZXIgPSB0eXBpY2FsQ2VsbERpYW1ldGVyKGRhdGFzZXQub2JzZXJ2YXRpb25zLnJhZGl1cyk7XG4gICAgLy8gV2hvbGUtZGF0YXNldCByaW5ncyBoYXZlIG9uZSBsZXZlbCBhbmQgbm8gY29hcnNlciBmYWxsYmFjaywgc28gdGhleSBhcmUgZHJhd24gYXNcbiAgICAvLyBzb29uIGFzIGEgY2VsbCBpcyBiaWcgZW5vdWdoIHRvIHJlYWQgYXMgYSBzaGFwZSByYXRoZXIgdGhhbiBhIGRvdC5cbiAgICBjb25zdCBsZXZlbCA9IHRpbGVkXG4gICAgICA/IHBvbHlnb25MZXZlbEZvcihweFBlclVuaXQsIGRpYW1ldGVyLCB0aWxlZC5sZXZlbHMubGVuZ3RoKVxuICAgICAgOiBweFBlclVuaXQgKiBkaWFtZXRlciA+PSBQT0xZR09OX0xFVkVMX01JTl9DRUxMX1BYWzJdXG4gICAgICAgID8gMFxuICAgICAgICA6IC0xO1xuICAgIGlmIChsZXZlbCA8IDApIHtcbiAgICAgIHRoaXMuZHJvcCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEdyb3VwcyBzd2l0Y2hlZCBvZmYgaW4gdGhlIGxpc3Q6IHRoZWlyIGNlbGxzIGFyZSBsZWZ0IG91dCBvZiB0aGUgZ2VvbWV0cnkuXG4gICAgY29uc3QgaGlkZGVuID0gYXdhaXQgdGhpcy5sb29rdXAuaGlkZGVuQ29kZXMoZGF0YXNldCwgdmlldyk7XG4gICAgaWYgKGN0eC5zdGFsZSgpKSByZXR1cm47XG4gICAgY29uc3QgbGFiZWwgPSB2aWV3LmNlbGxTZXQgPT09ICdib3RoJyA/ICdDZWxscyBhbmQgbnVjbGVpJyA6IHZpZXcuY2VsbFNldCA9PT0gJ251Y2xldXMnID8gJ051Y2xlaScgOiAnQ2VsbHMnO1xuICAgIGNvbnN0IGdlb21ldHJ5ID0gYXdhaXQgY3R4LnRyYWNrKGxhYmVsLCB0aGlzLmNlbGxHZW9tZXRyeShkYXRhc2V0LCB2aWV3LCByZWN0LCBsZXZlbCwgaGlkZGVuLCBjdHgpKTtcbiAgICBpZiAoIWdlb21ldHJ5KSByZXR1cm47XG4gICAgY29uc3QgeyByaW5ncywgbnVjbGVpLCBnZW9tZXRyeUtleSB9ID0gZ2VvbWV0cnk7XG5cbiAgICBjb25zdCBnZW9tZXRyeUNoYW5nZWQgPSBnZW9tZXRyeUtleSAhPT0gdGhpcy5jZWxsR2VvbWV0cnlLZXk7XG4gICAgY29uc3Qgc3R5bGVLZXkgPSBbXG4gICAgICBnZW9tZXRyeUtleSxcbiAgICAgIHZpZXcuY2VsbENvbG9yTW9kZSxcbiAgICAgIHZpZXcuY2VsbENvbG9yR2VuZSxcbiAgICAgIHZpZXcuY2VsbFNpbmdsZUNvbG9yLFxuICAgICAgY2VsbFR5cGVDb2x1bW5Gb3IoZGF0YXNldCwgdmlldyksXG4gICAgICB0aGlzLnNlbGVjdGlvblJldihzZWxlY3Rpb24pLFxuICAgICAgdmlldy5sb2dTY2FsZSxcbiAgICAgIHZpZXcucGVyY2VudGlsZUNsaXAuam9pbigpLFxuICAgICAgSlNPTi5zdHJpbmdpZnkodmlldy5jb250aW51b3VzQ29sb3JtYXApLFxuICAgICAgdmlldy5jZWxsRHJhdyxcbiAgICAgIHZpZXcuY2VsbE9wYWNpdHksXG4gICAgXS5qb2luKCd8Jyk7XG4gICAgY29uc3QgcHJlc2VudCA9IChbJ2NlbGxGaWxsJywgJ2NlbGxPdXRsaW5lJywgJ251Y2xldXNPdXRsaW5lJ10gYXMgY29uc3QpLnNvbWUoKGcpID0+IHRoaXMuZ3JvdXBzLnNob3duKGcpKTtcbiAgICBpZiAoIWdlb21ldHJ5Q2hhbmdlZCAmJiBzdHlsZUtleSA9PT0gdGhpcy5jZWxsU3R5bGVLZXkgJiYgcHJlc2VudCkge1xuICAgICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjb2xvcnMgPSBhd2FpdCB0aGlzLmNlbGxDb2xvcnMoZGF0YXNldCwgdmlldywgc2VsZWN0aW9uLCByaW5ncy5vYnNlcnZhdGlvbik7XG4gICAgaWYgKGN0eC5zdGFsZSgpKSByZXR1cm47XG5cbiAgICB0aGlzLmN1cnJlbnRSaW5ncyA9IHJpbmdzO1xuICAgIHRoaXMuY3VycmVudE51Y2xlaSA9IG51Y2xlaTtcbiAgICAvLyBBIGdlb21ldHJ5IG1pc3NpbmcgYSBmYWlsZWQgdGlsZSBpcyBkcmF3biBidXQgbm90IHJlbWVtYmVyZWQsIHNvIHRoZSByZXRyeSByZWZldGNoZXMgaXQuXG4gICAgdGhpcy5jZWxsR2VvbWV0cnlLZXkgPSBjdHguaW5jb21wbGV0ZSA/IG51bGwgOiBnZW9tZXRyeUtleTtcbiAgICB0aGlzLmNlbGxTdHlsZUtleSA9IHN0eWxlS2V5O1xuICAgIHRoaXMuZHJhd0NlbGxzKGRhdGFzZXQsIHZpZXcsIGdlb21ldHJ5LCBjb2xvcnMsIGdlb21ldHJ5Q2hhbmdlZCk7XG4gICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjZWxsIGxheWVyczogdGhlIGZpbGwgYW5kIHRoZSBvdXRsaW5lIHRoZSB2aWV3J3MgZHJhdyBtb2RlIGFza3MgZm9yLCBhbmQgd2l0aCBcImJvdGhcIiB0aGVcbiAgICogbnVjbGV1cyBvdXRsaW5lcyBvdmVyIHRoZW0uIEEgZ2VvbWV0cnkgY2hhbmdlIGJ1aWxkcyBuZXcgbGF5ZXJzOyBhIHN0eWxlIGNoYW5nZSByZXN0eWxlcyB0aGVtLlxuICAgKi9cbiAgcHJpdmF0ZSBkcmF3Q2VsbHMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICB7IHJpbmdzLCBudWNsZWkgfTogeyByaW5nczogU3BhdGlhbFBvbHlnb25UaWxlOyBudWNsZWk6IFNwYXRpYWxQb2x5Z29uVGlsZSB8IG51bGwgfSxcbiAgICBjb2xvcnM6IENlbGxDb2xvcnMsXG4gICAgZ2VvbWV0cnlDaGFuZ2VkOiBib29sZWFuLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCByZWYgPSBkYXRhc2V0LmltYWdlUmVmO1xuICAgIGNvbnN0IGNvbW1vbiA9IHsgc2NhbGU6IHJlZj8uc2NhbGUgPz8gWzEsIDFdLCB0cmFuc2xhdGU6IHJlZj8udHJhbnNsYXRlID8/IFswLCAwXSB9IGFzIGNvbnN0O1xuICAgIGNvbnN0IGZpbGwgPSB2aWV3LmNlbGxEcmF3ICE9PSAnb3V0bGluZSc7XG4gICAgY29uc3Qgb3V0bGluZSA9IHZpZXcuY2VsbERyYXcgIT09ICdmaWxsJztcblxuICAgIHRoaXMuZ3JvdXBzLnVwc2VydFNoYXBlcygnY2VsbEZpbGwnLCBmaWxsLCBnZW9tZXRyeUNoYW5nZWQsIHJpbmdzLCB7XG4gICAgICBuYW1lOiAnY2VsbHMnLFxuICAgICAgZHJhdzogJ2ZpbGwnLFxuICAgICAgb3BhY2l0eTogdmlldy5jZWxsT3BhY2l0eSxcbiAgICAgIC4uLmNvbG9ycyxcbiAgICAgIC4uLmNvbW1vbixcbiAgICB9KTtcbiAgICB0aGlzLmdyb3Vwcy51cHNlcnRTaGFwZXMoXG4gICAgICAnY2VsbE91dGxpbmUnLFxuICAgICAgb3V0bGluZSxcbiAgICAgIGdlb21ldHJ5Q2hhbmdlZCxcbiAgICAgIHJpbmdzLFxuICAgICAgZmlsbFxuICAgICAgICA/IC8vIE92ZXIgYSBmaWxsLCBhIGRhcmsgb3V0bGluZSBzZXBhcmF0ZXMgbmVpZ2hib3VycyBvZiB0aGUgc2FtZSB0eXBlLlxuICAgICAgICAgIHsgbmFtZTogJ2NlbGwgb3V0bGluZXMnLCBkcmF3OiAnb3V0bGluZScsIGNvbG9yOiBbMC4wOCwgMC4wOCwgMC4xLCAxXSwgb3BhY2l0eTogMC43LCAuLi5jb21tb24gfVxuICAgICAgICA6IHsgbmFtZTogJ2NlbGwgb3V0bGluZXMnLCBkcmF3OiAnb3V0bGluZScsIG9wYWNpdHk6IDEsIC4uLmNvbG9ycywgLi4uY29tbW9uIH0sXG4gICAgKTtcbiAgICAvLyBcIkJvdGhcIjogbnVjbGVpIG91dGxpbmVkIG92ZXIgdGhlIGNlbGxzLCBsaWdodCBzbyB0aGV5IHJlYWQgYWdhaW5zdCBhbnkgZmlsbC5cbiAgICBpZiAobnVjbGVpKSB7XG4gICAgICB0aGlzLmdyb3Vwcy51cHNlcnRTaGFwZXMoJ251Y2xldXNPdXRsaW5lJywgdHJ1ZSwgZ2VvbWV0cnlDaGFuZ2VkLCBudWNsZWksIHtcbiAgICAgICAgbmFtZTogJ251Y2xldXMgb3V0bGluZXMnLFxuICAgICAgICBkcmF3OiAnb3V0bGluZScsXG4gICAgICAgIGNvbG9yOiBbMC45NSwgMC45NSwgMC45OCwgMV0sXG4gICAgICAgIG9wYWNpdHk6IDAuOCxcbiAgICAgICAgLi4uY29tbW9uLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZ3JvdXBzLmRyb3AoJ251Y2xldXNPdXRsaW5lJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZWxlY3Rpb25SZXYoc2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayk6IG51bWJlciB7XG4gICAgaWYgKHNlbGVjdGlvbiAhPT0gdGhpcy5sYXN0U2VsZWN0aW9uKSB7XG4gICAgICB0aGlzLmxhc3RTZWxlY3Rpb24gPSBzZWxlY3Rpb247XG4gICAgICB0aGlzLnNlbGVjdGlvblJldmlzaW9uKys7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvblJldmlzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByaW5ncycgY29sb3VycyBieSB0aGVpciBvd25lcnMsIGJ5IHRoZSB2aWV3J3MgY2VsbC1jb2xvdXIgbW9kZSAoWGVuaXVtIEV4cGxvcmVyJ3MgXCJDZWxsXG4gICAqIENvbG9yXCIpOiBvbmUgUkdCQSBwZXIgc2hhcGUgZm9yIGEgZ3JvdXBpbmcsIHZhbHVlcyArIGNvbG9ybWFwIGZvciBhIG1lYXN1cmVtZW50LCBvbmUgY29sb3VyXG4gICAqIGZvciBcInNpbmdsZVwiLiBBIHNlbGVjdGlvbiBtdXRlcyB3aGF0IGl0IGxlYXZlcyBvdXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNlbGxDb2xvcnMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICBzZWxlY3Rpb246IFNwYXRpYWxTZWxlY3Rpb25NYXNrLFxuICAgIG93bmVyczogVWludDMyQXJyYXksXG4gICk6IFByb21pc2U8Q2VsbENvbG9ycz4ge1xuICAgIGNvbnN0IG11dGVkID0gc2VsZWN0aW9uLmNvdW50ID4gMCA/IHNlbGVjdGlvbi5tYXNrIDogbnVsbDtcbiAgICBjb25zdCBtb2RlID0gdmlldy5jZWxsQ29sb3JNb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdzaW5nbGUnKSB7XG4gICAgICBjb25zdCBbciwgZywgYl0gPSBwYXJzZUhleCh2aWV3LmNlbGxTaW5nbGVDb2xvcik7XG4gICAgICByZXR1cm4geyBjb2xvcjogW3IgLyAyNTUsIGcgLyAyNTUsIGIgLyAyNTUsIDFdIH07XG4gICAgfVxuXG4gICAgY29uc3QgY29udGludW91cyA9IGFzeW5jIChyYXc6IEZsb2F0MzJBcnJheSwgbG9nOiBib29sZWFuKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KG93bmVycy5sZW5ndGgpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvd25lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgdiA9IHJhd1tvd25lcnNbaV1dID8/IE5hTjtcbiAgICAgICAgdmFsdWVzW2ldID0gbG9nID8gTWF0aC5sb2cxcChNYXRoLm1heCgwLCB2KSkgOiB2O1xuICAgICAgfVxuICAgICAgY29uc3QgW2NsaXBMbywgY2xpcEhpXSA9IHZpZXcucGVyY2VudGlsZUNsaXA7XG4gICAgICAvLyBLZXllZCBieSB0aGUgU09VUkNFIHZlY3RvciAodGhlIGxvZyBjb3B5IHdvdWxkIGJlIG5ldyBvbiBldmVyeSBjYWxsKSwgYXMgdGhlIDNEIGNsb3VkJ3MuXG4gICAgICBjb25zdCBbbG8sIGhpXSA9IHRoaXMuY29udHJhc3RXaW5kb3dzLmdldChyYXcsIGNsaXBMbywgY2xpcEhpLCBsb2csICgpID0+XG4gICAgICAgIGNvbnRyYXN0V2luZG93KGxvZyA/IHJhdy5tYXAoKHYpID0+IE1hdGgubG9nMXAoTWF0aC5tYXgoMCwgdikpKSA6IHJhdywgY2xpcExvLCBjbGlwSGkpLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlcyxcbiAgICAgICAgY29sb3JtYXA6IGNvbG9ybWFwRnJvbUx1dCgnc3BhdGlhbC1jb250aW51b3VzJywgdGhpcy5ob3N0LmNvbnRpbnVvdXNMdXQodmlldykpLFxuICAgICAgICBjb250cmFzdExpbWl0czogW2xvLCBoaV0gYXMgW251bWJlciwgbnVtYmVyXSxcbiAgICAgIH07XG4gICAgfTtcbiAgICBpZiAobW9kZSA9PT0gJ2dlbmUnICYmIHZpZXcuY2VsbENvbG9yR2VuZSkge1xuICAgICAgcmV0dXJuIGNvbnRpbnVvdXMoYXdhaXQgdGhpcy5wb3J0LmdldEZlYXR1cmVWZWN0b3Iodmlldy5jZWxsQ29sb3JHZW5lKSwgdHJ1ZSk7XG4gICAgfVxuICAgIGlmIChtb2RlID09PSAndHJhbnNjcmlwdERlbnNpdHknICYmIGRhdGFzZXQuY29sdW1ucy5zb21lKChjKSA9PiBjLm5hbWUgPT09ICd0cmFuc2NyaXB0X2RlbnNpdHknKSkge1xuICAgICAgY29uc3QgY29sdW1uID0gYXdhaXQgdGhpcy5wb3J0LmdldENvbHVtbigndHJhbnNjcmlwdF9kZW5zaXR5Jyk7XG4gICAgICBpZiAoIWlzQ2F0ZWdvcmljYWxDb2x1bW4oY29sdW1uKSkgcmV0dXJuIGNvbnRpbnVvdXMoY29sdW1uLnZhbHVlcywgZmFsc2UpO1xuICAgIH1cblxuICAgIGNvbnN0IG5hbWUgPVxuICAgICAgbW9kZSA9PT0gJ3NlZ21lbnRhdGlvbicgJiYgZGF0YXNldC5jb2x1bW5zLnNvbWUoKGMpID0+IGMubmFtZSA9PT0gJ3NlZ21lbnRhdGlvbl9tZXRob2QnKVxuICAgICAgICA/ICdzZWdtZW50YXRpb25fbWV0aG9kJ1xuICAgICAgICA6IGNlbGxUeXBlQ29sdW1uRm9yKGRhdGFzZXQsIHZpZXcpO1xuICAgIGNvbnN0IGNvZGVzID0gbmFtZSA/IGF3YWl0IHRoaXMubG9va3VwLmNvZGVzKG5hbWUpIDogbnVsbDtcbiAgICBjb25zdCBwYWxldHRlID0gY2F0ZWdvcnlSZ2JhKGNvZGVzPy5tZXRhID8/IG51bGwpO1xuICAgIGNvbnN0IG1pc3NpbmcgPSByZ2JhMDEoTUlTU0lOR19DT0xPUik7XG4gICAgLy8gT25lIFJHQkEgcGVyIHNoYXBlIChuYXBhcmkgU2hhcGVzJyBgZmFjZV9jb2xvcmApOiBhbnkgbnVtYmVyIG9mIGNhdGVnb3JpZXMga2VlcHMgaXRzIG93blxuICAgIC8vIGNvbG91ciwgd2hlcmUgYSBjb2xvcm1hcCBiYW5kIHBlciBjYXRlZ29yeSByYW4gb3V0IG9mIExVVCBlbnRyaWVzIHBhc3QgfjEyNy5cbiAgICBjb25zdCBmYWNlQ29sb3IgPSBuZXcgRmxvYXQzMkFycmF5KG93bmVycy5sZW5ndGggKiA0KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG93bmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbyA9IG93bmVyc1tpXTtcbiAgICAgIGNvbnN0IGNvZGUgPSAhY29kZXMgfHwgKG11dGVkICYmICFtdXRlZFtvXSkgPyBOT19DQVRFR09SWSA6IGNvZGVzLmNvZGVzW29dO1xuICAgICAgZmFjZUNvbG9yLnNldChwYWxldHRlW2NvZGVdID8/IG1pc3NpbmcsIGkgKiA0KTtcbiAgICB9XG4gICAgcmV0dXJuIHsgZmFjZUNvbG9yIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNlbGwgcmluZ3MgKGFuZCwgZm9yIFwiYm90aFwiLCB0aGUgbnVjbGV1cyByaW5ncykgY292ZXJpbmcgYHJlY3RgIGF0IGBsZXZlbGAsIG1pbnVzXG4gICAqIHRoZSBoaWRkZW4gZ3JvdXBzIOKAlCByZXVzZWQgd2hlbiBub3RoaW5nIHRoYXQgZGVjaWRlcyB0aGVtIGNoYW5nZWQuIE51bGwgd2hlbiB0aGVcbiAgICogdmlldyB3ZW50IHN0YWxlIG9yIHRoZSBkYXRhc2V0IGhhcyBubyBzZXQgdG8gZHJhdy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY2VsbEdlb21ldHJ5KFxuICAgIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgcmVjdDogRGF0YVJlY3QsXG4gICAgbGV2ZWw6IG51bWJlcixcbiAgICBoaWRkZW46IEhpZGRlbkNvZGVzIHwgbnVsbCxcbiAgICBjdHg6IFBsYW5Db250ZXh0LFxuICApOiBQcm9taXNlPHsgcmluZ3M6IFNwYXRpYWxQb2x5Z29uVGlsZTsgbnVjbGVpOiBTcGF0aWFsUG9seWdvblRpbGUgfCBudWxsOyBnZW9tZXRyeUtleTogc3RyaW5nIH0gfCBudWxsPiB7XG4gICAgY29uc3QgdGlsZWQgPSBkYXRhc2V0LnBvbHlnb25UaWxlcztcbiAgICBjb25zdCBoaWRkZW5LZXkgPSB2aWV3LmhpZGRlbkdyb3Vwcy5qb2luKCdcXHUwMDAxJyk7XG4gICAgbGV0IHJpbmdzOiBTcGF0aWFsUG9seWdvblRpbGU7XG4gICAgbGV0IG51Y2xlaTogU3BhdGlhbFBvbHlnb25UaWxlIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGdlb21ldHJ5S2V5OiBzdHJpbmc7XG4gICAgaWYgKHRpbGVkKSB7XG4gICAgICBjb25zdCBib3RoID0gdmlldy5jZWxsU2V0ID09PSAnYm90aCc7XG4gICAgICBjb25zdCBzZXQgPVxuICAgICAgICAhYm90aCAmJiB2aWV3LmNlbGxTZXQgJiYgdGlsZWQuc2V0cy5zb21lKChzKSA9PiBzLm5hbWUgPT09IHZpZXcuY2VsbFNldClcbiAgICAgICAgICA/IHZpZXcuY2VsbFNldFxuICAgICAgICAgIDogKHRpbGVkLmRlZmF1bHRTZXQgPz8gdGlsZWQuc2V0c1swXT8ubmFtZSk7XG4gICAgICBpZiAoIXNldCkgcmV0dXJuIG51bGw7XG4gICAgICBjb25zdCBudWNsZXVzU2V0ID0gYm90aCA/IHRpbGVkLnNldHMuZmluZCgocykgPT4gcy5uYW1lICE9PSBzZXQpPy5uYW1lIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3Qga2V5cyA9IHRpbGVzSW5SZWN0KHJlY3QsIGxldmVsLCB0aWxlZC5sZXZlbHMsIHRpbGVkLmJvdW5kcywgTUFYX0NFTExfVElMRVMpO1xuICAgICAgZ2VvbWV0cnlLZXkgPSBgJHtkYXRhc2V0LmlkfXwke3NldH18JHtudWNsZXVzU2V0ID8/ICcnfXwke2hpZGRlbktleX18JHtrZXlzLm1hcCh0aWxlSWQpLmpvaW4oJywnKX1gO1xuICAgICAgaWYgKGdlb21ldHJ5S2V5ID09PSB0aGlzLmNlbGxHZW9tZXRyeUtleSAmJiB0aGlzLmN1cnJlbnRSaW5ncykge1xuICAgICAgICByaW5ncyA9IHRoaXMuY3VycmVudFJpbmdzO1xuICAgICAgICBudWNsZWkgPSB0aGlzLmN1cnJlbnROdWNsZWk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBbdGlsZXMsIG51Y2xldXNUaWxlc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgY3R4LmZldGNoQWxsKGtleXMsIChrKSA9PiB0aGlzLnBvcnQuZ2V0UG9seWdvblRpbGUhKHNldCwgay5sZXZlbCwgay5neCwgay5neSkpLFxuICAgICAgICAgIG51Y2xldXNTZXRcbiAgICAgICAgICAgID8gY3R4LmZldGNoQWxsKGtleXMsIChrKSA9PiB0aGlzLnBvcnQuZ2V0UG9seWdvblRpbGUhKG51Y2xldXNTZXQsIGsubGV2ZWwsIGsuZ3gsIGsuZ3kpKVxuICAgICAgICAgICAgOiBQcm9taXNlLnJlc29sdmUobnVsbCksXG4gICAgICAgIF0pO1xuICAgICAgICBpZiAoY3R4LnN0YWxlKCkpIHJldHVybiBudWxsO1xuICAgICAgICByaW5ncyA9IGZpbHRlclJpbmdzKG1lcmdlUG9seWdvblRpbGVzKHRpbGVzKSwgaGlkZGVuKTtcbiAgICAgICAgbnVjbGVpID0gbnVjbGV1c1RpbGVzID8gZmlsdGVyUmluZ3MobWVyZ2VQb2x5Z29uVGlsZXMobnVjbGV1c1RpbGVzKSwgaGlkZGVuKSA6IG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGdlb21ldHJ5S2V5ID0gYCR7ZGF0YXNldC5pZH18d2hvbGV8JHtoaWRkZW5LZXl9YDtcbiAgICAgIGlmIChnZW9tZXRyeUtleSA9PT0gdGhpcy5jZWxsR2VvbWV0cnlLZXkgJiYgdGhpcy5jdXJyZW50UmluZ3MpIHtcbiAgICAgICAgcmluZ3MgPSB0aGlzLmN1cnJlbnRSaW5ncztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHBvbHlzOiBTcGF0aWFsUG9seWdvbnMgPSBhd2FpdCB0aGlzLnBvcnQuZ2V0UG9seWdvbnMhKCk7XG4gICAgICAgIGlmIChjdHguc3RhbGUoKSkgcmV0dXJuIG51bGw7XG4gICAgICAgIC8vIFdob2xlLWRhdGFzZXQgcmluZ3MgYXJlIGluZGV4LWFsaWduZWQgd2l0aCB0aGUgb2JzZXJ2YXRpb25zLlxuICAgICAgICByaW5ncyA9IGZpbHRlclJpbmdzKFxuICAgICAgICAgIHsgLi4ucG9seXMsIG9ic2VydmF0aW9uOiBVaW50MzJBcnJheS5mcm9tKHsgbGVuZ3RoOiBwb2x5cy5jb3VudCB9LCAoX3YsIGkpID0+IGkpIH0sXG4gICAgICAgICAgaGlkZGVuLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyByaW5ncywgbnVjbGVpLCBnZW9tZXRyeUtleSB9O1xuICB9XG5cbiAgLyoqIFJlbW92ZSB0aGUgY2VsbCBsYXllcnMgYW5kIGZvcmdldCB3aGF0IHRoZXkgc2hvd2VkLiAqL1xuICBkcm9wKCk6IHZvaWQge1xuICAgIHRoaXMuZ3JvdXBzLmRyb3AoJ2NlbGxGaWxsJyk7XG4gICAgdGhpcy5ncm91cHMuZHJvcCgnY2VsbE91dGxpbmUnKTtcbiAgICB0aGlzLmdyb3Vwcy5kcm9wKCdudWNsZXVzT3V0bGluZScpO1xuICAgIHRoaXMuY3VycmVudE51Y2xlaSA9IG51bGw7XG4gICAgdGhpcy5jZWxsR2VvbWV0cnlLZXkgPSBudWxsO1xuICAgIHRoaXMuY2VsbFN0eWxlS2V5ID0gbnVsbDtcbiAgICB0aGlzLmN1cnJlbnRSaW5ncyA9IG51bGw7XG4gICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0UG9seWdvbnNTaG93bihzaG93bjogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChzaG93biA9PT0gdGhpcy5wb2x5Z29uc1Nob3duKSByZXR1cm47XG4gICAgdGhpcy5wb2x5Z29uc1Nob3duID0gc2hvd247XG4gICAgdGhpcy5ob3N0LnBvbHlnb25zU2hvd25DaGFuZ2VkKHNob3duKTtcbiAgfVxufVxuXG4vKiogQW4gOC1iaXQgUkdCIGFzIGFuIG9wYXF1ZSAwLi4xIFJHQkEuICovXG5mdW5jdGlvbiByZ2JhMDEoW3IsIGcsIGJdOiByZWFkb25seSBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBSR0JBIHtcbiAgcmV0dXJuIFtyIC8gMjU1LCBnIC8gMjU1LCBiIC8gMjU1LCAxXTtcbn1cblxuLyoqIEEgZ3JvdXBpbmcncyBjYXRlZ29yeSBjb2xvdXJzLCBhcyAwLi4xIFJHQkEgYnkgY2F0ZWdvcnkgY29kZSAob25lIGRlZmF1bHQgd2l0aG91dCBhIGdyb3VwaW5nKS4gKi9cbmZ1bmN0aW9uIGNhdGVnb3J5UmdiYShtZXRhOiBTcGF0aWFsQ29sdW1uWydtZXRhJ10gfCBudWxsKTogUkdCQVtdIHtcbiAgY29uc3QgaGV4ID0gbWV0YSAmJiBtZXRhLmtpbmQgPT09ICdjYXRlZ29yaWNhbCcgPyByZXNvbHZlQ2F0ZWdvcnlDb2xvcnMobWV0YSkgOiBbREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFWzBdXTtcbiAgcmV0dXJuIGhleC5tYXAoKGgpID0+IHJnYmEwMShwYXJzZUhleChoKSkpO1xufVxuIl19
@@ -0,0 +1,144 @@
1
+ import { colormapFromLut } from 'napari-js';
2
+ import { INFERNO_LUT } from 'napari-js/colormaps';
3
+ import { ALL_GENES } from '../../../contracts/ports/spatial-data.port';
4
+ import { lutFor } from '../../../spatial/spatial-encoding';
5
+ import { visibleArea, visibleDataRect } from '../../../spatial/lod';
6
+ import { densityAutoRange } from '../../../spatial/density-raster';
7
+ /**
8
+ * The transcript density image of the 2D spatial view: the visible genes' summed density
9
+ * raster, one scalar layer in the `density` group, windowed and coloured on the GPU.
10
+ *
11
+ * Bins at or below the window's low end are transparent (`transparentBelow`), so a window,
12
+ * colormap or opacity change is a uniform or LUT update of the same layer: only new genes or a
13
+ * new bin size fetch and upload a raster.
14
+ */
15
+ export class DensityLayer {
16
+ constructor(port, groups, changed) {
17
+ this.port = port;
18
+ this.groups = groups;
19
+ this.changed = changed;
20
+ /** The density window in use and the densest bin, for the panel's threshold control. */
21
+ this.stats = null;
22
+ /** The drawn raster in transcripts per unit area, its densest bin and its auto window. */
23
+ this.raster = null;
24
+ /** The colormap the layer was given, so an unchanged one does not rebuild its LUT. */
25
+ this.colormapKey = null;
26
+ }
27
+ /** Draw the view's density, or drop it; an unchanged (genes, bin, window, colormap) is a no-op. */
28
+ async plan(dataset, view, ctx) {
29
+ const hiddenGenes = new Set(view.transcriptHiddenGenes);
30
+ const genes = view.transcriptAllGenes ? [ALL_GENES] : view.transcriptGenes.filter((g) => !hiddenGenes.has(g));
31
+ if (!dataset.density || !this.port.getDensity || view.transcriptMode !== 'density' || !genes.length) {
32
+ this.groups.drop('density');
33
+ this.stats = null;
34
+ this.raster = null;
35
+ return;
36
+ }
37
+ // The raster's key: what it is a raster OF. Window, colormap and opacity are the layer's style.
38
+ const key = [dataset.id, genes.join(','), view.densityBin].join('|');
39
+ // `shown`, not `has`: a stitched slice re-render clears the layer list, and the key alone
40
+ // would call the cleared layer drawn.
41
+ if (key !== this.groups.key('density') || !this.groups.shown('density') || !this.raster) {
42
+ const raster = await ctx.track('Transcript density', this.port.getDensity(genes, view.densityBin));
43
+ if (ctx.stale())
44
+ return;
45
+ // Bins drawn as squares, as Xenium Explorer does; the window is in transcripts/µm².
46
+ const meta = raster.meta;
47
+ const area = meta.gridSize[0] * meta.gridSize[1];
48
+ const perArea = raster.values.map((v) => v / area);
49
+ this.raster = {
50
+ perArea,
51
+ max: perArea.reduce((m, v) => (v > m ? v : m), 0),
52
+ auto: densityAutoRange(perArea),
53
+ };
54
+ const ref = dataset.imageRef;
55
+ const sx = ref?.scale?.[0] ?? 1;
56
+ const sy = ref?.scale?.[1] ?? 1;
57
+ const layer = this.groups.viewer.addImage({ kind: 'typed', width: meta.cols, height: meta.rows, channels: 1, dtype: 'float32', data: perArea }, {
58
+ name: `density · ${view.transcriptAllGenes ? 'all genes' : genes.join(', ')}`,
59
+ scale: [meta.gridSize[0] * sx, meta.gridSize[1] * sy],
60
+ translate: [
61
+ meta.origin[0] * sx + (ref?.translate?.[0] ?? 0),
62
+ meta.origin[1] * sy + (ref?.translate?.[1] ?? 0),
63
+ ],
64
+ // Xenium Explorer's "scale threshold": empty tissue shows the image under it.
65
+ transparentBelow: true,
66
+ blending: 'translucent',
67
+ interpolation: 'nearest',
68
+ });
69
+ this.colormapKey = null;
70
+ this.groups.setKey('density', key);
71
+ this.groups.replace('density', layer);
72
+ }
73
+ this.restyle(this.groups.layer('density'), view);
74
+ }
75
+ /** Window, colour and opacity onto the drawn layer: uniforms and a LUT, no re-upload. */
76
+ restyle(layer, view) {
77
+ const raster = this.raster;
78
+ const [lo, hi] = view.densityRange ?? raster.auto;
79
+ layer.contrastLimits = [lo, hi];
80
+ layer.opacity = view.densityOpacity;
81
+ const colormapKey = JSON.stringify(view.densityColormap ?? null);
82
+ if (colormapKey !== this.colormapKey) {
83
+ this.colormapKey = colormapKey;
84
+ layer.colormap = colormapFromLut('transcript-density', lutFor(view.densityColormap ?? INFERNO_LUT));
85
+ }
86
+ this.groups.viewer.requestRender();
87
+ const stats = { lo, hi, max: raster.max };
88
+ if (this.stats?.lo === lo && this.stats.hi === hi && this.stats.max === raster.max)
89
+ return;
90
+ this.stats = stats;
91
+ this.changed(stats);
92
+ }
93
+ }
94
+ /**
95
+ * Transcripts in view for the visible genes, against the marker budget — it tells the user
96
+ * whether the budget will force grouping. Caches the per-gene dataset totals for the latest
97
+ * gene set.
98
+ */
99
+ export class TranscriptEstimator {
100
+ constructor(port, changed) {
101
+ this.port = port;
102
+ this.changed = changed;
103
+ /** Per-gene dataset totals for the in-view estimate, for the latest gene set. */
104
+ this.countsCache = null;
105
+ }
106
+ /**
107
+ * Transcripts in view for the visible genes: each gene's dataset total times the share
108
+ * of the tissue on screen. An estimate — expression is not uniform — which is also what
109
+ * Xenium Explorer shows; it tells the user whether the budget will force grouping.
110
+ */
111
+ async plan(dataset, view, viewer, w, h, ctx) {
112
+ const tiles = dataset.transcriptTiles;
113
+ if (!tiles || !this.port.getTranscriptCounts || view.transcriptMode === 'off') {
114
+ this.changed(null);
115
+ return;
116
+ }
117
+ const hiddenGenes = new Set(view.transcriptHiddenGenes);
118
+ const genes = view.transcriptAllGenes ? [] : view.transcriptGenes.filter((g) => !hiddenGenes.has(g));
119
+ const key = `${dataset.id}|${genes.join(',')}`;
120
+ if (this.countsCache?.key !== key) {
121
+ this.countsCache = { key, counts: this.port.getTranscriptCounts(genes) };
122
+ }
123
+ let counts;
124
+ try {
125
+ counts = await this.countsCache.counts;
126
+ }
127
+ catch {
128
+ this.countsCache = null;
129
+ return;
130
+ }
131
+ if (ctx.stale())
132
+ return;
133
+ const inView = visibleDataRect(viewer.camera.center, viewer.camera.zoom, w, h, dataset.imageRef, 0);
134
+ if (!inView)
135
+ return;
136
+ const b = counts.bounds;
137
+ const share = Math.min(1, visibleArea(inView, b) / Math.max(1, (b[2] - b[0]) * (b[3] - b[1])));
138
+ const selected = view.transcriptAllGenes
139
+ ? counts.total
140
+ : genes.reduce((sum, g) => sum + (counts.counts[g] ?? 0), 0);
141
+ this.changed({ points: Math.round(selected * share), max: view.transcriptBudget });
142
+ }
143
+ }
144
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVuc2l0eS1sYXllci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL25hcGFyaS1qcy9zcGF0aWFsLXRpbGVzL2RlbnNpdHktbGF5ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUU1QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbEQsT0FBTyxFQUFFLFNBQVMsRUFBd0IsTUFBTSw0Q0FBNEMsQ0FBQztBQUc3RixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDM0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQW1CbkU7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxZQUFZO0lBUXZCLFlBQ21CLElBQXFCLEVBQ3JCLE1BQXFDLEVBQ3JDLE9BQXNDO1FBRnRDLFNBQUksR0FBSixJQUFJLENBQWlCO1FBQ3JCLFdBQU0sR0FBTixNQUFNLENBQStCO1FBQ3JDLFlBQU8sR0FBUCxPQUFPLENBQStCO1FBVnpELHdGQUF3RjtRQUN4RixVQUFLLEdBQXdCLElBQUksQ0FBQztRQUNsQywwRkFBMEY7UUFDbEYsV0FBTSxHQUEwRSxJQUFJLENBQUM7UUFDN0Ysc0ZBQXNGO1FBQzlFLGdCQUFXLEdBQWtCLElBQUksQ0FBQztJQU12QyxDQUFDO0lBRUosbUdBQW1HO0lBQ25HLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBdUIsRUFBRSxJQUFzQixFQUFFLEdBQWdCO1FBQzFFLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxrQkFB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RUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztJQUNyRixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb2xvcm1hcEZyb21MdXQgfSBmcm9tICduYXBhcmktanMnO1xuaW1wb3J0IHR5cGUgeyBJbWFnZUxheWVyLCBWaWV3ZXIgfSBmcm9tICduYXBhcmktanMnO1xuaW1wb3J0IHsgSU5GRVJOT19MVVQgfSBmcm9tICduYXBhcmktanMvY29sb3JtYXBzJztcblxuaW1wb3J0IHsgQUxMX0dFTkVTLCB0eXBlIFNwYXRpYWxEYXRhUG9ydCB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9wb3J0cy9zcGF0aWFsLWRhdGEucG9ydCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxWaWV3U3RhdGUgfSBmcm9tICcuLi8uLi8uLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0LCBTcGF0aWFsVHJhbnNjcmlwdENvdW50cyB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9zcGF0aWFsLWRhdGFzZXQuY29udHJhY3QnO1xuaW1wb3J0IHsgbHV0Rm9yIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB7IHZpc2libGVBcmVhLCB2aXNpYmxlRGF0YVJlY3QgfSBmcm9tICcuLi8uLi8uLi9zcGF0aWFsL2xvZCc7XG5pbXBvcnQgeyBkZW5zaXR5QXV0b1JhbmdlIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9kZW5zaXR5LXJhc3Rlcic7XG5pbXBvcnQgdHlwZSB7IE9yZGVyZWRMYXllckdyb3VwcywgVGlsZUdyb3VwIH0gZnJvbSAnLi9sYXllci1ncm91cHMnO1xuaW1wb3J0IHR5cGUgeyBQbGFuQ29udGV4dCB9IGZyb20gJy4vcGxhbi1jb250ZXh0JztcblxuLyoqIFRoZSBkZW5zaXR5IHdpbmRvdyBpbiB1c2UgYW5kIHRoZSBkZW5zZXN0IGJpbiAodHJhbnNjcmlwdHMgcGVyIHVuaXQgYXJlYSkuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbnNpdHlTdGF0cyB7XG4gIGxvOiBudW1iZXI7XG4gIGhpOiBudW1iZXI7XG4gIG1heDogbnVtYmVyO1xufVxuXG4vKiogWGVuaXVtIEV4cGxvcmVyJ3MgXCJFc3RpbWF0ZWQgVHJhbnNjcmlwdCBQb2ludHNcIi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNjcmlwdEVzdGltYXRlIHtcbiAgLyoqIFRyYW5zY3JpcHRzIG9mIHRoZSB2aXNpYmxlIGdlbmVzIGVzdGltYXRlZCB0byBiZSBpbiB2aWV3LiAqL1xuICBwb2ludHM6IG51bWJlcjtcbiAgLyoqIFRoZSBtYXJrZXIgYnVkZ2V0LiAqL1xuICBtYXg6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgdHJhbnNjcmlwdCBkZW5zaXR5IGltYWdlIG9mIHRoZSAyRCBzcGF0aWFsIHZpZXc6IHRoZSB2aXNpYmxlIGdlbmVzJyBzdW1tZWQgZGVuc2l0eVxuICogcmFzdGVyLCBvbmUgc2NhbGFyIGxheWVyIGluIHRoZSBgZGVuc2l0eWAgZ3JvdXAsIHdpbmRvd2VkIGFuZCBjb2xvdXJlZCBvbiB0aGUgR1BVLlxuICpcbiAqIEJpbnMgYXQgb3IgYmVsb3cgdGhlIHdpbmRvdydzIGxvdyBlbmQgYXJlIHRyYW5zcGFyZW50IChgdHJhbnNwYXJlbnRCZWxvd2ApLCBzbyBhIHdpbmRvdyxcbiAqIGNvbG9ybWFwIG9yIG9wYWNpdHkgY2hhbmdlIGlzIGEgdW5pZm9ybSBvciBMVVQgdXBkYXRlIG9mIHRoZSBzYW1lIGxheWVyOiBvbmx5IG5ldyBnZW5lcyBvciBhXG4gKiBuZXcgYmluIHNpemUgZmV0Y2ggYW5kIHVwbG9hZCBhIHJhc3Rlci5cbiAqL1xuZXhwb3J0IGNsYXNzIERlbnNpdHlMYXllciB7XG4gIC8qKiBUaGUgZGVuc2l0eSB3aW5kb3cgaW4gdXNlIGFuZCB0aGUgZGVuc2VzdCBiaW4sIGZvciB0aGUgcGFuZWwncyB0aHJlc2hvbGQgY29udHJvbC4gKi9cbiAgc3RhdHM6IERlbnNpdHlTdGF0cyB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGRyYXduIHJhc3RlciBpbiB0cmFuc2NyaXB0cyBwZXIgdW5pdCBhcmVhLCBpdHMgZGVuc2VzdCBiaW4gYW5kIGl0cyBhdXRvIHdpbmRvdy4gKi9cbiAgcHJpdmF0ZSByYXN0ZXI6IHsgcGVyQXJlYTogRmxvYXQzMkFycmF5OyBtYXg6IG51bWJlcjsgYXV0bzogW251bWJlciwgbnVtYmVyXSB9IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgY29sb3JtYXAgdGhlIGxheWVyIHdhcyBnaXZlbiwgc28gYW4gdW5jaGFuZ2VkIG9uZSBkb2VzIG5vdCByZWJ1aWxkIGl0cyBMVVQuICovXG4gIHByaXZhdGUgY29sb3JtYXBLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcG9ydDogU3BhdGlhbERhdGFQb3J0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZ3JvdXBzOiBPcmRlcmVkTGF5ZXJHcm91cHM8VGlsZUdyb3VwPixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoYW5nZWQ6IChzdGF0czogRGVuc2l0eVN0YXRzKSA9PiB2b2lkLFxuICApIHt9XG5cbiAgLyoqIERyYXcgdGhlIHZpZXcncyBkZW5zaXR5LCBvciBkcm9wIGl0OyBhbiB1bmNoYW5nZWQgKGdlbmVzLCBiaW4sIHdpbmRvdywgY29sb3JtYXApIGlzIGEgbm8tb3AuICovXG4gIGFzeW5jIHBsYW4oZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIGN0eDogUGxhbkNvbnRleHQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBoaWRkZW5HZW5lcyA9IG5ldyBTZXQodmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMpO1xuICAgIGNvbnN0IGdlbmVzID0gdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyBbQUxMX0dFTkVTXSA6IHZpZXcudHJhbnNjcmlwdEdlbmVzLmZpbHRlcigoZykgPT4gIWhpZGRlbkdlbmVzLmhhcyhnKSk7XG4gICAgaWYgKCFkYXRhc2V0LmRlbnNpdHkgfHwgIXRoaXMucG9ydC5nZXREZW5zaXR5IHx8IHZpZXcudHJhbnNjcmlwdE1vZGUgIT09ICdkZW5zaXR5JyB8fCAhZ2VuZXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmdyb3Vwcy5kcm9wKCdkZW5zaXR5Jyk7XG4gICAgICB0aGlzLnN0YXRzID0gbnVsbDtcbiAgICAgIHRoaXMucmFzdGVyID0gbnVsbDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gVGhlIHJhc3RlcidzIGtleTogd2hhdCBpdCBpcyBhIHJhc3RlciBPRi4gV2luZG93LCBjb2xvcm1hcCBhbmQgb3BhY2l0eSBhcmUgdGhlIGxheWVyJ3Mgc3R5bGUuXG4gICAgY29uc3Qga2V5ID0gW2RhdGFzZXQuaWQsIGdlbmVzLmpvaW4oJywnKSwgdmlldy5kZW5zaXR5QmluXS5qb2luKCd8Jyk7XG4gICAgLy8gYHNob3duYCwgbm90IGBoYXNgOiBhIHN0aXRjaGVkIHNsaWNlIHJlLXJlbmRlciBjbGVhcnMgdGhlIGxheWVyIGxpc3QsIGFuZCB0aGUga2V5IGFsb25lXG4gICAgLy8gd291bGQgY2FsbCB0aGUgY2xlYXJlZCBsYXllciBkcmF3bi5cbiAgICBpZiAoa2V5ICE9PSB0aGlzLmdyb3Vwcy5rZXkoJ2RlbnNpdHknKSB8fCAhdGhpcy5ncm91cHMuc2hvd24oJ2RlbnNpdHknKSB8fCAhdGhpcy5yYXN0ZXIpIHtcbiAgICAgIGNvbnN0IHJhc3RlciA9IGF3YWl0IGN0eC50cmFjaygnVHJhbnNjcmlwdCBkZW5zaXR5JywgdGhpcy5wb3J0LmdldERlbnNpdHkoZ2VuZXMsIHZpZXcuZGVuc2l0eUJpbikpO1xuICAgICAgaWYgKGN0eC5zdGFsZSgpKSByZXR1cm47XG5cbiAgICAgIC8vIEJpbnMgZHJhd24gYXMgc3F1YXJlcywgYXMgWGVuaXVtIEV4cGxvcmVyIGRvZXM7IHRoZSB3aW5kb3cgaXMgaW4gdHJhbnNjcmlwdHMvwrVtwrIuXG4gICAgICBjb25zdCBtZXRhID0gcmFzdGVyLm1ldGE7XG4gICAgICBjb25zdCBhcmVhID0gbWV0YS5ncmlkU2l6ZVswXSAqIG1ldGEuZ3JpZFNpemVbMV07XG4gICAgICBjb25zdCBwZXJBcmVhID0gcmFzdGVyLnZhbHVlcy5tYXAoKHYpID0+IHYgLyBhcmVhKTtcbiAgICAgIHRoaXMucmFzdGVyID0ge1xuICAgICAgICBwZXJBcmVhLFxuICAgICAgICBtYXg6IHBlckFyZWEucmVkdWNlKChtLCB2KSA9PiAodiA+IG0gPyB2IDogbSksIDApLFxuICAgICAgICBhdXRvOiBkZW5zaXR5QXV0b1JhbmdlKHBlckFyZWEpLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlZiA9IGRhdGFzZXQuaW1hZ2VSZWY7XG4gICAgICBjb25zdCBzeCA9IHJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICAgICAgY29uc3Qgc3kgPSByZWY/LnNjYWxlPy5bMV0gPz8gMTtcbiAgICAgIGNvbnN0IGxheWVyOiBJbWFnZUxheWVyID0gdGhpcy5ncm91cHMudmlld2VyIS5hZGRJbWFnZShcbiAgICAgICAgeyBraW5kOiAndHlwZWQnLCB3aWR0aDogbWV0YS5jb2xzLCBoZWlnaHQ6IG1ldGEucm93cywgY2hhbm5lbHM6IDEsIGR0eXBlOiAnZmxvYXQzMicsIGRhdGE6IHBlckFyZWEgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IGBkZW5zaXR5IMK3ICR7dmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyAnYWxsIGdlbmVzJyA6IGdlbmVzLmpvaW4oJywgJyl9YCxcbiAgICAgICAgICBzY2FsZTogW21ldGEuZ3JpZFNpemVbMF0gKiBzeCwgbWV0YS5ncmlkU2l6ZVsxXSAqIHN5XSxcbiAgICAgICAgICB0cmFuc2xhdGU6IFtcbiAgICAgICAgICAgIG1ldGEub3JpZ2luWzBdICogc3ggKyAocmVmPy50cmFuc2xhdGU/LlswXSA/PyAwKSxcbiAgICAgICAgICAgIG1ldGEub3JpZ2luWzFdICogc3kgKyAocmVmPy50cmFuc2xhdGU/LlsxXSA/PyAwKSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIC8vIFhlbml1bSBFeHBsb3JlcidzIFwic2NhbGUgdGhyZXNob2xkXCI6IGVtcHR5IHRpc3N1ZSBzaG93cyB0aGUgaW1hZ2UgdW5kZXIgaXQuXG4gICAgICAgICAgdHJhbnNwYXJlbnRCZWxvdzogdHJ1ZSxcbiAgICAgICAgICBibGVuZGluZzogJ3RyYW5zbHVjZW50JyxcbiAgICAgICAgICBpbnRlcnBvbGF0aW9uOiAnbmVhcmVzdCcsXG4gICAgICAgIH0sXG4gICAgICApO1xuICAgICAgdGhpcy5jb2xvcm1hcEtleSA9IG51bGw7XG4gICAgICB0aGlzLmdyb3Vwcy5zZXRLZXkoJ2RlbnNpdHknLCBrZXkpO1xuICAgICAgdGhpcy5ncm91cHMucmVwbGFjZSgnZGVuc2l0eScsIGxheWVyKTtcbiAgICB9XG4gICAgdGhpcy5yZXN0eWxlKHRoaXMuZ3JvdXBzLmxheWVyKCdkZW5zaXR5JykgYXMgSW1hZ2VMYXllciwgdmlldyk7XG4gIH1cblxuICAvKiogV2luZG93LCBjb2xvdXIgYW5kIG9wYWNpdHkgb250byB0aGUgZHJhd24gbGF5ZXI6IHVuaWZvcm1zIGFuZCBhIExVVCwgbm8gcmUtdXBsb2FkLiAqL1xuICBwcml2YXRlIHJlc3R5bGUobGF5ZXI6IEltYWdlTGF5ZXIsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUpOiB2b2lkIHtcbiAgICBjb25zdCByYXN0ZXIgPSB0aGlzLnJhc3RlciE7XG4gICAgY29uc3QgW2xvLCBoaV0gPSB2aWV3LmRlbnNpdHlSYW5nZSA/PyByYXN0ZXIuYXV0bztcbiAgICBsYXllci5jb250cmFzdExpbWl0cyA9IFtsbywgaGldO1xuICAgIGxheWVyLm9wYWNpdHkgPSB2aWV3LmRlbnNpdHlPcGFjaXR5O1xuICAgIGNvbnN0IGNvbG9ybWFwS2V5ID0gSlNPTi5zdHJpbmdpZnkodmlldy5kZW5zaXR5Q29sb3JtYXAgPz8gbnVsbCk7XG4gICAgaWYgKGNvbG9ybWFwS2V5ICE9PSB0aGlzLmNvbG9ybWFwS2V5KSB7XG4gICAgICB0aGlzLmNvbG9ybWFwS2V5ID0gY29sb3JtYXBLZXk7XG4gICAgICBsYXllci5jb2xvcm1hcCA9IGNvbG9ybWFwRnJvbUx1dCgndHJhbnNjcmlwdC1kZW5zaXR5JywgbHV0Rm9yKHZpZXcuZGVuc2l0eUNvbG9ybWFwID8/IElORkVSTk9fTFVUKSk7XG4gICAgfVxuICAgIHRoaXMuZ3JvdXBzLnZpZXdlciEucmVxdWVzdFJlbmRlcigpO1xuICAgIGNvbnN0IHN0YXRzID0geyBsbywgaGksIG1heDogcmFzdGVyLm1heCB9O1xuICAgIGlmICh0aGlzLnN0YXRzPy5sbyA9PT0gbG8gJiYgdGhpcy5zdGF0cy5oaSA9PT0gaGkgJiYgdGhpcy5zdGF0cy5tYXggPT09IHJhc3Rlci5tYXgpIHJldHVybjtcbiAgICB0aGlzLnN0YXRzID0gc3RhdHM7XG4gICAgdGhpcy5jaGFuZ2VkKHN0YXRzKTtcbiAgfVxufVxuXG4vKipcbiAqIFRyYW5zY3JpcHRzIGluIHZpZXcgZm9yIHRoZSB2aXNpYmxlIGdlbmVzLCBhZ2FpbnN0IHRoZSBtYXJrZXIgYnVkZ2V0IOKAlCBpdCB0ZWxscyB0aGUgdXNlclxuICogd2hldGhlciB0aGUgYnVkZ2V0IHdpbGwgZm9yY2UgZ3JvdXBpbmcuIENhY2hlcyB0aGUgcGVyLWdlbmUgZGF0YXNldCB0b3RhbHMgZm9yIHRoZSBsYXRlc3RcbiAqIGdlbmUgc2V0LlxuICovXG5leHBvcnQgY2xhc3MgVHJhbnNjcmlwdEVzdGltYXRvciB7XG4gIC8qKiBQZXItZ2VuZSBkYXRhc2V0IHRvdGFscyBmb3IgdGhlIGluLXZpZXcgZXN0aW1hdGUsIGZvciB0aGUgbGF0ZXN0IGdlbmUgc2V0LiAqL1xuICBwcml2YXRlIGNvdW50c0NhY2hlOiB7IGtleTogc3RyaW5nOyBjb3VudHM6IFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRDb3VudHM+IH0gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBvcnQ6IFNwYXRpYWxEYXRhUG9ydCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoYW5nZWQ6IChlc3RpbWF0ZTogVHJhbnNjcmlwdEVzdGltYXRlIHwgbnVsbCkgPT4gdm9pZCxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBUcmFuc2NyaXB0cyBpbiB2aWV3IGZvciB0aGUgdmlzaWJsZSBnZW5lczogZWFjaCBnZW5lJ3MgZGF0YXNldCB0b3RhbCB0aW1lcyB0aGUgc2hhcmVcbiAgICogb2YgdGhlIHRpc3N1ZSBvbiBzY3JlZW4uIEFuIGVzdGltYXRlIOKAlCBleHByZXNzaW9uIGlzIG5vdCB1bmlmb3JtIOKAlCB3aGljaCBpcyBhbHNvIHdoYXRcbiAgICogWGVuaXVtIEV4cGxvcmVyIHNob3dzOyBpdCB0ZWxscyB0aGUgdXNlciB3aGV0aGVyIHRoZSBidWRnZXQgd2lsbCBmb3JjZSBncm91cGluZy5cbiAgICovXG4gIGFzeW5jIHBsYW4oXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICB2aWV3ZXI6IFZpZXdlcixcbiAgICB3OiBudW1iZXIsXG4gICAgaDogbnVtYmVyLFxuICAgIGN0eDogUGxhbkNvbnRleHQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRpbGVzID0gZGF0YXNldC50cmFuc2NyaXB0VGlsZXM7XG4gICAgaWYgKCF0aWxlcyB8fCAhdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRDb3VudHMgfHwgdmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ29mZicpIHtcbiAgICAgIHRoaXMuY2hhbmdlZChudWxsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaGlkZGVuR2VuZXMgPSBuZXcgU2V0KHZpZXcudHJhbnNjcmlwdEhpZGRlbkdlbmVzKTtcbiAgICBjb25zdCBnZW5lcyA9IHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gW10gOiB2aWV3LnRyYW5zY3JpcHRHZW5lcy5maWx0ZXIoKGcpID0+ICFoaWRkZW5HZW5lcy5oYXMoZykpO1xuICAgIGNvbnN0IGtleSA9IGAke2RhdGFzZXQuaWR9fCR7Z2VuZXMuam9pbignLCcpfWA7XG4gICAgaWYgKHRoaXMuY291bnRzQ2FjaGU/LmtleSAhPT0ga2V5KSB7XG4gICAgICB0aGlzLmNvdW50c0NhY2hlID0geyBrZXksIGNvdW50czogdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRDb3VudHMoZ2VuZXMpIH07XG4gICAgfVxuICAgIGxldCBjb3VudHM6IFNwYXRpYWxUcmFuc2NyaXB0Q291bnRzO1xuICAgIHRyeSB7XG4gICAgICBjb3VudHMgPSBhd2FpdCB0aGlzLmNvdW50c0NhY2hlLmNvdW50cztcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRoaXMuY291bnRzQ2FjaGUgPSBudWxsO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoY3R4LnN0YWxlKCkpIHJldHVybjtcbiAgICBjb25zdCBpblZpZXcgPSB2aXNpYmxlRGF0YVJlY3Qodmlld2VyLmNhbWVyYS5jZW50ZXIsIHZpZXdlci5jYW1lcmEuem9vbSwgdywgaCwgZGF0YXNldC5pbWFnZVJlZiwgMCk7XG4gICAgaWYgKCFpblZpZXcpIHJldHVybjtcbiAgICBjb25zdCBiID0gY291bnRzLmJvdW5kcztcbiAgICBjb25zdCBzaGFyZSA9IE1hdGgubWluKDEsIHZpc2libGVBcmVhKGluVmlldywgYikgLyBNYXRoLm1heCgxLCAoYlsyXSAtIGJbMF0pICogKGJbM10gLSBiWzFdKSkpO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdmlldy50cmFuc2NyaXB0QWxsR2VuZXNcbiAgICAgID8gY291bnRzLnRvdGFsXG4gICAgICA6IGdlbmVzLnJlZHVjZSgoc3VtLCBnKSA9PiBzdW0gKyAoY291bnRzLmNvdW50c1tnXSA/PyAwKSwgMCk7XG4gICAgdGhpcy5jaGFuZ2VkKHsgcG9pbnRzOiBNYXRoLnJvdW5kKHNlbGVjdGVkICogc2hhcmUpLCBtYXg6IHZpZXcudHJhbnNjcmlwdEJ1ZGdldCB9KTtcbiAgfVxufVxuIl19