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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +358 -4218
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -883
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,369 @@
1
+ import { LruCache } from 'napari-js';
2
+ import { ALL_GENES } from '../../../contracts/ports/spatial-data.port';
3
+ import { tileId, tilesInRect, tilesInRectFrom, transcriptLevelFor } from '../../../spatial/lod';
4
+ import { allGenesPlan, clipTranscripts, geneBinSize, groupTranscripts, groupedMarkerPx, quantileOf, transcriptMarkerPx, } from '../../../spatial/transcript-grouping';
5
+ import { clusterMarkers, mergeTranscriptTiles } from '../../../spatial/spatial-tile-merge';
6
+ /** The all-gene pyramid's finest bin (250 µm source tiles / 128) and default level count, used
7
+ * to group a gene selection on the same ladder when a dataset has no pyramid. */
8
+ const PYRAMID_BASE_BIN_UM = 250 / 128;
9
+ const PYRAMID_LEVELS = 7;
10
+ /** Transcripts drawn at once. Past this a screen is solid colour anyway; the level
11
+ * policy keeps a normal view far below it. */
12
+ const MAX_TRANSCRIPTS = 400_000;
13
+ const MAX_TRANSCRIPT_TILES = 36;
14
+ const MAX_BIN_TILES = 64;
15
+ /** Summed per-cluster density grids kept (one per cluster × bin × dataset). */
16
+ const DENSITY_CACHE_SIZE = 256;
17
+ /**
18
+ * Decides which transcripts the 2D spatial view fetches, at which level, for the current
19
+ * camera and selection: a {@link TranscriptJob} that can be keyed before it runs (so an
20
+ * unchanged plan is a no-op) and that fetches and merges when run.
21
+ *
22
+ * Pure apart from the port, so the level policy is testable without a viewer. Owns the
23
+ * cache of summed per-cluster density grids a zoomed-out gene selection is drawn from.
24
+ */
25
+ export class TranscriptJobPlanner {
26
+ constructor(port) {
27
+ this.port = port;
28
+ /** Summed per-cluster density grids (see densityFor). */
29
+ this.densityCache = new LruCache(DENSITY_CACHE_SIZE);
30
+ }
31
+ /**
32
+ * The job that draws the view's transcripts as markers (circles or icons), or null when the
33
+ * view draws none or the port cannot serve them.
34
+ */
35
+ jobFor(dataset, view, rect, pxPerUnit) {
36
+ const mode = view.transcriptMode;
37
+ if (mode !== 'circles' && mode !== 'glyphs')
38
+ return null;
39
+ const geneBins = this.port.getTranscriptGeneBins && dataset.transcriptGeneBins;
40
+ if (!this.port.getTranscriptTile && !geneBins)
41
+ return null;
42
+ return view.transcriptAllGenes
43
+ ? this.allGenesJob(dataset, view, rect, pxPerUnit)
44
+ : this.geneJob(dataset, view, rect, pxPerUnit);
45
+ }
46
+ /**
47
+ * The chosen genes, at the level the zoom calls for — or coarser, while the markers in
48
+ * view would exceed the budget.
49
+ */
50
+ geneJob(dataset, view, rect, pxPerUnit) {
51
+ const meta = dataset.transcriptTiles;
52
+ const genes = view.transcriptGenes;
53
+ if (!meta || !genes.length)
54
+ return null;
55
+ const first = transcriptLevelFor(pxPerUnit, meta.levels);
56
+ const keysAt = (l) => tilesInRect(rect, l, meta.levels, meta.bounds, MAX_TRANSCRIPT_TILES);
57
+ const query = { genes, quality: view.transcriptQuality };
58
+ const pxPerMicron = pxPerMicronOf(dataset, pxPerUnit);
59
+ const clip = clipWindow(rect);
60
+ // Zoomed out, each gene's transcripts are grouped on the all-gene pyramid's bin ladder,
61
+ // so a gene selection reads like "all genes" does: one marker per gene per area, sized
62
+ // by how many it holds; zoomed in far enough, every transcript is its own marker.
63
+ const ladder = dataset.transcriptBins?.levels;
64
+ const baseBin = ladder?.[0]?.binSize ?? (dataset.micronsPerUnit ? PYRAMID_BASE_BIN_UM / dataset.micronsPerUnit : 0);
65
+ const bin = geneBinSize(pxPerUnit, baseBin, ladder?.length ?? PYRAMID_LEVELS);
66
+ // Zoomed out to bins as wide as the density grid, a selection is drawn from the per-gene
67
+ // density grids — one cached request per cluster — rather than 10x's coarse per-gene
68
+ // tiles, which take minutes for a few hundred genes.
69
+ // With the pyramid's per-gene levels, every zoom of a selection reads them: the level the
70
+ // zoom calls for, coarser while the markers would exceed the max.
71
+ // Both are built from high-quality calls only: with low-quality calls included, the
72
+ // quality-aware tiles below serve every zoom (as long as there are tiles to serve).
73
+ const highOnly = view.transcriptQuality !== 'all' || !this.port.getTranscriptTile;
74
+ const geneBins = dataset.transcriptGeneBins;
75
+ const fromGeneBins = highOnly && geneBins && this.port.getTranscriptGeneBins;
76
+ if (fromGeneBins && (bin !== null || !this.port.getTranscriptTile)) {
77
+ return this.geneBinsJob(dataset, view, clip, geneBins, bin ?? geneBins.levels[0].binSize);
78
+ }
79
+ const grid = dataset.density?.gridSize[0] ?? 0;
80
+ if (highOnly && bin !== null && grid > 0 && this.port.getDensity && bin >= grid * 0.75) {
81
+ return this.clusterDensityJob(dataset, view, clip, pxPerUnit, Math.max(bin, grid));
82
+ }
83
+ return {
84
+ kind: 'genes',
85
+ // The clip window, in quarter-view steps: a pan past the margin re-clips.
86
+ key: `genes|${genes.join(',')}|${view.transcriptQuality}|${view.transcriptBudget}|${bin ?? 'each'}|` +
87
+ `${clip.key}|${keysAt(first).map(tileId)}`,
88
+ load: async (ctx) => {
89
+ // The zoom's own level only: over the budget, the transcripts are combined into
90
+ // larger markers (groupSelection), never fetched from slower coarse levels.
91
+ const tiles = await ctx.fetchAll(keysAt(first), (k) => this.port.getTranscriptTile(k.level, k.gx, k.gy, query));
92
+ // Only what is on screen (and a margin, so a small pan needs nothing new) counts
93
+ // against the budget and the cap; a tile reaches far past the view.
94
+ const merged = mergeTranscriptTiles(tiles.map((t) => clipTranscripts(t, clip.around)), MAX_TRANSCRIPTS);
95
+ const px = Float32Array.from(merged.weight, (w) => transcriptMarkerPx(w, view.transcriptScale, pxPerMicron));
96
+ return baseBin > 0
97
+ ? { merged, px, ladder: { baseBin, levels: ladder?.length ?? PYRAMID_LEVELS, start: bin } }
98
+ : { merged, px };
99
+ },
100
+ };
101
+ }
102
+ /**
103
+ * A gene selection from the pyramid's per-gene levels: starting at the level whose bins are
104
+ * `startBin`, fetch the view's tiles for the selected genes and step to a coarser level while
105
+ * one marker per cluster per bin would exceed the max. Hidden genes are fetched too (their
106
+ * counts in view still show) and dropped before drawing; grouping by cluster happens there.
107
+ */
108
+ geneBinsJob(dataset, view, clip, meta, startBin) {
109
+ const genes = view.transcriptGenes;
110
+ const levels = meta.levels;
111
+ let first = levels.findIndex((l) => l.binSize >= startBin * 0.999);
112
+ if (first < 0)
113
+ first = levels.length - 1;
114
+ const budget = Math.max(1, view.transcriptBudget);
115
+ const hidden = new Set(view.transcriptHiddenGenes);
116
+ const clusters = this.selectionClusters(view);
117
+ const clusterOf = new Map();
118
+ clusters.forEach((c, ci) => c.genes.forEach((g) => clusterOf.set(genes.indexOf(g), ci)));
119
+ const keysAt = (m) => tilesInRectFrom(meta.origin, clip.around, m, levels.map((l) => ({ tileSize: l.tileSize })), null, MAX_BIN_TILES);
120
+ return {
121
+ kind: 'genes',
122
+ key: `gene-bins|${genes.join(',')}|${budget}|${first}|${JSON.stringify(view.transcriptGeneGroups)}|` + clip.key,
123
+ load: async (ctx) => {
124
+ let m = first;
125
+ for (;;) {
126
+ const tiles = await ctx.fetchAll(keysAt(m), (k) => this.port.getTranscriptGeneBins(k.level, k.gx, k.gy, genes));
127
+ const clipped = tiles.map((t) => clipTranscripts(t, clip.around));
128
+ // Past the cap a merge would drop whole genes (the tail of every tile): go coarser.
129
+ if (clipped.reduce((n, t) => n + t.count, 0) > MAX_TRANSCRIPTS && m < levels.length - 1) {
130
+ m++;
131
+ continue;
132
+ }
133
+ const merged = mergeTranscriptTiles(clipped, MAX_TRANSCRIPTS);
134
+ // Markers this level would draw: one per (visible cluster, bin).
135
+ const seen = new Set();
136
+ const bin = levels[m].binSize;
137
+ for (let i = 0; i < merged.count; i++) {
138
+ if (hidden.has(genes[merged.gene[i]]))
139
+ continue;
140
+ const c = clusterOf.get(merged.gene[i]);
141
+ if (c === undefined)
142
+ continue;
143
+ seen.add(`${c}|${Math.floor(merged.x[i] / bin)}|${Math.floor(merged.y[i] / bin)}`);
144
+ }
145
+ if (seen.size <= budget || m >= levels.length - 1) {
146
+ return { merged, px: new Float32Array(merged.count), ladder: { baseBin: bin, levels: 1, start: bin } };
147
+ }
148
+ m++;
149
+ }
150
+ },
151
+ };
152
+ }
153
+ /** The selection's clusters: each gene-tree group's visible genes, then each ungrouped gene. */
154
+ selectionClusters(view) {
155
+ const hidden = new Set(view.transcriptHiddenGenes);
156
+ const slots = new Map(view.transcriptGenes.map((g, i) => [g, i]));
157
+ const taken = new Set();
158
+ const out = [];
159
+ for (const g of view.transcriptGeneGroups) {
160
+ const genes = g.genes.filter((x) => slots.has(x) && !hidden.has(x) && !taken.has(x));
161
+ genes.forEach((x) => taken.add(x));
162
+ if (genes.length)
163
+ out.push({ name: g.name, genes, slot: slots.get(genes[0]) });
164
+ }
165
+ for (const gene of view.transcriptGenes) {
166
+ if (!taken.has(gene) && !hidden.has(gene))
167
+ out.push({ name: gene, genes: [gene], slot: slots.get(gene) });
168
+ }
169
+ return out;
170
+ }
171
+ /**
172
+ * Per-gene density grids summed for `genes`, cached (a cluster is asked for once per bin).
173
+ * Keyed by dataset too: this manager outlives a dataset, and another may share gene names.
174
+ * Least-recently-USED eviction, so the clusters in view stay cached; a failed request is
175
+ * dropped so the next plan asks again.
176
+ */
177
+ densityFor(dataset, genes, bin) {
178
+ const key = `${dataset}|${bin}|${genes.join(',')}`;
179
+ let p = this.densityCache.get(key);
180
+ if (!p) {
181
+ const request = this.port.getDensity(genes, bin);
182
+ request.catch(() => {
183
+ if (this.densityCache.get(key) === request)
184
+ this.densityCache.delete(key);
185
+ });
186
+ this.densityCache.set(key, request);
187
+ p = request;
188
+ }
189
+ return p;
190
+ }
191
+ /**
192
+ * A gene selection zoomed out: one marker per cluster per bin, from the per-gene density
193
+ * grids. The bin starts where markers are 14 px apart and doubles until the markers fit the
194
+ * max; each marker sits at the count-weighted centre of the finer grid inside it, so markers
195
+ * follow the tissue rather than a lattice.
196
+ */
197
+ clusterDensityJob(dataset, view, clip, pxPerUnit, startBin) {
198
+ const grid = dataset.density.gridSize[0];
199
+ const clusters = this.selectionClusters(view);
200
+ let first = grid;
201
+ while (first < startBin * 0.999)
202
+ first *= 2;
203
+ const budget = Math.max(1, view.transcriptBudget);
204
+ return {
205
+ kind: 'genes',
206
+ key: `clusters|${clusters.map((c) => `${c.name}:${c.genes.join('+')}`).join(';')}|${budget}|${first}|` +
207
+ clip.key,
208
+ load: async () => {
209
+ let bin = first;
210
+ for (;;) {
211
+ // The finer grid gives each marker its centre; the server bins 1, 2, 4 or 8 cells.
212
+ const fine = Math.min(bin >= grid * 2 ? bin / 2 : bin, grid * 8);
213
+ const rasters = await Promise.all(clusters.map((c) => this.densityFor(dataset.id, c.genes, fine)));
214
+ const out = clusterMarkers(rasters, clusters.map((c) => c.slot), bin, clip.around);
215
+ if (out.tile.count <= budget || bin >= grid * 2 ** 12) {
216
+ const px = groupedSizes(out.tile.weight, bin * pxPerUnit, view.transcriptScale);
217
+ return {
218
+ merged: out.tile,
219
+ px,
220
+ kind: 'genes',
221
+ clustered: {
222
+ group: out.group,
223
+ names: clusters.map((c) => c.name),
224
+ genes: clusters.map((c) => c.genes),
225
+ bin,
226
+ origin: rasters[0]?.meta.origin ?? [0, 0],
227
+ },
228
+ };
229
+ }
230
+ bin *= 2;
231
+ }
232
+ },
233
+ };
234
+ }
235
+ /**
236
+ * Every gene: the transcripts themselves once they fit the budget, else bins of the
237
+ * all-gene pyramid sized by how many transcripts each holds.
238
+ */
239
+ allGenesJob(dataset, view, rect, pxPerUnit) {
240
+ const bins = dataset.transcriptBins;
241
+ const tiles = dataset.transcriptTiles;
242
+ const bounds = bins?.bounds ?? tiles?.bounds;
243
+ if (!bounds)
244
+ return null;
245
+ const plan = allGenesPlan({
246
+ rect,
247
+ bounds,
248
+ pxPerUnit,
249
+ budget: view.transcriptBudget,
250
+ total: bins?.count ?? tiles?.count ?? 0,
251
+ levels: bins && this.port.getTranscriptBins ? bins.levels : [],
252
+ canIndividual: !!tiles,
253
+ });
254
+ if (plan.kind === 'individual' && tiles) {
255
+ const keys = tilesInRect(rect, 0, tiles.levels, tiles.bounds, MAX_TRANSCRIPT_TILES);
256
+ // Each tile clipped to the view, rounded outward to 10 units so small pans hit cache.
257
+ const r10 = (v, up) => (up ? Math.ceil(v / 10) : Math.floor(v / 10)) * 10;
258
+ const size = tiles.levels[0].tileSize;
259
+ const boxes = keys.map((k) => [
260
+ Math.max(k.gx * size, r10(rect.x0, false)),
261
+ Math.max(k.gy * size, r10(rect.y0, false)),
262
+ Math.min((k.gx + 1) * size, r10(rect.x1, true)),
263
+ Math.min((k.gy + 1) * size, r10(rect.y1, true)),
264
+ ]);
265
+ const pxPerMicron = pxPerMicronOf(dataset, pxPerUnit);
266
+ return {
267
+ kind: 'individual',
268
+ key: `all|individual|${view.transcriptBudget}|${boxes.map((b) => b.join(',')).join(';')}`,
269
+ load: async (ctx) => {
270
+ const got = await ctx.fetchAll(keys.map((k, i) => ({ ...k, box: boxes[i] })), (k) => this.port.getTranscriptTile(0, k.gx, k.gy, { genes: [ALL_GENES], box: k.box }));
271
+ // The plan estimated the view from the dataset's average density; expression is
272
+ // uneven, so a dense view can hold far more. Rather than cut the excess off, show
273
+ // it grouped — the bin level the planner would pick if it had known.
274
+ const cap = Math.max(view.transcriptBudget * 1.5, 1);
275
+ const loaded = got.reduce((n, t) => n + t.count, 0);
276
+ if (loaded > cap && bins && this.port.getTranscriptBins) {
277
+ const fallback = allGenesPlan({
278
+ rect,
279
+ bounds,
280
+ pxPerUnit,
281
+ budget: view.transcriptBudget,
282
+ total: bins.count,
283
+ levels: bins.levels,
284
+ canIndividual: false,
285
+ });
286
+ if (fallback.kind === 'bins') {
287
+ const job = this.binsJob(view, rect, pxPerUnit, bounds, bins, fallback.level);
288
+ return { ...(await job.load(ctx)), kind: job.kind, bin: job.bin };
289
+ }
290
+ }
291
+ const merged = mergeTranscriptTiles(got, cap);
292
+ // One transcript per entry: every marker is the same size.
293
+ const px = new Float32Array(merged.count).fill(transcriptMarkerPx(1, view.transcriptScale, pxPerMicron));
294
+ return { merged, px };
295
+ },
296
+ };
297
+ }
298
+ if (plan.kind === 'bins' && bins && this.port.getTranscriptBins) {
299
+ return this.binsJob(view, rect, pxPerUnit, bounds, bins, plan.level);
300
+ }
301
+ return null;
302
+ }
303
+ /** Bins of the all-gene pyramid at `level`, sized by how many transcripts each holds. */
304
+ binsJob(view, rect, pxPerUnit, bounds, bins, level) {
305
+ const lv = bins.levels[level];
306
+ const keys = tilesInRectFrom(bins.origin, rect, level, bins.levels.map((l) => ({ tileSize: l.tileSize })), bounds, MAX_BIN_TILES);
307
+ return {
308
+ kind: 'bins',
309
+ bin: { size: lv.binSize, origin: bins.origin },
310
+ key: `all|bins|${level}|${view.transcriptBudget}|${keys.map(tileId)}`,
311
+ load: async (ctx) => {
312
+ const got = await ctx.fetchAll(keys, (k) => this.port.getTranscriptBins(k.level, k.gx, k.gy));
313
+ const merged = mergeTranscriptTiles(got, Math.max(view.transcriptBudget * 1.5, 1));
314
+ return { merged, px: groupedSizes(merged.weight, lv.binSize * pxPerUnit, view.transcriptScale) };
315
+ },
316
+ };
317
+ }
318
+ }
319
+ /**
320
+ * Group a gene selection for the zoom: one marker per gene-tree cluster (a gene in no
321
+ * cluster is its own) per bin of the pyramid ladder, starting at the finest bin whose
322
+ * markers are 14 px apart and stepping up while the markers would exceed the budget.
323
+ * Null to draw every transcript: zoomed in, with the selection within the budget.
324
+ */
325
+ export function groupSelection(t, view, ladder, pxPerUnit) {
326
+ const budget = Math.max(1, view.transcriptBudget);
327
+ const genes = view.transcriptGenes;
328
+ const groups = view.transcriptGeneGroups;
329
+ const names = [...groups.map((g) => g.name), ...genes];
330
+ const clusterOf = genes.map((gene, slot) => {
331
+ const g = groups.findIndex((x) => x.genes.includes(gene));
332
+ return g >= 0 ? g : groups.length + slot;
333
+ });
334
+ const keyOf = (slot) => clusterOf[slot] ?? groups.length + slot;
335
+ let bin = ladder.start;
336
+ if (bin === null) {
337
+ // Every transcript, if they fit the max and none was cut off at the cap.
338
+ if (t.count <= budget && t.count < MAX_TRANSCRIPTS)
339
+ return null;
340
+ bin = ladder.baseBin;
341
+ }
342
+ const top = ladder.baseBin * 2 ** (ladder.levels - 1);
343
+ let grouped = groupTranscripts(t, bin, keyOf);
344
+ // Over the max: combine into larger markers, a level at a time.
345
+ while (grouped.tile.count > budget && bin < top) {
346
+ bin *= 2;
347
+ grouped = groupTranscripts(t, bin, keyOf);
348
+ }
349
+ const px = groupedSizes(grouped.tile.weight, bin * pxPerUnit, view.transcriptScale);
350
+ return { merged: grouped.tile, px, bin, group: grouped.group, names };
351
+ }
352
+ /** Screen sizes of grouped markers: by weight against the 95th-percentile weight, over `binPx`. */
353
+ function groupedSizes(weight, binPx, scale) {
354
+ const refCount = quantileOf(weight, 0.95);
355
+ return Float32Array.from(weight, (w) => groupedMarkerPx(w, refCount, binPx, scale));
356
+ }
357
+ function clipWindow(rect) {
358
+ const mx = (rect.x1 - rect.x0) * 0.25;
359
+ const my = (rect.y1 - rect.y0) * 0.25;
360
+ return {
361
+ around: { x0: rect.x0 - mx, y0: rect.y0 - my, x1: rect.x1 + mx, y1: rect.y1 + my },
362
+ key: `${Math.floor(rect.x0 / (mx || 1))},${Math.floor(rect.y0 / (my || 1))}`,
363
+ };
364
+ }
365
+ /** Physical marker size needs µm; undefined when the dataset's unit is unknown. */
366
+ function pxPerMicronOf(dataset, pxPerUnit) {
367
+ return dataset.micronsPerUnit ? pxPerUnit / dataset.micronsPerUnit : undefined;
368
+ }
369
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNjcmlwdC1qb2JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvbmFwYXJpLWpzL3NwYXRpYWwtdGlsZXMvdHJhbnNjcmlwdC1qb2JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFckMsT0FBTyxFQUFFLFNBQVMsRUFBd0IsTUFBTSw0Q0FBNEMsQ0FBQztBQVE3RixPQUFPLEVBQVksTUFBTSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUMxRyxPQUFPLEVBQ0wsWUFBWSxFQUNaLGVBQWUsRUFDZixXQUFXLEVBQ1gsZ0JBQWdCLEVBQ2hCLGVBQWUsRUFDZixVQUFVLEVBQ1Ysa0JBQWtCLEdBQ25CLE1BQU0sc0NBQXNDLENBQUM7QUFDOUMsT0FBTyxFQUFFLGNBQWMsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBSTNGO2tGQUNrRjtBQUNsRixNQUFNLG1CQUFtQixHQUFHLEdBQUcsR0FBRyxHQUFHLENBQUM7QUFDdEMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxDQUFDO0FBQ3pCOytDQUMrQztBQUMvQyxNQUFNLGVBQWUsR0FBRyxPQUFPLENBQUM7QUFDaEMsTUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUM7QUFDaEMsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDO0FBQ3pCLCtFQUErRTtBQUMvRSxNQUFNLGtCQUFrQixHQUFHLEdBQUcsQ0FBQztBQTBCL0I7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxvQkFBb0I7SUFJL0IsWUFBNkIsSUFBcUI7UUFBckIsU0FBSSxHQUFKLElBQUksQ0FBaUI7UUFIbEQseURBQXlEO1FBQ3hDLGlCQUFZLEdBQUcsSUFBSSxRQUFRLENBQWdDLGtCQUFrQixDQUFDLENBQUM7SUFFM0MsQ0FB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QyxDQUFDLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0FBQ3RGLENBQUM7QUFVRCxTQUFTLFVBQVUsQ0FBQyxJQUFjO0lBQ2hDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQ3RDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQ3RDLE9BQU87UUFDTCxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDbEYsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUU7S0FDN0UsQ0FBQztBQUNKLENBQUM7QUFFRCxtRkFBbUY7QUFDbkYsU0FBUyxhQUFhLENBQUMsT0FBdUIsRUFBRSxTQUFpQjtJQUMvRCxPQUFPLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDakYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IExydUNhY2hlIH0gZnJvbSAnbmFwYXJpLWpzJztcblxuaW1wb3J0IHsgQUxMX0dFTkVTLCB0eXBlIFNwYXRpYWxEYXRhUG9ydCB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9wb3J0cy9zcGF0aWFsLWRhdGEucG9ydCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxWaWV3U3RhdGUgfSBmcm9tICcuLi8uLi8uLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQge1xuICBTcGF0aWFsQm91bmRzLFxuICBTcGF0aWFsRGF0YXNldCxcbiAgU3BhdGlhbERlbnNpdHlSYXN0ZXIsXG4gIFNwYXRpYWxUcmFuc2NyaXB0VGlsZSxcbn0gZnJvbSAnLi4vLi4vLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQgeyBEYXRhUmVjdCwgdGlsZUlkLCB0aWxlc0luUmVjdCwgdGlsZXNJblJlY3RGcm9tLCB0cmFuc2NyaXB0TGV2ZWxGb3IgfSBmcm9tICcuLi8uLi8uLi9zcGF0aWFsL2xvZCc7XG5pbXBvcnQge1xuICBhbGxHZW5lc1BsYW4sXG4gIGNsaXBUcmFuc2NyaXB0cyxcbiAgZ2VuZUJpblNpemUsXG4gIGdyb3VwVHJhbnNjcmlwdHMsXG4gIGdyb3VwZWRNYXJrZXJQeCxcbiAgcXVhbnRpbGVPZixcbiAgdHJhbnNjcmlwdE1hcmtlclB4LFxufSBmcm9tICcuLi8uLi8uLi9zcGF0aWFsL3RyYW5zY3JpcHQtZ3JvdXBpbmcnO1xuaW1wb3J0IHsgY2x1c3Rlck1hcmtlcnMsIG1lcmdlVHJhbnNjcmlwdFRpbGVzIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXRpbGUtbWVyZ2UnO1xuaW1wb3J0IHR5cGUgeyBQbGFuQ29udGV4dCB9IGZyb20gJy4vcGxhbi1jb250ZXh0JztcbmltcG9ydCB0eXBlIHsgVHJhbnNjcmlwdEJpbiwgVHJhbnNjcmlwdEtpbmQgfSBmcm9tICcuL3RyYW5zY3JpcHQtaG92ZXInO1xuXG4vKiogVGhlIGFsbC1nZW5lIHB5cmFtaWQncyBmaW5lc3QgYmluICgyNTAgwrVtIHNvdXJjZSB0aWxlcyAvIDEyOCkgYW5kIGRlZmF1bHQgbGV2ZWwgY291bnQsIHVzZWRcbiAqICB0byBncm91cCBhIGdlbmUgc2VsZWN0aW9uIG9uIHRoZSBzYW1lIGxhZGRlciB3aGVuIGEgZGF0YXNldCBoYXMgbm8gcHlyYW1pZC4gKi9cbmNvbnN0IFBZUkFNSURfQkFTRV9CSU5fVU0gPSAyNTAgLyAxMjg7XG5jb25zdCBQWVJBTUlEX0xFVkVMUyA9IDc7XG4vKiogVHJhbnNjcmlwdHMgZHJhd24gYXQgb25jZS4gUGFzdCB0aGlzIGEgc2NyZWVuIGlzIHNvbGlkIGNvbG91ciBhbnl3YXk7IHRoZSBsZXZlbFxuICogIHBvbGljeSBrZWVwcyBhIG5vcm1hbCB2aWV3IGZhciBiZWxvdyBpdC4gKi9cbmNvbnN0IE1BWF9UUkFOU0NSSVBUUyA9IDQwMF8wMDA7XG5jb25zdCBNQVhfVFJBTlNDUklQVF9USUxFUyA9IDM2O1xuY29uc3QgTUFYX0JJTl9USUxFUyA9IDY0O1xuLyoqIFN1bW1lZCBwZXItY2x1c3RlciBkZW5zaXR5IGdyaWRzIGtlcHQgKG9uZSBwZXIgY2x1c3RlciDDlyBiaW4gw5cgZGF0YXNldCkuICovXG5jb25zdCBERU5TSVRZX0NBQ0hFX1NJWkUgPSAyNTY7XG5cbi8qKiBBIHRyYW5zY3JpcHQgZmV0Y2ggdGhlIHBsYW5uZXIgY2FuIGtleSBiZWZvcmUgcnVubmluZy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNjcmlwdEpvYiB7XG4gIC8qKiBXaGF0IG9uZSBlbnRyeSBpcyDigJQgZGVjaWRlcyB3aGF0IGhvdmVyaW5nIGl0IHNheXMuICovXG4gIGtpbmQ6IFRyYW5zY3JpcHRLaW5kO1xuICAvKiogRm9yIGJpbnM6IHRoZWlyIHNpemUgYW5kIGdyaWQgb3JpZ2luLCBzbyBhIGhvdmVyZWQgYmluJ3Mgc3F1YXJlIGNhbiBiZSByZWNvdmVyZWQuICovXG4gIGJpbj86IFRyYW5zY3JpcHRCaW47XG4gIC8qKiBJZGVudGlmaWVzIHdoYXQgd2lsbCBiZSBkcmF3biwgc28gYW4gdW5jaGFuZ2VkIHBsYW4gaXMgYSBuby1vcC4gKi9cbiAga2V5OiBzdHJpbmc7XG4gIC8qKiBGZXRjaCBhbmQgbWVyZ2U7IGBweGAgaXMgZWFjaCBlbnRyeSdzIG1hcmtlciBkaWFtZXRlciBpbiBzY3JlZW4gcGl4ZWxzLiBBIGpvYiBtYXlcbiAgICogIHN3aXRjaCB0byBhbm90aGVyIGtpbmQgb25jZSBpdCBzZWVzIHRoZSBkYXRhIChpbmRpdmlkdWFsIOKGkiBiaW5zKTsgaXQgdGhlbiBzYXlzIHNvLiAqL1xuICBsb2FkKGN0eDogUGxhbkNvbnRleHQpOiBQcm9taXNlPFRyYW5zY3JpcHRMb2FkPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc2NyaXB0TG9hZCB7XG4gIG1lcmdlZDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlO1xuICBweDogRmxvYXQzMkFycmF5O1xuICAvKiogRm9yIGEgZ2VuZSBzZWxlY3Rpb246IGdyb3VwIGl0IG9uIHRoaXMgYmluIGxhZGRlciBvbmNlIGhpZGRlbiBnZW5lcyBhcmUgZHJvcHBlZC4gKi9cbiAgbGFkZGVyPzogeyBiYXNlQmluOiBudW1iZXI7IGxldmVsczogbnVtYmVyOyBzdGFydDogbnVtYmVyIHwgbnVsbCB9O1xuICAvKiogQWxyZWFkeSBvbmUgbWFya2VyIHBlciBjbHVzdGVyIHBlciBiaW4gKHpvb21lZCBvdXQsIGZyb20gdGhlIGRlbnNpdHkgZ3JpZHMpOiBubyBjZWxscy4gKi9cbiAgY2x1c3RlcmVkPzogeyBncm91cDogSW50MzJBcnJheTsgbmFtZXM6IHN0cmluZ1tdOyBnZW5lczogc3RyaW5nW11bXTsgYmluOiBudW1iZXI7IG9yaWdpbjogW251bWJlciwgbnVtYmVyXSB9O1xuICBraW5kPzogVHJhbnNjcmlwdEpvYlsna2luZCddO1xuICBiaW4/OiBUcmFuc2NyaXB0Sm9iWydiaW4nXTtcbn1cblxuLyoqXG4gKiBEZWNpZGVzIHdoaWNoIHRyYW5zY3JpcHRzIHRoZSAyRCBzcGF0aWFsIHZpZXcgZmV0Y2hlcywgYXQgd2hpY2ggbGV2ZWwsIGZvciB0aGUgY3VycmVudFxuICogY2FtZXJhIGFuZCBzZWxlY3Rpb246IGEge0BsaW5rIFRyYW5zY3JpcHRKb2J9IHRoYXQgY2FuIGJlIGtleWVkIGJlZm9yZSBpdCBydW5zIChzbyBhblxuICogdW5jaGFuZ2VkIHBsYW4gaXMgYSBuby1vcCkgYW5kIHRoYXQgZmV0Y2hlcyBhbmQgbWVyZ2VzIHdoZW4gcnVuLlxuICpcbiAqIFB1cmUgYXBhcnQgZnJvbSB0aGUgcG9ydCwgc28gdGhlIGxldmVsIHBvbGljeSBpcyB0ZXN0YWJsZSB3aXRob3V0IGEgdmlld2VyLiBPd25zIHRoZVxuICogY2FjaGUgb2Ygc3VtbWVkIHBlci1jbHVzdGVyIGRlbnNpdHkgZ3JpZHMgYSB6b29tZWQtb3V0IGdlbmUgc2VsZWN0aW9uIGlzIGRyYXduIGZyb20uXG4gKi9cbmV4cG9ydCBjbGFzcyBUcmFuc2NyaXB0Sm9iUGxhbm5lciB7XG4gIC8qKiBTdW1tZWQgcGVyLWNsdXN0ZXIgZGVuc2l0eSBncmlkcyAoc2VlIGRlbnNpdHlGb3IpLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGRlbnNpdHlDYWNoZSA9IG5ldyBMcnVDYWNoZTxQcm9taXNlPFNwYXRpYWxEZW5zaXR5UmFzdGVyPj4oREVOU0lUWV9DQUNIRV9TSVpFKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHBvcnQ6IFNwYXRpYWxEYXRhUG9ydCkge31cblxuICAvKipcbiAgICogVGhlIGpvYiB0aGF0IGRyYXdzIHRoZSB2aWV3J3MgdHJhbnNjcmlwdHMgYXMgbWFya2VycyAoY2lyY2xlcyBvciBpY29ucyksIG9yIG51bGwgd2hlbiB0aGVcbiAgICogdmlldyBkcmF3cyBub25lIG9yIHRoZSBwb3J0IGNhbm5vdCBzZXJ2ZSB0aGVtLlxuICAgKi9cbiAgam9iRm9yKFxuICAgIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgcmVjdDogRGF0YVJlY3QsXG4gICAgcHhQZXJVbml0OiBudW1iZXIsXG4gICk6IFRyYW5zY3JpcHRKb2IgfCBudWxsIHtcbiAgICBjb25zdCBtb2RlID0gdmlldy50cmFuc2NyaXB0TW9kZTtcbiAgICBpZiAobW9kZSAhPT0gJ2NpcmNsZXMnICYmIG1vZGUgIT09ICdnbHlwaHMnKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBnZW5lQmlucyA9IHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0R2VuZUJpbnMgJiYgZGF0YXNldC50cmFuc2NyaXB0R2VuZUJpbnM7XG4gICAgaWYgKCF0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFRpbGUgJiYgIWdlbmVCaW5zKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdmlldy50cmFuc2NyaXB0QWxsR2VuZXNcbiAgICAgID8gdGhpcy5hbGxHZW5lc0pvYihkYXRhc2V0LCB2aWV3LCByZWN0LCBweFBlclVuaXQpXG4gICAgICA6IHRoaXMuZ2VuZUpvYihkYXRhc2V0LCB2aWV3LCByZWN0LCBweFBlclVuaXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjaG9zZW4gZ2VuZXMsIGF0IHRoZSBsZXZlbCB0aGUgem9vbSBjYWxscyBmb3Ig4oCUIG9yIGNvYXJzZXIsIHdoaWxlIHRoZSBtYXJrZXJzIGluXG4gICAqIHZpZXcgd291bGQgZXhjZWVkIHRoZSBidWRnZXQuXG4gICAqL1xuICBwcml2YXRlIGdlbmVKb2IoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICByZWN0OiBEYXRhUmVjdCxcbiAgICBweFBlclVuaXQ6IG51bWJlcixcbiAgKTogVHJhbnNjcmlwdEpvYiB8IG51bGwge1xuICAgIGNvbnN0IG1ldGEgPSBkYXRhc2V0LnRyYW5zY3JpcHRUaWxlcztcbiAgICBjb25zdCBnZW5lcyA9IHZpZXcudHJhbnNjcmlwdEdlbmVzO1xuICAgIGlmICghbWV0YSB8fCAhZ2VuZXMubGVuZ3RoKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBmaXJzdCA9IHRyYW5zY3JpcHRMZXZlbEZvcihweFBlclVuaXQsIG1ldGEubGV2ZWxzKTtcbiAgICBjb25zdCBrZXlzQXQgPSAobDogbnVtYmVyKSA9PiB0aWxlc0luUmVjdChyZWN0LCBsLCBtZXRhLmxldmVscywgbWV0YS5ib3VuZHMsIE1BWF9UUkFOU0NSSVBUX1RJTEVTKTtcbiAgICBjb25zdCBxdWVyeSA9IHsgZ2VuZXMsIHF1YWxpdHk6IHZpZXcudHJhbnNjcmlwdFF1YWxpdHkgfTtcbiAgICBjb25zdCBweFBlck1pY3JvbiA9IHB4UGVyTWljcm9uT2YoZGF0YXNldCwgcHhQZXJVbml0KTtcbiAgICBjb25zdCBjbGlwID0gY2xpcFdpbmRvdyhyZWN0KTtcbiAgICAvLyBab29tZWQgb3V0LCBlYWNoIGdlbmUncyB0cmFuc2NyaXB0cyBhcmUgZ3JvdXBlZCBvbiB0aGUgYWxsLWdlbmUgcHlyYW1pZCdzIGJpbiBsYWRkZXIsXG4gICAgLy8gc28gYSBnZW5lIHNlbGVjdGlvbiByZWFkcyBsaWtlIFwiYWxsIGdlbmVzXCIgZG9lczogb25lIG1hcmtlciBwZXIgZ2VuZSBwZXIgYXJlYSwgc2l6ZWRcbiAgICAvLyBieSBob3cgbWFueSBpdCBob2xkczsgem9vbWVkIGluIGZhciBlbm91Z2gsIGV2ZXJ5IHRyYW5zY3JpcHQgaXMgaXRzIG93biBtYXJrZXIuXG4gICAgY29uc3QgbGFkZGVyID0gZGF0YXNldC50cmFuc2NyaXB0Qmlucz8ubGV2ZWxzO1xuICAgIGNvbnN0IGJhc2VCaW4gPVxuICAgICAgbGFkZGVyPy5bMF0/LmJpblNpemUgPz8gKGRhdGFzZXQubWljcm9uc1BlclVuaXQgPyBQWVJBTUlEX0JBU0VfQklOX1VNIC8gZGF0YXNldC5taWNyb25zUGVyVW5pdCA6IDApO1xuICAgIGNvbnN0IGJpbiA9IGdlbmVCaW5TaXplKHB4UGVyVW5pdCwgYmFzZUJpbiwgbGFkZGVyPy5sZW5ndGggPz8gUFlSQU1JRF9MRVZFTFMpO1xuICAgIC8vIFpvb21lZCBvdXQgdG8gYmlucyBhcyB3aWRlIGFzIHRoZSBkZW5zaXR5IGdyaWQsIGEgc2VsZWN0aW9uIGlzIGRyYXduIGZyb20gdGhlIHBlci1nZW5lXG4gICAgLy8gZGVuc2l0eSBncmlkcyDigJQgb25lIGNhY2hlZCByZXF1ZXN0IHBlciBjbHVzdGVyIOKAlCByYXRoZXIgdGhhbiAxMHgncyBjb2Fyc2UgcGVyLWdlbmVcbiAgICAvLyB0aWxlcywgd2hpY2ggdGFrZSBtaW51dGVzIGZvciBhIGZldyBodW5kcmVkIGdlbmVzLlxuICAgIC8vIFdpdGggdGhlIHB5cmFtaWQncyBwZXItZ2VuZSBsZXZlbHMsIGV2ZXJ5IHpvb20gb2YgYSBzZWxlY3Rpb24gcmVhZHMgdGhlbTogdGhlIGxldmVsIHRoZVxuICAgIC8vIHpvb20gY2FsbHMgZm9yLCBjb2Fyc2VyIHdoaWxlIHRoZSBtYXJrZXJzIHdvdWxkIGV4Y2VlZCB0aGUgbWF4LlxuICAgIC8vIEJvdGggYXJlIGJ1aWx0IGZyb20gaGlnaC1xdWFsaXR5IGNhbGxzIG9ubHk6IHdpdGggbG93LXF1YWxpdHkgY2FsbHMgaW5jbHVkZWQsIHRoZVxuICAgIC8vIHF1YWxpdHktYXdhcmUgdGlsZXMgYmVsb3cgc2VydmUgZXZlcnkgem9vbSAoYXMgbG9uZyBhcyB0aGVyZSBhcmUgdGlsZXMgdG8gc2VydmUpLlxuICAgIGNvbnN0IGhpZ2hPbmx5ID0gdmlldy50cmFuc2NyaXB0UXVhbGl0eSAhPT0gJ2FsbCcgfHwgIXRoaXMucG9ydC5nZXRUcmFuc2NyaXB0VGlsZTtcbiAgICBjb25zdCBnZW5lQmlucyA9IGRhdGFzZXQudHJhbnNjcmlwdEdlbmVCaW5zO1xuICAgIGNvbnN0IGZyb21HZW5lQmlucyA9IGhpZ2hPbmx5ICYmIGdlbmVCaW5zICYmIHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0R2VuZUJpbnM7XG4gICAgaWYgKGZyb21HZW5lQmlucyAmJiAoYmluICE9PSBudWxsIHx8ICF0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFRpbGUpKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZW5lQmluc0pvYihkYXRhc2V0LCB2aWV3LCBjbGlwLCBnZW5lQmlucywgYmluID8/IGdlbmVCaW5zLmxldmVsc1swXS5iaW5TaXplKTtcbiAgICB9XG4gICAgY29uc3QgZ3JpZCA9IGRhdGFzZXQuZGVuc2l0eT8uZ3JpZFNpemVbMF0gPz8gMDtcbiAgICBpZiAoaGlnaE9ubHkgJiYgYmluICE9PSBudWxsICYmIGdyaWQgPiAwICYmIHRoaXMucG9ydC5nZXREZW5zaXR5ICYmIGJpbiA+PSBncmlkICogMC43NSkge1xuICAgICAgcmV0dXJuIHRoaXMuY2x1c3RlckRlbnNpdHlKb2IoZGF0YXNldCwgdmlldywgY2xpcCwgcHhQZXJVbml0LCBNYXRoLm1heChiaW4sIGdyaWQpKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIGtpbmQ6ICdnZW5lcycsXG4gICAgICAvLyBUaGUgY2xpcCB3aW5kb3csIGluIHF1YXJ0ZXItdmlldyBzdGVwczogYSBwYW4gcGFzdCB0aGUgbWFyZ2luIHJlLWNsaXBzLlxuICAgICAga2V5OlxuICAgICAgICBgZ2VuZXN8JHtnZW5lcy5qb2luKCcsJyl9fCR7dmlldy50cmFuc2NyaXB0UXVhbGl0eX18JHt2aWV3LnRyYW5zY3JpcHRCdWRnZXR9fCR7YmluID8/ICdlYWNoJ318YCArXG4gICAgICAgIGAke2NsaXAua2V5fXwke2tleXNBdChmaXJzdCkubWFwKHRpbGVJZCl9YCxcbiAgICAgIGxvYWQ6IGFzeW5jIChjdHgpID0+IHtcbiAgICAgICAgLy8gVGhlIHpvb20ncyBvd24gbGV2ZWwgb25seTogb3ZlciB0aGUgYnVkZ2V0LCB0aGUgdHJhbnNjcmlwdHMgYXJlIGNvbWJpbmVkIGludG9cbiAgICAgICAgLy8gbGFyZ2VyIG1hcmtlcnMgKGdyb3VwU2VsZWN0aW9uKSwgbmV2ZXIgZmV0Y2hlZCBmcm9tIHNsb3dlciBjb2Fyc2UgbGV2ZWxzLlxuICAgICAgICBjb25zdCB0aWxlcyA9IGF3YWl0IGN0eC5mZXRjaEFsbChrZXlzQXQoZmlyc3QpLCAoaykgPT5cbiAgICAgICAgICB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFRpbGUhKGsubGV2ZWwsIGsuZ3gsIGsuZ3ksIHF1ZXJ5KSxcbiAgICAgICAgKTtcbiAgICAgICAgLy8gT25seSB3aGF0IGlzIG9uIHNjcmVlbiAoYW5kIGEgbWFyZ2luLCBzbyBhIHNtYWxsIHBhbiBuZWVkcyBub3RoaW5nIG5ldykgY291bnRzXG4gICAgICAgIC8vIGFnYWluc3QgdGhlIGJ1ZGdldCBhbmQgdGhlIGNhcDsgYSB0aWxlIHJlYWNoZXMgZmFyIHBhc3QgdGhlIHZpZXcuXG4gICAgICAgIGNvbnN0IG1lcmdlZCA9IG1lcmdlVHJhbnNjcmlwdFRpbGVzKFxuICAgICAgICAgIHRpbGVzLm1hcCgodCkgPT4gY2xpcFRyYW5zY3JpcHRzKHQsIGNsaXAuYXJvdW5kKSksXG4gICAgICAgICAgTUFYX1RSQU5TQ1JJUFRTLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBweCA9IEZsb2F0MzJBcnJheS5mcm9tKG1lcmdlZC53ZWlnaHQsICh3KSA9PlxuICAgICAgICAgIHRyYW5zY3JpcHRNYXJrZXJQeCh3LCB2aWV3LnRyYW5zY3JpcHRTY2FsZSwgcHhQZXJNaWNyb24pLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gYmFzZUJpbiA+IDBcbiAgICAgICAgICA/IHsgbWVyZ2VkLCBweCwgbGFkZGVyOiB7IGJhc2VCaW4sIGxldmVsczogbGFkZGVyPy5sZW5ndGggPz8gUFlSQU1JRF9MRVZFTFMsIHN0YXJ0OiBiaW4gfSB9XG4gICAgICAgICAgOiB7IG1lcmdlZCwgcHggfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIGdlbmUgc2VsZWN0aW9uIGZyb20gdGhlIHB5cmFtaWQncyBwZXItZ2VuZSBsZXZlbHM6IHN0YXJ0aW5nIGF0IHRoZSBsZXZlbCB3aG9zZSBiaW5zIGFyZVxuICAgKiBgc3RhcnRCaW5gLCBmZXRjaCB0aGUgdmlldydzIHRpbGVzIGZvciB0aGUgc2VsZWN0ZWQgZ2VuZXMgYW5kIHN0ZXAgdG8gYSBjb2Fyc2VyIGxldmVsIHdoaWxlXG4gICAqIG9uZSBtYXJrZXIgcGVyIGNsdXN0ZXIgcGVyIGJpbiB3b3VsZCBleGNlZWQgdGhlIG1heC4gSGlkZGVuIGdlbmVzIGFyZSBmZXRjaGVkIHRvbyAodGhlaXJcbiAgICogY291bnRzIGluIHZpZXcgc3RpbGwgc2hvdykgYW5kIGRyb3BwZWQgYmVmb3JlIGRyYXdpbmc7IGdyb3VwaW5nIGJ5IGNsdXN0ZXIgaGFwcGVucyB0aGVyZS5cbiAgICovXG4gIHByaXZhdGUgZ2VuZUJpbnNKb2IoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICBjbGlwOiBDbGlwV2luZG93LFxuICAgIG1ldGE6IE5vbk51bGxhYmxlPFNwYXRpYWxEYXRhc2V0Wyd0cmFuc2NyaXB0R2VuZUJpbnMnXT4sXG4gICAgc3RhcnRCaW46IG51bWJlcixcbiAgKTogVHJhbnNjcmlwdEpvYiB7XG4gICAgY29uc3QgZ2VuZXMgPSB2aWV3LnRyYW5zY3JpcHRHZW5lcztcbiAgICBjb25zdCBsZXZlbHMgPSBtZXRhLmxldmVscztcbiAgICBsZXQgZmlyc3QgPSBsZXZlbHMuZmluZEluZGV4KChsKSA9PiBsLmJpblNpemUgPj0gc3RhcnRCaW4gKiAwLjk5OSk7XG4gICAgaWYgKGZpcnN0IDwgMCkgZmlyc3QgPSBsZXZlbHMubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBidWRnZXQgPSBNYXRoLm1heCgxLCB2aWV3LnRyYW5zY3JpcHRCdWRnZXQpO1xuICAgIGNvbnN0IGhpZGRlbiA9IG5ldyBTZXQodmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMpO1xuICAgIGNvbnN0IGNsdXN0ZXJzID0gdGhpcy5zZWxlY3Rpb25DbHVzdGVycyh2aWV3KTtcbiAgICBjb25zdCBjbHVzdGVyT2YgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyPigpO1xuICAgIGNsdXN0ZXJzLmZvckVhY2goKGMsIGNpKSA9PiBjLmdlbmVzLmZvckVhY2goKGcpID0+IGNsdXN0ZXJPZi5zZXQoZ2VuZXMuaW5kZXhPZihnKSwgY2kpKSk7XG4gICAgY29uc3Qga2V5c0F0ID0gKG06IG51bWJlcikgPT5cbiAgICAgIHRpbGVzSW5SZWN0RnJvbShcbiAgICAgICAgbWV0YS5vcmlnaW4sXG4gICAgICAgIGNsaXAuYXJvdW5kLFxuICAgICAgICBtLFxuICAgICAgICBsZXZlbHMubWFwKChsKSA9PiAoeyB0aWxlU2l6ZTogbC50aWxlU2l6ZSB9KSksXG4gICAgICAgIG51bGwsXG4gICAgICAgIE1BWF9CSU5fVElMRVMsXG4gICAgICApO1xuICAgIHJldHVybiB7XG4gICAgICBraW5kOiAnZ2VuZXMnLFxuICAgICAga2V5OlxuICAgICAgICBgZ2VuZS1iaW5zfCR7Z2VuZXMuam9pbignLCcpfXwke2J1ZGdldH18JHtmaXJzdH18JHtKU09OLnN0cmluZ2lmeSh2aWV3LnRyYW5zY3JpcHRHZW5lR3JvdXBzKX18YCArIGNsaXAua2V5LFxuICAgICAgbG9hZDogYXN5bmMgKGN0eCkgPT4ge1xuICAgICAgICBsZXQgbSA9IGZpcnN0O1xuICAgICAgICBmb3IgKDs7KSB7XG4gICAgICAgICAgY29uc3QgdGlsZXMgPSBhd2FpdCBjdHguZmV0Y2hBbGwoa2V5c0F0KG0pLCAoaykgPT5cbiAgICAgICAgICAgIHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0R2VuZUJpbnMhKGsubGV2ZWwsIGsuZ3gsIGsuZ3ksIGdlbmVzKSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IGNsaXBwZWQgPSB0aWxlcy5tYXAoKHQpID0+IGNsaXBUcmFuc2NyaXB0cyh0LCBjbGlwLmFyb3VuZCkpO1xuICAgICAgICAgIC8vIFBhc3QgdGhlIGNhcCBhIG1lcmdlIHdvdWxkIGRyb3Agd2hvbGUgZ2VuZXMgKHRoZSB0YWlsIG9mIGV2ZXJ5IHRpbGUpOiBnbyBjb2Fyc2VyLlxuICAgICAgICAgIGlmIChjbGlwcGVkLnJlZHVjZSgobiwgdCkgPT4gbiArIHQuY291bnQsIDApID4gTUFYX1RSQU5TQ1JJUFRTICYmIG0gPCBsZXZlbHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgbSsrO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IG1lcmdlZCA9IG1lcmdlVHJhbnNjcmlwdFRpbGVzKGNsaXBwZWQsIE1BWF9UUkFOU0NSSVBUUyk7XG4gICAgICAgICAgLy8gTWFya2VycyB0aGlzIGxldmVsIHdvdWxkIGRyYXc6IG9uZSBwZXIgKHZpc2libGUgY2x1c3RlciwgYmluKS5cbiAgICAgICAgICBjb25zdCBzZWVuID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgICAgICAgY29uc3QgYmluID0gbGV2ZWxzW21dLmJpblNpemU7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtZXJnZWQuY291bnQ7IGkrKykge1xuICAgICAgICAgICAgaWYgKGhpZGRlbi5oYXMoZ2VuZXNbbWVyZ2VkLmdlbmVbaV1dKSkgY29udGludWU7XG4gICAgICAgICAgICBjb25zdCBjID0gY2x1c3Rlck9mLmdldChtZXJnZWQuZ2VuZVtpXSk7XG4gICAgICAgICAgICBpZiAoYyA9PT0gdW5kZWZpbmVkKSBjb250aW51ZTtcbiAgICAgICAgICAgIHNlZW4uYWRkKGAke2N9fCR7TWF0aC5mbG9vcihtZXJnZWQueFtpXSAvIGJpbil9fCR7TWF0aC5mbG9vcihtZXJnZWQueVtpXSAvIGJpbil9YCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzZWVuLnNpemUgPD0gYnVkZ2V0IHx8IG0gPj0gbGV2ZWxzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHJldHVybiB7IG1lcmdlZCwgcHg6IG5ldyBGbG9hdDMyQXJyYXkobWVyZ2VkLmNvdW50KSwgbGFkZGVyOiB7IGJhc2VCaW46IGJpbiwgbGV2ZWxzOiAxLCBzdGFydDogYmluIH0gfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbSsrO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKiogVGhlIHNlbGVjdGlvbidzIGNsdXN0ZXJzOiBlYWNoIGdlbmUtdHJlZSBncm91cCdzIHZpc2libGUgZ2VuZXMsIHRoZW4gZWFjaCB1bmdyb3VwZWQgZ2VuZS4gKi9cbiAgcHJpdmF0ZSBzZWxlY3Rpb25DbHVzdGVycyh2aWV3OiBTcGF0aWFsVmlld1N0YXRlKTogeyBuYW1lOiBzdHJpbmc7IGdlbmVzOiBzdHJpbmdbXTsgc2xvdDogbnVtYmVyIH1bXSB7XG4gICAgY29uc3QgaGlkZGVuID0gbmV3IFNldCh2aWV3LnRyYW5zY3JpcHRIaWRkZW5HZW5lcyk7XG4gICAgY29uc3Qgc2xvdHMgPSBuZXcgTWFwKHZpZXcudHJhbnNjcmlwdEdlbmVzLm1hcCgoZywgaSkgPT4gW2csIGldKSk7XG4gICAgY29uc3QgdGFrZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCBvdXQ6IHsgbmFtZTogc3RyaW5nOyBnZW5lczogc3RyaW5nW107IHNsb3Q6IG51bWJlciB9W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGcgb2Ygdmlldy50cmFuc2NyaXB0R2VuZUdyb3Vwcykge1xuICAgICAgY29uc3QgZ2VuZXMgPSBnLmdlbmVzLmZpbHRlcigoeCkgPT4gc2xvdHMuaGFzKHgpICYmICFoaWRkZW4uaGFzKHgpICYmICF0YWtlbi5oYXMoeCkpO1xuICAgICAgZ2VuZXMuZm9yRWFjaCgoeCkgPT4gdGFrZW4uYWRkKHgpKTtcbiAgICAgIGlmIChnZW5lcy5sZW5ndGgpIG91dC5wdXNoKHsgbmFtZTogZy5uYW1lLCBnZW5lcywgc2xvdDogc2xvdHMuZ2V0KGdlbmVzWzBdKSEgfSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZ2VuZSBvZiB2aWV3LnRyYW5zY3JpcHRHZW5lcykge1xuICAgICAgaWYgKCF0YWtlbi5oYXMoZ2VuZSkgJiYgIWhpZGRlbi5oYXMoZ2VuZSkpIG91dC5wdXNoKHsgbmFtZTogZ2VuZSwgZ2VuZXM6IFtnZW5lXSwgc2xvdDogc2xvdHMuZ2V0KGdlbmUpISB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXItZ2VuZSBkZW5zaXR5IGdyaWRzIHN1bW1lZCBmb3IgYGdlbmVzYCwgY2FjaGVkIChhIGNsdXN0ZXIgaXMgYXNrZWQgZm9yIG9uY2UgcGVyIGJpbikuXG4gICAqIEtleWVkIGJ5IGRhdGFzZXQgdG9vOiB0aGlzIG1hbmFnZXIgb3V0bGl2ZXMgYSBkYXRhc2V0LCBhbmQgYW5vdGhlciBtYXkgc2hhcmUgZ2VuZSBuYW1lcy5cbiAgICogTGVhc3QtcmVjZW50bHktVVNFRCBldmljdGlvbiwgc28gdGhlIGNsdXN0ZXJzIGluIHZpZXcgc3RheSBjYWNoZWQ7IGEgZmFpbGVkIHJlcXVlc3QgaXNcbiAgICogZHJvcHBlZCBzbyB0aGUgbmV4dCBwbGFuIGFza3MgYWdhaW4uXG4gICAqL1xuICBwcml2YXRlIGRlbnNpdHlGb3IoZGF0YXNldDogc3RyaW5nLCBnZW5lczogc3RyaW5nW10sIGJpbjogbnVtYmVyKTogUHJvbWlzZTxTcGF0aWFsRGVuc2l0eVJhc3Rlcj4ge1xuICAgIGNvbnN0IGtleSA9IGAke2RhdGFzZXR9fCR7YmlufXwke2dlbmVzLmpvaW4oJywnKX1gO1xuICAgIGxldCBwID0gdGhpcy5kZW5zaXR5Q2FjaGUuZ2V0KGtleSk7XG4gICAgaWYgKCFwKSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gdGhpcy5wb3J0LmdldERlbnNpdHkhKGdlbmVzLCBiaW4pO1xuICAgICAgcmVxdWVzdC5jYXRjaCgoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmRlbnNpdHlDYWNoZS5nZXQoa2V5KSA9PT0gcmVxdWVzdCkgdGhpcy5kZW5zaXR5Q2FjaGUuZGVsZXRlKGtleSk7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuZGVuc2l0eUNhY2hlLnNldChrZXksIHJlcXVlc3QpO1xuICAgICAgcCA9IHJlcXVlc3Q7XG4gICAgfVxuICAgIHJldHVybiBwO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgZ2VuZSBzZWxlY3Rpb24gem9vbWVkIG91dDogb25lIG1hcmtlciBwZXIgY2x1c3RlciBwZXIgYmluLCBmcm9tIHRoZSBwZXItZ2VuZSBkZW5zaXR5XG4gICAqIGdyaWRzLiBUaGUgYmluIHN0YXJ0cyB3aGVyZSBtYXJrZXJzIGFyZSAxNCBweCBhcGFydCBhbmQgZG91YmxlcyB1bnRpbCB0aGUgbWFya2VycyBmaXQgdGhlXG4gICAqIG1heDsgZWFjaCBtYXJrZXIgc2l0cyBhdCB0aGUgY291bnQtd2VpZ2h0ZWQgY2VudHJlIG9mIHRoZSBmaW5lciBncmlkIGluc2lkZSBpdCwgc28gbWFya2Vyc1xuICAgKiBmb2xsb3cgdGhlIHRpc3N1ZSByYXRoZXIgdGhhbiBhIGxhdHRpY2UuXG4gICAqL1xuICBwcml2YXRlIGNsdXN0ZXJEZW5zaXR5Sm9iKFxuICAgIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgY2xpcDogQ2xpcFdpbmRvdyxcbiAgICBweFBlclVuaXQ6IG51bWJlcixcbiAgICBzdGFydEJpbjogbnVtYmVyLFxuICApOiBUcmFuc2NyaXB0Sm9iIHtcbiAgICBjb25zdCBncmlkID0gZGF0YXNldC5kZW5zaXR5IS5ncmlkU2l6ZVswXTtcbiAgICBjb25zdCBjbHVzdGVycyA9IHRoaXMuc2VsZWN0aW9uQ2x1c3RlcnModmlldyk7XG4gICAgbGV0IGZpcnN0ID0gZ3JpZDtcbiAgICB3aGlsZSAoZmlyc3QgPCBzdGFydEJpbiAqIDAuOTk5KSBmaXJzdCAqPSAyO1xuICAgIGNvbnN0IGJ1ZGdldCA9IE1hdGgubWF4KDEsIHZpZXcudHJhbnNjcmlwdEJ1ZGdldCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGtpbmQ6ICdnZW5lcycsXG4gICAgICBrZXk6XG4gICAgICAgIGBjbHVzdGVyc3wke2NsdXN0ZXJzLm1hcCgoYykgPT4gYCR7Yy5uYW1lfToke2MuZ2VuZXMuam9pbignKycpfWApLmpvaW4oJzsnKX18JHtidWRnZXR9fCR7Zmlyc3R9fGAgK1xuICAgICAgICBjbGlwLmtleSxcbiAgICAgIGxvYWQ6IGFzeW5jICgpID0+IHtcbiAgICAgICAgbGV0IGJpbiA9IGZpcnN0O1xuICAgICAgICBmb3IgKDs7KSB7XG4gICAgICAgICAgLy8gVGhlIGZpbmVyIGdyaWQgZ2l2ZXMgZWFjaCBtYXJrZXIgaXRzIGNlbnRyZTsgdGhlIHNlcnZlciBiaW5zIDEsIDIsIDQgb3IgOCBjZWxscy5cbiAgICAgICAgICBjb25zdCBmaW5lID0gTWF0aC5taW4oYmluID49IGdyaWQgKiAyID8gYmluIC8gMiA6IGJpbiwgZ3JpZCAqIDgpO1xuICAgICAgICAgIGNvbnN0IHJhc3RlcnMgPSBhd2FpdCBQcm9taXNlLmFsbChjbHVzdGVycy5tYXAoKGMpID0+IHRoaXMuZGVuc2l0eUZvcihkYXRhc2V0LmlkLCBjLmdlbmVzLCBmaW5lKSkpO1xuICAgICAgICAgIGNvbnN0IG91dCA9IGNsdXN0ZXJNYXJrZXJzKFxuICAgICAgICAgICAgcmFzdGVycyxcbiAgICAgICAgICAgIGNsdXN0ZXJzLm1hcCgoYykgPT4gYy5zbG90KSxcbiAgICAgICAgICAgIGJpbixcbiAgICAgICAgICAgIGNsaXAuYXJvdW5kLFxuICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKG91dC50aWxlLmNvdW50IDw9IGJ1ZGdldCB8fCBiaW4gPj0gZ3JpZCAqIDIgKiogMTIpIHtcbiAgICAgICAgICAgIGNvbnN0IHB4ID0gZ3JvdXBlZFNpemVzKG91dC50aWxlLndlaWdodCwgYmluICogcHhQZXJVbml0LCB2aWV3LnRyYW5zY3JpcHRTY2FsZSk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBtZXJnZWQ6IG91dC50aWxlLFxuICAgICAgICAgICAgICBweCxcbiAgICAgICAgICAgICAga2luZDogJ2dlbmVzJyxcbiAgICAgICAgICAgICAgY2x1c3RlcmVkOiB7XG4gICAgICAgICAgICAgICAgZ3JvdXA6IG91dC5ncm91cCxcbiAgICAgICAgICAgICAgICBuYW1lczogY2x1c3RlcnMubWFwKChjKSA9PiBjLm5hbWUpLFxuICAgICAgICAgICAgICAgIGdlbmVzOiBjbHVzdGVycy5tYXAoKGMpID0+IGMuZ2VuZXMpLFxuICAgICAgICAgICAgICAgIGJpbixcbiAgICAgICAgICAgICAgICBvcmlnaW46IHJhc3RlcnNbMF0/Lm1ldGEub3JpZ2luID8/IFswLCAwXSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICAgIGJpbiAqPSAyO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXZlcnkgZ2VuZTogdGhlIHRyYW5zY3JpcHRzIHRoZW1zZWx2ZXMgb25jZSB0aGV5IGZpdCB0aGUgYnVkZ2V0LCBlbHNlIGJpbnMgb2YgdGhlXG4gICAqIGFsbC1nZW5lIHB5cmFtaWQgc2l6ZWQgYnkgaG93IG1hbnkgdHJhbnNjcmlwdHMgZWFjaCBob2xkcy5cbiAgICovXG4gIHByaXZhdGUgYWxsR2VuZXNKb2IoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICByZWN0OiBEYXRhUmVjdCxcbiAgICBweFBlclVuaXQ6IG51bWJlcixcbiAgKTogVHJhbnNjcmlwdEpvYiB8IG51bGwge1xuICAgIGNvbnN0IGJpbnMgPSBkYXRhc2V0LnRyYW5zY3JpcHRCaW5zO1xuICAgIGNvbnN0IHRpbGVzID0gZGF0YXNldC50cmFuc2NyaXB0VGlsZXM7XG4gICAgY29uc3QgYm91bmRzID0gYmlucz8uYm91bmRzID8/IHRpbGVzPy5ib3VuZHM7XG4gICAgaWYgKCFib3VuZHMpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IHBsYW4gPSBhbGxHZW5lc1BsYW4oe1xuICAgICAgcmVjdCxcbiAgICAgIGJvdW5kcyxcbiAgICAgIHB4UGVyVW5pdCxcbiAgICAgIGJ1ZGdldDogdmlldy50cmFuc2NyaXB0QnVkZ2V0LFxuICAgICAgdG90YWw6IGJpbnM/LmNvdW50ID8/IHRpbGVzPy5jb3VudCA/PyAwLFxuICAgICAgbGV2ZWxzOiBiaW5zICYmIHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0QmlucyA/IGJpbnMubGV2ZWxzIDogW10sXG4gICAgICBjYW5JbmRpdmlkdWFsOiAhIXRpbGVzLFxuICAgIH0pO1xuXG4gICAgaWYgKHBsYW4ua2luZCA9PT0gJ2luZGl2aWR1YWwnICYmIHRpbGVzKSB7XG4gICAgICBjb25zdCBrZXlzID0gdGlsZXNJblJlY3QocmVjdCwgMCwgdGlsZXMubGV2ZWxzLCB0aWxlcy5ib3VuZHMsIE1BWF9UUkFOU0NSSVBUX1RJTEVTKTtcbiAgICAgIC8vIEVhY2ggdGlsZSBjbGlwcGVkIHRvIHRoZSB2aWV3LCByb3VuZGVkIG91dHdhcmQgdG8gMTAgdW5pdHMgc28gc21hbGwgcGFucyBoaXQgY2FjaGUuXG4gICAgICBjb25zdCByMTAgPSAodjogbnVtYmVyLCB1cDogYm9vbGVhbikgPT4gKHVwID8gTWF0aC5jZWlsKHYgLyAxMCkgOiBNYXRoLmZsb29yKHYgLyAxMCkpICogMTA7XG4gICAgICBjb25zdCBzaXplID0gdGlsZXMubGV2ZWxzWzBdLnRpbGVTaXplO1xuICAgICAgY29uc3QgYm94ZXMgPSBrZXlzLm1hcCgoayk6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID0+IFtcbiAgICAgICAgTWF0aC5tYXgoay5neCAqIHNpemUsIHIxMChyZWN0LngwLCBmYWxzZSkpLFxuICAgICAgICBNYXRoLm1heChrLmd5ICogc2l6ZSwgcjEwKHJlY3QueTAsIGZhbHNlKSksXG4gICAgICAgIE1hdGgubWluKChrLmd4ICsgMSkgKiBzaXplLCByMTAocmVjdC54MSwgdHJ1ZSkpLFxuICAgICAgICBNYXRoLm1pbigoay5neSArIDEpICogc2l6ZSwgcjEwKHJlY3QueTEsIHRydWUpKSxcbiAgICAgIF0pO1xuICAgICAgY29uc3QgcHhQZXJNaWNyb24gPSBweFBlck1pY3Jvbk9mKGRhdGFzZXQsIHB4UGVyVW5pdCk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBraW5kOiAnaW5kaXZpZHVhbCcsXG4gICAgICAgIGtleTogYGFsbHxpbmRpdmlkdWFsfCR7dmlldy50cmFuc2NyaXB0QnVkZ2V0fXwke2JveGVzLm1hcCgoYikgPT4gYi5qb2luKCcsJykpLmpvaW4oJzsnKX1gLFxuICAgICAgICBsb2FkOiBhc3luYyAoY3R4KSA9PiB7XG4gICAgICAgICAgY29uc3QgZ290ID0gYXdhaXQgY3R4LmZldGNoQWxsKFxuICAgICAgICAgICAga2V5cy5tYXAoKGssIGkpID0+ICh7IC4uLmssIGJveDogYm94ZXNbaV0gfSkpLFxuICAgICAgICAgICAgKGspID0+IHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0VGlsZSEoMCwgay5neCwgay5neSwgeyBnZW5lczogW0FMTF9HRU5FU10sIGJveDogay5ib3ggfSksXG4gICAgICAgICAgKTtcbiAgICAgICAgICAvLyBUaGUgcGxhbiBlc3RpbWF0ZWQgdGhlIHZpZXcgZnJvbSB0aGUgZGF0YXNldCdzIGF2ZXJhZ2UgZGVuc2l0eTsgZXhwcmVzc2lvbiBpc1xuICAgICAgICAgIC8vIHVuZXZlbiwgc28gYSBkZW5zZSB2aWV3IGNhbiBob2xkIGZhciBtb3JlLiBSYXRoZXIgdGhhbiBjdXQgdGhlIGV4Y2VzcyBvZmYsIHNob3dcbiAgICAgICAgICAvLyBpdCBncm91cGVkIOKAlCB0aGUgYmluIGxldmVsIHRoZSBwbGFubmVyIHdvdWxkIHBpY2sgaWYgaXQgaGFkIGtub3duLlxuICAgICAgICAgIGNvbnN0IGNhcCA9IE1hdGgubWF4KHZpZXcudHJhbnNjcmlwdEJ1ZGdldCAqIDEuNSwgMSk7XG4gICAgICAgICAgY29uc3QgbG9hZGVkID0gZ290LnJlZHVjZSgobiwgdCkgPT4gbiArIHQuY291bnQsIDApO1xuICAgICAgICAgIGlmIChsb2FkZWQgPiBjYXAgJiYgYmlucyAmJiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdEJpbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGZhbGxiYWNrID0gYWxsR2VuZXNQbGFuKHtcbiAgICAgICAgICAgICAgcmVjdCxcbiAgICAgICAgICAgICAgYm91bmRzLFxuICAgICAgICAgICAgICBweFBlclVuaXQsXG4gICAgICAgICAgICAgIGJ1ZGdldDogdmlldy50cmFuc2NyaXB0QnVkZ2V0LFxuICAgICAgICAgICAgICB0b3RhbDogYmlucy5jb3VudCxcbiAgICAgICAgICAgICAgbGV2ZWxzOiBiaW5zLmxldmVscyxcbiAgICAgICAgICAgICAgY2FuSW5kaXZpZHVhbDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChmYWxsYmFjay5raW5kID09PSAnYmlucycpIHtcbiAgICAgICAgICAgICAgY29uc3Qgam9iID0gdGhpcy5iaW5zSm9iKHZpZXcsIHJlY3QsIHB4UGVyVW5pdCwgYm91bmRzLCBiaW5zLCBmYWxsYmFjay5sZXZlbCk7XG4gICAgICAgICAgICAgIHJldHVybiB7IC4uLihhd2FpdCBqb2IubG9hZChjdHgpKSwga2luZDogam9iLmtpbmQsIGJpbjogam9iLmJpbiB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBtZXJnZWQgPSBtZXJnZVRyYW5zY3JpcHRUaWxlcyhnb3QsIGNhcCk7XG4gICAgICAgICAgLy8gT25lIHRyYW5zY3JpcHQgcGVyIGVudHJ5OiBldmVyeSBtYXJrZXIgaXMgdGhlIHNhbWUgc2l6ZS5cbiAgICAgICAgICBjb25zdCBweCA9IG5ldyBGbG9hdDMyQXJyYXkobWVyZ2VkLmNvdW50KS5maWxsKHRyYW5zY3JpcHRNYXJrZXJQeCgxLCB2aWV3LnRyYW5zY3JpcHRTY2FsZSwgcHhQZXJNaWNyb24pKTtcbiAgICAgICAgICByZXR1cm4geyBtZXJnZWQsIHB4IH07XG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChwbGFuLmtpbmQgPT09ICdiaW5zJyAmJiBiaW5zICYmIHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0Qmlucykge1xuICAgICAgcmV0dXJuIHRoaXMuYmluc0pvYih2aWV3LCByZWN0LCBweFBlclVuaXQsIGJvdW5kcywgYmlucywgcGxhbi5sZXZlbCk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIEJpbnMgb2YgdGhlIGFsbC1nZW5lIHB5cmFtaWQgYXQgYGxldmVsYCwgc2l6ZWQgYnkgaG93IG1hbnkgdHJhbnNjcmlwdHMgZWFjaCBob2xkcy4gKi9cbiAgcHJpdmF0ZSBiaW5zSm9iKFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgcmVjdDogRGF0YVJlY3QsXG4gICAgcHhQZXJVbml0OiBudW1iZXIsXG4gICAgYm91bmRzOiBTcGF0aWFsQm91bmRzLFxuICAgIGJpbnM6IE5vbk51bGxhYmxlPFNwYXRpYWxEYXRhc2V0Wyd0cmFuc2NyaXB0QmlucyddPixcbiAgICBsZXZlbDogbnVtYmVyLFxuICApOiBUcmFuc2NyaXB0Sm9iIHtcbiAgICBjb25zdCBsdiA9IGJpbnMubGV2ZWxzW2xldmVsXTtcbiAgICBjb25zdCBrZXlzID0gdGlsZXNJblJlY3RGcm9tKFxuICAgICAgYmlucy5vcmlnaW4sXG4gICAgICByZWN0LFxuICAgICAgbGV2ZWwsXG4gICAgICBiaW5zLmxldmVscy5tYXAoKGwpID0+ICh7IHRpbGVTaXplOiBsLnRpbGVTaXplIH0pKSxcbiAgICAgIGJvdW5kcyxcbiAgICAgIE1BWF9CSU5fVElMRVMsXG4gICAgKTtcbiAgICByZXR1cm4ge1xuICAgICAga2luZDogJ2JpbnMnLFxuICAgICAgYmluOiB7IHNpemU6IGx2LmJpblNpemUsIG9yaWdpbjogYmlucy5vcmlnaW4gfSxcbiAgICAgIGtleTogYGFsbHxiaW5zfCR7bGV2ZWx9fCR7dmlldy50cmFuc2NyaXB0QnVkZ2V0fXwke2tleXMubWFwKHRpbGVJZCl9YCxcbiAgICAgIGxvYWQ6IGFzeW5jIChjdHgpID0+IHtcbiAgICAgICAgY29uc3QgZ290ID0gYXdhaXQgY3R4LmZldGNoQWxsKGtleXMsIChrKSA9PiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdEJpbnMhKGsubGV2ZWwsIGsuZ3gsIGsuZ3kpKTtcbiAgICAgICAgY29uc3QgbWVyZ2VkID0gbWVyZ2VUcmFuc2NyaXB0VGlsZXMoZ290LCBNYXRoLm1heCh2aWV3LnRyYW5zY3JpcHRCdWRnZXQgKiAxLjUsIDEpKTtcbiAgICAgICAgcmV0dXJuIHsgbWVyZ2VkLCBweDogZ3JvdXBlZFNpemVzKG1lcmdlZC53ZWlnaHQsIGx2LmJpblNpemUgKiBweFBlclVuaXQsIHZpZXcudHJhbnNjcmlwdFNjYWxlKSB9O1xuICAgICAgfSxcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogR3JvdXAgYSBnZW5lIHNlbGVjdGlvbiBmb3IgdGhlIHpvb206IG9uZSBtYXJrZXIgcGVyIGdlbmUtdHJlZSBjbHVzdGVyIChhIGdlbmUgaW4gbm9cbiAqIGNsdXN0ZXIgaXMgaXRzIG93bikgcGVyIGJpbiBvZiB0aGUgcHlyYW1pZCBsYWRkZXIsIHN0YXJ0aW5nIGF0IHRoZSBmaW5lc3QgYmluIHdob3NlXG4gKiBtYXJrZXJzIGFyZSAxNCBweCBhcGFydCBhbmQgc3RlcHBpbmcgdXAgd2hpbGUgdGhlIG1hcmtlcnMgd291bGQgZXhjZWVkIHRoZSBidWRnZXQuXG4gKiBOdWxsIHRvIGRyYXcgZXZlcnkgdHJhbnNjcmlwdDogem9vbWVkIGluLCB3aXRoIHRoZSBzZWxlY3Rpb24gd2l0aGluIHRoZSBidWRnZXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBncm91cFNlbGVjdGlvbihcbiAgdDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlLFxuICB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLFxuICBsYWRkZXI6IE5vbk51bGxhYmxlPFRyYW5zY3JpcHRMb2FkWydsYWRkZXInXT4sXG4gIHB4UGVyVW5pdDogbnVtYmVyLFxuKTogeyBtZXJnZWQ6IFNwYXRpYWxUcmFuc2NyaXB0VGlsZTsgcHg6IEZsb2F0MzJBcnJheTsgYmluOiBudW1iZXI7IGdyb3VwOiBJbnQzMkFycmF5OyBuYW1lczogc3RyaW5nW10gfSB8IG51bGwge1xuICBjb25zdCBidWRnZXQgPSBNYXRoLm1heCgxLCB2aWV3LnRyYW5zY3JpcHRCdWRnZXQpO1xuICBjb25zdCBnZW5lcyA9IHZpZXcudHJhbnNjcmlwdEdlbmVzO1xuICBjb25zdCBncm91cHMgPSB2aWV3LnRyYW5zY3JpcHRHZW5lR3JvdXBzO1xuICBjb25zdCBuYW1lcyA9IFsuLi5ncm91cHMubWFwKChnKSA9PiBnLm5hbWUpLCAuLi5nZW5lc107XG4gIGNvbnN0IGNsdXN0ZXJPZiA9IGdlbmVzLm1hcCgoZ2VuZSwgc2xvdCkgPT4ge1xuICAgIGNvbnN0IGcgPSBncm91cHMuZmluZEluZGV4KCh4KSA9PiB4LmdlbmVzLmluY2x1ZGVzKGdlbmUpKTtcbiAgICByZXR1cm4gZyA+PSAwID8gZyA6IGdyb3Vwcy5sZW5ndGggKyBzbG90O1xuICB9KTtcbiAgY29uc3Qga2V5T2YgPSAoc2xvdDogbnVtYmVyKSA9PiBjbHVzdGVyT2Zbc2xvdF0gPz8gZ3JvdXBzLmxlbmd0aCArIHNsb3Q7XG4gIGxldCBiaW4gPSBsYWRkZXIuc3RhcnQ7XG4gIGlmIChiaW4gPT09IG51bGwpIHtcbiAgICAvLyBFdmVyeSB0cmFuc2NyaXB0LCBpZiB0aGV5IGZpdCB0aGUgbWF4IGFuZCBub25lIHdhcyBjdXQgb2ZmIGF0IHRoZSBjYXAuXG4gICAgaWYgKHQuY291bnQgPD0gYnVkZ2V0ICYmIHQuY291bnQgPCBNQVhfVFJBTlNDUklQVFMpIHJldHVybiBudWxsO1xuICAgIGJpbiA9IGxhZGRlci5iYXNlQmluO1xuICB9XG4gIGNvbnN0IHRvcCA9IGxhZGRlci5iYXNlQmluICogMiAqKiAobGFkZGVyLmxldmVscyAtIDEpO1xuICBsZXQgZ3JvdXBlZCA9IGdyb3VwVHJhbnNjcmlwdHModCwgYmluLCBrZXlPZik7XG4gIC8vIE92ZXIgdGhlIG1heDogY29tYmluZSBpbnRvIGxhcmdlciBtYXJrZXJzLCBhIGxldmVsIGF0IGEgdGltZS5cbiAgd2hpbGUgKGdyb3VwZWQudGlsZS5jb3VudCA+IGJ1ZGdldCAmJiBiaW4gPCB0b3ApIHtcbiAgICBiaW4gKj0gMjtcbiAgICBncm91cGVkID0gZ3JvdXBUcmFuc2NyaXB0cyh0LCBiaW4sIGtleU9mKTtcbiAgfVxuICBjb25zdCBweCA9IGdyb3VwZWRTaXplcyhncm91cGVkLnRpbGUud2VpZ2h0LCBiaW4gKiBweFBlclVuaXQsIHZpZXcudHJhbnNjcmlwdFNjYWxlKTtcbiAgcmV0dXJuIHsgbWVyZ2VkOiBncm91cGVkLnRpbGUsIHB4LCBiaW4sIGdyb3VwOiBncm91cGVkLmdyb3VwLCBuYW1lcyB9O1xufVxuXG4vKiogU2NyZWVuIHNpemVzIG9mIGdyb3VwZWQgbWFya2VyczogYnkgd2VpZ2h0IGFnYWluc3QgdGhlIDk1dGgtcGVyY2VudGlsZSB3ZWlnaHQsIG92ZXIgYGJpblB4YC4gKi9cbmZ1bmN0aW9uIGdyb3VwZWRTaXplcyh3ZWlnaHQ6IFVpbnQzMkFycmF5LCBiaW5QeDogbnVtYmVyLCBzY2FsZTogbnVtYmVyKTogRmxvYXQzMkFycmF5IHtcbiAgY29uc3QgcmVmQ291bnQgPSBxdWFudGlsZU9mKHdlaWdodCwgMC45NSk7XG4gIHJldHVybiBGbG9hdDMyQXJyYXkuZnJvbSh3ZWlnaHQsICh3KSA9PiBncm91cGVkTWFya2VyUHgodywgcmVmQ291bnQsIGJpblB4LCBzY2FsZSkpO1xufVxuXG4vKiogV2hhdCBhIGdlbmUgc2VsZWN0aW9uJ3Mgam9iIGZldGNoZXMgYW5kIGNsaXBzIHRvOiB0aGUgdmlldyBhbmQgYSBxdWFydGVyLXZpZXcgbWFyZ2luIGVhY2ggc2lkZSxcbiAqICBzbyBhIHNtYWxsIHBhbiBuZWVkcyBub3RoaW5nIG5ldy4gKi9cbmludGVyZmFjZSBDbGlwV2luZG93IHtcbiAgYXJvdW5kOiBEYXRhUmVjdDtcbiAgLyoqIFRoZSB3aW5kb3cgaW4gcXVhcnRlci12aWV3IHN0ZXBzLCBmb3IgYSBqb2Iga2V5OiBhIHBhbiBwYXN0IHRoZSBtYXJnaW4gcmUtY2xpcHMuICovXG4gIGtleTogc3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjbGlwV2luZG93KHJlY3Q6IERhdGFSZWN0KTogQ2xpcFdpbmRvdyB7XG4gIGNvbnN0IG14ID0gKHJlY3QueDEgLSByZWN0LngwKSAqIDAuMjU7XG4gIGNvbnN0IG15ID0gKHJlY3QueTEgLSByZWN0LnkwKSAqIDAuMjU7XG4gIHJldHVybiB7XG4gICAgYXJvdW5kOiB7IHgwOiByZWN0LngwIC0gbXgsIHkwOiByZWN0LnkwIC0gbXksIHgxOiByZWN0LngxICsgbXgsIHkxOiByZWN0LnkxICsgbXkgfSxcbiAgICBrZXk6IGAke01hdGguZmxvb3IocmVjdC54MCAvIChteCB8fCAxKSl9LCR7TWF0aC5mbG9vcihyZWN0LnkwIC8gKG15IHx8IDEpKX1gLFxuICB9O1xufVxuXG4vKiogUGh5c2ljYWwgbWFya2VyIHNpemUgbmVlZHMgwrVtOyB1bmRlZmluZWQgd2hlbiB0aGUgZGF0YXNldCdzIHVuaXQgaXMgdW5rbm93bi4gKi9cbmZ1bmN0aW9uIHB4UGVyTWljcm9uT2YoZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHB4UGVyVW5pdDogbnVtYmVyKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIGRhdGFzZXQubWljcm9uc1BlclVuaXQgPyBweFBlclVuaXQgLyBkYXRhc2V0Lm1pY3JvbnNQZXJVbml0IDogdW5kZWZpbmVkO1xufVxuIl19