@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,614 @@
1
+ import { NO_CATEGORY, isCategoricalColumn, } from '../../contracts/spatial-dataset.contract';
2
+ import { encodeCategorical, markerDiameters, resolveCategoryColors } from '../../spatial/spatial-encoding';
3
+ import { emptySelection, maskToIndices, mutedFromSelection, } from '../../spatial/spatial-selection';
4
+ import { framePositions } from '../../spatial/spatial-framing';
5
+ import { PIXEL_WORLD_QUANTUM, worldQuantumForExtent } from '../../spatial/world-grid';
6
+ import { observationsInSlice, volumeImageRef } from '../../spatial/spatial-volume-image';
7
+ import { cellTypeColumnFor } from '../../spatial/spatial-tiles';
8
+ import { colorExpressionField, fieldContrastWindow } from '../../spatial/spatial-expression';
9
+ import { computeExpressionFieldAsync } from '../../workers/spatial-math';
10
+ import { Supersede } from '../../util/supersede';
11
+ import { isAbortError } from '../tile-server';
12
+ import { Image2dScene } from './napari-image-2d-scene';
13
+ import { GENE_MAP_MAX_SIDE, GENE_MAP_SIGMA, SPATIAL_FALLBACK_RADIUS, SPATIAL_NEUTRAL_COLOR, SPATIAL_NEUTRAL_HEX, SPATIAL_SLICE_MIN_DIAMETER_PX, encodeSpatialContinuous, gatherColors, } from './napari-spatial-encoding';
14
+ import { SpatialSceneBase } from './napari-spatial-scene';
15
+ /**
16
+ * SPATIAL_OMICS (review Appendix B, cluster J): the tissue image (an {@link Image2dScene}) with one
17
+ * marker per observation, coloured by an annotation column or a gene, the gene map under the
18
+ * cells, and the level-of-detail tile layers (outlines, transcripts, density) over them. The
19
+ * markers rebuild whenever the dataset or the view state changes, so switching the colour-by
20
+ * column does not remount the scene.
21
+ *
22
+ * Sets up the full 2D interaction stack — region overlay, pixel tools, readback currency — exactly
23
+ * as the plain image view does. That is NOT optional here: this mode's selection is driven by
24
+ * drawn ROIs, so without the overlay there is no way to make a selection at all.
25
+ */
26
+ export class Spatial2dScene extends SpatialSceneBase {
27
+ /** `noImage`: an image-less dataset opened before any image — the observations alone. */
28
+ constructor(ctx, session, noImage = false) {
29
+ super(ctx, session, false);
30
+ /** The observation markers, and which dataset/plane they were built for — so a display-only
31
+ * change (size, colour, opacity, selection) can update them in place. */
32
+ this.points = null;
33
+ this.layerKey = null;
34
+ /** The observation each marker is, in draw order; null when every observation is drawn. */
35
+ this.drawn = null;
36
+ /** The gene map's layer and the inputs it was coloured for (its field is cached in the session,
37
+ * on a clock of its own). */
38
+ this.geneMapLayer = null;
39
+ this.geneMapKey = null;
40
+ /** The dataset the camera has been framed on — see {@link frameOnce}. */
41
+ this.framed = null;
42
+ /** The gene-map estimate in flight (off the main thread past the worker threshold,
43
+ * SPATIAL-19): a new field key supersedes — and aborts — it; a rebuild that leaves the key
44
+ * alone lets it finish. */
45
+ this.geneMapLoads = new Supersede();
46
+ this.image = new Image2dScene(ctx, {
47
+ image: !noImage,
48
+ // Only fit to the image when this dataset actually has one. Otherwise there is nothing to
49
+ // fit, the image size still holds the LAST image's dimensions, and this fits to those — and
50
+ // because it defers to a frame, it lands AFTER the points are added and overwrites the
51
+ // framing they set. That is what left an image-less dataset as a ten-pixel speck.
52
+ fit: () => !!session.latest?.[0]?.imageRef,
53
+ onSlice: (rerendered) => {
54
+ this.redrawMarkers();
55
+ // The stitched re-render cleared the cells, transcripts and density too: re-plan them now
56
+ // rather than at the next camera move (each group redraws only what left the scene).
57
+ if (rerendered)
58
+ this.session.tiles?.refresh();
59
+ },
60
+ onNavigatorInteract: () => this.hover.hide(),
61
+ });
62
+ }
63
+ async mount() {
64
+ const { ctx } = this;
65
+ await this.image.mount();
66
+ // Disposed while the image loaded: claiming the tiles now would take them from the next scene,
67
+ // and the spatial subscription would outlive this one.
68
+ if (ctx.signal.aborted)
69
+ return;
70
+ this.hover.install(ctx.host);
71
+ this.session.claimTiles(this)?.attach(ctx.viewer);
72
+ this.subscribeSpatial();
73
+ ctx.tools.scheduleReadback();
74
+ }
75
+ setZ(z) {
76
+ this.image.setZ(z);
77
+ }
78
+ histogram(channel, bins) {
79
+ return this.image.histogram(channel, bins);
80
+ }
81
+ setImageSmoothing(enabled) {
82
+ this.image.setImageSmoothing(enabled);
83
+ }
84
+ setNavigatorVisible(visible) {
85
+ this.image.setNavigatorVisible(visible);
86
+ }
87
+ dispose() {
88
+ this.disposeSpatial();
89
+ this.geneMapLoads.cancel();
90
+ this.session.releaseTiles(this);
91
+ this.image.dispose();
92
+ }
93
+ canvasSize() {
94
+ return [this.ctx.canvas.clientWidth ?? 0, this.ctx.canvas.clientHeight ?? 0];
95
+ }
96
+ polygonsShownChanged() {
97
+ if (this.points)
98
+ this.points.visible = this.pointsVisible();
99
+ this.ctx.viewer.requestRender();
100
+ }
101
+ afterChange() {
102
+ this.session.tiles?.refresh();
103
+ }
104
+ hoverTiles() {
105
+ return this.session.tiles;
106
+ }
107
+ /**
108
+ * The observation under a client position: napari-js's pick on the marker layer itself (a grid
109
+ * over its positions, rebuilt only when they change), so the tooltip cannot name a cell that is
110
+ * not drawn, then the drawn index mapped back to the observation.
111
+ *
112
+ * A marker is hit anywhere on its drawn disc, or within `slackPx` screen pixels of its centre
113
+ * when it is smaller than that (a 1.5 px dot still has to be hoverable), and of several hits the
114
+ * NEAREST centre wins (an exact tie goes to the one drawn on top). Not napari's `'topmost'`: the
115
+ * slack is wider than most markers, and over a dense field of small ones "the last drawn within
116
+ * 10 px" names a neighbour rather than the cell under the cursor.
117
+ */
118
+ pickObservation(clientX, clientY, slackPx) {
119
+ const points = this.points;
120
+ if (!points)
121
+ return -1;
122
+ const viewer = this.ctx.viewer;
123
+ const [wx, wy] = viewer.canvasToWorld(clientX, clientY);
124
+ const zoom = viewer.camera.zoom;
125
+ const k = points.pick(wx, wy, { tolerance: slackPx / (zoom > 0 ? zoom : 1), tieBreak: 'nearest' });
126
+ if (k < 0)
127
+ return -1;
128
+ return this.drawn ? this.drawn[k] : k;
129
+ }
130
+ /**
131
+ * Whether the markers are drawn: when the user wants them, and not while cell outlines are on
132
+ * screen — then a cell IS its outline, and a circle on top of it is noise. Zoomed out past the
133
+ * outline threshold, the circles stand in for the cells.
134
+ */
135
+ pointsVisible() {
136
+ const view = this.session.latest?.[1];
137
+ return (view?.showPoints ?? true) && !this.session.tiles?.outlinesShown;
138
+ }
139
+ /**
140
+ * Redraw the markers over a freshly rendered image. Two reasons, both invisible from the
141
+ * spatial store — which is why a scrub or a re-render never reached the markers on its own:
142
+ * - the image render CLEARS the layer list, taking the markers with it;
143
+ * - over a volume-backed dataset the displayed plane decides which observations belong on
144
+ * screen at all, so the cells have to move with the section rather than hang over another.
145
+ */
146
+ redrawMarkers() {
147
+ const latest = this.session.latest;
148
+ if (!latest?.[0])
149
+ return;
150
+ void this.rebuild(...latest);
151
+ }
152
+ /** (Re)build the observation marker layer for the current dataset + view state. */
153
+ async rebuild(dataset, view, selection = emptySelection()) {
154
+ const viewer = this.ctx.viewer;
155
+ const task = this.rebuilds.next();
156
+ // Resolve colours BEFORE touching the scene: a gene fetch can fail or be
157
+ // superseded, and dropping the existing layer first would blank the view.
158
+ let faceColor;
159
+ const endLoading = this.ctx.badge.begin('Observations');
160
+ try {
161
+ faceColor = dataset ? await this.faceColors(dataset, view, selection) : SPATIAL_NEUTRAL_COLOR;
162
+ }
163
+ catch (err) {
164
+ console.warn('[napari-js] spatial colouring failed — falling back to a flat colour', err);
165
+ faceColor = SPATIAL_NEUTRAL_COLOR;
166
+ }
167
+ finally {
168
+ endLoading();
169
+ }
170
+ // A newer rebuild (or a teardown) started while the vector was in flight.
171
+ if (!task())
172
+ return;
173
+ if (!dataset || dataset.observations.count === 0) {
174
+ this.removeLayers(viewer);
175
+ return;
176
+ }
177
+ // A dataset whose image IS its volume shows ONE PLANE at a time, so the
178
+ // markers are the observations in the displayed plane, drawn in that plane's
179
+ // pixel grid. Without the filter the specimen's whole depth piles onto one
180
+ // section and reads as a smear; without the affine the coordinates are read
181
+ // as pixels and land off the slice entirely.
182
+ const slab = slabAt(dataset, this.ctx.z());
183
+ // The gene map goes UNDER the cells, so it is settled before they are added.
184
+ await this.ensureGeneMap(viewer, dataset, view, selection, slab);
185
+ if (!task())
186
+ return;
187
+ this.drawMarkers(viewer, dataset, view, faceColor, slab);
188
+ }
189
+ /** Nothing to draw: drop the markers and the gene map. */
190
+ removeLayers(viewer) {
191
+ if (this.points) {
192
+ viewer.layers.remove(this.points);
193
+ this.points = null;
194
+ this.layerKey = null;
195
+ this.drawn = null;
196
+ }
197
+ if (this.geneMapLayer) {
198
+ viewer.layers.remove(this.geneMapLayer);
199
+ this.geneMapLayer = null;
200
+ this.geneMapKey = null;
201
+ }
202
+ }
203
+ /**
204
+ * Draw the observation markers over the image (and the gene map): restyled in place for a
205
+ * display-only change, else a new layer.
206
+ */
207
+ drawMarkers(viewer, dataset, view, faceColor, slab) {
208
+ const obs = dataset.observations;
209
+ const ref = slab?.ref ?? dataset.imageRef;
210
+ const size = markerSizes(obs, view, slab);
211
+ // napari's image view CLEARS the whole layer list on every render, so the
212
+ // markers go with it whenever the image is re-rendered — a scrub, a contrast
213
+ // change. The cached handle is then detached, and mutating it draws nothing:
214
+ // treat a layer that is no longer in the scene as absent so it gets re-added.
215
+ if (this.points && !viewer.layers.items.includes(this.points)) {
216
+ this.points = null;
217
+ this.layerKey = null;
218
+ }
219
+ const showImage = (!!ref || !!dataset.volume) && view.showImage !== false;
220
+ // A size/colour/opacity/selection change is DISPLAY-only: mutate the layer
221
+ // rather than dropping and re-adding it. Both setters bump the layer's
222
+ // dataVersion, which is what makes napari-js rebuild the instance buffer and
223
+ // redraw — and it avoids rebuilding 84k positions to change one number.
224
+ // The slice is part of the key: a scrub changes WHICH observations are drawn,
225
+ // which is geometry, not display.
226
+ const key = `${dataset.id}:${obs.count}:${slab?.slice ?? ''}`;
227
+ if (this.points && key === this.layerKey) {
228
+ this.points.size = size;
229
+ this.points.visible = this.pointsVisible();
230
+ this.points.faceColor = gatherColors(faceColor, slab?.indices);
231
+ this.hideForeignImage(viewer, showImage);
232
+ this.ctx.tools.regionOverlay?.setRegionsVisible(view.showAnnotations !== false);
233
+ viewer.requestRender();
234
+ return;
235
+ }
236
+ if (this.points) {
237
+ viewer.layers.remove(this.points);
238
+ this.points = null;
239
+ }
240
+ const drawn = slab?.indices;
241
+ const positions = observationPositions(obs, drawn);
242
+ this.layerKey = key;
243
+ this.drawn = drawn ?? null;
244
+ this.points = viewer.addPoints(positions, {
245
+ name: 'observations',
246
+ size,
247
+ faceColor: gatherColors(faceColor, drawn),
248
+ // No border: at Visium spot density an outline per marker reads as noise,
249
+ // and it costs a second colour array.
250
+ borderWidth: 0,
251
+ // The dataset's data->world affine. SpatialData records one per coordinate
252
+ // system (Visium spot coords are in the FULL-resolution frame while the
253
+ // served image may be the hires downscale), so without this the markers
254
+ // land in the right shape at the wrong scale. Defaults to identity when
255
+ // the coordinates are already in the image's pixel space.
256
+ scale: ref?.scale ?? [1, 1],
257
+ translate: ref?.translate ?? [0, 0],
258
+ visible: this.pointsVisible(),
259
+ });
260
+ // Outlines, density and transcripts go back over the markers just added.
261
+ this.session.tiles?.afterObservations();
262
+ this.frameOnce(viewer, dataset.id, positions, !!ref);
263
+ this.hideForeignImage(viewer, showImage);
264
+ this.ctx.tools.regionOverlay?.setRegionsVisible(view.showAnnotations !== false);
265
+ this.setRegionGridFor(dataset, positions);
266
+ }
267
+ /**
268
+ * Tell the region overlay how finely a drawn vertex may be placed.
269
+ *
270
+ * Region geometry is stored in whole world units, which is right when the world IS
271
+ * pixels — a region should align to them. It is wrong for a dataset that registers onto
272
+ * no image: seqFISH's observations span about 5 x 7 units in total, so whole-unit
273
+ * vertices leave roughly six by eight placeable positions across the entire sample and
274
+ * an ROI cannot be drawn at any zoom. Nothing errors; the tool just cannot express the
275
+ * shape.
276
+ *
277
+ * Keyed on whether the dataset brings PIXELS rather than on the extent, because the
278
+ * extent cannot tell the two apart — 2,000 units is a small slide or a large section
279
+ * depending only on what the units are, and only the dataset knows.
280
+ */
281
+ setRegionGridFor(dataset, positions) {
282
+ const overlay = this.ctx.tools.regionOverlay;
283
+ if (!overlay?.setWorldQuantum)
284
+ return;
285
+ if (dataset.imageRef || dataset.volume) {
286
+ overlay.setWorldQuantum(PIXEL_WORLD_QUANTUM);
287
+ return;
288
+ }
289
+ let minX = Infinity;
290
+ let maxX = -Infinity;
291
+ let minY = Infinity;
292
+ let maxY = -Infinity;
293
+ for (let i = 0; i < positions.length; i += 2) {
294
+ const x = positions[i];
295
+ const y = positions[i + 1];
296
+ if (!Number.isFinite(x) || !Number.isFinite(y))
297
+ continue;
298
+ if (x < minX)
299
+ minX = x;
300
+ if (x > maxX)
301
+ maxX = x;
302
+ if (y < minY)
303
+ minY = y;
304
+ if (y > maxY)
305
+ maxY = y;
306
+ }
307
+ overlay.setWorldQuantum(worldQuantumForExtent(maxX - minX, maxY - minY));
308
+ }
309
+ /**
310
+ * Hide the image layer for a dataset that brings no image of its own.
311
+ *
312
+ * The host's viewer keeps whatever image was last loaded, and for a dataset that
313
+ * registers onto none that picture belongs to something else entirely — the example's
314
+ * default slide, say. It is not merely irrelevant: the two live in different coordinate
315
+ * spaces (image pixels against the embedding's own units), so the leftover is magnified
316
+ * roughly a hundredfold. At the fitted zoom the camera sits inside its corner, where it
317
+ * reads as blank background, and it appears only once you zoom out far enough to find
318
+ * it — which is exactly how it gets noticed.
319
+ *
320
+ * Hidden rather than removed, and hidden HERE rather than by clearing the host's image
321
+ * state: that state drives the whole render pipeline, including a Plotly backend whose
322
+ * fields are declared with definite-assignment assertions, so emptying it throws from
323
+ * whichever field the next path happens to read. This touches one layer's visibility
324
+ * and nothing else.
325
+ */
326
+ hideForeignImage(viewer, datasetHasPixels) {
327
+ // No image of its own → nothing for an overview to show either.
328
+ this.image.showNavigatorFor(datasetHasPixels);
329
+ const tiles = this.session.tiles;
330
+ for (const layer of viewer.layers.items) {
331
+ if (layer.kind !== 'image')
332
+ continue;
333
+ // The transcript-density raster and the gene map are image layers too, but they are
334
+ // data, not the tissue: the Images toggle must not take them down with the slide.
335
+ if (tiles?.owns(layer) || layer === this.geneMapLayer)
336
+ continue;
337
+ // Re-shown when a dataset that owns an image comes back, so switching between
338
+ // datasets does not leave the tissue permanently hidden.
339
+ layer.visible = datasetHasPixels;
340
+ }
341
+ viewer.requestRender();
342
+ }
343
+ /**
344
+ * Frame the camera on the observations, for a dataset that brings no image.
345
+ *
346
+ * The 2D camera is normally fitted to the IMAGE, because the observations are in that
347
+ * image's pixel space and framing the image frames them too. A dataset with no
348
+ * reference image has coordinates in its own units instead — seqFISH's span about
349
+ * 5x7 — so the image framing left over from whatever was on screen before puts the
350
+ * whole cloud offscreen: measured at 9.7 x 13.4 PIXELS, centred 256px from where the
351
+ * camera was looking. The points are all there and drawn; they are a speck. Which
352
+ * looks exactly like the dataset having failed to load.
353
+ *
354
+ * Once per dataset, as napari-js's `fit3d: 'once'` does for the cloud: re-colouring,
355
+ * slicing or picking a gene re-adds this layer, and re-framing on those would move
356
+ * the camera under the user — the camera tools and the canvas drag are meant to be
357
+ * the only things that do.
358
+ */
359
+ frameOnce(viewer, datasetId, positions, registered) {
360
+ // Gated on whether THIS dataset registers onto an image, not on the image size: that keeps
361
+ // the last plotted image's dimensions after the host clears it, so a stale 512x383 read as
362
+ // "there is an image" and skipped the framing entirely.
363
+ if (registered)
364
+ return;
365
+ // Once per dataset (see above).
366
+ if (this.framed === datasetId)
367
+ return;
368
+ const { canvas } = this.ctx;
369
+ const fit = framePositions(positions, canvas.clientWidth ?? 0, canvas.clientHeight ?? 0);
370
+ // Null means there is nothing to frame on; leave the camera where it is rather
371
+ // than moving the view for a dataset we cannot fit.
372
+ if (!fit)
373
+ return;
374
+ viewer.camera.set(fit.center, fit.zoom ?? viewer.camera.zoom);
375
+ this.framed = datasetId;
376
+ }
377
+ /**
378
+ * The **gene map**: the active gene's expression as a continuous field drawn under
379
+ * the cells.
380
+ *
381
+ * A scatter coloured by a gene says which cells express it; it cannot say where,
382
+ * because the eye will not integrate thousands of dots into a territory. The field
383
+ * is a kernel-weighted MEAN per cell (see `spatial-expression.ts`), so a dense
384
+ * region does not glow merely for being dense, and it is transparent wherever no
385
+ * cell was measured — an unsampled gap must not read as "not expressed".
386
+ *
387
+ * It shares the points' LUT, percentile window and log flag, so the layer under
388
+ * the cells and the cells themselves cannot disagree about what a colour means.
389
+ *
390
+ * Estimated on the DISPLAYED image's pixel grid, coarsened so the long side is at
391
+ * most `GENE_MAP_MAX_SIDE`: a smooth field gains nothing from a slide's full
392
+ * resolution. For a volume-backed dataset that grid is the current slice, and only
393
+ * that plane's observations are included — the same rule the markers follow.
394
+ */
395
+ async ensureGeneMap(viewer, dataset, view, selection, slab) {
396
+ const gene = view.geneMap && view.colorBy?.kind === 'feature' ? view.colorBy.name : null;
397
+ const port = this.session.port;
398
+ const cache = this.session.geneMap;
399
+ const smoothing = view.geneMapSmoothing > 0 ? view.geneMapSmoothing : 1;
400
+ const clip = view.percentileClip ?? [0.01, 0.99];
401
+ // Two clocks: the FIELD depends on the gene, the plane and the bandwidth, while
402
+ // the colours depend on the window, the log flag and the opacity. Recolouring a
403
+ // cached field is a fraction of estimating one.
404
+ const fieldKey = gene
405
+ ? [dataset.id, gene, slab?.slice ?? '', smoothing, this.session.selectionRev(selection)].join('|')
406
+ : null;
407
+ const key = fieldKey
408
+ ? [
409
+ fieldKey,
410
+ clip.join(','),
411
+ view.logScale ? 'log' : 'lin',
412
+ view.geneMapOpacity,
413
+ this.ctx.display.continuousColormapKey(view),
414
+ ].join('|')
415
+ : null;
416
+ // A stitched slice re-render clears the whole layer list, the map with it, and the key of a
417
+ // registered image's map does not name the slice: a map no longer in the scene is absent,
418
+ // as the markers' is (see `rebuild`), so it is drawn again from the cached field.
419
+ if (this.geneMapLayer && !viewer.layers.items.includes(this.geneMapLayer)) {
420
+ this.geneMapLayer = null;
421
+ this.geneMapKey = null;
422
+ }
423
+ if (key === this.geneMapKey)
424
+ return;
425
+ if (this.geneMapLayer) {
426
+ viewer.layers.remove(this.geneMapLayer);
427
+ this.geneMapLayer = null;
428
+ }
429
+ this.geneMapKey = key;
430
+ if (!key || !gene || !port) {
431
+ cache.field = null;
432
+ cache.key = null;
433
+ return;
434
+ }
435
+ // The raster covers the displayed image; without one there is nothing to
436
+ // overlay and the cloud is the 3D mode's business, not this one's. Gated on the
437
+ // DATASET bringing pixels, not on the image size: that keeps the last plotted image's
438
+ // size after the host clears it, which would size the map over the wrong extent.
439
+ if (!slab && !dataset.imageRef)
440
+ return;
441
+ const size = this.ctx.imageSize();
442
+ const imageW = slab ? dataset.volume.width : size.width;
443
+ const imageH = slab ? dataset.volume.height : size.height;
444
+ if (!imageW || !imageH)
445
+ return;
446
+ const step = Math.max(1, Math.ceil(Math.max(imageW, imageH) / GENE_MAP_MAX_SIDE));
447
+ if (fieldKey !== cache.key) {
448
+ const load = this.geneMapLoads.next();
449
+ let values;
450
+ try {
451
+ values = await port.getFeatureVector(gene);
452
+ }
453
+ catch (err) {
454
+ console.warn(`[napari-js] gene map: "${gene}" unavailable`, err);
455
+ this.geneMapKey = null;
456
+ return;
457
+ }
458
+ if (!load() || this.geneMapKey !== key)
459
+ return;
460
+ const inSelection = selection.count > 0 ? maskToIndices(selection.mask) : undefined;
461
+ let estimated;
462
+ try {
463
+ estimated = await computeExpressionFieldAsync(dataset.observations, {
464
+ ref: slab?.ref ?? dataset.imageRef,
465
+ width: Math.ceil(imageW / step),
466
+ height: Math.ceil(imageH / step),
467
+ step,
468
+ sigma: GENE_MAP_SIGMA * smoothing,
469
+ values,
470
+ // A plane wins over a selection: the 2D view is showing one section, so a
471
+ // field spanning the specimen's depth would not be the thing on screen.
472
+ indices: slab?.indices ?? inSelection,
473
+ }, { signal: load.signal });
474
+ }
475
+ catch (err) {
476
+ if (isAbortError(err))
477
+ return; // superseded by a newer map, or the scene went away
478
+ throw err;
479
+ }
480
+ if (!load() || this.geneMapKey !== key)
481
+ return;
482
+ cache.field = estimated;
483
+ cache.key = fieldKey;
484
+ }
485
+ const field = cache.field;
486
+ if (!field)
487
+ return;
488
+ const lut = this.ctx.display.spatialLut(view);
489
+ // Over the measured pixels only: unmeasured ones are 0 and would drag the low end down.
490
+ const [lo, hi] = fieldContrastWindow(field, clip[0], clip[1]);
491
+ const rgba = colorExpressionField(field, lut, [lo, hi], {
492
+ log: view.logScale,
493
+ // The MAP's own opacity: reading a field under the cells means turning the
494
+ // cells down, which must not take the field with them.
495
+ opacity: view.geneMapOpacity,
496
+ });
497
+ this.geneMapLayer = viewer.addImage({ kind: 'typed', width: field.width, height: field.height, channels: 4, dtype: 'uint8', data: rgba }, {
498
+ name: `gene map · ${gene}`,
499
+ scale: [step, step],
500
+ translate: [0, 0],
501
+ blending: 'translucent',
502
+ });
503
+ // `addImage` appends, so the map just landed over the cells (drawn by this rebuild's
504
+ // previous pass, or by a newer rebuild while the field was computing): move it to just under
505
+ // them. A move keeps the markers' GPU buffers, where dropping and re-adding the markers
506
+ // re-uploaded every one of them (NAPARI-BOUNDARY-11). Without markers on screen there is
507
+ // nothing to go under; the rebuild adds them over the map.
508
+ const under = this.points ? viewer.layers.items.indexOf(this.points) : -1;
509
+ if (under >= 0)
510
+ viewer.layers.move(this.geneMapLayer, under);
511
+ viewer.requestRender();
512
+ }
513
+ /**
514
+ * Per-observation colours for the current view state, or a single flat colour when nothing is
515
+ * selected to colour by. Categorical columns use the column's own palette; continuous columns
516
+ * and gene vectors go through the active colormap with a percentile-clipped window.
517
+ */
518
+ async faceColors(dataset, view, selection) {
519
+ const port = this.session.port;
520
+ const colorBy = view.colorBy;
521
+ // Everything NOT selected is muted; with nothing selected, nothing is muted
522
+ // and the whole tissue reads normally (the CosMx highlight-vs-mute rule).
523
+ const muted = mutedFromSelection(selection);
524
+ if (!port || !colorBy) {
525
+ // Genuinely uniform: one broadcast tuple, so a flat 84k-observation view
526
+ // does not allocate a colour per point.
527
+ if (!muted && view.opacity >= 1)
528
+ return SPATIAL_NEUTRAL_COLOR;
529
+ // Not uniform — the opacity control or a selection varies the alpha, so it
530
+ // has to be per-point. Returning the constant tuple here is what made the
531
+ // Opacity slider do nothing in the default state, which is the state anyone
532
+ // lands in before picking a colour source.
533
+ return encodeCategorical(new Uint16Array(dataset.observations.count), {
534
+ colors: [SPATIAL_NEUTRAL_HEX],
535
+ opacity: view.opacity,
536
+ muted,
537
+ });
538
+ }
539
+ if (colorBy.kind === 'column') {
540
+ const column = await port.getColumn(colorBy.name);
541
+ if (isCategoricalColumn(column)) {
542
+ const rgba = encodeCategorical(column.codes, {
543
+ colors: resolveCategoryColors(column.meta),
544
+ opacity: view.opacity,
545
+ muted,
546
+ });
547
+ // Groups switched off in the Cells panel hide their dots too, when the dots are
548
+ // coloured by that same grouping.
549
+ const groupColumn = cellTypeColumnFor(dataset, view);
550
+ if (view.hiddenGroups?.length && groupColumn === colorBy.name) {
551
+ const off = new Set(view.hiddenGroups);
552
+ const hide = column.meta.categories.map((c) => off.has(c));
553
+ for (let i = 0; i < column.codes.length; i++) {
554
+ const c = column.codes[i];
555
+ if (c !== NO_CATEGORY && hide[c])
556
+ rgba[4 * i + 3] = 0;
557
+ }
558
+ }
559
+ return rgba;
560
+ }
561
+ // A continuous column may carry its own log hint (counts); the view's
562
+ // toggle wins once the user has set it.
563
+ return this.encodeContinuous(column.values, view, muted);
564
+ }
565
+ const values = await port.getFeatureVector(colorBy.name);
566
+ return this.encodeContinuous(values, view, muted);
567
+ }
568
+ /** Continuous values → RGBA through the active colormap and a clipped window. */
569
+ encodeContinuous(values, view, muted = null) {
570
+ return encodeSpatialContinuous(values, view, this.ctx.display.spatialLut(view), this.session.contrastWindows, muted);
571
+ }
572
+ }
573
+ /** The markers' diameters: each observation's own (or the fallback), at least the slab's floor,
574
+ * times the view's point scale; one number when every marker is drawn at the same size. */
575
+ function markerSizes(obs, view, slab) {
576
+ const base = markerDiameters(obs, SPATIAL_FALLBACK_RADIUS);
577
+ const scale = view.pointScale > 0 ? view.pointScale : 1;
578
+ const floor = slab?.minDiameter ?? 0;
579
+ if (typeof base === 'number' && !slab)
580
+ return Math.max(base, floor) * scale;
581
+ const sizeOf = (i) => Math.max(typeof base === 'number' ? base : base[i], floor) * scale;
582
+ return Float32Array.from(slab?.indices ?? { length: obs.count }, (_v, i) => sizeOf(slab ? slab.indices[i] : i));
583
+ }
584
+ /** Interleaved x,y of the `drawn` observations (undefined: all of them). */
585
+ function observationPositions(obs, drawn) {
586
+ const count = drawn ? drawn.length : obs.count;
587
+ const positions = new Float32Array(count * 2);
588
+ for (let i = 0; i < count; i++) {
589
+ const o = drawn ? drawn[i] : i;
590
+ positions[i * 2] = obs.x[o];
591
+ positions[i * 2 + 1] = obs.y[o];
592
+ }
593
+ return positions;
594
+ }
595
+ /**
596
+ * The plane `slice` of a volume-backed dataset: its pixel affine, the observations that fall in
597
+ * it, and the marker floor that grid needs.
598
+ *
599
+ * Null for a dataset with a real `imageRef` (its coordinates are already the image's pixels and
600
+ * every observation belongs to the one section) and for one with no volume at all — both of
601
+ * which draw exactly as before.
602
+ */
603
+ function slabAt(dataset, slice) {
604
+ const volume = dataset.volume;
605
+ if (dataset.imageRef || !volume)
606
+ return null;
607
+ return {
608
+ ref: volumeImageRef(volume, dataset.micronsPerUnit),
609
+ indices: observationsInSlice(dataset.observations, volume, slice),
610
+ slice,
611
+ minDiameter: SPATIAL_SLICE_MIN_DIAMETER_PX * volume.voxelSize[0],
612
+ };
613
+ }
614
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFwYXJpLXNwYXRpYWwtMmQtc2NlbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9uYXBhcmktanMvbmFwYXJpLXNwYXRpYWwtMmQtc2NlbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0EsT0FBTyxFQUNMLFdBQVcsRUFLWCxtQkFBbUIsR0FDcEIsTUFBTSwwQ0FBMEMsQ0FBQztBQUVsRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsZUFBZSxFQUFFLHFCQUFxQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDM0csT0FBTyxFQUVMLGNBQWMsRUFDZCxhQUFhLEVBQ2Isa0JBQWtCLEdBQ25CLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQy9ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxjQUFjLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUN6RixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEVBQW1CLG9CQUFvQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDOUcsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUU5QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdkQsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixjQUFjLEVBQ2QsdUJBQXVCLEVBQ3ZCLHFCQUFxQixFQUNyQixtQkFBbUIsRUFDbkIsNkJBQTZCLEVBRTdCLHVCQUF1QixFQUN2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ZnJvbSAnbmFwYXJpLWpzJztcblxuaW1wb3J0IHsgSUhpc3RvZ3JhbSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9jaGFubmVsLWhpc3RvZ3JhbS1hcGkuY29udHJhY3QnO1xuaW1wb3J0IHtcbiAgTk9fQ0FURUdPUlksXG4gIFNwYXRpYWxDb2x1bW4sXG4gIFNwYXRpYWxEYXRhc2V0LFxuICBTcGF0aWFsSW1hZ2VSZWYsXG4gIFNwYXRpYWxPYnNlcnZhdGlvbnMsXG4gIGlzQ2F0ZWdvcmljYWxDb2x1bW4sXG59IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9zcGF0aWFsLWRhdGFzZXQuY29udHJhY3QnO1xuaW1wb3J0IHsgU3BhdGlhbFZpZXdTdGF0ZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9kaXNwbGF5LXR5cGVzJztcbmltcG9ydCB7IGVuY29kZUNhdGVnb3JpY2FsLCBtYXJrZXJEaWFtZXRlcnMsIHJlc29sdmVDYXRlZ29yeUNvbG9ycyB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC1lbmNvZGluZyc7XG5pbXBvcnQge1xuICBTcGF0aWFsU2VsZWN0aW9uTWFzayxcbiAgZW1wdHlTZWxlY3Rpb24sXG4gIG1hc2tUb0luZGljZXMsXG4gIG11dGVkRnJvbVNlbGVjdGlvbixcbn0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXNlbGVjdGlvbic7XG5pbXBvcnQgeyBmcmFtZVBvc2l0aW9ucyB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC1mcmFtaW5nJztcbmltcG9ydCB7IFBJWEVMX1dPUkxEX1FVQU5UVU0sIHdvcmxkUXVhbnR1bUZvckV4dGVudCB9IGZyb20gJy4uLy4uL3NwYXRpYWwvd29ybGQtZ3JpZCc7XG5pbXBvcnQgeyBvYnNlcnZhdGlvbnNJblNsaWNlLCB2b2x1bWVJbWFnZVJlZiB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC12b2x1bWUtaW1hZ2UnO1xuaW1wb3J0IHsgY2VsbFR5cGVDb2x1bW5Gb3IgfSBmcm9tICcuLi8uLi9zcGF0aWFsL3NwYXRpYWwtdGlsZXMnO1xuaW1wb3J0IHsgRXhwcmVzc2lvbkZpZWxkLCBjb2xvckV4cHJlc3Npb25GaWVsZCwgZmllbGRDb250cmFzdFdpbmRvdyB9IGZyb20gJy4uLy4uL3NwYXRpYWwvc3BhdGlhbC1leHByZXNzaW9uJztcbmltcG9ydCB7IGNvbXB1dGVFeHByZXNzaW9uRmllbGRBc3luYyB9IGZyb20gJy4uLy4uL3dvcmtlcnMvc3BhdGlhbC1tYXRoJztcbmltcG9ydCB7IFN1cGVyc2VkZSB9IGZyb20gJy4uLy4uL3V0aWwvc3VwZXJzZWRlJztcbmltcG9ydCB7IGlzQWJvcnRFcnJvciB9IGZyb20gJy4uL3RpbGUtc2VydmVyJztcbmltcG9ydCB7IE5hcGFyaVNwYXRpYWxUaWxlTGF5ZXJzIH0gZnJvbSAnLi9uYXBhcmktc3BhdGlhbC10aWxlcyc7XG5pbXBvcnQgeyBJbWFnZTJkU2NlbmUgfSBmcm9tICcuL25hcGFyaS1pbWFnZS0yZC1zY2VuZSc7XG5pbXBvcnQge1xuICBHRU5FX01BUF9NQVhfU0lERSxcbiAgR0VORV9NQVBfU0lHTUEsXG4gIFNQQVRJQUxfRkFMTEJBQ0tfUkFESVVTLFxuICBTUEFUSUFMX05FVVRSQUxfQ09MT1IsXG4gIFNQQVRJQUxfTkVVVFJBTF9IRVgsXG4gIFNQQVRJQUxfU0xJQ0VfTUlOX0RJQU1FVEVSX1BYLFxuICBQb2ludENvbG9ycyxcbiAgZW5jb2RlU3BhdGlhbENvbnRpbnVvdXMsXG4gIGdhdGhlckNvbG9ycyxcbn0gZnJvbSAnLi9uYXBhcmktc3BhdGlhbC1lbmNvZGluZyc7XG5pbXBvcnQgeyBTcGF0aWFsU2NlbmVCYXNlLCBTcGF0aWFsU2Vzc2lvbiwgU3BhdGlhbFRpbGVPd25lciB9IGZyb20gJy4vbmFwYXJpLXNwYXRpYWwtc2NlbmUnO1xuaW1wb3J0IHR5cGUgeyBOYXBhcmlTY2VuZSwgU2NlbmVDb250ZXh0IH0gZnJvbSAnLi9uYXBhcmktc2NlbmUnO1xuXG4vKiogVGhlIHBsYW5lIGEgdm9sdW1lLWJhY2tlZCBkYXRhc2V0IGlzIHNob3dpbmcgKHNlZSB7QGxpbmsgU3BhdGlhbDJkU2NlbmUuc2xhYn0pLiAqL1xuaW50ZXJmYWNlIFNsYWIge1xuICByZWY6IFNwYXRpYWxJbWFnZVJlZjtcbiAgaW5kaWNlczogVWludDMyQXJyYXk7XG4gIHNsaWNlOiBudW1iZXI7XG4gIG1pbkRpYW1ldGVyOiBudW1iZXI7XG59XG5cbi8qKlxuICogU1BBVElBTF9PTUlDUyAocmV2aWV3IEFwcGVuZGl4IEIsIGNsdXN0ZXIgSik6IHRoZSB0aXNzdWUgaW1hZ2UgKGFuIHtAbGluayBJbWFnZTJkU2NlbmV9KSB3aXRoIG9uZVxuICogbWFya2VyIHBlciBvYnNlcnZhdGlvbiwgY29sb3VyZWQgYnkgYW4gYW5ub3RhdGlvbiBjb2x1bW4gb3IgYSBnZW5lLCB0aGUgZ2VuZSBtYXAgdW5kZXIgdGhlXG4gKiBjZWxscywgYW5kIHRoZSBsZXZlbC1vZi1kZXRhaWwgdGlsZSBsYXllcnMgKG91dGxpbmVzLCB0cmFuc2NyaXB0cywgZGVuc2l0eSkgb3ZlciB0aGVtLiBUaGVcbiAqIG1hcmtlcnMgcmVidWlsZCB3aGVuZXZlciB0aGUgZGF0YXNldCBvciB0aGUgdmlldyBzdGF0ZSBjaGFuZ2VzLCBzbyBzd2l0Y2hpbmcgdGhlIGNvbG91ci1ieVxuICogY29sdW1uIGRvZXMgbm90IHJlbW91bnQgdGhlIHNjZW5lLlxuICpcbiAqIFNldHMgdXAgdGhlIGZ1bGwgMkQgaW50ZXJhY3Rpb24gc3RhY2sg4oCUIHJlZ2lvbiBvdmVybGF5LCBwaXhlbCB0b29scywgcmVhZGJhY2sgY3VycmVuY3kg4oCUIGV4YWN0bHlcbiAqIGFzIHRoZSBwbGFpbiBpbWFnZSB2aWV3IGRvZXMuIFRoYXQgaXMgTk9UIG9wdGlvbmFsIGhlcmU6IHRoaXMgbW9kZSdzIHNlbGVjdGlvbiBpcyBkcml2ZW4gYnlcbiAqIGRyYXduIFJPSXMsIHNvIHdpdGhvdXQgdGhlIG92ZXJsYXkgdGhlcmUgaXMgbm8gd2F5IHRvIG1ha2UgYSBzZWxlY3Rpb24gYXQgYWxsLlxuICovXG5leHBvcnQgY2xhc3MgU3BhdGlhbDJkU2NlbmUgZXh0ZW5kcyBTcGF0aWFsU2NlbmVCYXNlIGltcGxlbWVudHMgTmFwYXJpU2NlbmUsIFNwYXRpYWxUaWxlT3duZXIge1xuICByZWFkb25seSBpbWFnZTogSW1hZ2UyZFNjZW5lO1xuICAvKiogVGhlIG9ic2VydmF0aW9uIG1hcmtlcnMsIGFuZCB3aGljaCBkYXRhc2V0L3BsYW5lIHRoZXkgd2VyZSBidWlsdCBmb3Ig4oCUIHNvIGEgZGlzcGxheS1vbmx5XG4gICAqICBjaGFuZ2UgKHNpemUsIGNvbG91ciwgb3BhY2l0eSwgc2VsZWN0aW9uKSBjYW4gdXBkYXRlIHRoZW0gaW4gcGxhY2UuICovXG4gIHByaXZhdGUgcG9pbnRzOiBQb2ludHNMYXllciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGxheWVyS2V5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgLyoqIFRoZSBvYnNlcnZhdGlvbiBlYWNoIG1hcmtlciBpcywgaW4gZHJhdyBvcmRlcjsgbnVsbCB3aGVuIGV2ZXJ5IG9ic2VydmF0aW9uIGlzIGRyYXduLiAqL1xuICBwcml2YXRlIGRyYXduOiBVaW50MzJBcnJheSB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGdlbmUgbWFwJ3MgbGF5ZXIgYW5kIHRoZSBpbnB1dHMgaXQgd2FzIGNvbG91cmVkIGZvciAoaXRzIGZpZWxkIGlzIGNhY2hlZCBpbiB0aGUgc2Vzc2lvbixcbiAgICogIG9uIGEgY2xvY2sgb2YgaXRzIG93bikuICovXG4gIGdlbmVNYXBMYXllcjogSW1hZ2VMYXllciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGdlbmVNYXBLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGRhdGFzZXQgdGhlIGNhbWVyYSBoYXMgYmVlbiBmcmFtZWQgb24g4oCUIHNlZSB7QGxpbmsgZnJhbWVPbmNlfS4gKi9cbiAgcHJpdmF0ZSBmcmFtZWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGdlbmUtbWFwIGVzdGltYXRlIGluIGZsaWdodCAob2ZmIHRoZSBtYWluIHRocmVhZCBwYXN0IHRoZSB3b3JrZXIgdGhyZXNob2xkLFxuICAgKiAgU1BBVElBTC0xOSk6IGEgbmV3IGZpZWxkIGtleSBzdXBlcnNlZGVzIOKAlCBhbmQgYWJvcnRzIOKAlCBpdDsgYSByZWJ1aWxkIHRoYXQgbGVhdmVzIHRoZSBrZXlcbiAgICogIGFsb25lIGxldHMgaXQgZmluaXNoLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGdlbmVNYXBMb2FkcyA9IG5ldyBTdXBlcnNlZGUoKTtcblxuICAvKiogYG5vSW1hZ2VgOiBhbiBpbWFnZS1sZXNzIGRhdGFzZXQgb3BlbmVkIGJlZm9yZSBhbnkgaW1hZ2Ug4oCUIHRoZSBvYnNlcnZhdGlvbnMgYWxvbmUuICovXG4gIGNvbnN0cnVjdG9yKGN0eDogU2NlbmVDb250ZXh0LCBzZXNzaW9uOiBTcGF0aWFsU2Vzc2lvbiwgbm9JbWFnZSA9IGZhbHNlKSB7XG4gICAgc3VwZXIoY3R4LCBzZXNzaW9uLCBmYWxzZSk7XG4gICAgdGhpcy5pbWFnZSA9IG5ldyBJbWFnZTJkU2NlbmUoY3R4LCB7XG4gICAgICBpbWFnZTogIW5vSW1hZ2UsXG4gICAgICAvLyBPbmx5IGZpdCB0byB0aGUgaW1hZ2Ugd2hlbiB0aGlzIGRhdGFzZXQgYWN0dWFsbHkgaGFzIG9uZS4gT3RoZXJ3aXNlIHRoZXJlIGlzIG5vdGhpbmcgdG9cbiAgICAgIC8vIGZpdCwgdGhlIGltYWdlIHNpemUgc3RpbGwgaG9sZHMgdGhlIExBU1QgaW1hZ2UncyBkaW1lbnNpb25zLCBhbmQgdGhpcyBmaXRzIHRvIHRob3NlIOKAlCBhbmRcbiAgICAgIC8vIGJlY2F1c2UgaXQgZGVmZXJzIHRvIGEgZnJhbWUsIGl0IGxhbmRzIEFGVEVSIHRoZSBwb2ludHMgYXJlIGFkZGVkIGFuZCBvdmVyd3JpdGVzIHRoZVxuICAgICAgLy8gZnJhbWluZyB0aGV5IHNldC4gVGhhdCBpcyB3aGF0IGxlZnQgYW4gaW1hZ2UtbGVzcyBkYXRhc2V0IGFzIGEgdGVuLXBpeGVsIHNwZWNrLlxuICAgICAgZml0OiAoKSA9PiAhIXNlc3Npb24ubGF0ZXN0Py5bMF0/LmltYWdlUmVmLFxuICAgICAgb25TbGljZTogKHJlcmVuZGVyZWQpID0+IHtcbiAgICAgICAgdGhpcy5yZWRyYXdNYXJrZXJzKCk7XG4gICAgICAgIC8vIFRoZSBzdGl0Y2hlZCByZS1yZW5kZXIgY2xlYXJlZCB0aGUgY2VsbHMsIHRyYW5zY3JpcHRzIGFuZCBkZW5zaXR5IHRvbzogcmUtcGxhbiB0aGVtIG5vd1xuICAgICAgICAvLyByYXRoZXIgdGhhbiBhdCB0aGUgbmV4dCBjYW1lcmEgbW92ZSAoZWFjaCBncm91cCByZWRyYXdzIG9ubHkgd2hhdCBsZWZ0IHRoZSBzY2VuZSkuXG4gICAgICAgIGlmIChyZXJlbmRlcmVkKSB0aGlzLnNlc3Npb24udGlsZXM/LnJlZnJlc2goKTtcbiAgICAgIH0sXG4gICAgICBvbk5hdmlnYXRvckludGVyYWN0OiAoKSA9PiB0aGlzLmhvdmVyLmhpZGUoKSxcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIG1vdW50KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgY3R4IH0gPSB0aGlzO1xuICAgIGF3YWl0IHRoaXMuaW1hZ2UubW91bnQoKTtcbiAgICAvLyBEaXNwb3NlZCB3aGlsZSB0aGUgaW1hZ2UgbG9hZGVkOiBjbGFpbWluZyB0aGUgdGlsZXMgbm93IHdvdWxkIHRha2UgdGhlbSBmcm9tIHRoZSBuZXh0IHNjZW5lLFxuICAgIC8vIGFuZCB0aGUgc3BhdGlhbCBzdWJzY3JpcHRpb24gd291bGQgb3V0bGl2ZSB0aGlzIG9uZS5cbiAgICBpZiAoY3R4LnNpZ25hbC5hYm9ydGVkKSByZXR1cm47XG4gICAgdGhpcy5ob3Zlci5pbnN0YWxsKGN0eC5ob3N0KTtcbiAgICB0aGlzLnNlc3Npb24uY2xhaW1UaWxlcyh0aGlzKT8uYXR0YWNoKGN0eC52aWV3ZXIpO1xuICAgIHRoaXMuc3Vic2NyaWJlU3BhdGlhbCgpO1xuICAgIGN0eC50b29scy5zY2hlZHVsZVJlYWRiYWNrKCk7XG4gIH1cblxuICBzZXRaKHo6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuaW1hZ2Uuc2V0Wih6KTtcbiAgfVxuXG4gIGhpc3RvZ3JhbShjaGFubmVsOiBudW1iZXIsIGJpbnM6IG51bWJlcik6IElIaXN0b2dyYW0gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5pbWFnZS5oaXN0b2dyYW0oY2hhbm5lbCwgYmlucyk7XG4gIH1cblxuICBzZXRJbWFnZVNtb290aGluZyhlbmFibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5pbWFnZS5zZXRJbWFnZVNtb290aGluZyhlbmFibGVkKTtcbiAgfVxuXG4gIHNldE5hdmlnYXRvclZpc2libGUodmlzaWJsZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaW1hZ2Uuc2V0TmF2aWdhdG9yVmlzaWJsZSh2aXNpYmxlKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5kaXNwb3NlU3BhdGlhbCgpO1xuICAgIHRoaXMuZ2VuZU1hcExvYWRzLmNhbmNlbCgpO1xuICAgIHRoaXMuc2Vzc2lvbi5yZWxlYXNlVGlsZXModGhpcyk7XG4gICAgdGhpcy5pbWFnZS5kaXNwb3NlKCk7XG4gIH1cblxuICBjYW52YXNTaXplKCk6IFtudW1iZXIsIG51bWJlcl0ge1xuICAgIHJldHVybiBbdGhpcy5jdHguY2FudmFzLmNsaWVudFdpZHRoID8/IDAsIHRoaXMuY3R4LmNhbnZhcy5jbGllbnRIZWlnaHQgPz8gMF07XG4gIH1cblxuICBwb2x5Z29uc1Nob3duQ2hhbmdlZCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wb2ludHMpIHRoaXMucG9pbnRzLnZpc2libGUgPSB0aGlzLnBvaW50c1Zpc2libGUoKTtcbiAgICB0aGlzLmN0eC52aWV3ZXIucmVxdWVzdFJlbmRlcigpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFmdGVyQ2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMuc2Vzc2lvbi50aWxlcz8ucmVmcmVzaCgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGhvdmVyVGlsZXMoKTogTmFwYXJpU3BhdGlhbFRpbGVMYXllcnMgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uLnRpbGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvYnNlcnZhdGlvbiB1bmRlciBhIGNsaWVudCBwb3NpdGlvbjogbmFwYXJpLWpzJ3MgcGljayBvbiB0aGUgbWFya2VyIGxheWVyIGl0c2VsZiAoYSBncmlkXG4gICAqIG92ZXIgaXRzIHBvc2l0aW9ucywgcmVidWlsdCBvbmx5IHdoZW4gdGhleSBjaGFuZ2UpLCBzbyB0aGUgdG9vbHRpcCBjYW5ub3QgbmFtZSBhIGNlbGwgdGhhdCBpc1xuICAgKiBub3QgZHJhd24sIHRoZW4gdGhlIGRyYXduIGluZGV4IG1hcHBlZCBiYWNrIHRvIHRoZSBvYnNlcnZhdGlvbi5cbiAgICpcbiAgICogQSBtYXJrZXIgaXMgaGl0IGFueXdoZXJlIG9uIGl0cyBkcmF3biBkaXNjLCBvciB3aXRoaW4gYHNsYWNrUHhgIHNjcmVlbiBwaXhlbHMgb2YgaXRzIGNlbnRyZVxuICAgKiB3aGVuIGl0IGlzIHNtYWxsZXIgdGhhbiB0aGF0IChhIDEuNSBweCBkb3Qgc3RpbGwgaGFzIHRvIGJlIGhvdmVyYWJsZSksIGFuZCBvZiBzZXZlcmFsIGhpdHMgdGhlXG4gICAqIE5FQVJFU1QgY2VudHJlIHdpbnMgKGFuIGV4YWN0IHRpZSBnb2VzIHRvIHRoZSBvbmUgZHJhd24gb24gdG9wKS4gTm90IG5hcGFyaSdzIGAndG9wbW9zdCdgOiB0aGVcbiAgICogc2xhY2sgaXMgd2lkZXIgdGhhbiBtb3N0IG1hcmtlcnMsIGFuZCBvdmVyIGEgZGVuc2UgZmllbGQgb2Ygc21hbGwgb25lcyBcInRoZSBsYXN0IGRyYXduIHdpdGhpblxuICAgKiAxMCBweFwiIG5hbWVzIGEgbmVpZ2hib3VyIHJhdGhlciB0aGFuIHRoZSBjZWxsIHVuZGVyIHRoZSBjdXJzb3IuXG4gICAqL1xuICBwcm90ZWN0ZWQgcGlja09ic2VydmF0aW9uKGNsaWVudFg6IG51bWJlciwgY2xpZW50WTogbnVtYmVyLCBzbGFja1B4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHBvaW50cyA9IHRoaXMucG9pbnRzO1xuICAgIGlmICghcG9pbnRzKSByZXR1cm4gLTE7XG4gICAgY29uc3Qgdmlld2VyID0gdGhpcy5jdHgudmlld2VyO1xuICAgIGNvbnN0IFt3eCwgd3ldID0gdmlld2VyLmNhbnZhc1RvV29ybGQoY2xpZW50WCwgY2xpZW50WSk7XG4gICAgY29uc3Qgem9vbSA9IHZpZXdlci5jYW1lcmEuem9vbTtcbiAgICBjb25zdCBrID0gcG9pbnRzLnBpY2sod3gsIHd5LCB7IHRvbGVyYW5jZTogc2xhY2tQeCAvICh6b29tID4gMCA/IHpvb20gOiAxKSwgdGllQnJlYWs6ICduZWFyZXN0JyB9KTtcbiAgICBpZiAoayA8IDApIHJldHVybiAtMTtcbiAgICByZXR1cm4gdGhpcy5kcmF3biA/IHRoaXMuZHJhd25ba10gOiBrO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIG1hcmtlcnMgYXJlIGRyYXduOiB3aGVuIHRoZSB1c2VyIHdhbnRzIHRoZW0sIGFuZCBub3Qgd2hpbGUgY2VsbCBvdXRsaW5lcyBhcmUgb25cbiAgICogc2NyZWVuIOKAlCB0aGVuIGEgY2VsbCBJUyBpdHMgb3V0bGluZSwgYW5kIGEgY2lyY2xlIG9uIHRvcCBvZiBpdCBpcyBub2lzZS4gWm9vbWVkIG91dCBwYXN0IHRoZVxuICAgKiBvdXRsaW5lIHRocmVzaG9sZCwgdGhlIGNpcmNsZXMgc3RhbmQgaW4gZm9yIHRoZSBjZWxscy5cbiAgICovXG4gIHByaXZhdGUgcG9pbnRzVmlzaWJsZSgpOiBib29sZWFuIHtcbiAgICBjb25zdCB2aWV3ID0gdGhpcy5zZXNzaW9uLmxhdGVzdD8uWzFdO1xuICAgIHJldHVybiAodmlldz8uc2hvd1BvaW50cyA/PyB0cnVlKSAmJiAhdGhpcy5zZXNzaW9uLnRpbGVzPy5vdXRsaW5lc1Nob3duO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZHJhdyB0aGUgbWFya2VycyBvdmVyIGEgZnJlc2hseSByZW5kZXJlZCBpbWFnZS4gVHdvIHJlYXNvbnMsIGJvdGggaW52aXNpYmxlIGZyb20gdGhlXG4gICAqIHNwYXRpYWwgc3RvcmUg4oCUIHdoaWNoIGlzIHdoeSBhIHNjcnViIG9yIGEgcmUtcmVuZGVyIG5ldmVyIHJlYWNoZWQgdGhlIG1hcmtlcnMgb24gaXRzIG93bjpcbiAgICogIC0gdGhlIGltYWdlIHJlbmRlciBDTEVBUlMgdGhlIGxheWVyIGxpc3QsIHRha2luZyB0aGUgbWFya2VycyB3aXRoIGl0O1xuICAgKiAgLSBvdmVyIGEgdm9sdW1lLWJhY2tlZCBkYXRhc2V0IHRoZSBkaXNwbGF5ZWQgcGxhbmUgZGVjaWRlcyB3aGljaCBvYnNlcnZhdGlvbnMgYmVsb25nIG9uXG4gICAqICAgIHNjcmVlbiBhdCBhbGwsIHNvIHRoZSBjZWxscyBoYXZlIHRvIG1vdmUgd2l0aCB0aGUgc2VjdGlvbiByYXRoZXIgdGhhbiBoYW5nIG92ZXIgYW5vdGhlci5cbiAgICovXG4gIHByaXZhdGUgcmVkcmF3TWFya2VycygpOiB2b2lkIHtcbiAgICBjb25zdCBsYXRlc3QgPSB0aGlzLnNlc3Npb24ubGF0ZXN0O1xuICAgIGlmICghbGF0ZXN0Py5bMF0pIHJldHVybjtcbiAgICB2b2lkIHRoaXMucmVidWlsZCguLi5sYXRlc3QpO1xuICB9XG5cbiAgLyoqIChSZSlidWlsZCB0aGUgb2JzZXJ2YXRpb24gbWFya2VyIGxheWVyIGZvciB0aGUgY3VycmVudCBkYXRhc2V0ICsgdmlldyBzdGF0ZS4gKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYnVpbGQoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQgfCBudWxsLFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgc2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayA9IGVtcHR5U2VsZWN0aW9uKCksXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHZpZXdlciA9IHRoaXMuY3R4LnZpZXdlcjtcbiAgICBjb25zdCB0YXNrID0gdGhpcy5yZWJ1aWxkcy5uZXh0KCk7XG5cbiAgICAvLyBSZXNvbHZlIGNvbG91cnMgQkVGT1JFIHRvdWNoaW5nIHRoZSBzY2VuZTogYSBnZW5lIGZldGNoIGNhbiBmYWlsIG9yIGJlXG4gICAgLy8gc3VwZXJzZWRlZCwgYW5kIGRyb3BwaW5nIHRoZSBleGlzdGluZyBsYXllciBmaXJzdCB3b3VsZCBibGFuayB0aGUgdmlldy5cbiAgICBsZXQgZmFjZUNvbG9yOiBQb2ludENvbG9ycztcbiAgICBjb25zdCBlbmRMb2FkaW5nID0gdGhpcy5jdHguYmFkZ2UuYmVnaW4oJ09ic2VydmF0aW9ucycpO1xuICAgIHRyeSB7XG4gICAgICBmYWNlQ29sb3IgPSBkYXRhc2V0ID8gYXdhaXQgdGhpcy5mYWNlQ29sb3JzKGRhdGFzZXQsIHZpZXcsIHNlbGVjdGlvbikgOiBTUEFUSUFMX05FVVRSQUxfQ09MT1I7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1tuYXBhcmktanNdIHNwYXRpYWwgY29sb3VyaW5nIGZhaWxlZCDigJQgZmFsbGluZyBiYWNrIHRvIGEgZmxhdCBjb2xvdXInLCBlcnIpO1xuICAgICAgZmFjZUNvbG9yID0gU1BBVElBTF9ORVVUUkFMX0NPTE9SO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBlbmRMb2FkaW5nKCk7XG4gICAgfVxuICAgIC8vIEEgbmV3ZXIgcmVidWlsZCAob3IgYSB0ZWFyZG93bikgc3RhcnRlZCB3aGlsZSB0aGUgdmVjdG9yIHdhcyBpbiBmbGlnaHQuXG4gICAgaWYgKCF0YXNrKCkpIHJldHVybjtcblxuICAgIGlmICghZGF0YXNldCB8fCBkYXRhc2V0Lm9ic2VydmF0aW9ucy5jb3VudCA9PT0gMCkge1xuICAgICAgdGhpcy5yZW1vdmVMYXllcnModmlld2VyKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBBIGRhdGFzZXQgd2hvc2UgaW1hZ2UgSVMgaXRzIHZvbHVtZSBzaG93cyBPTkUgUExBTkUgYXQgYSB0aW1lLCBzbyB0aGVcbiAgICAvLyBtYXJrZXJzIGFyZSB0aGUgb2JzZXJ2YXRpb25zIGluIHRoZSBkaXNwbGF5ZWQgcGxhbmUsIGRyYXduIGluIHRoYXQgcGxhbmUnc1xuICAgIC8vIHBpeGVsIGdyaWQuIFdpdGhvdXQgdGhlIGZpbHRlciB0aGUgc3BlY2ltZW4ncyB3aG9sZSBkZXB0aCBwaWxlcyBvbnRvIG9uZVxuICAgIC8vIHNlY3Rpb24gYW5kIHJlYWRzIGFzIGEgc21lYXI7IHdpdGhvdXQgdGhlIGFmZmluZSB0aGUgY29vcmRpbmF0ZXMgYXJlIHJlYWRcbiAgICAvLyBhcyBwaXhlbHMgYW5kIGxhbmQgb2ZmIHRoZSBzbGljZSBlbnRpcmVseS5cbiAgICBjb25zdCBzbGFiID0gc2xhYkF0KGRhdGFzZXQsIHRoaXMuY3R4LnooKSk7XG4gICAgLy8gVGhlIGdlbmUgbWFwIGdvZXMgVU5ERVIgdGhlIGNlbGxzLCBzbyBpdCBpcyBzZXR0bGVkIGJlZm9yZSB0aGV5IGFyZSBhZGRlZC5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZUdlbmVNYXAodmlld2VyLCBkYXRhc2V0LCB2aWV3LCBzZWxlY3Rpb24sIHNsYWIpO1xuICAgIGlmICghdGFzaygpKSByZXR1cm47XG4gICAgdGhpcy5kcmF3TWFya2Vycyh2aWV3ZXIsIGRhdGFzZXQsIHZpZXcsIGZhY2VDb2xvciwgc2xhYik7XG4gIH1cblxuICAvKiogTm90aGluZyB0byBkcmF3OiBkcm9wIHRoZSBtYXJrZXJzIGFuZCB0aGUgZ2VuZSBtYXAuICovXG4gIHByaXZhdGUgcmVtb3ZlTGF5ZXJzKHZpZXdlcjogVmlld2VyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucG9pbnRzKSB7XG4gICAgICB2aWV3ZXIubGF5ZXJzLnJlbW92ZSh0aGlzLnBvaW50cyk7XG4gICAgICB0aGlzLnBvaW50cyA9IG51bGw7XG4gICAgICB0aGlzLmxheWVyS2V5ID0gbnVsbDtcbiAgICAgIHRoaXMuZHJhd24gPSBudWxsO1xuICAgIH1cbiAgICBpZiAodGhpcy5nZW5lTWFwTGF5ZXIpIHtcbiAgICAgIHZpZXdlci5sYXllcnMucmVtb3ZlKHRoaXMuZ2VuZU1hcExheWVyKTtcbiAgICAgIHRoaXMuZ2VuZU1hcExheWVyID0gbnVsbDtcbiAgICAgIHRoaXMuZ2VuZU1hcEtleSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERyYXcgdGhlIG9ic2VydmF0aW9uIG1hcmtlcnMgb3ZlciB0aGUgaW1hZ2UgKGFuZCB0aGUgZ2VuZSBtYXApOiByZXN0eWxlZCBpbiBwbGFjZSBmb3IgYVxuICAgKiBkaXNwbGF5LW9ubHkgY2hhbmdlLCBlbHNlIGEgbmV3IGxheWVyLlxuICAgKi9cbiAgcHJpdmF0ZSBkcmF3TWFya2VycyhcbiAgICB2aWV3ZXI6IFZpZXdlcixcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCxcbiAgICB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLFxuICAgIGZhY2VDb2xvcjogUG9pbnRDb2xvcnMsXG4gICAgc2xhYjogU2xhYiB8IG51bGwsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IG9icyA9IGRhdGFzZXQub2JzZXJ2YXRpb25zO1xuICAgIGNvbnN0IHJlZiA9IHNsYWI/LnJlZiA/PyBkYXRhc2V0LmltYWdlUmVmO1xuICAgIGNvbnN0IHNpemUgPSBtYXJrZXJTaXplcyhvYnMsIHZpZXcsIHNsYWIpO1xuXG4gICAgLy8gbmFwYXJpJ3MgaW1hZ2UgdmlldyBDTEVBUlMgdGhlIHdob2xlIGxheWVyIGxpc3Qgb24gZXZlcnkgcmVuZGVyLCBzbyB0aGVcbiAgICAvLyBtYXJrZXJzIGdvIHdpdGggaXQgd2hlbmV2ZXIgdGhlIGltYWdlIGlzIHJlLXJlbmRlcmVkIOKAlCBhIHNjcnViLCBhIGNvbnRyYXN0XG4gICAgLy8gY2hhbmdlLiBUaGUgY2FjaGVkIGhhbmRsZSBpcyB0aGVuIGRldGFjaGVkLCBhbmQgbXV0YXRpbmcgaXQgZHJhd3Mgbm90aGluZzpcbiAgICAvLyB0cmVhdCBhIGxheWVyIHRoYXQgaXMgbm8gbG9uZ2VyIGluIHRoZSBzY2VuZSBhcyBhYnNlbnQgc28gaXQgZ2V0cyByZS1hZGRlZC5cbiAgICBpZiAodGhpcy5wb2ludHMgJiYgIXZpZXdlci5sYXllcnMuaXRlbXMuaW5jbHVkZXModGhpcy5wb2ludHMpKSB7XG4gICAgICB0aGlzLnBvaW50cyA9IG51bGw7XG4gICAgICB0aGlzLmxheWVyS2V5ID0gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBzaG93SW1hZ2UgPSAoISFyZWYgfHwgISFkYXRhc2V0LnZvbHVtZSkgJiYgdmlldy5zaG93SW1hZ2UgIT09IGZhbHNlO1xuICAgIC8vIEEgc2l6ZS9jb2xvdXIvb3BhY2l0eS9zZWxlY3Rpb24gY2hhbmdlIGlzIERJU1BMQVktb25seTogbXV0YXRlIHRoZSBsYXllclxuICAgIC8vIHJhdGhlciB0aGFuIGRyb3BwaW5nIGFuZCByZS1hZGRpbmcgaXQuIEJvdGggc2V0dGVycyBidW1wIHRoZSBsYXllcidzXG4gICAgLy8gZGF0YVZlcnNpb24sIHdoaWNoIGlzIHdoYXQgbWFrZXMgbmFwYXJpLWpzIHJlYnVpbGQgdGhlIGluc3RhbmNlIGJ1ZmZlciBhbmRcbiAgICAvLyByZWRyYXcg4oCUIGFuZCBpdCBhdm9pZHMgcmVidWlsZGluZyA4NGsgcG9zaXRpb25zIHRvIGNoYW5nZSBvbmUgbnVtYmVyLlxuICAgIC8vIFRoZSBzbGljZSBpcyBwYXJ0IG9mIHRoZSBrZXk6IGEgc2NydWIgY2hhbmdlcyBXSElDSCBvYnNlcnZhdGlvbnMgYXJlIGRyYXduLFxuICAgIC8vIHdoaWNoIGlzIGdlb21ldHJ5LCBub3QgZGlzcGxheS5cbiAgICBjb25zdCBrZXkgPSBgJHtkYXRhc2V0LmlkfToke29icy5jb3VudH06JHtzbGFiPy5zbGljZSA/PyAnJ31gO1xuICAgIGlmICh0aGlzLnBvaW50cyAmJiBrZXkgPT09IHRoaXMubGF5ZXJLZXkpIHtcbiAgICAgIHRoaXMucG9pbnRzLnNpemUgPSBzaXplO1xuICAgICAgdGhpcy5wb2ludHMudmlzaWJsZSA9IHRoaXMucG9pbnRzVmlzaWJsZSgpO1xuICAgICAgdGhpcy5wb2ludHMuZmFjZUNvbG9yID0gZ2F0aGVyQ29sb3JzKGZhY2VDb2xvciwgc2xhYj8uaW5kaWNlcyk7XG4gICAgICB0aGlzLmhpZGVGb3JlaWduSW1hZ2Uodmlld2VyLCBzaG93SW1hZ2UpO1xuICAgICAgdGhpcy5jdHgudG9vbHMucmVnaW9uT3ZlcmxheT8uc2V0UmVnaW9uc1Zpc2libGUodmlldy5zaG93QW5ub3RhdGlvbnMgIT09IGZhbHNlKTtcbiAgICAgIHZpZXdlci5yZXF1ZXN0UmVuZGVyKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucG9pbnRzKSB7XG4gICAgICB2aWV3ZXIubGF5ZXJzLnJlbW92ZSh0aGlzLnBvaW50cyk7XG4gICAgICB0aGlzLnBvaW50cyA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgZHJhd24gPSBzbGFiPy5pbmRpY2VzO1xuICAgIGNvbnN0IHBvc2l0aW9ucyA9IG9ic2VydmF0aW9uUG9zaXRpb25zKG9icywgZHJhd24pO1xuICAgIHRoaXMubGF5ZXJLZXkgPSBrZXk7XG4gICAgdGhpcy5kcmF3biA9IGRyYXduID8/IG51bGw7XG4gICAgdGhpcy5wb2ludHMgPSB2aWV3ZXIuYWRkUG9pbnRzKHBvc2l0aW9ucywge1xuICAgICAgbmFtZTogJ29ic2VydmF0aW9ucycsXG4gICAgICBzaXplLFxuICAgICAgZmFjZUNvbG9yOiBnYXRoZXJDb2xvcnMoZmFjZUNvbG9yLCBkcmF3biksXG4gICAgICAvLyBObyBib3JkZXI6IGF0IFZpc2l1bSBzcG90IGRlbnNpdHkgYW4gb3V0bGluZSBwZXIgbWFya2VyIHJlYWRzIGFzIG5vaXNlLFxuICAgICAgLy8gYW5kIGl0IGNvc3RzIGEgc2Vjb25kIGNvbG91ciBhcnJheS5cbiAgICAgIGJvcmRlcldpZHRoOiAwLFxuICAgICAgLy8gVGhlIGRhdGFzZXQncyBkYXRhLT53b3JsZCBhZmZpbmUuIFNwYXRpYWxEYXRhIHJlY29yZHMgb25lIHBlciBjb29yZGluYXRlXG4gICAgICAvLyBzeXN0ZW0gKFZpc2l1bSBzcG90IGNvb3JkcyBhcmUgaW4gdGhlIEZVTEwtcmVzb2x1dGlvbiBmcmFtZSB3aGlsZSB0aGVcbiAgICAgIC8vIHNlcnZlZCBpbWFnZSBtYXkgYmUgdGhlIGhpcmVzIGRvd25zY2FsZSksIHNvIHdpdGhvdXQgdGhpcyB0aGUgbWFya2Vyc1xuICAgICAgLy8gbGFuZCBpbiB0aGUgcmlnaHQgc2hhcGUgYXQgdGhlIHdyb25nIHNjYWxlLiBEZWZhdWx0cyB0byBpZGVudGl0eSB3aGVuXG4gICAgICAvLyB0aGUgY29vcmRpbmF0ZXMgYXJlIGFscmVhZHkgaW4gdGhlIGltYWdlJ3MgcGl4ZWwgc3BhY2UuXG4gICAgICBzY2FsZTogcmVmPy5zY2FsZSA/PyBbMSwgMV0sXG4gICAgICB0cmFuc2xhdGU6IHJlZj8udHJhbnNsYXRlID8/IFswLCAwXSxcbiAgICAgIHZpc2libGU6IHRoaXMucG9pbnRzVmlzaWJsZSgpLFxuICAgIH0pO1xuICAgIC8vIE91dGxpbmVzLCBkZW5zaXR5IGFuZCB0cmFuc2NyaXB0cyBnbyBiYWNrIG92ZXIgdGhlIG1hcmtlcnMganVzdCBhZGRlZC5cbiAgICB0aGlzLnNlc3Npb24udGlsZXM/LmFmdGVyT2JzZXJ2YXRpb25zKCk7XG4gICAgdGhpcy5mcmFtZU9uY2Uodmlld2VyLCBkYXRhc2V0LmlkLCBwb3NpdGlvbnMsICEhcmVmKTtcbiAgICB0aGlzLmhpZGVGb3JlaWduSW1hZ2Uodmlld2VyLCBzaG93SW1hZ2UpO1xuICAgIHRoaXMuY3R4LnRvb2xzLnJlZ2lvbk92ZXJsYXk/LnNldFJlZ2lvbnNWaXNpYmxlKHZpZXcuc2hvd0Fubm90YXRpb25zICE9PSBmYWxzZSk7XG4gICAgdGhpcy5zZXRSZWdpb25HcmlkRm9yKGRhdGFzZXQsIHBvc2l0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogVGVsbCB0aGUgcmVnaW9uIG92ZXJsYXkgaG93IGZpbmVseSBhIGRyYXduIHZlcnRleCBtYXkgYmUgcGxhY2VkLlxuICAgKlxuICAgKiBSZWdpb24gZ2VvbWV0cnkgaXMgc3RvcmVkIGluIHdob2xlIHdvcmxkIHVuaXRzLCB3aGljaCBpcyByaWdodCB3aGVuIHRoZSB3b3JsZCBJU1xuICAgKiBwaXhlbHMg4oCUIGEgcmVnaW9uIHNob3VsZCBhbGlnbiB0byB0aGVtLiBJdCBpcyB3cm9uZyBmb3IgYSBkYXRhc2V0IHRoYXQgcmVnaXN0ZXJzIG9udG9cbiAgICogbm8gaW1hZ2U6IHNlcUZJU0gncyBvYnNlcnZhdGlvbnMgc3BhbiBhYm91dCA1IHggNyB1bml0cyBpbiB0b3RhbCwgc28gd2hvbGUtdW5pdFxuICAgKiB2ZXJ0aWNlcyBsZWF2ZSByb3VnaGx5IHNpeCBieSBlaWdodCBwbGFjZWFibGUgcG9zaXRpb25zIGFjcm9zcyB0aGUgZW50aXJlIHNhbXBsZSBhbmRcbiAgICogYW4gUk9JIGNhbm5vdCBiZSBkcmF3biBhdCBhbnkgem9vbS4gTm90aGluZyBlcnJvcnM7IHRoZSB0b29sIGp1c3QgY2Fubm90IGV4cHJlc3MgdGhlXG4gICAqIHNoYXBlLlxuICAgKlxuICAgKiBLZXllZCBvbiB3aGV0aGVyIHRoZSBkYXRhc2V0IGJyaW5ncyBQSVhFTFMgcmF0aGVyIHRoYW4gb24gdGhlIGV4dGVudCwgYmVjYXVzZSB0aGVcbiAgICogZXh0ZW50IGNhbm5vdCB0ZWxsIHRoZSB0d28gYXBhcnQg4oCUIDIsMDAwIHVuaXRzIGlzIGEgc21hbGwgc2xpZGUgb3IgYSBsYXJnZSBzZWN0aW9uXG4gICAqIGRlcGVuZGluZyBvbmx5IG9uIHdoYXQgdGhlIHVuaXRzIGFyZSwgYW5kIG9ubHkgdGhlIGRhdGFzZXQga25vd3MuXG4gICAqL1xuICBwcml2YXRlIHNldFJlZ2lvbkdyaWRGb3IoZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHBvc2l0aW9uczogRmxvYXQzMkFycmF5KTogdm9pZCB7XG4gICAgY29uc3Qgb3ZlcmxheSA9IHRoaXMuY3R4LnRvb2xzLnJlZ2lvbk92ZXJsYXk7XG4gICAgaWYgKCFvdmVybGF5Py5zZXRXb3JsZFF1YW50dW0pIHJldHVybjtcbiAgICBpZiAoZGF0YXNldC5pbWFnZVJlZiB8fCBkYXRhc2V0LnZvbHVtZSkge1xuICAgICAgb3ZlcmxheS5zZXRXb3JsZFF1YW50dW0oUElYRUxfV09STERfUVVBTlRVTSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBtaW5YID0gSW5maW5pdHk7XG4gICAgbGV0IG1heFggPSAtSW5maW5pdHk7XG4gICAgbGV0IG1pblkgPSBJbmZpbml0eTtcbiAgICBsZXQgbWF4WSA9IC1JbmZpbml0eTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvc2l0aW9ucy5sZW5ndGg7IGkgKz0gMikge1xuICAgICAgY29uc3QgeCA9IHBvc2l0aW9uc1tpXTtcbiAgICAgIGNvbnN0IHkgPSBwb3NpdGlvbnNbaSArIDFdO1xuICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoeCkgfHwgIU51bWJlci5pc0Zpbml0ZSh5KSkgY29udGludWU7XG4gICAgICBpZiAoeCA8IG1pblgpIG1pblggPSB4O1xuICAgICAgaWYgKHggPiBtYXhYKSBtYXhYID0geDtcbiAgICAgIGlmICh5IDwgbWluWSkgbWluWSA9IHk7XG4gICAgICBpZiAoeSA+IG1heFkpIG1heFkgPSB5O1xuICAgIH1cbiAgICBvdmVybGF5LnNldFdvcmxkUXVhbnR1bSh3b3JsZFF1YW50dW1Gb3JFeHRlbnQobWF4WCAtIG1pblgsIG1heFkgLSBtaW5ZKSk7XG4gIH1cblxuICAvKipcbiAgICogSGlkZSB0aGUgaW1hZ2UgbGF5ZXIgZm9yIGEgZGF0YXNldCB0aGF0IGJyaW5ncyBubyBpbWFnZSBvZiBpdHMgb3duLlxuICAgKlxuICAgKiBUaGUgaG9zdCdzIHZpZXdlciBrZWVwcyB3aGF0ZXZlciBpbWFnZSB3YXMgbGFzdCBsb2FkZWQsIGFuZCBmb3IgYSBkYXRhc2V0IHRoYXRcbiAgICogcmVnaXN0ZXJzIG9udG8gbm9uZSB0aGF0IHBpY3R1cmUgYmVsb25ncyB0byBzb21ldGhpbmcgZWxzZSBlbnRpcmVseSDigJQgdGhlIGV4YW1wbGUnc1xuICAgKiBkZWZhdWx0IHNsaWRlLCBzYXkuIEl0IGlzIG5vdCBtZXJlbHkgaXJyZWxldmFudDogdGhlIHR3byBsaXZlIGluIGRpZmZlcmVudCBjb29yZGluYXRlXG4gICAqIHNwYWNlcyAoaW1hZ2UgcGl4ZWxzIGFnYWluc3QgdGhlIGVtYmVkZGluZydzIG93biB1bml0cyksIHNvIHRoZSBsZWZ0b3ZlciBpcyBtYWduaWZpZWRcbiAgICogcm91Z2hseSBhIGh1bmRyZWRmb2xkLiBBdCB0aGUgZml0dGVkIHpvb20gdGhlIGNhbWVyYSBzaXRzIGluc2lkZSBpdHMgY29ybmVyLCB3aGVyZSBpdFxuICAgKiByZWFkcyBhcyBibGFuayBiYWNrZ3JvdW5kLCBhbmQgaXQgYXBwZWFycyBvbmx5IG9uY2UgeW91IHpvb20gb3V0IGZhciBlbm91Z2ggdG8gZmluZFxuICAgKiBpdCDigJQgd2hpY2ggaXMgZXhhY3RseSBob3cgaXQgZ2V0cyBub3RpY2VkLlxuICAgKlxuICAgKiBIaWRkZW4gcmF0aGVyIHRoYW4gcmVtb3ZlZCwgYW5kIGhpZGRlbiBIRVJFIHJhdGhlciB0aGFuIGJ5IGNsZWFyaW5nIHRoZSBob3N0J3MgaW1hZ2VcbiAgICogc3RhdGU6IHRoYXQgc3RhdGUgZHJpdmVzIHRoZSB3aG9sZSByZW5kZXIgcGlwZWxpbmUsIGluY2x1ZGluZyBhIFBsb3RseSBiYWNrZW5kIHdob3NlXG4gICAqIGZpZWxkcyBhcmUgZGVjbGFyZWQgd2l0aCBkZWZpbml0ZS1hc3NpZ25tZW50IGFzc2VydGlvbnMsIHNvIGVtcHR5aW5nIGl0IHRocm93cyBmcm9tXG4gICAqIHdoaWNoZXZlciBmaWVsZCB0aGUgbmV4dCBwYXRoIGhhcHBlbnMgdG8gcmVhZC4gVGhpcyB0b3VjaGVzIG9uZSBsYXllcidzIHZpc2liaWxpdHlcbiAgICogYW5kIG5vdGhpbmcgZWxzZS5cbiAgICovXG4gIGhpZGVGb3JlaWduSW1hZ2Uodmlld2VyOiBQaWNrPFZpZXdlciwgJ2xheWVycycgfCAncmVxdWVzdFJlbmRlcic+LCBkYXRhc2V0SGFzUGl4ZWxzOiBib29sZWFuKTogdm9pZCB7XG4gICAgLy8gTm8gaW1hZ2Ugb2YgaXRzIG93biDihpIgbm90aGluZyBmb3IgYW4gb3ZlcnZpZXcgdG8gc2hvdyBlaXRoZXIuXG4gICAgdGhpcy5pbWFnZS5zaG93TmF2aWdhdG9yRm9yKGRhdGFzZXRIYXNQaXhlbHMpO1xuICAgIGNvbnN0IHRpbGVzID0gdGhpcy5zZXNzaW9uLnRpbGVzO1xuICAgIGZvciAoY29uc3QgbGF5ZXIgb2Ygdmlld2VyLmxheWVycy5pdGVtcykge1xuICAgICAgaWYgKGxheWVyLmtpbmQgIT09ICdpbWFnZScpIGNvbnRpbnVlO1xuICAgICAgLy8gVGhlIHRyYW5zY3JpcHQtZGVuc2l0eSByYXN0ZXIgYW5kIHRoZSBnZW5lIG1hcCBhcmUgaW1hZ2UgbGF5ZXJzIHRvbywgYnV0IHRoZXkgYXJlXG4gICAgICAvLyBkYXRhLCBub3QgdGhlIHRpc3N1ZTogdGhlIEltYWdlcyB0b2dnbGUgbXVzdCBub3QgdGFrZSB0aGVtIGRvd24gd2l0aCB0aGUgc2xpZGUuXG4gICAgICBpZiAodGlsZXM/Lm93bnMobGF5ZXIpIHx8IGxheWVyID09PSB0aGlzLmdlbmVNYXBMYXllcikgY29udGludWU7XG4gICAgICAvLyBSZS1zaG93biB3aGVuIGEgZGF0YXNldCB0aGF0IG93bnMgYW4gaW1hZ2UgY29tZXMgYmFjaywgc28gc3dpdGNoaW5nIGJldHdlZW5cbiAgICAgIC8vIGRhdGFzZXRzIGRvZXMgbm90IGxlYXZlIHRoZSB0aXNzdWUgcGVybWFuZW50bHkgaGlkZGVuLlxuICAgICAgbGF5ZXIudmlzaWJsZSA9IGRhdGFzZXRIYXNQaXhlbHM7XG4gICAgfVxuICAgIHZpZXdlci5yZXF1ZXN0UmVuZGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogRnJhbWUgdGhlIGNhbWVyYSBvbiB0aGUgb2JzZXJ2YXRpb25zLCBmb3IgYSBkYXRhc2V0IHRoYXQgYnJpbmdzIG5vIGltYWdlLlxuICAgKlxuICAgKiBUaGUgMkQgY2FtZXJhIGlzIG5vcm1hbGx5IGZpdHRlZCB0byB0aGUgSU1BR0UsIGJlY2F1c2UgdGhlIG9ic2VydmF0aW9ucyBhcmUgaW4gdGhhdFxuICAgKiBpbWFnZSdzIHBpeGVsIHNwYWNlIGFuZCBmcmFtaW5nIHRoZSBpbWFnZSBmcmFtZXMgdGhlbSB0b28uIEEgZGF0YXNldCB3aXRoIG5vXG4gICAqIHJlZmVyZW5jZSBpbWFnZSBoYXMgY29vcmRpbmF0ZXMgaW4gaXRzIG93biB1bml0cyBpbnN0ZWFkIOKAlCBzZXFGSVNIJ3Mgc3BhbiBhYm91dFxuICAgKiA1eDcg4oCUIHNvIHRoZSBpbWFnZSBmcmFtaW5nIGxlZnQgb3ZlciBmcm9tIHdoYXRldmVyIHdhcyBvbiBzY3JlZW4gYmVmb3JlIHB1dHMgdGhlXG4gICAqIHdob2xlIGNsb3VkIG9mZnNjcmVlbjogbWVhc3VyZWQgYXQgOS43IHggMTMuNCBQSVhFTFMsIGNlbnRyZWQgMjU2cHggZnJvbSB3aGVyZSB0aGVcbiAgICogY2FtZXJhIHdhcyBsb29raW5nLiBUaGUgcG9pbnRzIGFyZSBhbGwgdGhlcmUgYW5kIGRyYXduOyB0aGV5IGFyZSBhIHNwZWNrLiBXaGljaFxuICAgKiBsb29rcyBleGFjdGx5IGxpa2UgdGhlIGRhdGFzZXQgaGF2aW5nIGZhaWxlZCB0byBsb2FkLlxuICAgKlxuICAgKiBPbmNlIHBlciBkYXRhc2V0LCBhcyBuYXBhcmktanMncyBgZml0M2Q6ICdvbmNlJ2AgZG9lcyBmb3IgdGhlIGNsb3VkOiByZS1jb2xvdXJpbmcsXG4gICAqIHNsaWNpbmcgb3IgcGlja2luZyBhIGdlbmUgcmUtYWRkcyB0aGlzIGxheWVyLCBhbmQgcmUtZnJhbWluZyBvbiB0aG9zZSB3b3VsZCBtb3ZlXG4gICAqIHRoZSBjYW1lcmEgdW5kZXIgdGhlIHVzZXIg4oCUIHRoZSBjYW1lcmEgdG9vbHMgYW5kIHRoZSBjYW52YXMgZHJhZyBhcmUgbWVhbnQgdG8gYmVcbiAgICogdGhlIG9ubHkgdGhpbmdzIHRoYXQgZG8uXG4gICAqL1xuICBwcml2YXRlIGZyYW1lT25jZSh2aWV3ZXI6IFZpZXdlciwgZGF0YXNldElkOiBzdHJpbmcsIHBvc2l0aW9uczogRmxvYXQzMkFycmF5LCByZWdpc3RlcmVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgLy8gR2F0ZWQgb24gd2hldGhlciBUSElTIGRhdGFzZXQgcmVnaXN0ZXJzIG9udG8gYW4gaW1hZ2UsIG5vdCBvbiB0aGUgaW1hZ2Ugc2l6ZTogdGhhdCBrZWVwc1xuICAgIC8vIHRoZSBsYXN0IHBsb3R0ZWQgaW1hZ2UncyBkaW1lbnNpb25zIGFmdGVyIHRoZSBob3N0IGNsZWFycyBpdCwgc28gYSBzdGFsZSA1MTJ4MzgzIHJlYWQgYXNcbiAgICAvLyBcInRoZXJlIGlzIGFuIGltYWdlXCIgYW5kIHNraXBwZWQgdGhlIGZyYW1pbmcgZW50aXJlbHkuXG4gICAgaWYgKHJlZ2lzdGVyZWQpIHJldHVybjtcbiAgICAvLyBPbmNlIHBlciBkYXRhc2V0IChzZWUgYWJvdmUpLlxuICAgIGlmICh0aGlzLmZyYW1lZCA9PT0gZGF0YXNldElkKSByZXR1cm47XG5cbiAgICBjb25zdCB7IGNhbnZhcyB9ID0gdGhpcy5jdHg7XG4gICAgY29uc3QgZml0ID0gZnJhbWVQb3NpdGlvbnMocG9zaXRpb25zLCBjYW52YXMuY2xpZW50V2lkdGggPz8gMCwgY2FudmFzLmNsaWVudEhlaWdodCA/PyAwKTtcbiAgICAvLyBOdWxsIG1lYW5zIHRoZXJlIGlzIG5vdGhpbmcgdG8gZnJhbWUgb247IGxlYXZlIHRoZSBjYW1lcmEgd2hlcmUgaXQgaXMgcmF0aGVyXG4gICAgLy8gdGhhbiBtb3ZpbmcgdGhlIHZpZXcgZm9yIGEgZGF0YXNldCB3ZSBjYW5ub3QgZml0LlxuICAgIGlmICghZml0KSByZXR1cm47XG4gICAgdmlld2VyLmNhbWVyYS5zZXQoZml0LmNlbnRlciwgZml0Lnpvb20gPz8gdmlld2VyLmNhbWVyYS56b29tKTtcbiAgICB0aGlzLmZyYW1lZCA9IGRhdGFzZXRJZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgKipnZW5lIG1hcCoqOiB0aGUgYWN0aXZlIGdlbmUncyBleHByZXNzaW9uIGFzIGEgY29udGludW91cyBmaWVsZCBkcmF3biB1bmRlclxuICAgKiB0aGUgY2VsbHMuXG4gICAqXG4gICAqIEEgc2NhdHRlciBjb2xvdXJlZCBieSBhIGdlbmUgc2F5cyB3aGljaCBjZWxscyBleHByZXNzIGl0OyBpdCBjYW5ub3Qgc2F5IHdoZXJlLFxuICAgKiBiZWNhdXNlIHRoZSBleWUgd2lsbCBub3QgaW50ZWdyYXRlIHRob3VzYW5kcyBvZiBkb3RzIGludG8gYSB0ZXJyaXRvcnkuIFRoZSBmaWVsZFxuICAgKiBpcyBhIGtlcm5lbC13ZWlnaHRlZCBNRUFOIHBlciBjZWxsIChzZWUgYHNwYXRpYWwtZXhwcmVzc2lvbi50c2ApLCBzbyBhIGRlbnNlXG4gICAqIHJlZ2lvbiBkb2VzIG5vdCBnbG93IG1lcmVseSBmb3IgYmVpbmcgZGVuc2UsIGFuZCBpdCBpcyB0cmFuc3BhcmVudCB3aGVyZXZlciBub1xuICAgKiBjZWxsIHdhcyBtZWFzdXJlZCDigJQgYW4gdW5zYW1wbGVkIGdhcCBtdXN0IG5vdCByZWFkIGFzIFwibm90IGV4cHJlc3NlZFwiLlxuICAgKlxuICAgKiBJdCBzaGFyZXMgdGhlIHBvaW50cycgTFVULCBwZXJjZW50aWxlIHdpbmRvdyBhbmQgbG9nIGZsYWcsIHNvIHRoZSBsYXllciB1bmRlclxuICAgKiB0aGUgY2VsbHMgYW5kIHRoZSBjZWxscyB0aGVtc2VsdmVzIGNhbm5vdCBkaXNhZ3JlZSBhYm91dCB3aGF0IGEgY29sb3VyIG1lYW5zLlxuICAgKlxuICAgKiBFc3RpbWF0ZWQgb24gdGhlIERJU1BMQVlFRCBpbWFnZSdzIHBpeGVsIGdyaWQsIGNvYXJzZW5lZCBzbyB0aGUgbG9uZyBzaWRlIGlzIGF0XG4gICAqIG1vc3QgYEdFTkVfTUFQX01BWF9TSURFYDogYSBzbW9vdGggZmllbGQgZ2FpbnMgbm90aGluZyBmcm9tIGEgc2xpZGUncyBmdWxsXG4gICAqIHJlc29sdXRpb24uIEZvciBhIHZvbHVtZS1iYWNrZWQgZGF0YXNldCB0aGF0IGdyaWQgaXMgdGhlIGN1cnJlbnQgc2xpY2UsIGFuZCBvbmx5XG4gICAqIHRoYXQgcGxhbmUncyBvYnNlcnZhdGlvbnMgYXJlIGluY2x1ZGVkIOKAlCB0aGUgc2FtZSBydWxlIHRoZSBtYXJrZXJzIGZvbGxvdy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlR2VuZU1hcChcbiAgICB2aWV3ZXI6IFZpZXdlcixcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCxcbiAgICB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLFxuICAgIHNlbGVjdGlvbjogU3BhdGlhbFNlbGVjdGlvbk1hc2ssXG4gICAgc2xhYjogU2xhYiB8IG51bGwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGdlbmUgPSB2aWV3LmdlbmVNYXAgJiYgdmlldy5jb2xvckJ5Py5raW5kID09PSAnZmVhdHVyZScgPyB2aWV3LmNvbG9yQnkubmFtZSA6IG51bGw7XG4gICAgY29uc3QgcG9ydCA9IHRoaXMuc2Vzc2lvbi5wb3J0O1xuICAgIGNvbnN0IGNhY2hlID0gdGhpcy5zZXNzaW9uLmdlbmVNYXA7XG4gICAgY29uc3Qgc21vb3RoaW5nID0gdmlldy5nZW5lTWFwU21vb3RoaW5nID4gMCA/IHZpZXcuZ2VuZU1hcFNtb290aGluZyA6IDE7XG4gICAgY29uc3QgY2xpcCA9IHZpZXcucGVyY2VudGlsZUNsaXAgPz8gWzAuMDEsIDAuOTldO1xuXG4gICAgLy8gVHdvIGNsb2NrczogdGhlIEZJRUxEIGRlcGVuZHMgb24gdGhlIGdlbmUsIHRoZSBwbGFuZSBhbmQgdGhlIGJhbmR3aWR0aCwgd2hpbGVcbiAgICAvLyB0aGUgY29sb3VycyBkZXBlbmQgb24gdGhlIHdpbmRvdywgdGhlIGxvZyBmbGFnIGFuZCB0aGUgb3BhY2l0eS4gUmVjb2xvdXJpbmcgYVxuICAgIC8vIGNhY2hlZCBmaWVsZCBpcyBhIGZyYWN0aW9uIG9mIGVzdGltYXRpbmcgb25lLlxuICAgIGNvbnN0IGZpZWxkS2V5ID0gZ2VuZVxuICAgICAgPyBbZGF0YXNldC5pZCwgZ2VuZSwgc2xhYj8uc2xpY2UgPz8gJycsIHNtb290aGluZywgdGhpcy5zZXNzaW9uLnNlbGVjdGlvblJldihzZWxlY3Rpb24pXS5qb2luKCd8JylcbiAgICAgIDogbnVsbDtcbiAgICBjb25zdCBrZXkgPSBmaWVsZEtleVxuICAgICAgPyBbXG4gICAgICAgICAgZmllbGRLZXksXG4gICAgICAgICAgY2xpcC5qb2luKCcsJyksXG4gICAgICAgICAgdmlldy5sb2dTY2FsZSA/ICdsb2cnIDogJ2xpbicsXG4gICAgICAgICAgdmlldy5nZW5lTWFwT3BhY2l0eSxcbiAgICAgICAgICB0aGlzLmN0eC5kaXNwbGF5LmNvbnRpbnVvdXNDb2xvcm1hcEtleSh2aWV3KSxcbiAgICAgICAgXS5qb2luKCd8JylcbiAgICAgIDogbnVsbDtcbiAgICAvLyBBIHN0aXRjaGVkIHNsaWNlIHJlLXJlbmRlciBjbGVhcnMgdGhlIHdob2xlIGxheWVyIGxpc3QsIHRoZSBtYXAgd2l0aCBpdCwgYW5kIHRoZSBrZXkgb2YgYVxuICAgIC8vIHJlZ2lzdGVyZWQgaW1hZ2UncyBtYXAgZG9lcyBub3QgbmFtZSB0aGUgc2xpY2U6IGEgbWFwIG5vIGxvbmdlciBpbiB0aGUgc2NlbmUgaXMgYWJzZW50LFxuICAgIC8vIGFzIHRoZSBtYXJrZXJzJyBpcyAoc2VlIGByZWJ1aWxkYCksIHNvIGl0IGlzIGRyYXduIGFnYWluIGZyb20gdGhlIGNhY2hlZCBmaWVsZC5cbiAgICBpZiAodGhpcy5nZW5lTWFwTGF5ZXIgJiYgIXZpZXdlci5sYXllcnMuaXRlbXMuaW5jbHVkZXModGhpcy5nZW5lTWFwTGF5ZXIpKSB7XG4gICAgICB0aGlzLmdlbmVNYXBMYXllciA9IG51bGw7XG4gICAgICB0aGlzLmdlbmVNYXBLZXkgPSBudWxsO1xuICAgIH1cbiAgICBpZiAoa2V5ID09PSB0aGlzLmdlbmVNYXBLZXkpIHJldHVybjtcblxuICAgIGlmICh0aGlzLmdlbmVNYXBMYXllcikge1xuICAgICAgdmlld2VyLmxheWVycy5yZW1vdmUodGhpcy5nZW5lTWFwTGF5ZXIpO1xuICAgICAgdGhpcy5nZW5lTWFwTGF5ZXIgPSBudWxsO1xuICAgIH1cbiAgICB0aGlzLmdlbmVNYXBLZXkgPSBrZXk7XG4gICAgaWYgKCFrZXkgfHwgIWdlbmUgfHwgIXBvcnQpIHtcbiAgICAgIGNhY2hlLmZpZWxkID0gbnVsbDtcbiAgICAgIGNhY2hlLmtleSA9IG51bGw7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVGhlIHJhc3RlciBjb3ZlcnMgdGhlIGRpc3BsYXllZCBpbWFnZTsgd2l0aG91dCBvbmUgdGhlcmUgaXMgbm90aGluZyB0b1xuICAgIC8vIG92ZXJsYXkgYW5kIHRoZSBjbG91ZCBpcyB0aGUgM0QgbW9kZSdzIGJ1c2luZXNzLCBub3QgdGhpcyBvbmUncy4gR2F0ZWQgb24gdGhlXG4gICAgLy8gREFUQVNFVCBicmluZ2luZyBwaXhlbHMsIG5vdCBvbiB0aGUgaW1hZ2Ugc2l6ZTogdGhhdCBrZWVwcyB0aGUgbGFzdCBwbG90dGVkIGltYWdlJ3NcbiAgICAvLyBzaXplIGFmdGVyIHRoZSBob3N0IGNsZWFycyBpdCwgd2hpY2ggd291bGQgc2l6ZSB0aGUgbWFwIG92ZXIgdGhlIHdyb25nIGV4dGVudC5cbiAgICBpZiAoIXNsYWIgJiYgIWRhdGFzZXQuaW1hZ2VSZWYpIHJldHVybjtcbiAgICBjb25zdCBzaXplID0gdGhpcy5jdHguaW1hZ2VTaXplKCk7XG4gICAgY29uc3QgaW1hZ2VXID0gc2xhYiA/IGRhdGFzZXQudm9sdW1lIS53aWR0aCA6IHNpemUud2lkdGg7XG4gICAgY29uc3QgaW1hZ2VIID0gc2xhYiA/IGRhdGFzZXQudm9sdW1lIS5oZWlnaHQgOiBzaXplLmhlaWdodDtcbiAgICBpZiAoIWltYWdlVyB8fCAhaW1hZ2VIKSByZXR1cm47XG4gICAgY29uc3Qgc3RlcCA9IE1hdGgubWF4KDEsIE1hdGguY2VpbChNYXRoLm1heChpbWFnZVcsIGltYWdlSCkgLyBHRU5FX01BUF9NQVhfU0lERSkpO1xuXG4gICAgaWYgKGZpZWxkS2V5ICE9PSBjYWNoZS5rZXkpIHtcbiAgICAgIGNvbnN0IGxvYWQgPSB0aGlzLmdlbmVNYXBMb2Fkcy5uZXh0KCk7XG4gICAgICBsZXQgdmFsdWVzOiBGbG9hdDMyQXJyYXk7XG4gICAgICB0cnkge1xuICAgICAgICB2YWx1ZXMgPSBhd2FpdCBwb3J0LmdldEZlYXR1cmVWZWN0b3IoZ2VuZSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBbbmFwYXJpLWpzXSBnZW5lIG1hcDogXCIke2dlbmV9XCIgdW5hdmFpbGFibGVgLCBlcnIpO1xuICAgICAgICB0aGlzLmdlbmVNYXBLZXkgPSBudWxsO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoIWxvYWQoKSB8fCB0aGlzLmdlbmVNYXBLZXkgIT09IGtleSkgcmV0dXJuO1xuICAgICAgY29uc3QgaW5TZWxlY3Rpb24gPSBzZWxlY3Rpb24uY291bnQgPiAwID8gbWFza1RvSW5kaWNlcyhzZWxlY3Rpb24ubWFzaykgOiB1bmRlZmluZWQ7XG4gICAgICBsZXQgZXN0aW1hdGVkOiBFeHByZXNzaW9uRmllbGQgfCBudWxsO1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXN0aW1hdGVkID0gYXdhaXQgY29tcHV0ZUV4cHJlc3Npb25GaWVsZEFzeW5jKFxuICAgICAgICAgIGRhdGFzZXQub2JzZXJ2YXRpb25zLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHJlZjogc2xhYj8ucmVmID8/IGRhdGFzZXQuaW1hZ2VSZWYsXG4gICAgICAgICAgICB3aWR0aDogTWF0aC5jZWlsKGltYWdlVyAvIHN0ZXApLFxuICAgICAgICAgICAgaGVpZ2h0OiBNYXRoLmNlaWwoaW1hZ2VIIC8gc3RlcCksXG4gICAgICAgICAgICBzdGVwLFxuICAgICAgICAgICAgc2lnbWE6IEdFTkVfTUFQX1NJR01BICogc21vb3RoaW5nLFxuICAgICAgICAgICAgdmFsdWVzLFxuICAgICAgICAgICAgLy8gQSBwbGFuZSB3aW5zIG92ZXIgYSBzZWxlY3Rpb246IHRoZSAyRCB2aWV3IGlzIHNob3dpbmcgb25lIHNlY3Rpb24sIHNvIGFcbiAgICAgICAgICAgIC8vIGZpZWxkIHNwYW5uaW5nIHRoZSBzcGVjaW1lbidzIGRlcHRoIHdvdWxkIG5vdCBiZSB0aGUgdGhpbmcgb24gc2NyZWVuLlxuICAgICAgICAgICAgaW5kaWNlczogc2xhYj8uaW5kaWNlcyA/PyBpblNlbGVjdGlvbixcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgc2lnbmFsOiBsb2FkLnNpZ25hbCB9LFxuICAgICAgICApO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmIChpc0Fib3J0RXJyb3IoZXJyKSkgcmV0dXJuOyAvLyBzdXBlcnNlZGVkIGJ5IGEgbmV3ZXIgbWFwLCBvciB0aGUgc2NlbmUgd2VudCBhd2F5XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICAgIGlmICghbG9hZCgpIHx8IHRoaXMuZ2VuZU1hcEtleSAhPT0ga2V5KSByZXR1cm47XG4gICAgICBjYWNoZS5maWVsZCA9IGVzdGltYXRlZDtcbiAgICAgIGNhY2hlLmtleSA9IGZpZWxkS2V5O1xuICAgIH1cbiAgICBjb25zdCBmaWVsZCA9IGNhY2hlLmZpZWxkO1xuICAgIGlmICghZmllbGQpIHJldHVybjtcblxuICAgIGNvbnN0IGx1dCA9IHRoaXMuY3R4LmRpc3BsYXkuc3BhdGlhbEx1dCh2aWV3KTtcbiAgICAvLyBPdmVyIHRoZSBtZWFzdXJlZCBwaXhlbHMgb25seTogdW5tZWFzdXJlZCBvbmVzIGFyZSAwIGFuZCB3b3VsZCBkcmFnIHRoZSBsb3cgZW5kIGRvd24uXG4gICAgY29uc3QgW2xvLCBoaV0gPSBmaWVsZENvbnRyYXN0V2luZG93KGZpZWxkLCBjbGlwWzBdLCBjbGlwWzFdKTtcbiAgICBjb25zdCByZ2JhID0gY29sb3JFeHByZXNzaW9uRmllbGQoZmllbGQsIGx1dCwgW2xvLCBoaV0sIHtcbiAgICAgIGxvZzogdmlldy5sb2dTY2FsZSxcbiAgICAgIC8vIFRoZSBNQVAncyBvd24gb3BhY2l0eTogcmVhZGluZyBhIGZpZWxkIHVuZGVyIHRoZSBjZWxscyBtZWFucyB0dXJuaW5nIHRoZVxuICAgICAgLy8gY2VsbHMgZG93biwgd2hpY2ggbXVzdCBub3QgdGFrZSB0aGUgZmllbGQgd2l0aCB0aGVtLlxuICAgICAgb3BhY2l0eTogdmlldy5nZW5lTWFwT3BhY2l0eSxcbiAgICB9KTtcbiAgICB0aGlzLmdlbmVNYXBMYXllciA9IHZpZXdlci5hZGRJbWFnZShcbiAgICAgIHsga2luZDogJ3R5cGVkJywgd2lkdGg6IGZpZWxkLndpZHRoLCBoZWlnaHQ6IGZpZWxkLmhlaWdodCwgY2hhbm5lbHM6IDQsIGR0eXBlOiAndWludDgnLCBkYXRhOiByZ2JhIH0sXG4gICAgICB7XG4gICAgICAgIG5hbWU6IGBnZW5lIG1hcCDCtyAke2dlbmV9YCxcbiAgICAgICAgc2NhbGU6IFtzdGVwLCBzdGVwXSxcbiAgICAgICAgdHJhbnNsYXRlOiBbMCwgMF0sXG4gICAgICAgIGJsZW5kaW5nOiAndHJhbnNsdWNlbnQnLFxuICAgICAgfSxcbiAgICApO1xuICAgIC8vIGBhZGRJbWFnZWAgYXBwZW5kcywgc28gdGhlIG1hcCBqdXN0IGxhbmRlZCBvdmVyIHRoZSBjZWxscyAoZHJhd24gYnkgdGhpcyByZWJ1aWxkJ3NcbiAgICAvLyBwcmV2aW91cyBwYXNzLCBvciBieSBhIG5ld2VyIHJlYnVpbGQgd2hpbGUgdGhlIGZpZWxkIHdhcyBjb21wdXRpbmcpOiBtb3ZlIGl0IHRvIGp1c3QgdW5kZXJcbiAgICAvLyB0aGVtLiBBIG1vdmUga2VlcHMgdGhlIG1hcmtlcnMnIEdQVSBidWZmZXJzLCB3aGVyZSBkcm9wcGluZyBhbmQgcmUtYWRkaW5nIHRoZSBtYXJrZXJzXG4gICAgLy8gcmUtdXBsb2FkZWQgZXZlcnkgb25lIG9mIHRoZW0gKE5BUEFSSS1CT1VOREFSWS0xMSkuIFdpdGhvdXQgbWFya2VycyBvbiBzY3JlZW4gdGhlcmUgaXNcbiAgICAvLyBub3RoaW5nIHRvIGdvIHVuZGVyOyB0aGUgcmVidWlsZCBhZGRzIHRoZW0gb3ZlciB0aGUgbWFwLlxuICAgIGNvbnN0IHVuZGVyID0gdGhpcy5wb2ludHMgPyB2aWV3ZXIubGF5ZXJzLml0ZW1zLmluZGV4T2YodGhpcy5wb2ludHMpIDogLTE7XG4gICAgaWYgKHVuZGVyID49IDApIHZpZXdlci5sYXllcnMubW92ZSh0aGlzLmdlbmVNYXBMYXllciwgdW5kZXIpO1xuICAgIHZpZXdlci5yZXF1ZXN0UmVuZGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogUGVyLW9ic2VydmF0aW9uIGNvbG91cnMgZm9yIHRoZSBjdXJyZW50IHZpZXcgc3RhdGUsIG9yIGEgc2luZ2xlIGZsYXQgY29sb3VyIHdoZW4gbm90aGluZyBpc1xuICAgKiBzZWxlY3RlZCB0byBjb2xvdXIgYnkuIENhdGVnb3JpY2FsIGNvbHVtbnMgdXNlIHRoZSBjb2x1bW4ncyBvd24gcGFsZXR0ZTsgY29udGludW91cyBjb2x1bW5zXG4gICAqIGFuZCBnZW5lIHZlY3RvcnMgZ28gdGhyb3VnaCB0aGUgYWN0aXZlIGNvbG9ybWFwIHdpdGggYSBwZXJjZW50aWxlLWNsaXBwZWQgd2luZG93LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmYWNlQ29sb3JzKFxuICAgIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgc2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayxcbiAgKTogUHJvbWlzZTxQb2ludENvbG9ycz4ge1xuICAgIGNvbnN0IHBvcnQgPSB0aGlzLnNlc3Npb24ucG9ydDtcbiAgICBjb25zdCBjb2xvckJ5ID0gdmlldy5jb2xvckJ5O1xuICAgIC8vIEV2ZXJ5dGhpbmcgTk9UIHNlbGVjdGVkIGlzIG11dGVkOyB3aXRoIG5vdGhpbmcgc2VsZWN0ZWQsIG5vdGhpbmcgaXMgbXV0ZWRcbiAgICAvLyBhbmQgdGhlIHdob2xlIHRpc3N1ZSByZWFkcyBub3JtYWxseSAodGhlIENvc014IGhpZ2hsaWdodC12cy1tdXRlIHJ1bGUpLlxuICAgIGNvbnN0IG11dGVkID0gbXV0ZWRGcm9tU2VsZWN0aW9uKHNlbGVjdGlvbik7XG5cbiAgICBpZiAoIXBvcnQgfHwgIWNvbG9yQnkpIHtcbiAgICAgIC8vIEdlbnVpbmVseSB1bmlmb3JtOiBvbmUgYnJvYWRjYXN0IHR1cGxlLCBzbyBhIGZsYXQgODRrLW9ic2VydmF0aW9uIHZpZXdcbiAgICAgIC8vIGRvZXMgbm90IGFsbG9jYXRlIGEgY29sb3VyIHBlciBwb2ludC5cbiAgICAgIGlmICghbXV0ZWQgJiYgdmlldy5vcGFjaXR5ID49IDEpIHJldHVybiBTUEFUSUFMX05FVVRSQUxfQ09MT1I7XG4gICAgICAvLyBOb3QgdW5pZm9ybSDigJQgdGhlIG9wYWNpdHkgY29udHJvbCBvciBhIHNlbGVjdGlvbiB2YXJpZXMgdGhlIGFscGhhLCBzbyBpdFxuICAgICAgLy8gaGFzIHRvIGJlIHBlci1wb2ludC4gUmV0dXJuaW5nIHRoZSBjb25zdGFudCB0dXBsZSBoZXJlIGlzIHdoYXQgbWFkZSB0aGVcbiAgICAgIC8vIE9wYWNpdHkgc2xpZGVyIGRvIG5vdGhpbmcgaW4gdGhlIGRlZmF1bHQgc3RhdGUsIHdoaWNoIGlzIHRoZSBzdGF0ZSBhbnlvbmVcbiAgICAgIC8vIGxhbmRzIGluIGJlZm9yZSBwaWNraW5nIGEgY29sb3VyIHNvdXJjZS5cbiAgICAgIHJldHVybiBlbmNvZGVDYXRlZ29yaWNhbChuZXcgVWludDE2QXJyYXkoZGF0YXNldC5vYnNlcnZhdGlvbnMuY291bnQpLCB7XG4gICAgICAgIGNvbG9yczogW1NQQVRJQUxfTkVVVFJBTF9IRVhdLFxuICAgICAgICBvcGFjaXR5OiB2aWV3Lm9wYWNpdHksXG4gICAgICAgIG11dGVkLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGNvbG9yQnkua2luZCA9PT0gJ2NvbHVtbicpIHtcbiAgICAgIGNvbnN0IGNvbHVtbjogU3BhdGlhbENvbHVtbiA9IGF3YWl0IHBvcnQuZ2V0Q29sdW1uKGNvbG9yQnkubmFtZSk7XG4gICAgICBpZiAoaXNDYXRlZ29yaWNhbENvbHVtbihjb2x1bW4pKSB7XG4gICAgICAgIGNvbnN0IHJnYmEgPSBlbmNvZGVDYXRlZ29yaWNhbChjb2x1bW4uY29kZXMsIHtcbiAgICAgICAgICBjb2xvcnM6IHJlc29sdmVDYXRlZ29yeUNvbG9ycyhjb2x1bW4ubWV0YSksXG4gICAgICAgICAgb3BhY2l0eTogdmlldy5vcGFjaXR5LFxuICAgICAgICAgIG11dGVkLFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gR3JvdXBzIHN3aXRjaGVkIG9mZiBpbiB0aGUgQ2VsbHMgcGFuZWwgaGlkZSB0aGVpciBkb3RzIHRvbywgd2hlbiB0aGUgZG90cyBhcmVcbiAgICAgICAgLy8gY29sb3VyZWQgYnkgdGhhdCBzYW1lIGdyb3VwaW5nLlxuICAgICAgICBjb25zdCBncm91cENvbHVtbiA9IGNlbGxUeXBlQ29sdW1uRm9yKGRhdGFzZXQsIHZpZXcpO1xuICAgICAgICBpZiAodmlldy5oaWRkZW5Hcm91cHM/Lmxlbmd0aCAmJiBncm91cENvbHVtbiA9PT0gY29sb3JCeS5uYW1lKSB7XG4gICAgICAgICAgY29uc3Qgb2ZmID0gbmV3IFNldCh2aWV3LmhpZGRlbkdyb3Vwcyk7XG4gICAgICAgICAgY29uc3QgaGlkZSA9IGNvbHVtbi5tZXRhLmNhdGVnb3JpZXMubWFwKChjKSA9PiBvZmYuaGFzKGMpKTtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbHVtbi5jb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgYyA9IGNvbHVtbi5jb2Rlc1tpXTtcbiAgICAgICAgICAgIGlmIChjICE9PSBOT19DQVRFR09SWSAmJiBoaWRlW2NdKSByZ2JhWzQgKiBpICsgM10gPSAwO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmdiYTtcbiAgICAgIH1cbiAgICAgIC8vIEEgY29udGludW91cyBjb2x1bW4gbWF5IGNhcnJ5IGl0cyBvd24gbG9nIGhpbnQgKGNvdW50cyk7IHRoZSB2aWV3J3NcbiAgICAgIC8vIHRvZ2dsZSB3aW5zIG9uY2UgdGhlIHVzZXIgaGFzIHNldCBpdC5cbiAgICAgIHJldHVybiB0aGlzLmVuY29kZUNvbnRpbnVvdXMoY29sdW1uLnZhbHVlcywgdmlldywgbXV0ZWQpO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlcyA9IGF3YWl0IHBvcnQuZ2V0RmVhdHVyZVZlY3Rvcihjb2xvckJ5Lm5hbWUpO1xuICAgIHJldHVybiB0aGlzLmVuY29kZUNvbnRpbnVvdXModmFsdWVzLCB2aWV3LCBtdXRlZCk7XG4gIH1cblxuICAvKiogQ29udGludW91cyB2YWx1ZXMg4oaSIFJHQkEgdGhyb3VnaCB0aGUgYWN0aXZlIGNvbG9ybWFwIGFuZCBhIGNsaXBwZWQgd2luZG93LiAqL1xuICBlbmNvZGVDb250aW51b3VzKHZhbHVlczogRmxvYXQzMkFycmF5LCB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLCBtdXRlZDogVWludDhBcnJheSB8IG51bGwgPSBudWxsKTogRmxvYXQzMkFycmF5IHtcbiAgICByZXR1cm4gZW5jb2RlU3BhdGlhbENvbnRpbnVvdXMoXG4gICAgICB2YWx1ZXMsXG4gICAgICB2aWV3LFxuICAgICAgdGhpcy5jdHguZGlzcGxheS5zcGF0aWFsTHV0KHZpZXcpLFxuICAgICAgdGhpcy5zZXNzaW9uLmNvbnRyYXN0V2luZG93cyxcbiAgICAgIG11dGVkLFxuICAgICk7XG4gIH1cbn1cblxuLyoqIFRoZSBtYXJrZXJzJyBkaWFtZXRlcnM6IGVhY2ggb2JzZXJ2YXRpb24ncyBvd24gKG9yIHRoZSBmYWxsYmFjayksIGF0IGxlYXN0IHRoZSBzbGFiJ3MgZmxvb3IsXG4gKiAgdGltZXMgdGhlIHZpZXcncyBwb2ludCBzY2FsZTsgb25lIG51bWJlciB3aGVuIGV2ZXJ5IG1hcmtlciBpcyBkcmF3biBhdCB0aGUgc2FtZSBzaXplLiAqL1xuZnVuY3Rpb24gbWFya2VyU2l6ZXMob2JzOiBTcGF0aWFsT2JzZXJ2YXRpb25zLCB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLCBzbGFiOiBTbGFiIHwgbnVsbCk6IG51bWJlciB8IEZsb2F0MzJBcnJheSB7XG4gIGNvbnN0IGJhc2UgPSBtYXJrZXJEaWFtZXRlcnMob2JzLCBTUEFUSUFMX0ZBTExCQUNLX1JBRElVUyk7XG4gIGNvbnN0IHNjYWxlID0gdmlldy5wb2ludFNjYWxlID4gMCA/IHZpZXcucG9pbnRTY2FsZSA6IDE7XG4gIGNvbnN0IGZsb29yID0gc2xhYj8ubWluRGlhbWV0ZXIgPz8gMDtcbiAgaWYgKHR5cGVvZiBiYXNlID09PSAnbnVtYmVyJyAmJiAhc2xhYikgcmV0dXJuIE1hdGgubWF4KGJhc2UsIGZsb29yKSAqIHNjYWxlO1xuICBjb25zdCBzaXplT2YgPSAoaTogbnVtYmVyKSA9PiBNYXRoLm1heCh0eXBlb2YgYmFzZSA9PT0gJ251bWJlcicgPyBiYXNlIDogYmFzZVtpXSwgZmxvb3IpICogc2NhbGU7XG4gIHJldHVybiBGbG9hdDMyQXJyYXkuZnJvbShzbGFiPy5pbmRpY2VzID8/IHsgbGVuZ3RoOiBvYnMuY291bnQgfSwgKF92LCBpKSA9PiBzaXplT2Yoc2xhYiA/IHNsYWIuaW5kaWNlc1tpXSA6IGkpKTtcbn1cblxuLyoqIEludGVybGVhdmVkIHgseSBvZiB0aGUgYGRyYXduYCBvYnNlcnZhdGlvbnMgKHVuZGVmaW5lZDogYWxsIG9mIHRoZW0pLiAqL1xuZnVuY3Rpb24gb2JzZXJ2YXRpb25Qb3NpdGlvbnMob2JzOiBTcGF0aWFsT2JzZXJ2YXRpb25zLCBkcmF3bjogVWludDMyQXJyYXkgfCB1bmRlZmluZWQpOiBGbG9hdDMyQXJyYXkge1xuICBjb25zdCBjb3VudCA9IGRyYXduID8gZHJhd24ubGVuZ3RoIDogb2JzLmNvdW50O1xuICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgIGNvbnN0IG8gPSBkcmF3biA/IGRyYXduW2ldIDogaTtcbiAgICBwb3NpdGlvbnNbaSAqIDJdID0gb2JzLnhbb107XG4gICAgcG9zaXRpb25zW2kgKiAyICsgMV0gPSBvYnMueVtvXTtcbiAgfVxuICByZXR1cm4gcG9zaXRpb25zO1xufVxuXG4vKipcbiAqIFRoZSBwbGFuZSBgc2xpY2VgIG9mIGEgdm9sdW1lLWJhY2tlZCBkYXRhc2V0OiBpdHMgcGl4ZWwgYWZmaW5lLCB0aGUgb2JzZXJ2YXRpb25zIHRoYXQgZmFsbCBpblxuICogaXQsIGFuZCB0aGUgbWFya2VyIGZsb29yIHRoYXQgZ3JpZCBuZWVkcy5cbiAqXG4gKiBOdWxsIGZvciBhIGRhdGFzZXQgd2l0aCBhIHJlYWwgYGltYWdlUmVmYCAoaXRzIGNvb3JkaW5hdGVzIGFyZSBhbHJlYWR5IHRoZSBpbWFnZSdzIHBpeGVscyBhbmRcbiAqIGV2ZXJ5IG9ic2VydmF0aW9uIGJlbG9uZ3MgdG8gdGhlIG9uZSBzZWN0aW9uKSBhbmQgZm9yIG9uZSB3aXRoIG5vIHZvbHVtZSBhdCBhbGwg4oCUIGJvdGggb2ZcbiAqIHdoaWNoIGRyYXcgZXhhY3RseSBhcyBiZWZvcmUuXG4gKi9cbmZ1bmN0aW9uIHNsYWJBdChkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCwgc2xpY2U6IG51bWJlcik6IFNsYWIgfCBudWxsIHtcbiAgY29uc3Qgdm9sdW1lID0gZGF0YXNldC52b2x1bWU7XG4gIGlmIChkYXRhc2V0LmltYWdlUmVmIHx8ICF2b2x1bWUpIHJldHVybiBudWxsO1xuICByZXR1cm4ge1xuICAgIHJlZjogdm9sdW1lSW1hZ2VSZWYodm9sdW1lLCBkYXRhc2V0Lm1pY3JvbnNQZXJVbml0KSxcbiAgICBpbmRpY2VzOiBvYnNlcnZhdGlvbnNJblNsaWNlKGRhdGFzZXQub2JzZXJ2YXRpb25zLCB2b2x1bWUsIHNsaWNlKSxcbiAgICBzbGljZSxcbiAgICBtaW5EaWFtZXRlcjogU1BBVElBTF9TTElDRV9NSU5fRElBTUVURVJfUFggKiB2b2x1bWUudm94ZWxTaXplWzBdLFxuICB9O1xufVxuIl19