@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,602 @@
1
+ import { MultiChannelImageView, decodeImageRGBA, histogramScalar, tintColormap } from 'napari-js';
2
+ import { NavigatorOverlay, ScaleBarOverlay } from 'napari-js/overlays';
3
+ import { rgbNeedsRecolor } from '../osd/display-pipeline';
4
+ import { regionCentroids } from '../region-centroids';
5
+ import { isServerlessMultichannel, splitRgbBands, tintFor, tintedComposite, toIHistogram, toNapariGamma, typedPlane, } from './napari-helpers';
6
+ /**
7
+ * Composite additive channel layers onto black, as OSD and Plotly merge them: the bottom-most
8
+ * SHOWN layer replaces what is under it, the others add onto it. All-additive layers added onto
9
+ * the viewer's dark-grey background instead, lifting every black pixel to that grey.
10
+ */
11
+ function mergeOntoBlack(layers) {
12
+ const base = layers.find((layer) => layer.visible);
13
+ for (const layer of layers)
14
+ layer.blending = layer === base ? 'translucent' : 'additive';
15
+ }
16
+ /**
17
+ * The 2D image (review Appendix B, cluster E): pyramidal `TiledSource`s against the `/tile`
18
+ * endpoint when `/tiles/info` describes the image, else a single stitched level (`tiled:false`
19
+ * stacks fetch each slice's own URL, a serverless multichannel stack each channel's own plane);
20
+ * multichannel additive tints, grayscale colormap or RGB (recoloured per band, see
21
+ * {@link syncRgbBands}); the coarse histogram samples of the tiled path, the scale bar, the
22
+ * overview navigator and the 2D interaction stack (region overlay + pixel tools). The
23
+ * region-centroid scatter and the spatial 2D scene are built over it.
24
+ */
25
+ export class Image2dScene {
26
+ constructor(ctx, opts = {}) {
27
+ this.ctx = ctx;
28
+ this.opts = opts;
29
+ /** How the image is composited (drives the histogram and the display-state updates). */
30
+ this.imageMode = 'rgb';
31
+ /** True when the image is rendered via pyramidal TiledSources (descriptor available). */
32
+ this.tiled = false;
33
+ /** napari-js high-level view owning the per-channel layer set for {@link imageMode}. */
34
+ this.channelView = null;
35
+ /** Latest wins for a stitched slice: a slow older slice can't clobber a newer one. */
36
+ this.sliceReq = 0;
37
+ /** RGB: the R, G and B bands as layer sources (typed planes, or band `TiledSource`s that share
38
+ * one request per tile) and the stitched level's scale — what {@link syncRgbBands} draws. */
39
+ this.rgbBands = null;
40
+ /** RGB: the three additive band layers while the channel states recolour the image; null while
41
+ * the RGB layer draws it as it is. */
42
+ this.bandLayers = null;
43
+ /** Coarse per-channel luminance sample (keyed by channel index) for the histogram in tiled mode,
44
+ * where the layers have no full in-memory pixels — and an RGB image's raw bands in either mode.
45
+ * Refreshed on mount + slice change. */
46
+ this.histSamples = new Map();
47
+ /** Latest-wins token for {@link refreshHistogramSamples}. */
48
+ this.histGen = 0;
49
+ /** Physical scale bar overlay (null when the image has no µm/pixel). */
50
+ this.scaleBar = null;
51
+ /** Overview minimap (bottom-right), as OSD's navigator. */
52
+ this.navigator = null;
53
+ /** Bumped per thumbnail request, so a slow one cannot overwrite a newer slice's. */
54
+ this.navigatorToken = 0;
55
+ /** The current slice's per-channel thumbnail bitmaps (multichannel only), kept so a tint or
56
+ * visibility change recolours the thumbnail without re-fetching it. */
57
+ this.navigatorChannels = null;
58
+ /** The tints/visibility the thumbnail was last composited with — see {@link recolorNavigator}. */
59
+ this.navigatorTintKey = '';
60
+ this.displaySub = null;
61
+ }
62
+ get hasImage() {
63
+ return this.opts.image !== false;
64
+ }
65
+ async mount() {
66
+ const { ctx } = this;
67
+ const z = ctx.z();
68
+ if (this.hasImage)
69
+ await this.render(z);
70
+ // Reset into a newer scene while the image loaded: this scene is already disposed, and the
71
+ // tool bridge is the next scene's — install nothing more.
72
+ if (ctx.signal.aborted)
73
+ return;
74
+ if (this.opts.fit ? this.opts.fit() : this.hasImage)
75
+ ctx.fitCameraSoon();
76
+ this.followDisplayState();
77
+ // The scale bar and navigator describe an image; with none loaded, whatever they would
78
+ // read is left over from the last one.
79
+ if (this.hasImage) {
80
+ this.installScaleBar();
81
+ this.installNavigator(z);
82
+ }
83
+ ctx.tools.install2dInteraction(ctx.viewer, ctx.host);
84
+ }
85
+ setZ(z) {
86
+ const { ctx } = this;
87
+ if (this.navigator)
88
+ void this.refreshNavigatorImage(z);
89
+ // Tiled: just move the dims plane — the tiled visual fetches the new slice's tiles (cached per
90
+ // z), no layer rebuild. Refresh the coarse histogram sample for the new slice.
91
+ if (this.tiled) {
92
+ ctx.viewer.dims.z = z;
93
+ const desc = ctx.tiles.currentDescriptor(ctx.info());
94
+ if (desc)
95
+ void this.refreshHistogramSamples(z, desc);
96
+ this.opts.onSlice?.(false);
97
+ ctx.tools.scheduleReadback();
98
+ return;
99
+ }
100
+ // Stitch fallback: re-render the slice (re-fetches per-channel / composite). The token lets
101
+ // render drop a superseded scrub so a slow older slice can't clobber a newer one.
102
+ const req = ++this.sliceReq;
103
+ void this.render(z, req)
104
+ .then(() => {
105
+ if (req !== this.sliceReq || ctx.signal.aborted)
106
+ return;
107
+ // AFTER the image, never before: the render clears the layer list, so whatever sits over
108
+ // the image is wiped by the very image meant to sit under it.
109
+ this.opts.onSlice?.(true);
110
+ ctx.tools.scheduleReadback();
111
+ })
112
+ .catch((err) => console.error('[napari-js] setZIndex slice failed:', err));
113
+ }
114
+ histogram(channel, bins) {
115
+ // Tiled mode has no full in-memory pixels → the coarse per-channel sample. RGB: its raw band
116
+ // (either mode) — never the displayed pixels, which the channel states have recoloured.
117
+ if (this.tiled || this.imageMode === 'rgb') {
118
+ const sample = this.histSamples.get(this.imageMode === 'grayscale' ? 0 : channel);
119
+ return sample ? toIHistogram(histogramScalar(sample, bins, 0, 255)) : null;
120
+ }
121
+ // Grayscale/multichannel (stitch): native per-channel histogram straight from the in-memory
122
+ // scalar layer (no GPU readback).
123
+ const layer = this.channelView?.layers[this.imageMode === 'grayscale' ? 0 : channel];
124
+ const h = layer ? this.ctx.viewer.layerHistogram(layer, bins) : null;
125
+ return h ? toIHistogram(h) : null;
126
+ }
127
+ setImageSmoothing(enabled) {
128
+ // Apply live to the rendered image layers; baked into the next render too.
129
+ const interpolation = enabled ? 'linear' : 'nearest';
130
+ this.channelView?.setInterpolation(interpolation);
131
+ this.bandLayers?.forEach((layer) => (layer.interpolation = interpolation));
132
+ }
133
+ setNavigatorVisible(visible) {
134
+ this.navigator?.setVisible(visible);
135
+ }
136
+ /** Show the navigator only for a dataset that brings pixels of its own (and when the user
137
+ * wants it): with no image of its own there is nothing for an overview to show. */
138
+ showNavigatorFor(datasetHasPixels) {
139
+ this.navigator?.setVisible(datasetHasPixels && this.ctx.settings.navigatorVisible);
140
+ }
141
+ dispose() {
142
+ this.displaySub?.unsubscribe();
143
+ this.displaySub = null;
144
+ this.scaleBar?.dispose();
145
+ this.scaleBar = null;
146
+ this.navigator?.dispose();
147
+ this.navigator = null;
148
+ this.setNavigatorChannels(null);
149
+ this.histGen++;
150
+ this.histSamples.clear();
151
+ this.channelView = null;
152
+ this.rgbBands = null;
153
+ this.bandLayers = null;
154
+ }
155
+ /**
156
+ * Render slice `z`. With a server pyramid descriptor each layer is a pyramidal
157
+ * {@link TiledSource}, so the view refines to higher resolution on zoom (like OSD) and sits
158
+ * naturally in full-resolution coordinates; without one, the single-level stitch. Three display
159
+ * modes either way: multichannel additive tint, grayscale colormap, RGB.
160
+ */
161
+ async render(z, token) {
162
+ const { ctx } = this;
163
+ const scene = ctx.signal;
164
+ const desc = await ctx.tiles.ensureDescriptor(ctx.info());
165
+ // Reset into a newer scene while the descriptor was in flight: this render is superseded.
166
+ if (scene.aborted)
167
+ return;
168
+ if (desc && desc.levels?.length) {
169
+ if (token != null && token !== this.sliceReq)
170
+ return;
171
+ await this.renderTiled(z, desc, scene);
172
+ return;
173
+ }
174
+ return this.renderStitched(z, token);
175
+ }
176
+ /** Single-level stitch fallback (no descriptor): the pre-tiling path. */
177
+ async renderStitched(z, token) {
178
+ const { ctx } = this;
179
+ const info = ctx.info();
180
+ const desc = await ctx.tiles.ensureDescriptor(info);
181
+ const states = ctx.store.currentChannelStates();
182
+ // A serverless multichannel stack has no descriptor: its channels are its own plane URLs
183
+ // (`channelUrls[z][c]`, which fetchChannelData reads), and `urls[z]` only a composite.
184
+ const serverlessMc = isServerlessMultichannel(ctx.tiles.isSimple(info), info);
185
+ const channelCount = desc?.channels ?? (serverlessMc ? (info?.imageMeta?.[0]?.channelCount ?? 1) : states.length || 1);
186
+ const multichannel = (!!desc?.multichannel || serverlessMc) && channelCount > 1;
187
+ // 1) Fetch all pixel data BEFORE touching the viewer, so a superseded scrub can bail without
188
+ // having torn down the visible layers (avoids flicker / out-of-order layer state).
189
+ let mode;
190
+ let planes = [];
191
+ let bitmap = null;
192
+ if (multichannel) {
193
+ mode = 'multichannel';
194
+ planes = await Promise.all(Array.from({ length: channelCount }, (_, c) => ctx.tiles.fetchChannelData(info, z, c)));
195
+ }
196
+ else if (channelCount === 1) {
197
+ mode = 'grayscale';
198
+ // Composite fetch (no channel) → all overview levels usable, so a large grayscale image
199
+ // selects a fitting downscaled level instead of the full-res real level (texture limit).
200
+ planes = [await ctx.tiles.fetchChannelData(info, z)];
201
+ }
202
+ else {
203
+ mode = 'rgb';
204
+ // The bitmap draws the image as it is; its raw bands, the per-band layers and histograms.
205
+ bitmap = await ctx.tiles.fetchImage(info, z);
206
+ planes = splitRgbBands(decodeImageRGBA(bitmap));
207
+ }
208
+ // 2) Commit — unless a newer scrub superseded us or the scene was torn down.
209
+ if ((token != null && token !== this.sliceReq) || ctx.signal.aborted) {
210
+ bitmap?.close?.();
211
+ return;
212
+ }
213
+ // The displayed texture may be a downscaled pyramid level; scale the layer into FULL-RESOLUTION
214
+ // world coordinates (level-0 pixels) so the camera, readback and — critically — pre-saved
215
+ // regions (stored in full-res coords, e.g. ndpi) all line up regardless of which level is shown.
216
+ // This mirrors OSD, whose coordinate system is always level 0.
217
+ const texW = planes[0]?.width ?? 0;
218
+ const texH = planes[0]?.height ?? 0;
219
+ const fullW = desc?.width || texW || 1;
220
+ const fullH = desc?.height || texH || 1;
221
+ const scale = [texW ? fullW / texW : 1, texH ? fullH / texH : 1];
222
+ this.imageMode = mode;
223
+ const interpolation = ctx.settings.imageSmoothing ? 'linear' : 'nearest';
224
+ this.channelView = new MultiChannelImageView(ctx.viewer);
225
+ this.bandLayers = null; // the render clears the layer list, band layers included
226
+ if (mode === 'multichannel') {
227
+ const views = planes.map((d, c) => this.tintedChannelView(c, states, desc, typedPlane(d), scale));
228
+ this.channelView.render('multichannel', views, { interpolation });
229
+ mergeOntoBlack(this.channelView.layers);
230
+ }
231
+ else if (mode === 'grayscale') {
232
+ const view = this.grayscaleChannelView(states[0], typedPlane(planes[0]), scale);
233
+ this.channelView.render('grayscale', [view], { interpolation });
234
+ }
235
+ else {
236
+ this.channelView.render('rgb', [{ source: bitmap, scale }], { interpolation });
237
+ this.rgbBands = { sources: planes.map(typedPlane), scale };
238
+ this.histSamples.clear();
239
+ planes.forEach((band, c) => this.histSamples.set(c, band.data));
240
+ this.syncRgbBands(states);
241
+ }
242
+ ctx.setImageSize(fullW, fullH);
243
+ }
244
+ /**
245
+ * Render with pyramidal {@link TiledSource}s — the view refines to higher resolution as you
246
+ * zoom in (the visual fetches the level whose texels ≈ screen pixels) and sits in full-res
247
+ * coordinates so regions align. Same three modes as the stitch path. Per-channel layers use the
248
+ * REAL pyramid levels (per-channel tiles only exist there); the composite uses all levels.
249
+ */
250
+ async renderTiled(z, desc, scene) {
251
+ const { ctx } = this;
252
+ const states = ctx.store.currentChannelStates();
253
+ const channelCount = desc.channels ?? (states.length || 1);
254
+ const multichannel = !!desc.multichannel && channelCount > 1;
255
+ const interpolation = ctx.settings.imageSmoothing ? 'linear' : 'nearest';
256
+ this.tiled = true;
257
+ this.channelView = new MultiChannelImageView(ctx.viewer);
258
+ if (multichannel) {
259
+ this.imageMode = 'multichannel';
260
+ const views = Array.from({ length: channelCount }, (_, c) => this.tintedChannelView(c, states, desc, this.tiledSource(desc, c, 1, scene)));
261
+ this.channelView.render('multichannel', views, { interpolation });
262
+ mergeOntoBlack(this.channelView.layers);
263
+ }
264
+ else if (channelCount === 1) {
265
+ this.imageMode = 'grayscale';
266
+ const view = this.grayscaleChannelView(states[0], this.tiledSource(desc, undefined, 1, scene));
267
+ this.channelView.render('grayscale', [view], { interpolation });
268
+ }
269
+ else {
270
+ this.imageMode = 'rgb';
271
+ this.channelView.render('rgb', [{ source: this.tiledSource(desc, undefined, 4, scene) }], {
272
+ interpolation,
273
+ });
274
+ this.rgbBands = {
275
+ sources: ctx.tiles.rgbBandSources(desc, scene, () => this.ctx.badge.begin('Image')),
276
+ };
277
+ this.syncRgbBands(states);
278
+ }
279
+ ctx.setImageSize(desc.width, desc.height);
280
+ // Await on the initial render so getHistogram/autoContrast have data immediately; slice changes
281
+ // refresh fire-and-forget (the histogram pane retries).
282
+ await this.refreshHistogramSamples(z, desc);
283
+ }
284
+ /** A pyramidal TiledSource whose tiles count on the loading badge while `scene` (the render that
285
+ * asked for it, taken before its awaits) is current. */
286
+ tiledSource(desc, channel, channels, scene) {
287
+ return this.ctx.tiles.tiledSource(desc, channel, channels, scene, () => this.ctx.badge.begin('Image'));
288
+ }
289
+ /** Channel `c`'s layer in the additive multichannel composite: tinted by its display colour
290
+ * (store, else descriptor, else the Fiji palette), with its window, gamma and visibility. */
291
+ tintedChannelView(c, states, desc, source, scale) {
292
+ const st = states.find((s) => s.index === c);
293
+ return {
294
+ source,
295
+ tint: st?.color ?? desc?.channelInfo?.[c]?.color ?? tintFor(c),
296
+ name: st?.name ?? `ch${c}`,
297
+ contrastLimits: [st?.min ?? 0, st?.max ?? 255],
298
+ gamma: toNapariGamma(st?.gamma), // ImageJ γ → napari-js γ
299
+ visible: st?.visible ?? true,
300
+ invert: this.ctx.display.invert,
301
+ ...(scale ? { scale } : {}),
302
+ };
303
+ }
304
+ /** The single grayscale layer: the selected colormap, with the channel's window and gamma. */
305
+ grayscaleChannelView(st, source, scale) {
306
+ return {
307
+ source,
308
+ colormap: this.ctx.display.grayscaleColormap(),
309
+ contrastLimits: [st?.min ?? 0, st?.max ?? 255],
310
+ gamma: toNapariGamma(st?.gamma), // ImageJ γ → napari-js γ
311
+ invert: this.ctx.display.invert,
312
+ ...(scale ? { scale } : {}),
313
+ };
314
+ }
315
+ /** (Re)fetch a coarse per-channel luminance sample for the histogram (tiled mode has no full
316
+ * in-memory pixels). One cheap overview tile per channel, fetched together; cached by channel
317
+ * index. Latest wins: a scrub fires one refresh per slice, and an older slice's samples that
318
+ * land after a newer one's are dropped rather than shown as the current distribution. */
319
+ async refreshHistogramSamples(z, desc) {
320
+ const gen = ++this.histGen;
321
+ this.histSamples.clear();
322
+ const info = this.ctx.info();
323
+ if (this.imageMode === 'rgb') {
324
+ // One coarse composite tile, split into its raw R, G and B bands.
325
+ const bands = await this.ctx.tiles.readRgbBands(info, z, 1).catch(() => null);
326
+ if (gen !== this.histGen || !bands)
327
+ return;
328
+ bands.forEach((band, c) => this.histSamples.set(c, band.data));
329
+ return;
330
+ }
331
+ const multichannel = this.imageMode === 'multichannel';
332
+ const channelCount = multichannel ? (desc.channels ?? 1) : 1;
333
+ const samples = await Promise.all(Array.from({ length: channelCount }, (_, c) =>
334
+ // budget 1 → coarsest single tile; a failed channel leaves its sample unset.
335
+ this.ctx.tiles.fetchChannelData(info, z, multichannel ? c : undefined, 1).then((d) => d.data, () => null)));
336
+ if (gen !== this.histGen)
337
+ return;
338
+ samples.forEach((data, c) => {
339
+ if (data)
340
+ this.histSamples.set(c, data);
341
+ });
342
+ }
343
+ /** Channel states + grayscale colormap → live-apply to the rendered layers (no re-fetch; only z
344
+ * changes re-fetch), and recolour the navigator thumbnail. */
345
+ followDisplayState() {
346
+ this.displaySub = this.ctx.display.watch((channels) => {
347
+ this.applyDisplayState(channels);
348
+ this.recolorNavigator();
349
+ });
350
+ }
351
+ /** Apply the current channel states / colormap to the live layers (no re-fetch), delegating the
352
+ * per-channel layer mutations to the {@link MultiChannelImageView}. */
353
+ applyDisplayState(channels) {
354
+ const view = this.channelView;
355
+ const { display } = this.ctx;
356
+ if (!view)
357
+ return;
358
+ if (this.imageMode === 'rgb') {
359
+ this.syncRgbBands(channels);
360
+ }
361
+ else if (this.imageMode === 'multichannel') {
362
+ view.layers.forEach((_, c) => {
363
+ const st = channels.find((s) => s.index === c);
364
+ if (!st)
365
+ return;
366
+ view.updateChannel(c, {
367
+ tint: st.color,
368
+ contrastLimits: [st.min, st.max],
369
+ gamma: toNapariGamma(st.gamma), // ImageJ γ → napari-js γ
370
+ visible: st.visible,
371
+ invert: display.invert,
372
+ });
373
+ });
374
+ mergeOntoBlack(view.layers);
375
+ }
376
+ else if (this.imageMode === 'grayscale') {
377
+ const st = channels[0];
378
+ view.updateChannel(0, {
379
+ colormap: display.grayscaleColormap(),
380
+ invert: display.invert,
381
+ ...(st ? { contrastLimits: [st.min, st.max], gamma: toNapariGamma(st.gamma) } : {}),
382
+ });
383
+ }
384
+ }
385
+ /**
386
+ * RGB: draw the image as it is while its channel states leave it so (default R/G/B tints, full
387
+ * window, γ 1, all shown, no invert: {@link rgbNeedsRecolor}) — the RGB layer, unchanged, with
388
+ * the coarse underlay a tiled one keeps while it pans. Otherwise draw its R, G and B bands as
389
+ * three additive layers, each with its channel's window, invert, gamma, tint and visibility —
390
+ * what OSD's RGB recolour computes per pixel (the merge order of `osd/display-pipeline`). The
391
+ * band layers sit just above the hidden RGB layer, so whatever is drawn over the image stays
392
+ * over it. A host with no R/G/B channel model (fewer than three states) gets only the invert.
393
+ */
394
+ syncRgbBands(channels) {
395
+ const { viewer, display } = this.ctx;
396
+ const rgb = this.channelView?.layers[0];
397
+ const bands = this.rgbBands;
398
+ if (!rgb || !bands)
399
+ return;
400
+ const states = channels.length >= 3 ? channels : [];
401
+ if (!rgbNeedsRecolor(states, display.invert)) {
402
+ this.bandLayers?.forEach((layer) => viewer.layers.remove(layer));
403
+ this.bandLayers = null;
404
+ rgb.visible = true;
405
+ viewer.requestRender();
406
+ return;
407
+ }
408
+ if (!this.bandLayers) {
409
+ const at = viewer.layers.items.indexOf(rgb);
410
+ this.bandLayers = bands.sources.map((source, c) => {
411
+ const layer = viewer.addImage(source, {
412
+ name: `rgb${c}`,
413
+ blending: 'additive',
414
+ interpolation: rgb.interpolation,
415
+ ...(bands.scale ? { scale: bands.scale } : {}),
416
+ });
417
+ viewer.layers.move(layer, at + 1 + c);
418
+ return layer;
419
+ });
420
+ rgb.visible = false;
421
+ }
422
+ this.bandLayers.forEach((layer, c) => {
423
+ const st = states.find((s) => s.index === c);
424
+ layer.colormap = tintColormap(st?.color ?? tintFor(c));
425
+ layer.contrastLimits = [st?.min ?? 0, st?.max ?? 255];
426
+ layer.gamma = toNapariGamma(st?.gamma); // ImageJ γ → napari-js γ
427
+ layer.visible = st?.visible ?? true;
428
+ layer.invert = display.invert;
429
+ });
430
+ mergeOntoBlack(this.bandLayers);
431
+ viewer.requestRender();
432
+ }
433
+ /** (Re)install the physical scale bar (napari-js's `ScaleBarOverlay` on the 2D camera's zoom),
434
+ * sized from the image's µm/pixel (`/tiles/info` mppX, falling back to the image metadata).
435
+ * No-op without a physical size. */
436
+ installScaleBar() {
437
+ const { ctx } = this;
438
+ this.scaleBar?.dispose();
439
+ this.scaleBar = null;
440
+ const mppX = ctx.tiles.mppX(ctx.info());
441
+ if (mppX > 0)
442
+ this.scaleBar = new ScaleBarOverlay(ctx.host, ctx.viewer, { unitPerWorld: mppX, mode: '2d' });
443
+ }
444
+ /**
445
+ * The overview navigator (napari-js's `NavigatorOverlay`): a coarse thumbnail of the whole
446
+ * image with the viewport on it; click or drag to pan at the current zoom (as OSD).
447
+ */
448
+ installNavigator(z) {
449
+ const { ctx } = this;
450
+ this.navigator?.dispose();
451
+ this.navigator = null;
452
+ const { width, height } = ctx.imageSize();
453
+ if (!width || !height)
454
+ return;
455
+ this.navigator = new NavigatorOverlay(ctx.host, ctx.viewer, {
456
+ worldWidth: width,
457
+ worldHeight: height,
458
+ onEnter: () => this.opts.onNavigatorInteract?.(),
459
+ visible: ctx.settings.navigatorVisible,
460
+ });
461
+ void this.refreshNavigatorImage(z);
462
+ }
463
+ /**
464
+ * Draw the navigator's thumbnail from the coarsest pyramid level. A multichannel image
465
+ * is composited from its channels in their display colours (see {@link recolorNavigator}),
466
+ * so the overview looks like the view rather than like channel 0 in grey.
467
+ */
468
+ async refreshNavigatorImage(z) {
469
+ const nav = this.navigator;
470
+ if (!nav)
471
+ return;
472
+ const token = ++this.navigatorToken;
473
+ const { tiles } = this.ctx;
474
+ const info = this.ctx.info();
475
+ try {
476
+ const desc = await tiles.ensureDescriptor(info);
477
+ // Superseded (a newer slice, or the scene was torn down): fetch nothing.
478
+ if (token !== this.navigatorToken || this.navigator !== nav)
479
+ return;
480
+ // A serverless multichannel stack's thumbnails are its own channel planes.
481
+ const count = desc?.multichannel
482
+ ? (desc.channelInfo?.length ?? 0)
483
+ : isServerlessMultichannel(tiles.isSimple(info), info)
484
+ ? (info?.imageMeta?.[0]?.channelCount ?? 0)
485
+ : 0;
486
+ if (count > 1) {
487
+ const bitmaps = await Promise.all(Array.from({ length: count }, (_c, c) => tiles.overviewImage(info, z, c)));
488
+ if (token !== this.navigatorToken || this.navigator !== nav)
489
+ return;
490
+ this.setNavigatorChannels(bitmaps);
491
+ this.recolorNavigator();
492
+ }
493
+ else {
494
+ const image = await tiles.overviewImage(info, z);
495
+ if (token !== this.navigatorToken || this.navigator !== nav)
496
+ return;
497
+ this.setNavigatorChannels(null);
498
+ nav.setImage(image);
499
+ }
500
+ }
501
+ catch (err) {
502
+ console.warn('[napari-js] navigator thumbnail unavailable', err);
503
+ }
504
+ }
505
+ /** Replace the per-channel thumbnail bitmaps (closing the previous ones). */
506
+ setNavigatorChannels(bitmaps) {
507
+ for (const bmp of this.navigatorChannels ?? [])
508
+ if ('close' in bmp)
509
+ bmp.close?.();
510
+ this.navigatorChannels = bitmaps;
511
+ this.navigatorTintKey = '';
512
+ }
513
+ /**
514
+ * Composite the multichannel thumbnail in the channels' CURRENT display tints, skipping hidden
515
+ * channels — the store's channel states, as the 2D layers use, not the server's defaults.
516
+ * Re-run on every display-state change; it only redraws (never re-fetches), and only when a
517
+ * tint or a visibility actually changed, so a window/gamma drag costs a string compare.
518
+ */
519
+ recolorNavigator() {
520
+ const nav = this.navigator;
521
+ const bitmaps = this.navigatorChannels;
522
+ if (!nav || !bitmaps)
523
+ return;
524
+ const info = this.ctx.tiles.currentDescriptor(this.ctx.info())?.channelInfo;
525
+ const states = this.ctx.store.currentChannelStates();
526
+ const shown = bitmaps
527
+ .map((bmp, c) => {
528
+ const st = states.find((s) => s.index === c);
529
+ return { bmp, visible: st?.visible ?? true, color: st?.color ?? info?.[c]?.color ?? tintFor(c) };
530
+ })
531
+ .filter((ch) => ch.visible);
532
+ const key = shown.map((ch) => `${bitmaps.indexOf(ch.bmp)}:${ch.color}`).join('|');
533
+ if (key === this.navigatorTintKey)
534
+ return;
535
+ this.navigatorTintKey = key;
536
+ nav.setImage(tintedComposite(shown.map((ch) => ch.bmp), shown.map((ch) => ch.color)));
537
+ }
538
+ }
539
+ /**
540
+ * NAPARI_SCATTER (review Appendix B, cluster H): the slice image with a points layer at each
541
+ * region's centroid (the napari-js analog of Plotly's region-centroid scatter), rebuilt live as
542
+ * regions change. This mode plots REGION centroids, so the image's region tools come with it —
543
+ * drawing a region adds a point at once.
544
+ */
545
+ export class ScatterRegionsScene {
546
+ constructor(ctx) {
547
+ this.ctx = ctx;
548
+ this.points = null;
549
+ this.regionSub = null;
550
+ this.image = new Image2dScene(ctx, {
551
+ // The region-centroid points went with the re-render's layer clear.
552
+ onSlice: (rerendered) => {
553
+ if (rerendered && this.points)
554
+ this.rebuildPoints();
555
+ },
556
+ });
557
+ }
558
+ async mount() {
559
+ await this.image.mount();
560
+ // Disposed while the image loaded: a subscription now would outlive the scene.
561
+ if (this.ctx.signal.aborted)
562
+ return;
563
+ this.rebuildPoints();
564
+ this.regionSub = this.ctx.regionStore.getRegionUpdateEvent().subscribe(() => this.rebuildPoints());
565
+ this.ctx.tools.scheduleReadback();
566
+ }
567
+ setZ(z) {
568
+ this.image.setZ(z);
569
+ }
570
+ histogram(channel, bins) {
571
+ return this.image.histogram(channel, bins);
572
+ }
573
+ setImageSmoothing(enabled) {
574
+ this.image.setImageSmoothing(enabled);
575
+ }
576
+ setNavigatorVisible(visible) {
577
+ this.image.setNavigatorVisible(visible);
578
+ }
579
+ dispose() {
580
+ this.regionSub?.unsubscribe();
581
+ this.regionSub = null;
582
+ this.image.dispose();
583
+ }
584
+ /** (Re)build the point layer at the current region centroids. */
585
+ rebuildPoints() {
586
+ const v = this.ctx.viewer;
587
+ if (this.points) {
588
+ v.layers.remove(this.points);
589
+ this.points = null;
590
+ }
591
+ const centroids = regionCentroids(this.ctx.regionStore.getRegions());
592
+ if (centroids.length === 0)
593
+ return;
594
+ this.points = v.addPoints(centroids, {
595
+ size: 12,
596
+ faceColor: [1, 0.85, 0.2, 1],
597
+ borderColor: [0, 0, 0, 1],
598
+ borderWidth: 2,
599
+ });
600
+ }
601
+ }
602
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFwYXJpLWltYWdlLTJkLXNjZW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvbmFwYXJpLWpzL25hcGFyaS1pbWFnZS0yZC1zY2VuZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFbEcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBSXZFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUVMLHdCQUF3QixFQUN4QixhQUFhLEVBQ2IsT0FBTyxFQUNQLGVBQWUsRUFDZixZQUFZLEVBQ1osYUFBYSxFQUNiLFVBQVUsR0FDWCxNQUFNLGtCQUFrQixDQUFDO0FBZ0IxQjs7OztHQUlHO0FBQ0gsU0FBUyxjQUFjLENBQUMsTUFBNkI7SUFDbkQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ25ELEtBQUssTUFBTSxLQUFLLElBQUksTUFBTTtRQUFFLEtBQUssQ0FBQyxRQUFRLEdBQUcsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7QUFDM0YsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFrQ3ZCLFlBQ21CLEdBQWlCLEVBQ2pCLE9BQXVCLEVBQUU7UUFEekIsUUFBRyxHQUFILEdBQUcsQ0FBYztRQUNqQixTQUFJLEdBQUosSUFBSSxDQUFxQjtRQW5DNUMsd0ZBQXdGO1FBQ3hGLGNB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TCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE11bHRpQ2hhbm5lbEltYWdlVmlldywgZGVjb2RlSW1hZ2VSR0JBLCBoaXN0b2dyYW1TY2FsYXIsIHRpbnRDb2xvcm1hcCB9IGZyb20gJ25hcGFyaS1qcyc7XG5pbXBvcnQgdHlwZSB7IENoYW5uZWxWaWV3LCBJbWFnZUxheWVyLCBQb2ludHNMYXllciwgVGlsZWRTb3VyY2UgfSBmcm9tICduYXBhcmktanMnO1xuaW1wb3J0IHsgTmF2aWdhdG9yT3ZlcmxheSwgU2NhbGVCYXJPdmVybGF5IH0gZnJvbSAnbmFwYXJpLWpzL292ZXJsYXlzJztcblxuaW1wb3J0IHsgSUNoYW5uZWxTdGF0ZSwgSUhpc3RvZ3JhbSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9jaGFubmVsLWhpc3RvZ3JhbS1hcGkuY29udHJhY3QnO1xuaW1wb3J0IHsgVGlsZURlc2NyaXB0b3IgfSBmcm9tICcuLi90aWxlLXNlcnZlcic7XG5pbXBvcnQgeyByZ2JOZWVkc1JlY29sb3IgfSBmcm9tICcuLi9vc2QvZGlzcGxheS1waXBlbGluZSc7XG5pbXBvcnQgdHlwZSB7IE92ZXJ2aWV3SW1hZ2UgfSBmcm9tICcuL25hcGFyaS10aWxlLWNsaWVudCc7XG5pbXBvcnQgeyByZWdpb25DZW50cm9pZHMgfSBmcm9tICcuLi9yZWdpb24tY2VudHJvaWRzJztcbmltcG9ydCB7XG4gIEx1bWFQbGFuZSxcbiAgaXNTZXJ2ZXJsZXNzTXVsdGljaGFubmVsLFxuICBzcGxpdFJnYkJhbmRzLFxuICB0aW50Rm9yLFxuICB0aW50ZWRDb21wb3NpdGUsXG4gIHRvSUhpc3RvZ3JhbSxcbiAgdG9OYXBhcmlHYW1tYSxcbiAgdHlwZWRQbGFuZSxcbn0gZnJvbSAnLi9uYXBhcmktaGVscGVycyc7XG5pbXBvcnQgdHlwZSB7IE5hcGFyaVNjZW5lLCBTY2VuZUNvbnRleHQgfSBmcm9tICcuL25hcGFyaS1zY2VuZSc7XG5cbi8qKiBXaGF0IHRoZSBzY2VuZXMgYnVpbHQgb3ZlciB0aGUgMkQgaW1hZ2UgYWRkIHRvIGl0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbWFnZTJkT3B0aW9ucyB7XG4gIC8qKiBEcmF3IHRoZSBsb2FkZWQgaW1hZ2UgKGZhbHNlOiBhbiBpbWFnZS1sZXNzIHNwYXRpYWwgZGF0YXNldCwgdGhlIG9ic2VydmF0aW9ucyBhbG9uZSkuICovXG4gIGltYWdlPzogYm9vbGVhbjtcbiAgLyoqIFdoZXRoZXIgdG8gZml0IHRoZSBjYW1lcmEgdG8gdGhlIGltYWdlIG9uY2UgaXQgaXMgZHJhd24gKGRlZmF1bHQ6IHdoZW4gdGhlcmUgaXMgb25lKS4gKi9cbiAgZml0PzogKCkgPT4gYm9vbGVhbjtcbiAgLyoqIEFmdGVyIGEgc2xpY2UgY2hhbmdlLiBgcmVyZW5kZXJlZGAgd2hlbiB0aGUgc3RpdGNoZWQgcGF0aCByZS1yZW5kZXJlZCB0aGUgaW1hZ2Ug4oCUIHdoaWNoXG4gICAqICBDTEVBUlMgdGhlIGxheWVyIGxpc3QsIHRha2luZyBldmVyeSBvdGhlciBsYXllciB3aXRoIGl0LiAqL1xuICBvblNsaWNlPzogKHJlcmVuZGVyZWQ6IGJvb2xlYW4pID0+IHZvaWQ7XG4gIC8qKiBUaGUgcG9pbnRlciBlbnRlcmVkIHRoZSBuYXZpZ2F0b3IgKGUuZy4gdG8gaGlkZSBhIGhvdmVyIHRvb2x0aXAgb3ZlciB0aGUgY2FudmFzKS4gKi9cbiAgb25OYXZpZ2F0b3JJbnRlcmFjdD86ICgpID0+IHZvaWQ7XG59XG5cbi8qKlxuICogQ29tcG9zaXRlIGFkZGl0aXZlIGNoYW5uZWwgbGF5ZXJzIG9udG8gYmxhY2ssIGFzIE9TRCBhbmQgUGxvdGx5IG1lcmdlIHRoZW06IHRoZSBib3R0b20tbW9zdFxuICogU0hPV04gbGF5ZXIgcmVwbGFjZXMgd2hhdCBpcyB1bmRlciBpdCwgdGhlIG90aGVycyBhZGQgb250byBpdC4gQWxsLWFkZGl0aXZlIGxheWVycyBhZGRlZCBvbnRvXG4gKiB0aGUgdmlld2VyJ3MgZGFyay1ncmV5IGJhY2tncm91bmQgaW5zdGVhZCwgbGlmdGluZyBldmVyeSBibGFjayBwaXhlbCB0byB0aGF0IGdyZXkuXG4gKi9cbmZ1bmN0aW9uIG1lcmdlT250b0JsYWNrKGxheWVyczogcmVhZG9ubHkgSW1hZ2VMYXllcltdKTogdm9pZCB7XG4gIGNvbnN0IGJhc2UgPSBsYXllcnMuZmluZCgobGF5ZXIpID0+IGxheWVyLnZpc2libGUpO1xuICBmb3IgKGNvbnN0IGxheWVyIG9mIGxheWVycykgbGF5ZXIuYmxlbmRpbmcgPSBsYXllciA9PT0gYmFzZSA/ICd0cmFuc2x1Y2VudCcgOiAnYWRkaXRpdmUnO1xufVxuXG4vKipcbiAqIFRoZSAyRCBpbWFnZSAocmV2aWV3IEFwcGVuZGl4IEIsIGNsdXN0ZXIgRSk6IHB5cmFtaWRhbCBgVGlsZWRTb3VyY2VgcyBhZ2FpbnN0IHRoZSBgL3RpbGVgXG4gKiBlbmRwb2ludCB3aGVuIGAvdGlsZXMvaW5mb2AgZGVzY3JpYmVzIHRoZSBpbWFnZSwgZWxzZSBhIHNpbmdsZSBzdGl0Y2hlZCBsZXZlbCAoYHRpbGVkOmZhbHNlYFxuICogc3RhY2tzIGZldGNoIGVhY2ggc2xpY2UncyBvd24gVVJMLCBhIHNlcnZlcmxlc3MgbXVsdGljaGFubmVsIHN0YWNrIGVhY2ggY2hhbm5lbCdzIG93biBwbGFuZSk7XG4gKiBtdWx0aWNoYW5uZWwgYWRkaXRpdmUgdGludHMsIGdyYXlzY2FsZSBjb2xvcm1hcCBvciBSR0IgKHJlY29sb3VyZWQgcGVyIGJhbmQsIHNlZVxuICoge0BsaW5rIHN5bmNSZ2JCYW5kc30pOyB0aGUgY29hcnNlIGhpc3RvZ3JhbSBzYW1wbGVzIG9mIHRoZSB0aWxlZCBwYXRoLCB0aGUgc2NhbGUgYmFyLCB0aGVcbiAqIG92ZXJ2aWV3IG5hdmlnYXRvciBhbmQgdGhlIDJEIGludGVyYWN0aW9uIHN0YWNrIChyZWdpb24gb3ZlcmxheSArIHBpeGVsIHRvb2xzKS4gVGhlXG4gKiByZWdpb24tY2VudHJvaWQgc2NhdHRlciBhbmQgdGhlIHNwYXRpYWwgMkQgc2NlbmUgYXJlIGJ1aWx0IG92ZXIgaXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBJbWFnZTJkU2NlbmUgaW1wbGVtZW50cyBOYXBhcmlTY2VuZSB7XG4gIC8qKiBIb3cgdGhlIGltYWdlIGlzIGNvbXBvc2l0ZWQgKGRyaXZlcyB0aGUgaGlzdG9ncmFtIGFuZCB0aGUgZGlzcGxheS1zdGF0ZSB1cGRhdGVzKS4gKi9cbiAgaW1hZ2VNb2RlOiAnZ3JheXNjYWxlJyB8ICdtdWx0aWNoYW5uZWwnIHwgJ3JnYicgPSAncmdiJztcbiAgLyoqIFRydWUgd2hlbiB0aGUgaW1hZ2UgaXMgcmVuZGVyZWQgdmlhIHB5cmFtaWRhbCBUaWxlZFNvdXJjZXMgKGRlc2NyaXB0b3IgYXZhaWxhYmxlKS4gKi9cbiAgdGlsZWQgPSBmYWxzZTtcbiAgLyoqIG5hcGFyaS1qcyBoaWdoLWxldmVsIHZpZXcgb3duaW5nIHRoZSBwZXItY2hhbm5lbCBsYXllciBzZXQgZm9yIHtAbGluayBpbWFnZU1vZGV9LiAqL1xuICBwcml2YXRlIGNoYW5uZWxWaWV3OiBNdWx0aUNoYW5uZWxJbWFnZVZpZXcgfCBudWxsID0gbnVsbDtcbiAgLyoqIExhdGVzdCB3aW5zIGZvciBhIHN0aXRjaGVkIHNsaWNlOiBhIHNsb3cgb2xkZXIgc2xpY2UgY2FuJ3QgY2xvYmJlciBhIG5ld2VyIG9uZS4gKi9cbiAgcHJpdmF0ZSBzbGljZVJlcSA9IDA7XG4gIC8qKiBSR0I6IHRoZSBSLCBHIGFuZCBCIGJhbmRzIGFzIGxheWVyIHNvdXJjZXMgKHR5cGVkIHBsYW5lcywgb3IgYmFuZCBgVGlsZWRTb3VyY2VgcyB0aGF0IHNoYXJlXG4gICAqICBvbmUgcmVxdWVzdCBwZXIgdGlsZSkgYW5kIHRoZSBzdGl0Y2hlZCBsZXZlbCdzIHNjYWxlIOKAlCB3aGF0IHtAbGluayBzeW5jUmdiQmFuZHN9IGRyYXdzLiAqL1xuICBwcml2YXRlIHJnYkJhbmRzOiB7IHNvdXJjZXM6IENoYW5uZWxWaWV3Wydzb3VyY2UnXVtdOyBzY2FsZT86IFtudW1iZXIsIG51bWJlcl0gfSB8IG51bGwgPSBudWxsO1xuICAvKiogUkdCOiB0aGUgdGhyZWUgYWRkaXRpdmUgYmFuZCBsYXllcnMgd2hpbGUgdGhlIGNoYW5uZWwgc3RhdGVzIHJlY29sb3VyIHRoZSBpbWFnZTsgbnVsbCB3aGlsZVxuICAgKiAgdGhlIFJHQiBsYXllciBkcmF3cyBpdCBhcyBpdCBpcy4gKi9cbiAgcHJpdmF0ZSBiYW5kTGF5ZXJzOiBJbWFnZUxheWVyW10gfCBudWxsID0gbnVsbDtcbiAgLyoqIENvYXJzZSBwZXItY2hhbm5lbCBsdW1pbmFuY2Ugc2FtcGxlIChrZXllZCBieSBjaGFubmVsIGluZGV4KSBmb3IgdGhlIGhpc3RvZ3JhbSBpbiB0aWxlZCBtb2RlLFxuICAgKiAgd2hlcmUgdGhlIGxheWVycyBoYXZlIG5vIGZ1bGwgaW4tbWVtb3J5IHBpeGVscyDigJQgYW5kIGFuIFJHQiBpbWFnZSdzIHJhdyBiYW5kcyBpbiBlaXRoZXIgbW9kZS5cbiAgICogIFJlZnJlc2hlZCBvbiBtb3VudCArIHNsaWNlIGNoYW5nZS4gKi9cbiAgcmVhZG9ubHkgaGlzdFNhbXBsZXMgPSBuZXcgTWFwPG51bWJlciwgVWludDhBcnJheT4oKTtcbiAgLyoqIExhdGVzdC13aW5zIHRva2VuIGZvciB7QGxpbmsgcmVmcmVzaEhpc3RvZ3JhbVNhbXBsZXN9LiAqL1xuICBwcml2YXRlIGhpc3RHZW4gPSAwO1xuICAvKiogUGh5c2ljYWwgc2NhbGUgYmFyIG92ZXJsYXkgKG51bGwgd2hlbiB0aGUgaW1hZ2UgaGFzIG5vIMK1bS9waXhlbCkuICovXG4gIHByaXZhdGUgc2NhbGVCYXI6IFNjYWxlQmFyT3ZlcmxheSB8IG51bGwgPSBudWxsO1xuICAvKiogT3ZlcnZpZXcgbWluaW1hcCAoYm90dG9tLXJpZ2h0KSwgYXMgT1NEJ3MgbmF2aWdhdG9yLiAqL1xuICBwcml2YXRlIG5hdmlnYXRvcjogTmF2aWdhdG9yT3ZlcmxheSB8IG51bGwgPSBudWxsO1xuICAvKiogQnVtcGVkIHBlciB0aHVtYm5haWwgcmVxdWVzdCwgc28gYSBzbG93IG9uZSBjYW5ub3Qgb3ZlcndyaXRlIGEgbmV3ZXIgc2xpY2Uncy4gKi9cbiAgcHJpdmF0ZSBuYXZpZ2F0b3JUb2tlbiA9IDA7XG4gIC8qKiBUaGUgY3VycmVudCBzbGljZSdzIHBlci1jaGFubmVsIHRodW1ibmFpbCBiaXRtYXBzIChtdWx0aWNoYW5uZWwgb25seSksIGtlcHQgc28gYSB0aW50IG9yXG4gICAqICB2aXNpYmlsaXR5IGNoYW5nZSByZWNvbG91cnMgdGhlIHRodW1ibmFpbCB3aXRob3V0IHJlLWZldGNoaW5nIGl0LiAqL1xuICBwcml2YXRlIG5hdmlnYXRvckNoYW5uZWxzOiBPdmVydmlld0ltYWdlW10gfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSB0aW50cy92aXNpYmlsaXR5IHRoZSB0aHVtYm5haWwgd2FzIGxhc3QgY29tcG9zaXRlZCB3aXRoIOKAlCBzZWUge0BsaW5rIHJlY29sb3JOYXZpZ2F0b3J9LiAqL1xuICBwcml2YXRlIG5hdmlnYXRvclRpbnRLZXkgPSAnJztcbiAgcHJpdmF0ZSBkaXNwbGF5U3ViOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGN0eDogU2NlbmVDb250ZXh0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0czogSW1hZ2UyZE9wdGlvbnMgPSB7fSxcbiAgKSB7fVxuXG4gIHByaXZhdGUgZ2V0IGhhc0ltYWdlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm9wdHMuaW1hZ2UgIT09IGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgbW91bnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IHRoaXM7XG4gICAgY29uc3QgeiA9IGN0eC56KCk7XG4gICAgaWYgKHRoaXMuaGFzSW1hZ2UpIGF3YWl0IHRoaXMucmVuZGVyKHopO1xuICAgIC8vIFJlc2V0IGludG8gYSBuZXdlciBzY2VuZSB3aGlsZSB0aGUgaW1hZ2UgbG9hZGVkOiB0aGlzIHNjZW5lIGlzIGFscmVhZHkgZGlzcG9zZWQsIGFuZCB0aGVcbiAgICAvLyB0b29sIGJyaWRnZSBpcyB0aGUgbmV4dCBzY2VuZSdzIOKAlCBpbnN0YWxsIG5vdGhpbmcgbW9yZS5cbiAgICBpZiAoY3R4LnNpZ25hbC5hYm9ydGVkKSByZXR1cm47XG4gICAgaWYgKHRoaXMub3B0cy5maXQgPyB0aGlzLm9wdHMuZml0KCkgOiB0aGlzLmhhc0ltYWdlKSBjdHguZml0Q2FtZXJhU29vbigpO1xuICAgIHRoaXMuZm9sbG93RGlzcGxheVN0YXRlKCk7XG4gICAgLy8gVGhlIHNjYWxlIGJhciBhbmQgbmF2aWdhdG9yIGRlc2NyaWJlIGFuIGltYWdlOyB3aXRoIG5vbmUgbG9hZGVkLCB3aGF0ZXZlciB0aGV5IHdvdWxkXG4gICAgLy8gcmVhZCBpcyBsZWZ0IG92ZXIgZnJvbSB0aGUgbGFzdCBvbmUuXG4gICAgaWYgKHRoaXMuaGFzSW1hZ2UpIHtcbiAgICAgIHRoaXMuaW5zdGFsbFNjYWxlQmFyKCk7XG4gICAgICB0aGlzLmluc3RhbGxOYXZpZ2F0b3Ioeik7XG4gICAgfVxuICAgIGN0eC50b29scy5pbnN0YWxsMmRJbnRlcmFjdGlvbihjdHgudmlld2VyLCBjdHguaG9zdCk7XG4gIH1cblxuICBzZXRaKHo6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzO1xuICAgIGlmICh0aGlzLm5hdmlnYXRvcikgdm9pZCB0aGlzLnJlZnJlc2hOYXZpZ2F0b3JJbWFnZSh6KTtcbiAgICAvLyBUaWxlZDoganVzdCBtb3ZlIHRoZSBkaW1zIHBsYW5lIOKAlCB0aGUgdGlsZWQgdmlzdWFsIGZldGNoZXMgdGhlIG5ldyBzbGljZSdzIHRpbGVzIChjYWNoZWQgcGVyXG4gICAgLy8geiksIG5vIGxheWVyIHJlYnVpbGQuIFJlZnJlc2ggdGhlIGNvYXJzZSBoaXN0b2dyYW0gc2FtcGxlIGZvciB0aGUgbmV3IHNsaWNlLlxuICAgIGlmICh0aGlzLnRpbGVkKSB7XG4gICAgICBjdHgudmlld2VyLmRpbXMueiA9IHo7XG4gICAgICBjb25zdCBkZXNjID0gY3R4LnRpbGVzLmN1cnJlbnREZXNjcmlwdG9yKGN0eC5pbmZvKCkpO1xuICAgICAgaWYgKGRlc2MpIHZvaWQgdGhpcy5yZWZyZXNoSGlzdG9ncmFtU2FtcGxlcyh6LCBkZXNjKTtcbiAgICAgIHRoaXMub3B0cy5vblNsaWNlPy4oZmFsc2UpO1xuICAgICAgY3R4LnRvb2xzLnNjaGVkdWxlUmVhZGJhY2soKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gU3RpdGNoIGZhbGxiYWNrOiByZS1yZW5kZXIgdGhlIHNsaWNlIChyZS1mZXRjaGVzIHBlci1jaGFubmVsIC8gY29tcG9zaXRlKS4gVGhlIHRva2VuIGxldHNcbiAgICAvLyByZW5kZXIgZHJvcCBhIHN1cGVyc2VkZWQgc2NydWIgc28gYSBzbG93IG9sZGVyIHNsaWNlIGNhbid0IGNsb2JiZXIgYSBuZXdlciBvbmUuXG4gICAgY29uc3QgcmVxID0gKyt0aGlzLnNsaWNlUmVxO1xuICAgIHZvaWQgdGhpcy5yZW5kZXIoeiwgcmVxKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAocmVxICE9PSB0aGlzLnNsaWNlUmVxIHx8IGN0eC5zaWduYWwuYWJvcnRlZCkgcmV0dXJuO1xuICAgICAgICAvLyBBRlRFUiB0aGUgaW1hZ2UsIG5ldmVyIGJlZm9yZTogdGhlIHJlbmRlciBjbGVhcnMgdGhlIGxheWVyIGxpc3QsIHNvIHdoYXRldmVyIHNpdHMgb3ZlclxuICAgICAgICAvLyB0aGUgaW1hZ2UgaXMgd2lwZWQgYnkgdGhlIHZlcnkgaW1hZ2UgbWVhbnQgdG8gc2l0IHVuZGVyIGl0LlxuICAgICAgICB0aGlzLm9wdHMub25TbGljZT8uKHRydWUpO1xuICAgICAgICBjdHgudG9vbHMuc2NoZWR1bGVSZWFkYmFjaygpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyKSA9PiBjb25zb2xlLmVycm9yKCdbbmFwYXJpLWpzXSBzZXRaSW5kZXggc2xpY2UgZmFpbGVkOicsIGVycikpO1xuICB9XG5cbiAgaGlzdG9ncmFtKGNoYW5uZWw6IG51bWJlciwgYmluczogbnVtYmVyKTogSUhpc3RvZ3JhbSB8IG51bGwge1xuICAgIC8vIFRpbGVkIG1vZGUgaGFzIG5vIGZ1bGwgaW4tbWVtb3J5IHBpeGVscyDihpIgdGhlIGNvYXJzZSBwZXItY2hhbm5lbCBzYW1wbGUuIFJHQjogaXRzIHJhdyBiYW5kXG4gICAgLy8gKGVpdGhlciBtb2RlKSDigJQgbmV2ZXIgdGhlIGRpc3BsYXllZCBwaXhlbHMsIHdoaWNoIHRoZSBjaGFubmVsIHN0YXRlcyBoYXZlIHJlY29sb3VyZWQuXG4gICAgaWYgKHRoaXMudGlsZWQgfHwgdGhpcy5pbWFnZU1vZGUgPT09ICdyZ2InKSB7XG4gICAgICBjb25zdCBzYW1wbGUgPSB0aGlzLmhpc3RTYW1wbGVzLmdldCh0aGlzLmltYWdlTW9kZSA9PT0gJ2dyYXlzY2FsZScgPyAwIDogY2hhbm5lbCk7XG4gICAgICByZXR1cm4gc2FtcGxlID8gdG9JSGlzdG9ncmFtKGhpc3RvZ3JhbVNjYWxhcihzYW1wbGUsIGJpbnMsIDAsIDI1NSkpIDogbnVsbDtcbiAgICB9XG4gICAgLy8gR3JheXNjYWxlL211bHRpY2hhbm5lbCAoc3RpdGNoKTogbmF0aXZlIHBlci1jaGFubmVsIGhpc3RvZ3JhbSBzdHJhaWdodCBmcm9tIHRoZSBpbi1tZW1vcnlcbiAgICAvLyBzY2FsYXIgbGF5ZXIgKG5vIEdQVSByZWFkYmFjaykuXG4gICAgY29uc3QgbGF5ZXIgPSB0aGlzLmNoYW5uZWxWaWV3Py5sYXllcnNbdGhpcy5pbWFnZU1vZGUgPT09ICdncmF5c2NhbGUnID8gMCA6IGNoYW5uZWxdO1xuICAgIGNvbnN0IGggPSBsYXllciA/IHRoaXMuY3R4LnZpZXdlci5sYXllckhpc3RvZ3JhbShsYXllciwgYmlucykgOiBudWxsO1xuICAgIHJldHVybiBoID8gdG9JSGlzdG9ncmFtKGgpIDogbnVsbDtcbiAgfVxuXG4gIHNldEltYWdlU21vb3RoaW5nKGVuYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAvLyBBcHBseSBsaXZlIHRvIHRoZSByZW5kZXJlZCBpbWFnZSBsYXllcnM7IGJha2VkIGludG8gdGhlIG5leHQgcmVuZGVyIHRvby5cbiAgICBjb25zdCBpbnRlcnBvbGF0aW9uID0gZW5hYmxlZCA/ICdsaW5lYXInIDogJ25lYXJlc3QnO1xuICAgIHRoaXMuY2hhbm5lbFZpZXc/LnNldEludGVycG9sYXRpb24oaW50ZXJwb2xhdGlvbik7XG4gICAgdGhpcy5iYW5kTGF5ZXJzPy5mb3JFYWNoKChsYXllcikgPT4gKGxheWVyLmludGVycG9sYXRpb24gPSBpbnRlcnBvbGF0aW9uKSk7XG4gIH1cblxuICBzZXROYXZpZ2F0b3JWaXNpYmxlKHZpc2libGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLm5hdmlnYXRvcj8uc2V0VmlzaWJsZSh2aXNpYmxlKTtcbiAgfVxuXG4gIC8qKiBTaG93IHRoZSBuYXZpZ2F0b3Igb25seSBmb3IgYSBkYXRhc2V0IHRoYXQgYnJpbmdzIHBpeGVscyBvZiBpdHMgb3duIChhbmQgd2hlbiB0aGUgdXNlclxuICAgKiAgd2FudHMgaXQpOiB3aXRoIG5vIGltYWdlIG9mIGl0cyBvd24gdGhlcmUgaXMgbm90aGluZyBmb3IgYW4gb3ZlcnZpZXcgdG8gc2hvdy4gKi9cbiAgc2hvd05hdmlnYXRvckZvcihkYXRhc2V0SGFzUGl4ZWxzOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5uYXZpZ2F0b3I/LnNldFZpc2libGUoZGF0YXNldEhhc1BpeGVscyAmJiB0aGlzLmN0eC5zZXR0aW5ncy5uYXZpZ2F0b3JWaXNpYmxlKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5kaXNwbGF5U3ViPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuZGlzcGxheVN1YiA9IG51bGw7XG4gICAgdGhpcy5zY2FsZUJhcj8uZGlzcG9zZSgpO1xuICAgIHRoaXMuc2NhbGVCYXIgPSBudWxsO1xuICAgIHRoaXMubmF2aWdhdG9yPy5kaXNwb3NlKCk7XG4gICAgdGhpcy5uYXZpZ2F0b3IgPSBudWxsO1xuICAgIHRoaXMuc2V0TmF2aWdhdG9yQ2hhbm5lbHMobnVsbCk7XG4gICAgdGhpcy5oaXN0R2VuKys7XG4gICAgdGhpcy5oaXN0U2FtcGxlcy5jbGVhcigpO1xuICAgIHRoaXMuY2hhbm5lbFZpZXcgPSBudWxsO1xuICAgIHRoaXMucmdiQmFuZHMgPSBudWxsO1xuICAgIHRoaXMuYmFuZExheWVycyA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIHNsaWNlIGB6YC4gV2l0aCBhIHNlcnZlciBweXJhbWlkIGRlc2NyaXB0b3IgZWFjaCBsYXllciBpcyBhIHB5cmFtaWRhbFxuICAgKiB7QGxpbmsgVGlsZWRTb3VyY2V9LCBzbyB0aGUgdmlldyByZWZpbmVzIHRvIGhpZ2hlciByZXNvbHV0aW9uIG9uIHpvb20gKGxpa2UgT1NEKSBhbmQgc2l0c1xuICAgKiBuYXR1cmFsbHkgaW4gZnVsbC1yZXNvbHV0aW9uIGNvb3JkaW5hdGVzOyB3aXRob3V0IG9uZSwgdGhlIHNpbmdsZS1sZXZlbCBzdGl0Y2guIFRocmVlIGRpc3BsYXlcbiAgICogbW9kZXMgZWl0aGVyIHdheTogbXVsdGljaGFubmVsIGFkZGl0aXZlIHRpbnQsIGdyYXlzY2FsZSBjb2xvcm1hcCwgUkdCLlxuICAgKi9cbiAgYXN5bmMgcmVuZGVyKHo6IG51bWJlciwgdG9rZW4/OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGN0eCB9ID0gdGhpcztcbiAgICBjb25zdCBzY2VuZSA9IGN0eC5zaWduYWw7XG4gICAgY29uc3QgZGVzYyA9IGF3YWl0IGN0eC50aWxlcy5lbnN1cmVEZXNjcmlwdG9yKGN0eC5pbmZvKCkpO1xuICAgIC8vIFJlc2V0IGludG8gYSBuZXdlciBzY2VuZSB3aGlsZSB0aGUgZGVzY3JpcHRvciB3YXMgaW4gZmxpZ2h0OiB0aGlzIHJlbmRlciBpcyBzdXBlcnNlZGVkLlxuICAgIGlmIChzY2VuZS5hYm9ydGVkKSByZXR1cm47XG4gICAgaWYgKGRlc2MgJiYgZGVzYy5sZXZlbHM/Lmxlbmd0aCkge1xuICAgICAgaWYgKHRva2VuICE9IG51bGwgJiYgdG9rZW4gIT09IHRoaXMuc2xpY2VSZXEpIHJldHVybjtcbiAgICAgIGF3YWl0IHRoaXMucmVuZGVyVGlsZWQoeiwgZGVzYywgc2NlbmUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5yZW5kZXJTdGl0Y2hlZCh6LCB0b2tlbik7XG4gIH1cblxuICAvKiogU2luZ2xlLWxldmVsIHN0aXRjaCBmYWxsYmFjayAobm8gZGVzY3JpcHRvcik6IHRoZSBwcmUtdGlsaW5nIHBhdGguICovXG4gIHByaXZhdGUgYXN5bmMgcmVuZGVyU3RpdGNoZWQoejogbnVtYmVyLCB0b2tlbj86IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzO1xuICAgIGNvbnN0IGluZm8gPSBjdHguaW5mbygpO1xuICAgIGNvbnN0IGRlc2MgPSBhd2FpdCBjdHgudGlsZXMuZW5zdXJlRGVzY3JpcHRvcihpbmZvKTtcbiAgICBjb25zdCBzdGF0ZXMgPSBjdHguc3RvcmUuY3VycmVudENoYW5uZWxTdGF0ZXMoKTtcbiAgICAvLyBBIHNlcnZlcmxlc3MgbXVsdGljaGFubmVsIHN0YWNrIGhhcyBubyBkZXNjcmlwdG9yOiBpdHMgY2hhbm5lbHMgYXJlIGl0cyBvd24gcGxhbmUgVVJMc1xuICAgIC8vIChgY2hhbm5lbFVybHNbel1bY11gLCB3aGljaCBmZXRjaENoYW5uZWxEYXRhIHJlYWRzKSwgYW5kIGB1cmxzW3pdYCBvbmx5IGEgY29tcG9zaXRlLlxuICAgIGNvbnN0IHNlcnZlcmxlc3NNYyA9IGlzU2VydmVybGVzc011bHRpY2hhbm5lbChjdHgudGlsZXMuaXNTaW1wbGUoaW5mbyksIGluZm8pO1xuICAgIGNvbnN0IGNoYW5uZWxDb3VudCA9XG4gICAgICBkZXNjPy5jaGFubmVscyA/PyAoc2VydmVybGVzc01jID8gKGluZm8/LmltYWdlTWV0YT8uWzBdPy5jaGFubmVsQ291bnQgPz8gMSkgOiBzdGF0ZXMubGVuZ3RoIHx8IDEpO1xuICAgIGNvbnN0IG11bHRpY2hhbm5lbCA9ICghIWRlc2M/Lm11bHRpY2hhbm5lbCB8fCBzZXJ2ZXJsZXNzTWMpICYmIGNoYW5uZWxDb3VudCA+IDE7XG5cbiAgICAvLyAxKSBGZXRjaCBhbGwgcGl4ZWwgZGF0YSBCRUZPUkUgdG91Y2hpbmcgdGhlIHZpZXdlciwgc28gYSBzdXBlcnNlZGVkIHNjcnViIGNhbiBiYWlsIHdpdGhvdXRcbiAgICAvLyAgICBoYXZpbmcgdG9ybiBkb3duIHRoZSB2aXNpYmxlIGxheWVycyAoYXZvaWRzIGZsaWNrZXIgLyBvdXQtb2Ytb3JkZXIgbGF5ZXIgc3RhdGUpLlxuICAgIGxldCBtb2RlOiAnZ3JheXNjYWxlJyB8ICdtdWx0aWNoYW5uZWwnIHwgJ3JnYic7XG4gICAgbGV0IHBsYW5lczogTHVtYVBsYW5lW10gPSBbXTtcbiAgICBsZXQgYml0bWFwOiBJbWFnZUJpdG1hcCB8IG51bGwgPSBudWxsO1xuICAgIGlmIChtdWx0aWNoYW5uZWwpIHtcbiAgICAgIG1vZGUgPSAnbXVsdGljaGFubmVsJztcbiAgICAgIHBsYW5lcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBBcnJheS5mcm9tKHsgbGVuZ3RoOiBjaGFubmVsQ291bnQgfSwgKF8sIGMpID0+IGN0eC50aWxlcy5mZXRjaENoYW5uZWxEYXRhKGluZm8sIHosIGMpKSxcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmIChjaGFubmVsQ291bnQgPT09IDEpIHtcbiAgICAgIG1vZGUgPSAnZ3JheXNjYWxlJztcbiAgICAgIC8vIENvbXBvc2l0ZSBmZXRjaCAobm8gY2hhbm5lbCkg4oaSIGFsbCBvdmVydmlldyBsZXZlbHMgdXNhYmxlLCBzbyBhIGxhcmdlIGdyYXlzY2FsZSBpbWFnZVxuICAgICAgLy8gc2VsZWN0cyBhIGZpdHRpbmcgZG93bnNjYWxlZCBsZXZlbCBpbnN0ZWFkIG9mIHRoZSBmdWxsLXJlcyByZWFsIGxldmVsICh0ZXh0dXJlIGxpbWl0KS5cbiAgICAgIHBsYW5lcyA9IFthd2FpdCBjdHgudGlsZXMuZmV0Y2hDaGFubmVsRGF0YShpbmZvLCB6KV07XG4gICAgfSBlbHNlIHtcbiAgICAgIG1vZGUgPSAncmdiJztcbiAgICAgIC8vIFRoZSBiaXRtYXAgZHJhd3MgdGhlIGltYWdlIGFzIGl0IGlzOyBpdHMgcmF3IGJhbmRzLCB0aGUgcGVyLWJhbmQgbGF5ZXJzIGFuZCBoaXN0b2dyYW1zLlxuICAgICAgYml0bWFwID0gYXdhaXQgY3R4LnRpbGVzLmZldGNoSW1hZ2UoaW5mbywgeik7XG4gICAgICBwbGFuZXMgPSBzcGxpdFJnYkJhbmRzKGRlY29kZUltYWdlUkdCQShiaXRtYXApKTtcbiAgICB9XG5cbiAgICAvLyAyKSBDb21taXQg4oCUIHVubGVzcyBhIG5ld2VyIHNjcnViIHN1cGVyc2VkZWQgdXMgb3IgdGhlIHNjZW5lIHdhcyB0b3JuIGRvd24uXG4gICAgaWYgKCh0b2tlbiAhPSBudWxsICYmIHRva2VuICE9PSB0aGlzLnNsaWNlUmVxKSB8fCBjdHguc2lnbmFsLmFib3J0ZWQpIHtcbiAgICAgIGJpdG1hcD8uY2xvc2U/LigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRoZSBkaXNwbGF5ZWQgdGV4dHVyZSBtYXkgYmUgYSBkb3duc2NhbGVkIHB5cmFtaWQgbGV2ZWw7IHNjYWxlIHRoZSBsYXllciBpbnRvIEZVTEwtUkVTT0xVVElPTlxuICAgIC8vIHdvcmxkIGNvb3JkaW5hdGVzIChsZXZlbC0wIHBpeGVscykgc28gdGhlIGNhbWVyYSwgcmVhZGJhY2sgYW5kIOKAlCBjcml0aWNhbGx5IOKAlCBwcmUtc2F2ZWRcbiAgICAvLyByZWdpb25zIChzdG9yZWQgaW4gZnVsbC1yZXMgY29vcmRzLCBlLmcuIG5kcGkpIGFsbCBsaW5lIHVwIHJlZ2FyZGxlc3Mgb2Ygd2hpY2ggbGV2ZWwgaXMgc2hvd24uXG4gICAgLy8gVGhpcyBtaXJyb3JzIE9TRCwgd2hvc2UgY29vcmRpbmF0ZSBzeXN0ZW0gaXMgYWx3YXlzIGxldmVsIDAuXG4gICAgY29uc3QgdGV4VyA9IHBsYW5lc1swXT8ud2lkdGggPz8gMDtcbiAgICBjb25zdCB0ZXhIID0gcGxhbmVzWzBdPy5oZWlnaHQgPz8gMDtcbiAgICBjb25zdCBmdWxsVyA9IGRlc2M/LndpZHRoIHx8IHRleFcgfHwgMTtcbiAgICBjb25zdCBmdWxsSCA9IGRlc2M/LmhlaWdodCB8fCB0ZXhIIHx8IDE7XG4gICAgY29uc3Qgc2NhbGU6IFtudW1iZXIsIG51bWJlcl0gPSBbdGV4VyA/IGZ1bGxXIC8gdGV4VyA6IDEsIHRleEggPyBmdWxsSCAvIHRleEggOiAxXTtcblxuICAgIHRoaXMuaW1hZ2VNb2RlID0gbW9kZTtcbiAgICBjb25zdCBpbnRlcnBvbGF0aW9uOiAnbGluZWFyJyB8ICduZWFyZXN0JyA9IGN0eC5zZXR0aW5ncy5pbWFnZVNtb290aGluZyA/ICdsaW5lYXInIDogJ25lYXJlc3QnO1xuICAgIHRoaXMuY2hhbm5lbFZpZXcgPSBuZXcgTXVsdGlDaGFubmVsSW1hZ2VWaWV3KGN0eC52aWV3ZXIpO1xuICAgIHRoaXMuYmFuZExheWVycyA9IG51bGw7IC8vIHRoZSByZW5kZXIgY2xlYXJzIHRoZSBsYXllciBsaXN0LCBiYW5kIGxheWVycyBpbmNsdWRlZFxuICAgIGlmIChtb2RlID09PSAnbXVsdGljaGFubmVsJykge1xuICAgICAgY29uc3Qgdmlld3MgPSBwbGFuZXMubWFwKChkLCBjKSA9PiB0aGlzLnRpbnRlZENoYW5uZWxWaWV3KGMsIHN0YXRlcywgZGVzYywgdHlwZWRQbGFuZShkKSwgc2NhbGUpKTtcbiAgICAgIHRoaXMuY2hhbm5lbFZpZXcucmVuZGVyKCdtdWx0aWNoYW5uZWwnLCB2aWV3cywgeyBpbnRlcnBvbGF0aW9uIH0pO1xuICAgICAgbWVyZ2VPbnRvQmxhY2sodGhpcy5jaGFubmVsVmlldy5sYXllcnMpO1xuICAgIH0gZWxzZSBpZiAobW9kZSA9PT0gJ2dyYXlzY2FsZScpIHtcbiAgICAgIGNvbnN0IHZpZXcgPSB0aGlzLmdyYXlzY2FsZUNoYW5uZWxWaWV3KHN0YXRlc1swXSwgdHlwZWRQbGFuZShwbGFuZXNbMF0pLCBzY2FsZSk7XG4gICAgICB0aGlzLmNoYW5uZWxWaWV3LnJlbmRlcignZ3JheXNjYWxlJywgW3ZpZXddLCB7IGludGVycG9sYXRpb24gfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY2hhbm5lbFZpZXcucmVuZGVyKCdyZ2InLCBbeyBzb3VyY2U6IGJpdG1hcCBhcyBJbWFnZUJpdG1hcCwgc2NhbGUgfV0sIHsgaW50ZXJwb2xhdGlvbiB9KTtcbiAgICAgIHRoaXMucmdiQmFuZHMgPSB7IHNvdXJjZXM6IHBsYW5lcy5tYXAodHlwZWRQbGFuZSksIHNjYWxlIH07XG4gICAgICB0aGlzLmhpc3RTYW1wbGVzLmNsZWFyKCk7XG4gICAgICBwbGFuZXMuZm9yRWFjaCgoYmFuZCwgYykgPT4gdGhpcy5oaXN0U2FtcGxlcy5zZXQoYywgYmFuZC5kYXRhKSk7XG4gICAgICB0aGlzLnN5bmNSZ2JCYW5kcyhzdGF0ZXMpO1xuICAgIH1cbiAgICBjdHguc2V0SW1hZ2VTaXplKGZ1bGxXLCBmdWxsSCk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIHdpdGggcHlyYW1pZGFsIHtAbGluayBUaWxlZFNvdXJjZX1zIOKAlCB0aGUgdmlldyByZWZpbmVzIHRvIGhpZ2hlciByZXNvbHV0aW9uIGFzIHlvdVxuICAgKiB6b29tIGluICh0aGUgdmlzdWFsIGZldGNoZXMgdGhlIGxldmVsIHdob3NlIHRleGVscyDiiYggc2NyZWVuIHBpeGVscykgYW5kIHNpdHMgaW4gZnVsbC1yZXNcbiAgICogY29vcmRpbmF0ZXMgc28gcmVnaW9ucyBhbGlnbi4gU2FtZSB0aHJlZSBtb2RlcyBhcyB0aGUgc3RpdGNoIHBhdGguIFBlci1jaGFubmVsIGxheWVycyB1c2UgdGhlXG4gICAqIFJFQUwgcHlyYW1pZCBsZXZlbHMgKHBlci1jaGFubmVsIHRpbGVzIG9ubHkgZXhpc3QgdGhlcmUpOyB0aGUgY29tcG9zaXRlIHVzZXMgYWxsIGxldmVscy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVuZGVyVGlsZWQoejogbnVtYmVyLCBkZXNjOiBUaWxlRGVzY3JpcHRvciwgc2NlbmU6IEFib3J0U2lnbmFsKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgeyBjdHggfSA9IHRoaXM7XG4gICAgY29uc3Qgc3RhdGVzID0gY3R4LnN0b3JlLmN1cnJlbnRDaGFubmVsU3RhdGVzKCk7XG4gICAgY29uc3QgY2hhbm5lbENvdW50ID0gZGVzYy5jaGFubmVscyA/PyAoc3RhdGVzLmxlbmd0aCB8fCAxKTtcbiAgICBjb25zdCBtdWx0aWNoYW5uZWwgPSAhIWRlc2MubXVsdGljaGFubmVsICYmIGNoYW5uZWxDb3VudCA+IDE7XG4gICAgY29uc3QgaW50ZXJwb2xhdGlvbjogJ2xpbmVhcicgfCAnbmVhcmVzdCcgPSBjdHguc2V0dGluZ3MuaW1hZ2VTbW9vdGhpbmcgPyAnbGluZWFyJyA6ICduZWFyZXN0JztcblxuICAgIHRoaXMudGlsZWQgPSB0cnVlO1xuICAgIHRoaXMuY2hhbm5lbFZpZXcgPSBuZXcgTXVsdGlDaGFubmVsSW1hZ2VWaWV3KGN0eC52aWV3ZXIpO1xuXG4gICAgaWYgKG11bHRpY2hhbm5lbCkge1xuICAgICAgdGhpcy5pbWFnZU1vZGUgPSAnbXVsdGljaGFubmVsJztcbiAgICAgIGNvbnN0IHZpZXdzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogY2hhbm5lbENvdW50IH0sIChfLCBjKSA9PlxuICAgICAgICB0aGlzLnRpbnRlZENoYW5uZWxWaWV3KGMsIHN0YXRlcywgZGVzYywgdGhpcy50aWxlZFNvdXJjZShkZXNjLCBjLCAxLCBzY2VuZSkpLFxuICAgICAgKTtcbiAgICAgIHRoaXMuY2hhbm5lbFZpZXcucmVuZGVyKCdtdWx0aWNoYW5uZWwnLCB2aWV3cywgeyBpbnRlcnBvbGF0aW9uIH0pO1xuICAgICAgbWVyZ2VPbnRvQmxhY2sodGhpcy5jaGFubmVsVmlldy5sYXllcnMpO1xuICAgIH0gZWxzZSBpZiAoY2hhbm5lbENvdW50ID09PSAxKSB7XG4gICAgICB0aGlzLmltYWdlTW9kZSA9ICdncmF5c2NhbGUnO1xuICAgICAgY29uc3QgdmlldyA9IHRoaXMuZ3JheXNjYWxlQ2hhbm5lbFZpZXcoc3RhdGVzWzBdLCB0aGlzLnRpbGVkU291cmNlKGRlc2MsIHVuZGVmaW5lZCwgMSwgc2NlbmUpKTtcbiAgICAgIHRoaXMuY2hhbm5lbFZpZXcucmVuZGVyKCdncmF5c2NhbGUnLCBbdmlld10sIHsgaW50ZXJwb2xhdGlvbiB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pbWFnZU1vZGUgPSAncmdiJztcbiAgICAgIHRoaXMuY2hhbm5lbFZpZXcucmVuZGVyKCdyZ2InLCBbeyBzb3VyY2U6IHRoaXMudGlsZWRTb3VyY2UoZGVzYywgdW5kZWZpbmVkLCA0LCBzY2VuZSkgfV0sIHtcbiAgICAgICAgaW50ZXJwb2xhdGlvbixcbiAgICAgIH0pO1xuICAgICAgdGhpcy5yZ2JCYW5kcyA9IHtcbiAgICAgICAgc291cmNlczogY3R4LnRpbGVzLnJnYkJhbmRTb3VyY2VzKGRlc2MsIHNjZW5lLCAoKSA9PiB0aGlzLmN0eC5iYWRnZS5iZWdpbignSW1hZ2UnKSksXG4gICAgICB9O1xuICAgICAgdGhpcy5zeW5jUmdiQmFuZHMoc3RhdGVzKTtcbiAgICB9XG4gICAgY3R4LnNldEltYWdlU2l6ZShkZXNjLndpZHRoLCBkZXNjLmhlaWdodCk7XG4gICAgLy8gQXdhaXQgb24gdGhlIGluaXRpYWwgcmVuZGVyIHNvIGdldEhpc3RvZ3JhbS9hdXRvQ29udHJhc3QgaGF2ZSBkYXRhIGltbWVkaWF0ZWx5OyBzbGljZSBjaGFuZ2VzXG4gICAgLy8gcmVmcmVzaCBmaXJlLWFuZC1mb3JnZXQgKHRoZSBoaXN0b2dyYW0gcGFuZSByZXRyaWVzKS5cbiAgICBhd2FpdCB0aGlzLnJlZnJlc2hIaXN0b2dyYW1TYW1wbGVzKHosIGRlc2MpO1xuICB9XG5cbiAgLyoqIEEgcHlyYW1pZGFsIFRpbGVkU291cmNlIHdob3NlIHRpbGVzIGNvdW50IG9uIHRoZSBsb2FkaW5nIGJhZGdlIHdoaWxlIGBzY2VuZWAgKHRoZSByZW5kZXIgdGhhdFxuICAgKiAgYXNrZWQgZm9yIGl0LCB0YWtlbiBiZWZvcmUgaXRzIGF3YWl0cykgaXMgY3VycmVudC4gKi9cbiAgdGlsZWRTb3VyY2UoXG4gICAgZGVzYzogVGlsZURlc2NyaXB0b3IsXG4gICAgY2hhbm5lbDogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICAgIGNoYW5uZWxzOiAxIHwgNCxcbiAgICBzY2VuZTogQWJvcnRTaWduYWwsXG4gICk6IFRpbGVkU291cmNlIHtcbiAgICByZXR1cm4gdGhpcy5jdHgudGlsZXMudGlsZWRTb3VyY2UoZGVzYywgY2hhbm5lbCwgY2hhbm5lbHMsIHNjZW5lLCAoKSA9PiB0aGlzLmN0eC5iYWRnZS5iZWdpbignSW1hZ2UnKSk7XG4gIH1cblxuICAvKiogQ2hhbm5lbCBgY2AncyBsYXllciBpbiB0aGUgYWRkaXRpdmUgbXVsdGljaGFubmVsIGNvbXBvc2l0ZTogdGludGVkIGJ5IGl0cyBkaXNwbGF5IGNvbG91clxuICAgKiAgKHN0b3JlLCBlbHNlIGRlc2NyaXB0b3IsIGVsc2UgdGhlIEZpamkgcGFsZXR0ZSksIHdpdGggaXRzIHdpbmRvdywgZ2FtbWEgYW5kIHZpc2liaWxpdHkuICovXG4gIHByaXZhdGUgdGludGVkQ2hhbm5lbFZpZXcoXG4gICAgYzogbnVtYmVyLFxuICAgIHN0YXRlczogSUNoYW5uZWxTdGF0ZVtdLFxuICAgIGRlc2M6IFRpbGVEZXNjcmlwdG9yIHwgbnVsbCxcbiAgICBzb3VyY2U6IENoYW5uZWxWaWV3Wydzb3VyY2UnXSxcbiAgICBzY2FsZT86IFtudW1iZXIsIG51bWJlcl0sXG4gICk6IENoYW5uZWxWaWV3IHtcbiAgICBjb25zdCBzdCA9IHN0YXRlcy5maW5kKChzKSA9PiBzLmluZGV4ID09PSBjKTtcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlLFxuICAgICAgdGludDogc3Q/LmNvbG9yID8/IGRlc2M/LmNoYW5uZWxJbmZvPy5bY10/LmNvbG9yID8/IHRpbnRGb3IoYyksXG4gICAgICBuYW1lOiBzdD8ubmFtZSA/PyBgY2gke2N9YCxcbiAgICAgIGNvbnRyYXN0TGltaXRzOiBbc3Q/Lm1pbiA/PyAwLCBzdD8ubWF4ID8/IDI1NV0sXG4gICAgICBnYW1tYTogdG9OYXBhcmlHYW1tYShzdD8uZ2FtbWEpLCAvLyBJbWFnZUogzrMg4oaSIG5hcGFyaS1qcyDOs1xuICAgICAgdmlzaWJsZTogc3Q/LnZpc2libGUgPz8gdHJ1ZSxcbiAgICAgIGludmVydDogdGhpcy5jdHguZGlzcGxheS5pbnZlcnQsXG4gICAgICAuLi4oc2NhbGUgPyB7IHNjYWxlIH0gOiB7fSksXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBUaGUgc2luZ2xlIGdyYXlzY2FsZSBsYXllcjogdGhlIHNlbGVjdGVkIGNvbG9ybWFwLCB3aXRoIHRoZSBjaGFubmVsJ3Mgd2luZG93IGFuZCBnYW1tYS4gKi9cbiAgcHJpdmF0ZSBncmF5c2NhbGVDaGFubmVsVmlldyhcbiAgICBzdDogSUNoYW5uZWxTdGF0ZSB8IHVuZGVmaW5lZCxcbiAgICBzb3VyY2U6IENoYW5uZWxWaWV3Wydzb3VyY2UnXSxcbiAgICBzY2FsZT86IFtudW1iZXIsIG51bWJlcl0sXG4gICk6IENoYW5uZWxWaWV3IHtcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlLFxuICAgICAgY29sb3JtYXA6IHRoaXMuY3R4LmRpc3BsYXkuZ3JheXNjYWxlQ29sb3JtYXAoKSxcbiAgICAgIGNvbnRyYXN0TGltaXRzOiBbc3Q/Lm1pbiA/PyAwLCBzdD8ubWF4ID8/IDI1NV0sXG4gICAgICBnYW1tYTogdG9OYXBhcmlHYW1tYShzdD8uZ2FtbWEpLCAvLyBJbWFnZUogzrMg4oaSIG5hcGFyaS1qcyDOs1xuICAgICAgaW52ZXJ0OiB0aGlzLmN0eC5kaXNwbGF5LmludmVydCxcbiAgICAgIC4uLihzY2FsZSA/IHsgc2NhbGUgfSA6IHt9KSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIChSZSlmZXRjaCBhIGNvYXJzZSBwZXItY2hhbm5lbCBsdW1pbmFuY2Ugc2FtcGxlIGZvciB0aGUgaGlzdG9ncmFtICh0aWxlZCBtb2RlIGhhcyBubyBmdWxsXG4gICAqICBpbi1tZW1vcnkgcGl4ZWxzKS4gT25lIGNoZWFwIG92ZXJ2aWV3IHRpbGUgcGVyIGNoYW5uZWwsIGZldGNoZWQgdG9nZXRoZXI7IGNhY2hlZCBieSBjaGFubmVsXG4gICAqICBpbmRleC4gTGF0ZXN0IHdpbnM6IGEgc2NydWIgZmlyZXMgb25lIHJlZnJlc2ggcGVyIHNsaWNlLCBhbmQgYW4gb2xkZXIgc2xpY2UncyBzYW1wbGVzIHRoYXRcbiAgICogIGxhbmQgYWZ0ZXIgYSBuZXdlciBvbmUncyBhcmUgZHJvcHBlZCByYXRoZXIgdGhhbiBzaG93biBhcyB0aGUgY3VycmVudCBkaXN0cmlidXRpb24uICovXG4gIGFzeW5jIHJlZnJlc2hIaXN0b2dyYW1TYW1wbGVzKHo6IG51bWJlciwgZGVzYzogUGljazxUaWxlRGVzY3JpcHRvciwgJ2NoYW5uZWxzJz4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBnZW4gPSArK3RoaXMuaGlzdEdlbjtcbiAgICB0aGlzLmhpc3RTYW1wbGVzLmNsZWFyKCk7XG4gICAgY29uc3QgaW5mbyA9IHRoaXMuY3R4LmluZm8oKTtcbiAgICBpZiAodGhpcy5pbWFnZU1vZGUgPT09ICdyZ2InKSB7XG4gICAgICAvLyBPbmUgY29hcnNlIGNvbXBvc2l0ZSB0aWxlLCBzcGxpdCBpbnRvIGl0cyByYXcgUiwgRyBhbmQgQiBiYW5kcy5cbiAgICAgIGNvbnN0IGJhbmRzID0gYXdhaXQgdGhpcy5jdHgudGlsZXMucmVhZFJnYkJhbmRzKGluZm8sIHosIDEpLmNhdGNoKCgpID0+IG51bGwpO1xuICAgICAgaWYgKGdlbiAhPT0gdGhpcy5oaXN0R2VuIHx8ICFiYW5kcykgcmV0dXJuO1xuICAgICAgYmFuZHMuZm9yRWFjaCgoYmFuZCwgYykgPT4gdGhpcy5oaXN0U2FtcGxlcy5zZXQoYywgYmFuZC5kYXRhKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG11bHRpY2hhbm5lbCA9IHRoaXMuaW1hZ2VNb2RlID09PSAnbXVsdGljaGFubmVsJztcbiAgICBjb25zdCBjaGFubmVsQ291bnQgPSBtdWx0aWNoYW5uZWwgPyAoZGVzYy5jaGFubmVscyA/PyAxKSA6IDE7XG4gICAgY29uc3Qgc2FtcGxlcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgQXJyYXkuZnJvbSh7IGxlbmd0aDogY2hhbm5lbENvdW50IH0sIChfLCBjKSA9PlxuICAgICAgICAvLyBidWRnZXQgMSDihpIgY29hcnNlc3Qgc2luZ2xlIHRpbGU7IGEgZmFpbGVkIGNoYW5uZWwgbGVhdmVzIGl0cyBzYW1wbGUgdW5zZXQuXG4gICAgICAgIHRoaXMuY3R4LnRpbGVzLmZldGNoQ2hhbm5lbERhdGEoaW5mbywgeiwgbXVsdGljaGFubmVsID8gYyA6IHVuZGVmaW5lZCwgMSkudGhlbihcbiAgICAgICAgICAoZCkgPT4gZC5kYXRhLFxuICAgICAgICAgICgpID0+IG51bGwsXG4gICAgICAgICksXG4gICAgICApLFxuICAgICk7XG4gICAgaWYgKGdlbiAhPT0gdGhpcy5oaXN0R2VuKSByZXR1cm47XG4gICAgc2FtcGxlcy5mb3JFYWNoKChkYXRhLCBjKSA9PiB7XG4gICAgICBpZiAoZGF0YSkgdGhpcy5oaXN0U2FtcGxlcy5zZXQoYywgZGF0YSk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQ2hhbm5lbCBzdGF0ZXMgKyBncmF5c2NhbGUgY29sb3JtYXAg4oaSIGxpdmUtYXBwbHkgdG8gdGhlIHJlbmRlcmVkIGxheWVycyAobm8gcmUtZmV0Y2g7IG9ubHkgelxuICAgKiAgY2hhbmdlcyByZS1mZXRjaCksIGFuZCByZWNvbG91ciB0aGUgbmF2aWdhdG9yIHRodW1ibmFpbC4gKi9cbiAgcHJpdmF0ZSBmb2xsb3dEaXNwbGF5U3RhdGUoKTogdm9pZCB7XG4gICAgdGhpcy5kaXNwbGF5U3ViID0gdGhpcy5jdHguZGlzcGxheS53YXRjaCgoY2hhbm5lbHMpID0+IHtcbiAgICAgIHRoaXMuYXBwbHlEaXNwbGF5U3RhdGUoY2hhbm5lbHMpO1xuICAgICAgdGhpcy5yZWNvbG9yTmF2aWdhdG9yKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogQXBwbHkgdGhlIGN1cnJlbnQgY2hhbm5lbCBzdGF0ZXMgLyBjb2xvcm1hcCB0byB0aGUgbGl2ZSBsYXllcnMgKG5vIHJlLWZldGNoKSwgZGVsZWdhdGluZyB0aGVcbiAgICogIHBlci1jaGFubmVsIGxheWVyIG11dGF0aW9ucyB0byB0aGUge0BsaW5rIE11bHRpQ2hhbm5lbEltYWdlVmlld30uICovXG4gIHByaXZhdGUgYXBwbHlEaXNwbGF5U3RhdGUoY2hhbm5lbHM6IElDaGFubmVsU3RhdGVbXSk6IHZvaWQge1xuICAgIGNvbnN0IHZpZXcgPSB0aGlzLmNoYW5uZWxWaWV3O1xuICAgIGNvbnN0IHsgZGlzcGxheSB9ID0gdGhpcy5jdHg7XG4gICAgaWYgKCF2aWV3KSByZXR1cm47XG4gICAgaWYgKHRoaXMuaW1hZ2VNb2RlID09PSAncmdiJykge1xuICAgICAgdGhpcy5zeW5jUmdiQmFuZHMoY2hhbm5lbHMpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5pbWFnZU1vZGUgPT09ICdtdWx0aWNoYW5uZWwnKSB7XG4gICAgICB2aWV3LmxheWVycy5mb3JFYWNoKChfLCBjKSA9PiB7XG4gICAgICAgIGNvbnN0IHN0ID0gY2hhbm5lbHMuZmluZCgocykgPT4gcy5pbmRleCA9PT0gYyk7XG4gICAgICAgIGlmICghc3QpIHJldHVybjtcbiAgICAgICAgdmlldy51cGRhdGVDaGFubmVsKGMsIHtcbiAgICAgICAgICB0aW50OiBzdC5jb2xvcixcbiAgICAgICAgICBjb250cmFzdExpbWl0czogW3N0Lm1pbiwgc3QubWF4XSxcbiAgICAgICAgICBnYW1tYTogdG9OYXBhcmlHYW1tYShzdC5nYW1tYSksIC8vIEltYWdlSiDOsyDihpIgbmFwYXJpLWpzIM6zXG4gICAgICAgICAgdmlzaWJsZTogc3QudmlzaWJsZSxcbiAgICAgICAgICBpbnZlcnQ6IGRpc3BsYXkuaW52ZXJ0LFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgbWVyZ2VPbnRvQmxhY2sodmlldy5sYXllcnMpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5pbWFnZU1vZGUgPT09ICdncmF5c2NhbGUnKSB7XG4gICAgICBjb25zdCBzdCA9IGNoYW5uZWxzWzBdO1xuICAgICAgdmlldy51cGRhdGVDaGFubmVsKDAsIHtcbiAgICAgICAgY29sb3JtYXA6IGRpc3BsYXkuZ3JheXNjYWxlQ29sb3JtYXAoKSxcbiAgICAgICAgaW52ZXJ0OiBkaXNwbGF5LmludmVydCxcbiAgICAgICAgLi4uKHN0ID8geyBjb250cmFzdExpbWl0czogW3N0Lm1pbiwgc3QubWF4XSBhcyBbbnVtYmVyLCBudW1iZXJdLCBnYW1tYTogdG9OYXBhcmlHYW1tYShzdC5nYW1tYSkgfSA6IHt9KSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSR0I6IGRyYXcgdGhlIGltYWdlIGFzIGl0IGlzIHdoaWxlIGl0cyBjaGFubmVsIHN0YXRlcyBsZWF2ZSBpdCBzbyAoZGVmYXVsdCBSL0cvQiB0aW50cywgZnVsbFxuICAgKiB3aW5kb3csIM6zIDEsIGFsbCBzaG93biwgbm8gaW52ZXJ0OiB7QGxpbmsgcmdiTmVlZHNSZWNvbG9yfSkg4oCUIHRoZSBSR0IgbGF5ZXIsIHVuY2hhbmdlZCwgd2l0aFxuICAgKiB0aGUgY29hcnNlIHVuZGVybGF5IGEgdGlsZWQgb25lIGtlZXBzIHdoaWxlIGl0IHBhbnMuIE90aGVyd2lzZSBkcmF3IGl0cyBSLCBHIGFuZCBCIGJhbmRzIGFzXG4gICAqIHRocmVlIGFkZGl0aXZlIGxheWVycywgZWFjaCB3aXRoIGl0cyBjaGFubmVsJ3Mgd2luZG93LCBpbnZlcnQsIGdhbW1hLCB0aW50IGFuZCB2aXNpYmlsaXR5IOKAlFxuICAgKiB3aGF0IE9TRCdzIFJHQiByZWNvbG91ciBjb21wdXRlcyBwZXIgcGl4ZWwgKHRoZSBtZXJnZSBvcmRlciBvZiBgb3NkL2Rpc3BsYXktcGlwZWxpbmVgKS4gVGhlXG4gICAqIGJhbmQgbGF5ZXJzIHNpdCBqdXN0IGFib3ZlIHRoZSBoaWRkZW4gUkdCIGxheWVyLCBzbyB3aGF0ZXZlciBpcyBkcmF3biBvdmVyIHRoZSBpbWFnZSBzdGF5c1xuICAgKiBvdmVyIGl0LiBBIGhvc3Qgd2l0aCBubyBSL0cvQiBjaGFubmVsIG1vZGVsIChmZXdlciB0aGFuIHRocmVlIHN0YXRlcykgZ2V0cyBvbmx5IHRoZSBpbnZlcnQuXG4gICAqL1xuICBwcml2YXRlIHN5bmNSZ2JCYW5kcyhjaGFubmVsczogSUNoYW5uZWxTdGF0ZVtdKTogdm9pZCB7XG4gICAgY29uc3QgeyB2aWV3ZXIsIGRpc3BsYXkgfSA9IHRoaXMuY3R4O1xuICAgIGNvbnN0IHJnYiA9IHRoaXMuY2hhbm5lbFZpZXc/LmxheWVyc1swXTtcbiAgICBjb25zdCBiYW5kcyA9IHRoaXMucmdiQmFuZHM7XG4gICAgaWYgKCFyZ2IgfHwgIWJhbmRzKSByZXR1cm47XG4gICAgY29uc3Qgc3RhdGVzID0gY2hhbm5lbHMubGVuZ3RoID49IDMgPyBjaGFubmVscyA6IFtdO1xuICAgIGlmICghcmdiTmVlZHNSZWNvbG9yKHN0YXRlcywgZGlzcGxheS5pbnZlcnQpKSB7XG4gICAgICB0aGlzLmJhbmRMYXllcnM/LmZvckVhY2goKGxheWVyKSA9PiB2aWV3ZXIubGF5ZXJzLnJlbW92ZShsYXllcikpO1xuICAgICAgdGhpcy5iYW5kTGF5ZXJzID0gbnVsbDtcbiAgICAgIHJnYi52aXNpYmxlID0gdHJ1ZTtcbiAgICAgIHZpZXdlci5yZXF1ZXN0UmVuZGVyKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5iYW5kTGF5ZXJzKSB7XG4gICAgICBjb25zdCBhdCA9IHZpZXdlci5sYXllcnMuaXRlbXMuaW5kZXhPZihyZ2IpO1xuICAgICAgdGhpcy5iYW5kTGF5ZXJzID0gYmFuZHMuc291cmNlcy5tYXAoKHNvdXJjZSwgYykgPT4ge1xuICAgICAgICBjb25zdCBsYXllciA9IHZpZXdlci5hZGRJbWFnZShzb3VyY2UsIHtcbiAgICAgICAgICBuYW1lOiBgcmdiJHtjfWAsXG4gICAgICAgICAgYmxlbmRpbmc6ICdhZGRpdGl2ZScsXG4gICAgICAgICAgaW50ZXJwb2xhdGlvbjogcmdiLmludGVycG9sYXRpb24sXG4gICAgICAgICAgLi4uKGJhbmRzLnNjYWxlID8geyBzY2FsZTogYmFuZHMuc2NhbGUgfSA6IHt9KSxcbiAgICAgICAgfSk7XG4gICAgICAgIHZpZXdlci5sYXllcnMubW92ZShsYXllciwgYXQgKyAxICsgYyk7XG4gICAgICAgIHJldHVybiBsYXllcjtcbiAgICAgIH0pO1xuICAgICAgcmdiLnZpc2libGUgPSBmYWxzZTtcbiAgICB9XG4gICAgdGhpcy5iYW5kTGF5ZXJzLmZvckVhY2goKGxheWVyLCBjKSA9PiB7XG4gICAgICBjb25zdCBzdCA9IHN0YXRlcy5maW5kKChzKSA9PiBzLmluZGV4ID09PSBjKTtcbiAgICAgIGxheWVyLmNvbG9ybWFwID0gdGludENvbG9ybWFwKHN0Py5jb2xvciA/PyB0aW50Rm9yKGMpKTtcbiAgICAgIGxheWVyLmNvbnRyYXN0TGltaXRzID0gW3N0Py5taW4gPz8gMCwgc3Q/Lm1heCA/PyAyNTVdO1xuICAgICAgbGF5ZXIuZ2FtbWEgPSB0b05hcGFyaUdhbW1hKHN0Py5nYW1tYSk7IC8vIEltYWdlSiDOsyDihpIgbmFwYXJpLWpzIM6zXG4gICAgICBsYXllci52aXNpYmxlID0gc3Q/LnZpc2libGUgPz8gdHJ1ZTtcbiAgICAgIGxheWVyLmludmVydCA9IGRpc3BsYXkuaW52ZXJ0O1xuICAgIH0pO1xuICAgIG1lcmdlT250b0JsYWNrKHRoaXMuYmFuZExheWVycyk7XG4gICAgdmlld2VyLnJlcXVlc3RSZW5kZXIoKTtcbiAgfVxuXG4gIC8qKiAoUmUpaW5zdGFsbCB0aGUgcGh5c2ljYWwgc2NhbGUgYmFyIChuYXBhcmktanMncyBgU2NhbGVCYXJPdmVybGF5YCBvbiB0aGUgMkQgY2FtZXJhJ3Mgem9vbSksXG4gICAqICBzaXplZCBmcm9tIHRoZSBpbWFnZSdzIMK1bS9waXhlbCAoYC90aWxlcy9pbmZvYCBtcHBYLCBmYWxsaW5nIGJhY2sgdG8gdGhlIGltYWdlIG1ldGFkYXRhKS5cbiAgICogIE5vLW9wIHdpdGhvdXQgYSBwaHlzaWNhbCBzaXplLiAqL1xuICBpbnN0YWxsU2NhbGVCYXIoKTogdm9pZCB7XG4gICAgY29uc3QgeyBjdHggfSA9IHRoaXM7XG4gICAgdGhpcy5zY2FsZUJhcj8uZGlzcG9zZSgpO1xuICAgIHRoaXMuc2NhbGVCYXIgPSBudWxsO1xuICAgIGNvbnN0IG1wcFggPSBjdHgudGlsZXMubXBwWChjdHguaW5mbygpKTtcbiAgICBpZiAobXBwWCA+IDApIHRoaXMuc2NhbGVCYXIgPSBuZXcgU2NhbGVCYXJPdmVybGF5KGN0eC5ob3N0LCBjdHgudmlld2VyLCB7IHVuaXRQZXJXb3JsZDogbXBwWCwgbW9kZTogJzJkJyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgb3ZlcnZpZXcgbmF2aWdhdG9yIChuYXBhcmktanMncyBgTmF2aWdhdG9yT3ZlcmxheWApOiBhIGNvYXJzZSB0aHVtYm5haWwgb2YgdGhlIHdob2xlXG4gICAqIGltYWdlIHdpdGggdGhlIHZpZXdwb3J0IG9uIGl0OyBjbGljayBvciBkcmFnIHRvIHBhbiBhdCB0aGUgY3VycmVudCB6b29tIChhcyBPU0QpLlxuICAgKi9cbiAgcHJpdmF0ZSBpbnN0YWxsTmF2aWdhdG9yKHo6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzO1xuICAgIHRoaXMubmF2aWdhdG9yPy5kaXNwb3NlKCk7XG4gICAgdGhpcy5uYXZpZ2F0b3IgPSBudWxsO1xuICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gY3R4LmltYWdlU2l6ZSgpO1xuICAgIGlmICghd2lkdGggfHwgIWhlaWdodCkgcmV0dXJuO1xuICAgIHRoaXMubmF2aWdhdG9yID0gbmV3IE5hdmlnYXRvck92ZXJsYXkoY3R4Lmhvc3QsIGN0eC52aWV3ZXIsIHtcbiAgICAgIHdvcmxkV2lkdGg6IHdpZHRoLFxuICAgICAgd29ybGRIZWlnaHQ6IGhlaWdodCxcbiAgICAgIG9uRW50ZXI6ICgpID0+IHRoaXMub3B0cy5vbk5hdmlnYXRvckludGVyYWN0Py4oKSxcbiAgICAgIHZpc2libGU6IGN0eC5zZXR0aW5ncy5uYXZpZ2F0b3JWaXNpYmxlLFxuICAgIH0pO1xuICAgIHZvaWQgdGhpcy5yZWZyZXNoTmF2aWdhdG9ySW1hZ2Uoeik7XG4gIH1cblxuICAvKipcbiAgICogRHJhdyB0aGUgbmF2aWdhdG9yJ3MgdGh1bWJuYWlsIGZyb20gdGhlIGNvYXJzZXN0IHB5cmFtaWQgbGV2ZWwuIEEgbXVsdGljaGFubmVsIGltYWdlXG4gICAqIGlzIGNvbXBvc2l0ZWQgZnJvbSBpdHMgY2hhbm5lbHMgaW4gdGhlaXIgZGlzcGxheSBjb2xvdXJzIChzZWUge0BsaW5rIHJlY29sb3JOYXZpZ2F0b3J9KSxcbiAgICogc28gdGhlIG92ZXJ2aWV3IGxvb2tzIGxpa2UgdGhlIHZpZXcgcmF0aGVyIHRoYW4gbGlrZSBjaGFubmVsIDAgaW4gZ3JleS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVmcmVzaE5hdmlnYXRvckltYWdlKHo6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG5hdiA9IHRoaXMubmF2aWdhdG9yO1xuICAgIGlmICghbmF2KSByZXR1cm47XG4gICAgY29uc3QgdG9rZW4gPSArK3RoaXMubmF2aWdhdG9yVG9rZW47XG4gICAgY29uc3QgeyB0aWxlcyB9ID0gdGhpcy5jdHg7XG4gICAgY29uc3QgaW5mbyA9IHRoaXMuY3R4LmluZm8oKTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgZGVzYyA9IGF3YWl0IHRpbGVzLmVuc3VyZURlc2NyaXB0b3IoaW5mbyk7XG4gICAgICAvLyBTdXBlcnNlZGVkIChhIG5ld2VyIHNsaWNlLCBvciB0aGUgc2NlbmUgd2FzIHRvcm4gZG93bik6IGZldGNoIG5vdGhpbmcuXG4gICAgICBpZiAodG9rZW4gIT09IHRoaXMubmF2aWdhdG9yVG9rZW4gfHwgdGhpcy5uYXZpZ2F0b3IgIT09IG5hdikgcmV0dXJuO1xuICAgICAgLy8gQSBzZXJ2ZXJsZXNzIG11bHRpY2hhbm5lbCBzdGFjaydzIHRodW1ibmFpbHMgYXJlIGl0cyBvd24gY2hhbm5lbCBwbGFuZXMuXG4gICAgICBjb25zdCBjb3VudCA9IGRlc2M/Lm11bHRpY2hhbm5lbFxuICAgICAgICA/IChkZXNjLmNoYW5uZWxJbmZvPy5sZW5ndGggPz8gMClcbiAgICAgICAgOiBpc1NlcnZlcmxlc3NNdWx0aWNoYW5uZWwodGlsZXMuaXNTaW1wbGUoaW5mbyksIGluZm8pXG4gICAgICAgICAgPyAoaW5mbz8uaW1hZ2VNZXRhPy5bMF0/LmNoYW5uZWxDb3VudCA/PyAwKVxuICAgICAgICAgIDogMDtcbiAgICAgIGlmIChjb3VudCA+IDEpIHtcbiAgICAgICAgY29uc3QgYml0bWFwcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgIEFycmF5LmZyb20oeyBsZW5ndGg6IGNvdW50IH0sIChfYywgYykgPT4gdGlsZXMub3ZlcnZpZXdJbWFnZShpbmZvLCB6LCBjKSksXG4gICAgICAgICk7XG4gICAgICAgIGlmICh0b2tlbiAhPT0gdGhpcy5uYXZpZ2F0b3JUb2tlbiB8fCB0aGlzLm5hdmlnYXRvciAhPT0gbmF2KSByZXR1cm47XG4gICAgICAgIHRoaXMuc2V0TmF2aWdhdG9yQ2hhbm5lbHMoYml0bWFwcyk7XG4gICAgICAgIHRoaXMucmVjb2xvck5hdmlnYXRvcigpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgaW1hZ2UgPSBhd2FpdCB0aWxlcy5vdmVydmlld0ltYWdlKGluZm8sIHopO1xuICAgICAgICBpZiAodG9rZW4gIT09IHRoaXMubmF2aWdhdG9yVG9rZW4gfHwgdGhpcy5uYXZpZ2F0b3IgIT09IG5hdikgcmV0dXJuO1xuICAgICAgICB0aGlzLnNldE5hdmlnYXRvckNoYW5uZWxzKG51bGwpO1xuICAgICAgICBuYXYuc2V0SW1hZ2UoaW1hZ2UpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS53YXJuKCdbbmFwYXJpLWpzXSBuYXZpZ2F0b3IgdGh1bWJuYWlsIHVuYXZhaWxhYmxlJywgZXJyKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmVwbGFjZSB0aGUgcGVyLWNoYW5uZWwgdGh1bWJuYWlsIGJpdG1hcHMgKGNsb3NpbmcgdGhlIHByZXZpb3VzIG9uZXMpLiAqL1xuICBwcml2YXRlIHNldE5hdmlnYXRvckNoYW5uZWxzKGJpdG1hcHM6IE92ZXJ2aWV3SW1hZ2VbXSB8IG51bGwpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGJtcCBvZiB0aGlzLm5hdmlnYXRvckNoYW5uZWxzID8/IFtdKSBpZiAoJ2Nsb3NlJyBpbiBibXApIGJtcC5jbG9zZT8uKCk7XG4gICAgdGhpcy5uYXZpZ2F0b3JDaGFubmVscyA9IGJpdG1hcHM7XG4gICAgdGhpcy5uYXZpZ2F0b3JUaW50S2V5ID0gJyc7XG4gIH1cblxuICAvKipcbiAgICogQ29tcG9zaXRlIHRoZSBtdWx0aWNoYW5uZWwgdGh1bWJuYWlsIGluIHRoZSBjaGFubmVscycgQ1VSUkVOVCBkaXNwbGF5IHRpbnRzLCBza2lwcGluZyBoaWRkZW5cbiAgICogY2hhbm5lbHMg4oCUIHRoZSBzdG9yZSdzIGNoYW5uZWwgc3RhdGVzLCBhcyB0aGUgMkQgbGF5ZXJzIHVzZSwgbm90IHRoZSBzZXJ2ZXIncyBkZWZhdWx0cy5cbiAgICogUmUtcnVuIG9uIGV2ZXJ5IGRpc3BsYXktc3RhdGUgY2hhbmdlOyBpdCBvbmx5IHJlZHJhd3MgKG5ldmVyIHJlLWZldGNoZXMpLCBhbmQgb25seSB3aGVuIGFcbiAgICogdGludCBvciBhIHZpc2liaWxpdHkgYWN0dWFsbHkgY2hhbmdlZCwgc28gYSB3aW5kb3cvZ2FtbWEgZHJhZyBjb3N0cyBhIHN0cmluZyBjb21wYXJlLlxuICAgKi9cbiAgcHJpdmF0ZSByZWNvbG9yTmF2aWdhdG9yKCk6IHZvaWQge1xuICAgIGNvbnN0IG5hdiA9IHRoaXMubmF2aWdhdG9yO1xuICAgIGNvbnN0IGJpdG1hcHMgPSB0aGlzLm5hdmlnYXRvckNoYW5uZWxzO1xuICAgIGlmICghbmF2IHx8ICFiaXRtYXBzKSByZXR1cm47XG4gICAgY29uc3QgaW5mbyA9IHRoaXMuY3R4LnRpbGVzLmN1cnJlbnREZXNjcmlwdG9yKHRoaXMuY3R4LmluZm8oKSk/LmNoYW5uZWxJbmZvO1xuICAgIGNvbnN0IHN0YXRlcyA9IHRoaXMuY3R4LnN0b3JlLmN1cnJlbnRDaGFubmVsU3RhdGVzKCk7XG4gICAgY29uc3Qgc2hvd24gPSBiaXRtYXBzXG4gICAgICAubWFwKChibXAsIGMpID0+IHtcbiAgICAgICAgY29uc3Qgc3QgPSBzdGF0ZXMuZmluZCgocykgPT4gcy5pbmRleCA9PT0gYyk7XG4gICAgICAgIHJldHVybiB7IGJtcCwgdmlzaWJsZTogc3Q/LnZpc2libGUgPz8gdHJ1ZSwgY29sb3I6IHN0Py5jb2xvciA/PyBpbmZvPy5bY10/LmNvbG9yID8/IHRpbnRGb3IoYykgfTtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKChjaCkgPT4gY2gudmlzaWJsZSk7XG4gICAgY29uc3Qga2V5ID0gc2hvd24ubWFwKChjaCkgPT4gYCR7Yml0bWFwcy5pbmRleE9mKGNoLmJtcCl9OiR7Y2guY29sb3J9YCkuam9pbignfCcpO1xuICAgIGlmIChrZXkgPT09IHRoaXMubmF2aWdhdG9yVGludEtleSkgcmV0dXJuO1xuICAgIHRoaXMubmF2aWdhdG9yVGludEtleSA9IGtleTtcbiAgICBuYXYuc2V0SW1hZ2UoXG4gICAgICB0aW50ZWRDb21wb3NpdGUoXG4gICAgICAgIHNob3duLm1hcCgoY2gpID0+IGNoLmJtcCksXG4gICAgICAgIHNob3duLm1hcCgoY2gpID0+IGNoLmNvbG9yKSxcbiAgICAgICksXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIE5BUEFSSV9TQ0FUVEVSIChyZXZpZXcgQXBwZW5kaXggQiwgY2x1c3RlciBIKTogdGhlIHNsaWNlIGltYWdlIHdpdGggYSBwb2ludHMgbGF5ZXIgYXQgZWFjaFxuICogcmVnaW9uJ3MgY2VudHJvaWQgKHRoZSBuYXBhcmktanMgYW5hbG9nIG9mIFBsb3RseSdzIHJlZ2lvbi1jZW50cm9pZCBzY2F0dGVyKSwgcmVidWlsdCBsaXZlIGFzXG4gKiByZWdpb25zIGNoYW5nZS4gVGhpcyBtb2RlIHBsb3RzIFJFR0lPTiBjZW50cm9pZHMsIHNvIHRoZSBpbWFnZSdzIHJlZ2lvbiB0b29scyBjb21lIHdpdGggaXQg4oCUXG4gKiBkcmF3aW5nIGEgcmVnaW9uIGFkZHMgYSBwb2ludCBhdCBvbmNlLlxuICovXG5leHBvcnQgY2xhc3MgU2NhdHRlclJlZ2lvbnNTY2VuZSBpbXBsZW1lbnRzIE5hcGFyaVNjZW5lIHtcbiAgcmVhZG9ubHkgaW1hZ2U6IEltYWdlMmRTY2VuZTtcbiAgcHJpdmF0ZSBwb2ludHM6IFBvaW50c0xheWVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVnaW9uU3ViOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGN0eDogU2NlbmVDb250ZXh0KSB7XG4gICAgdGhpcy5pbWFnZSA9IG5ldyBJbWFnZTJkU2NlbmUoY3R4LCB7XG4gICAgICAvLyBUaGUgcmVnaW9uLWNlbnRyb2lkIHBvaW50cyB3ZW50IHdpdGggdGhlIHJlLXJlbmRlcidzIGxheWVyIGNsZWFyLlxuICAgICAgb25TbGljZTogKHJlcmVuZGVyZWQpID0+IHtcbiAgICAgICAgaWYgKHJlcmVuZGVyZWQgJiYgdGhpcy5wb2ludHMpIHRoaXMucmVidWlsZFBvaW50cygpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIG1vdW50KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuaW1hZ2UubW91bnQoKTtcbiAgICAvLyBEaXNwb3NlZCB3aGlsZSB0aGUgaW1hZ2UgbG9hZGVkOiBhIHN1YnNjcmlwdGlvbiBub3cgd291bGQgb3V0bGl2ZSB0aGUgc2NlbmUuXG4gICAgaWYgKHRoaXMuY3R4LnNpZ25hbC5hYm9ydGVkKSByZXR1cm47XG4gICAgdGhpcy5yZWJ1aWxkUG9pbnRzKCk7XG4gICAgdGhpcy5yZWdpb25TdWIgPSB0aGlzLmN0eC5yZWdpb25TdG9yZS5nZXRSZWdpb25VcGRhdGVFdmVudCgpLnN1YnNjcmliZSgoKSA9PiB0aGlzLnJlYnVpbGRQb2ludHMoKSk7XG4gICAgdGhpcy5jdHgudG9vbHMuc2NoZWR1bGVSZWFkYmFjaygpO1xuICB9XG5cbiAgc2V0Wih6OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLmltYWdlLnNldFooeik7XG4gIH1cblxuICBoaXN0b2dyYW0oY2hhbm5lbDogbnVtYmVyLCBiaW5zOiBudW1iZXIpOiBJSGlzdG9ncmFtIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2UuaGlzdG9ncmFtKGNoYW5uZWwsIGJpbnMpO1xuICB9XG5cbiAgc2V0SW1hZ2VTbW9vdGhpbmcoZW5hYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaW1hZ2Uuc2V0SW1hZ2VTbW9vdGhpbmcoZW5hYmxlZCk7XG4gIH1cblxuICBzZXROYXZpZ2F0b3JWaXNpYmxlKHZpc2libGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmltYWdlLnNldE5hdmlnYXRvclZpc2libGUodmlzaWJsZSk7XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMucmVnaW9uU3ViPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMucmVnaW9uU3ViID0gbnVsbDtcbiAgICB0aGlzLmltYWdlLmRpc3Bvc2UoKTtcbiAgfVxuXG4gIC8qKiAoUmUpYnVpbGQgdGhlIHBvaW50IGxheWVyIGF0IHRoZSBjdXJyZW50IHJlZ2lvbiBjZW50cm9pZHMuICovXG4gIHByaXZhdGUgcmVidWlsZFBvaW50cygpOiB2b2lkIHtcbiAgICBjb25zdCB2ID0gdGhpcy5jdHgudmlld2VyO1xuICAgIGlmICh0aGlzLnBvaW50cykge1xuICAgICAgdi5sYXllcnMucmVtb3ZlKHRoaXMucG9pbnRzKTtcbiAgICAgIHRoaXMucG9pbnRzID0gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgY2VudHJvaWRzID0gcmVnaW9uQ2VudHJvaWRzKHRoaXMuY3R4LnJlZ2lvblN0b3JlLmdldFJlZ2lvbnMoKSk7XG4gICAgaWYgKGNlbnRyb2lkcy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgICB0aGlzLnBvaW50cyA9IHYuYWRkUG9pbnRzKGNlbnRyb2lkcywge1xuICAgICAgc2l6ZTogMTIsXG4gICAgICBmYWNlQ29sb3I6IFsxLCAwLjg1LCAwLjIsIDFdLFxuICAgICAgYm9yZGVyQ29sb3I6IFswLCAwLCAwLCAxXSxcbiAgICAgIGJvcmRlcldpZHRoOiAyLFxuICAgIH0pO1xuICB9XG59XG4iXX0=