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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/README.md +201 -460
  2. package/esm2022/index.mjs +28 -15
  3. package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
  4. package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
  5. package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
  7. package/esm2022/lib/contracts/color.mjs +60 -0
  8. package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
  9. package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
  10. package/esm2022/lib/contracts/display-types.mjs +11 -1
  11. package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
  12. package/esm2022/lib/contracts/intensity.mjs +48 -5
  13. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  14. package/esm2022/lib/contracts/plot-type.mjs +134 -17
  15. package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
  16. package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
  17. package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
  18. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
  19. package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
  20. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  21. package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
  22. package/esm2022/lib/contracts/sam.contract.mjs +1 -1
  23. package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
  24. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  25. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
  26. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  27. package/esm2022/lib/contracts/viz-config.mjs +2 -1
  28. package/esm2022/lib/geometry/contour.mjs +63 -0
  29. package/esm2022/lib/geometry/raster.mjs +98 -0
  30. package/esm2022/lib/geometry/ring.mjs +201 -0
  31. package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
  32. package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
  33. package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
  34. package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
  35. package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
  36. package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
  37. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
  38. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
  39. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
  40. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
  41. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
  42. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
  43. package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
  44. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
  45. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
  46. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
  47. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
  48. package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
  49. package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
  50. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
  51. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +361 -4184
  52. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
  53. package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
  54. package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
  55. package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
  56. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
  57. package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
  58. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
  59. package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
  60. package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
  61. package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
  62. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
  63. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
  64. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
  65. package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
  66. package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
  67. package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
  68. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
  69. package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
  70. package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
  71. package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
  72. package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
  73. package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
  74. package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
  75. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
  76. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
  77. package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
  78. package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
  79. package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
  80. package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
  81. package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
  82. package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
  83. package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
  84. package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
  85. package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
  86. package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
  87. package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
  88. package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
  89. package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
  90. package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
  91. package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
  92. package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
  93. package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
  94. package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
  95. package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
  96. package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
  97. package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
  98. package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
  99. package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
  100. package/esm2022/lib/implementations/region-centroids.mjs +47 -0
  101. package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
  102. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
  103. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
  104. package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
  105. package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
  106. package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
  107. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
  108. package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
  109. package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
  110. package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
  111. package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
  112. package/esm2022/lib/models/bezier.mjs +1 -11
  113. package/esm2022/lib/models/class-preset.mjs +41 -3
  114. package/esm2022/lib/models/geometry.mjs +27 -164
  115. package/esm2022/lib/models/polygon-edit.mjs +254 -0
  116. package/esm2022/lib/models/polygon-factory.mjs +118 -0
  117. package/esm2022/lib/models/region-clone.mjs +68 -0
  118. package/esm2022/lib/models/region-geojson.mjs +373 -0
  119. package/esm2022/lib/models/region.mjs +34 -33
  120. package/esm2022/lib/models/shape.mjs +18 -16
  121. package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
  122. package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
  123. package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
  124. package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
  125. package/esm2022/lib/plot.utilities.mjs +296 -473
  126. package/esm2022/lib/processing/image-crop.mjs +1 -1
  127. package/esm2022/lib/processing/processing-image.mjs +28 -15
  128. package/esm2022/lib/provide-visualization.mjs +40 -14
  129. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
  130. package/esm2022/lib/region-editor/file-stem.mjs +13 -0
  131. package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
  132. package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
  133. package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
  134. package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
  135. package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
  136. package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
  137. package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
  138. package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
  139. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
  140. package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
  141. package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
  142. package/esm2022/lib/region-ops.service.mjs +28 -70
  143. package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
  144. package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
  145. package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
  146. package/esm2022/lib/render-orchestrator.mjs +14 -11
  147. package/esm2022/lib/render-session.mjs +207 -0
  148. package/esm2022/lib/routing-visualizer.service.mjs +459 -411
  149. package/esm2022/lib/spatial/density-raster.mjs +14 -0
  150. package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
  151. package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
  152. package/esm2022/lib/spatial/gene-search.mjs +1 -1
  153. package/esm2022/lib/spatial/glyphs.mjs +97 -0
  154. package/esm2022/lib/spatial/lod.mjs +187 -0
  155. package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
  156. package/esm2022/lib/spatial/spatial-density.mjs +25 -16
  157. package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
  158. package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
  159. package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
  160. package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
  161. package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
  162. package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
  163. package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
  164. package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
  165. package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
  166. package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
  167. package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
  168. package/esm2022/lib/spatial/stats.mjs +71 -0
  169. package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
  170. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
  171. package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
  172. package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
  173. package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
  174. package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
  175. package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
  176. package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
  177. package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
  178. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
  179. package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
  180. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
  181. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
  182. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
  183. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
  184. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
  185. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
  186. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
  187. package/esm2022/lib/store/class-color.util.mjs +46 -3
  188. package/esm2022/lib/store/region-history.mjs +146 -0
  189. package/esm2022/lib/store/region-scope-cache.mjs +140 -0
  190. package/esm2022/lib/store/region-selection.mjs +82 -0
  191. package/esm2022/lib/store/region-store.service.mjs +279 -675
  192. package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
  193. package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
  194. package/esm2022/lib/toast-outlets.mjs +5 -4
  195. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
  196. package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
  197. package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
  198. package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
  199. package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
  200. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
  201. package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
  202. package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
  203. package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
  204. package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
  205. package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
  206. package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
  207. package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
  208. package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
  209. package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
  210. package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
  211. package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
  212. package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
  213. package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
  214. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
  215. package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
  216. package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
  217. package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
  218. package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
  219. package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
  220. package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
  221. package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
  222. package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
  223. package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
  224. package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
  225. package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
  226. package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
  227. package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
  228. package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
  229. package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
  230. package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
  231. package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
  232. package/esm2022/lib/util/mark-for-check.mjs +17 -0
  233. package/esm2022/lib/util/supersede.mjs +56 -0
  234. package/esm2022/lib/visualization.module.mjs +39 -141
  235. package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
  236. package/esm2022/lib/visualizer/region-actions.mjs +149 -0
  237. package/esm2022/lib/visualizer/region-load.mjs +60 -0
  238. package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
  239. package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
  240. package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
  241. package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
  242. package/esm2022/lib/visualizer.component.mjs +480 -1902
  243. package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
  244. package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
  245. package/esm2022/lib/workers/spatial-math.mjs +190 -0
  246. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
  247. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
  248. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
  249. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
  250. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
  251. package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
  252. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34430
  253. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  254. package/fesm2022/mask.worker.js +36 -917
  255. package/fesm2022/onnx-sam.worker.js +52 -16
  256. package/fesm2022/spatial-math.worker.js +471 -0
  257. package/fesm2022/tsne.worker.js +32 -15
  258. package/index.d.ts +13 -10
  259. package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
  260. package/lib/contracts/capabilities.contract.d.ts +4 -2
  261. package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
  262. package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
  263. package/lib/contracts/color.d.ts +27 -0
  264. package/lib/contracts/colormap-lut.d.ts +19 -4
  265. package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
  266. package/lib/contracts/display-types.d.ts +21 -0
  267. package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
  268. package/lib/contracts/intensity.d.ts +13 -2
  269. package/lib/contracts/plot-type.d.ts +3 -1
  270. package/lib/contracts/ports/image-state.port.d.ts +6 -2
  271. package/lib/contracts/ports/preferences.port.d.ts +4 -0
  272. package/lib/contracts/ports/region-io.port.d.ts +1 -0
  273. package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
  274. package/lib/contracts/ports/tile-access.port.d.ts +1 -0
  275. package/lib/contracts/region-editor-api.contract.d.ts +1 -1
  276. package/lib/contracts/region-overlay.contract.d.ts +5 -0
  277. package/lib/contracts/sam.contract.d.ts +7 -0
  278. package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
  279. package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
  280. package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
  281. package/lib/contracts/visualizer.contract.d.ts +221 -54
  282. package/lib/contracts/viz-config.d.ts +1 -0
  283. package/lib/geometry/contour.d.ts +24 -0
  284. package/lib/geometry/raster.d.ts +42 -0
  285. package/lib/geometry/ring.d.ts +67 -0
  286. package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
  287. package/lib/implementations/base-store-visualizer.d.ts +61 -15
  288. package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
  289. package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
  290. package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
  291. package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
  292. package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
  293. package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
  294. package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
  295. package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
  296. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
  297. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
  298. package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
  299. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
  300. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
  301. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
  302. package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
  303. package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
  304. package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
  305. package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
  306. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -878
  307. package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
  308. package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
  309. package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
  310. package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
  311. package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
  312. package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
  313. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
  314. package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
  315. package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
  316. package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
  317. package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
  318. package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
  319. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
  320. package/lib/implementations/osd/display-pipeline.d.ts +38 -9
  321. package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
  322. package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
  323. package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
  324. package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
  325. package/lib/implementations/osd/osd-coords.d.ts +6 -4
  326. package/lib/implementations/osd/osd-export.d.ts +36 -0
  327. package/lib/implementations/osd/osd-lib.d.ts +7 -0
  328. package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
  329. package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
  330. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
  331. package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
  332. package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
  333. package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
  334. package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
  335. package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
  336. package/lib/implementations/osd/osd-viewport.d.ts +77 -0
  337. package/lib/implementations/osd/osd-zoom.d.ts +6 -0
  338. package/lib/implementations/osd/simple-source.d.ts +161 -0
  339. package/lib/implementations/osd/slice-cache.d.ts +12 -3
  340. package/lib/implementations/osd/tile-client.d.ts +11 -14
  341. package/lib/implementations/osd/tile-recolor.d.ts +141 -0
  342. package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
  343. package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
  344. package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
  345. package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
  346. package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
  347. package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
  348. package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
  349. package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
  350. package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
  351. package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
  352. package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
  353. package/lib/implementations/plotly/plotly.service.d.ts +136 -401
  354. package/lib/implementations/region-centroids.d.ts +14 -0
  355. package/lib/implementations/simple-slice-access.service.d.ts +7 -4
  356. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
  357. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
  358. package/lib/implementations/tile-server/index.d.ts +5 -0
  359. package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
  360. package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
  361. package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
  362. package/lib/implementations/tile-server/transport.d.ts +62 -0
  363. package/lib/intensity/intensity-profile.d.ts +66 -0
  364. package/lib/intensity/intensity-profile.service.d.ts +108 -0
  365. package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
  366. package/lib/models/bezier.d.ts +0 -5
  367. package/lib/models/class-preset.d.ts +18 -0
  368. package/lib/models/geometry.d.ts +14 -48
  369. package/lib/models/polygon-edit.d.ts +72 -0
  370. package/lib/models/polygon-factory.d.ts +40 -0
  371. package/lib/models/region-clone.d.ts +20 -0
  372. package/lib/models/region-geojson.d.ts +17 -0
  373. package/lib/models/region.d.ts +40 -4
  374. package/lib/models/shape.d.ts +8 -0
  375. package/lib/plot-mode/contribution-host.d.ts +125 -0
  376. package/lib/plot-mode/plot-type-menu.d.ts +60 -0
  377. package/lib/plot-mode/tool-params-model.d.ts +49 -0
  378. package/lib/plot.utilities.d.ts +19 -30
  379. package/lib/processing/processing-image.d.ts +5 -2
  380. package/lib/provide-visualization.d.ts +19 -2
  381. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
  382. package/lib/region-editor/file-stem.d.ts +7 -0
  383. package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
  384. package/lib/region-editor/mask-export.service.d.ts +54 -0
  385. package/lib/region-editor/mask-raster.d.ts +2 -8
  386. package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
  387. package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
  388. package/lib/region-editor/region-editor.component.d.ts +166 -199
  389. package/lib/region-editor/region-metrics.d.ts +26 -0
  390. package/lib/region-editor/region-persistence.service.d.ts +69 -0
  391. package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
  392. package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
  393. package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
  394. package/lib/region-ops.service.d.ts +1 -7
  395. package/lib/region-overlay/region-geometry.d.ts +157 -0
  396. package/lib/region-overlay/region-hit-test.d.ts +38 -0
  397. package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
  398. package/lib/render-orchestrator.d.ts +6 -2
  399. package/lib/render-session.d.ts +75 -0
  400. package/lib/routing-visualizer.service.d.ts +110 -58
  401. package/lib/spatial/density-raster.d.ts +6 -0
  402. package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
  403. package/lib/spatial/embedding-compute.d.ts +21 -2
  404. package/lib/spatial/glyphs.d.ts +16 -0
  405. package/lib/spatial/lod.d.ts +94 -0
  406. package/lib/spatial/spatial-controls.facade.d.ts +64 -0
  407. package/lib/spatial/spatial-density.d.ts +15 -5
  408. package/lib/spatial/spatial-encoding.d.ts +11 -44
  409. package/lib/spatial/spatial-expression.d.ts +40 -22
  410. package/lib/spatial/spatial-framing.d.ts +1 -0
  411. package/lib/spatial/spatial-heatmap.d.ts +2 -0
  412. package/lib/spatial/spatial-hover.d.ts +4 -16
  413. package/lib/spatial/spatial-panel-model.d.ts +135 -0
  414. package/lib/spatial/spatial-selection.d.ts +21 -26
  415. package/lib/spatial/spatial-tile-merge.d.ts +41 -0
  416. package/lib/spatial/spatial-tiles.d.ts +9 -256
  417. package/lib/spatial/stats.d.ts +38 -0
  418. package/lib/spatial/transcript-grouping.d.ts +119 -0
  419. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
  420. package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
  421. package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
  422. package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
  423. package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
  424. package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
  425. package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
  426. package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
  427. package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
  428. package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
  429. package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
  430. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
  431. package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
  432. package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
  433. package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
  434. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
  435. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
  436. package/lib/store/class-color.util.d.ts +35 -1
  437. package/lib/store/region-history.d.ts +66 -0
  438. package/lib/store/region-scope-cache.d.ts +63 -0
  439. package/lib/store/region-selection.d.ts +36 -0
  440. package/lib/store/region-store.service.d.ts +104 -112
  441. package/lib/store/visualizer-store.service.d.ts +22 -33
  442. package/lib/toast-outlets.d.ts +4 -3
  443. package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
  444. package/lib/toolbar/canvas-tools.d.ts +20 -0
  445. package/lib/toolbar/crop/slide-crop.d.ts +10 -4
  446. package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
  447. package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
  448. package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
  449. package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
  450. package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
  451. package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
  452. package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
  453. package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
  454. package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
  455. package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
  456. package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
  457. package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
  458. package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
  459. package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
  460. package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
  461. package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
  462. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
  463. package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
  464. package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
  465. package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
  466. package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
  467. package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
  468. package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
  469. package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
  470. package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
  471. package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
  472. package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
  473. package/lib/toolbar/toolbar.component.d.ts +47 -83
  474. package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
  475. package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
  476. package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
  477. package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
  478. package/lib/toolbar/wand/wand.service.d.ts +22 -116
  479. package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
  480. package/lib/util/mark-for-check.d.ts +11 -0
  481. package/lib/util/supersede.d.ts +53 -0
  482. package/lib/visualization.module.d.ts +18 -39
  483. package/lib/visualizer/floating-drag.directive.d.ts +30 -0
  484. package/lib/visualizer/region-actions.d.ts +54 -0
  485. package/lib/visualizer/region-load.d.ts +27 -0
  486. package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
  487. package/lib/visualizer/tool-modes.d.ts +49 -0
  488. package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
  489. package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
  490. package/lib/visualizer.component.d.ts +201 -447
  491. package/lib/workers/spatial-math-ops.d.ts +65 -0
  492. package/lib/workers/spatial-math-worker.d.ts +7 -0
  493. package/lib/workers/spatial-math.d.ts +74 -0
  494. package/package.json +12 -3
  495. package/src/lib/styles/_viz-icons-rules.scss +73 -0
  496. package/src/lib/styles/viz-icons.scss +14 -0
  497. package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
  498. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
  499. package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
  500. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
  501. package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
  502. package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
  503. package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
  504. package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
  505. package/src/lib/assets/cell-detection.svg +0 -37
  506. package/src/lib/assets/click.svg +0 -1
  507. package/src/lib/assets/colormap-luts.json +0 -1
  508. package/src/lib/assets/edit-selection-white.svg +0 -47
  509. package/src/lib/assets/icons/colormap-earth.png +0 -0
  510. package/src/lib/assets/icons/colormap-placeholder.png +0 -0
  511. package/src/lib/assets/icons/colormap-pubu.png +0 -0
  512. package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
  513. package/src/lib/assets/picture-segmentation.svg +0 -43
  514. package/src/lib/assets/test/download-379.svg +0 -1
  515. package/src/lib/assets/test/download-98.svg +0 -1
  516. package/src/lib/assets/test/json-1.svg +0 -1
  517. package/src/lib/assets/test/load-53.svg +0 -1
  518. package/src/lib/assets/test/mask-44.svg +0 -1
  519. package/src/lib/assets/test/mask-download-44.svg +0 -15
  520. package/src/lib/assets/test/mask-save-44.svg +0 -11
  521. package/src/lib/assets/test/overlay-1.svg +0 -1
  522. package/src/lib/assets/test/overlay-4.svg +0 -1
  523. package/src/lib/assets/test/region-26.svg +0 -1
  524. package/src/lib/assets/test/save-56.svg +0 -1
  525. package/src/lib/assets/test/upload-43.svg +0 -1
@@ -0,0 +1,330 @@
1
+ import { combineLatest } from 'rxjs';
2
+ import { quiet } from './osd-lib';
3
+ import { DisplayPipeline } from './display-pipeline';
4
+ import { buildColormapLut } from '../../contracts/colormap-lut';
5
+ /**
6
+ * Client-side display for OpenSeadragon tiles: window/gamma/colormap/invert and
7
+ * per-channel tints, applied through OSD's `tile-invalidated` pixel pipeline.
8
+ *
9
+ * Owns the display state mirrored from the shared {@link VisualizerStore} (the
10
+ * LUT, the channel states, invert) and the recolor invariant: invalidations are
11
+ * coalesced to one per animation frame, and every round captures
12
+ * {@link displayToken} — a round that a newer one has superseded must not write
13
+ * its pixels back.
14
+ */
15
+ export class OsdTileRecolorer {
16
+ constructor(host, store) {
17
+ this.host = host;
18
+ this.store = store;
19
+ /** Pixel display pipeline (window/gamma/invert/colormap + additive tint) —
20
+ * shared by tile recoloring, the serverless compositor and the composite
21
+ * export so they stay identical (see DisplayPipeline). */
22
+ this.display = new DisplayPipeline({
23
+ isGrayscale: () => this.host.isGrayscale(),
24
+ colorLut: () => this.colorLut,
25
+ channelStates: () => this.channelStates,
26
+ invertBg: () => this.invertBg,
27
+ });
28
+ /** 256-entry RGB LUT for the active colormap, applied to grayscale tiles
29
+ * (mirrors Plotly's heatmap colorscale). Null while options resolve;
30
+ * recoloring is skipped until it's built. */
31
+ this.colorLut = null;
32
+ /** Latest per-channel display state (window/gamma/visibility) from the store,
33
+ * read synchronously by recolorTile. Channel 0 drives grayscale windowing;
34
+ * R/G/B (indices 0-2) drive RGB per-channel windowing. */
35
+ this.channelStates = [];
36
+ /** Inverted background (white = zero): inverts the windowed value before the
37
+ * gamma and the LUT (grayscale) / per channel before the additive merge (RGB
38
+ * and multichannel), as napari-js does. */
39
+ this.invertBg = false;
40
+ /** Bumped by every display invalidation. A recolor round captures it and, after
41
+ * each `await`, abandons the tile once a newer round has started. Writing a
42
+ * superseded context back is not merely wasted work: OSD's conversion sees a
43
+ * canvas the newer round already replaced, throws `DOMException`, and
44
+ * `_handleConversionError` DESTROYS the cache record and unloads the tile
45
+ * (unlike the drawer's rasterBlob path, it does not re-prepare). Enough of
46
+ * those and the viewer goes white mid-drag. */
47
+ this.displayToken = 0;
48
+ /** Pending coalesced invalidation (see {@link scheduleInvalidate}). */
49
+ this.invalidateHandle = null;
50
+ this.sub = null;
51
+ }
52
+ /** Whether display round `token` is still the current one. */
53
+ isCurrent(token) {
54
+ return token === this.displayToken;
55
+ }
56
+ /**
57
+ * Subscribe to the shared VisualizerStore colormap/reverse so OSD recolors in
58
+ * lock-step with Plotly. Idempotent and self-healing: the service is a root
59
+ * singleton, but `unsubscribe()` (called on VisualizerComponent destroy)
60
+ * tears the subscription down — and the constructor never runs again. So
61
+ * `plot()` calls this to re-establish it after a component teardown/recreate
62
+ * (e.g. switching images), otherwise colormap changes would be silently
63
+ * dropped on every image after the first switch.
64
+ */
65
+ ensureSubscription() {
66
+ if (this.sub)
67
+ return;
68
+ // Colormap/reverse + per-channel window/gamma/visibility + invert all live in
69
+ // the shared VisualizerStore. Rebuild the LUT and re-run the pixel pipeline
70
+ // whenever any of them changes, so the Channels & Histogram pane updates the
71
+ // image live and OSD stays in lock-step with Plotly.
72
+ this.sub = combineLatest([
73
+ this.store.getColormap(),
74
+ this.store.getReverseScale(),
75
+ this.store.getChannelStates(),
76
+ this.store.getInvert(),
77
+ ]).subscribe(([cm, rev, channels, invert]) => {
78
+ this.colorLut = buildColormapLut(cm?.data?.value, !!rev);
79
+ this.channelStates = channels;
80
+ this.invertBg = !!invert;
81
+ // Multichannel: each channel is its own TiledImage — visibility is the
82
+ // image's opacity (window/gamma/colour are applied by recolorChannelTile
83
+ // on the invalidate below). Re-applying the current slice's reveal picks up
84
+ // the new per-channel visibility (cached slices stay hidden).
85
+ if (this.host.isMultiChannel()) {
86
+ this.host.revealChannelSlice(this.host.currentZ());
87
+ }
88
+ // requestInvalidate(true) restores each tile to its original data before
89
+ // re-running recolorTile, so a change always maps afresh (no compounding).
90
+ // RGB now recolors too (per-channel window/visibility), so don't gate on
91
+ // grayscale. Coalesced: PrimeNG's slider fires (onChange) continuously, so
92
+ // a single drag would otherwise queue dozens of overlapping restore +
93
+ // re-process rounds over every channel image. (Serverless multichannel
94
+ // re-composites from its cached planes instead — see invalidateDisplay.)
95
+ this.scheduleInvalidate();
96
+ });
97
+ }
98
+ /** Tear the store subscription down and drop a queued invalidation, so it
99
+ * can't fire against a torn-down viewer. */
100
+ unsubscribe() {
101
+ this.sub?.unsubscribe();
102
+ this.sub = null;
103
+ if (this.invalidateHandle !== null) {
104
+ if (typeof cancelAnimationFrame === 'function')
105
+ cancelAnimationFrame(this.invalidateHandle);
106
+ else
107
+ clearTimeout(this.invalidateHandle);
108
+ this.invalidateHandle = null;
109
+ }
110
+ }
111
+ /** Seed the Intensity channel with a measured auto-window while it's still
112
+ * at full range (never clobber the user's manual window); if the user
113
+ * already windowed, just re-invalidate so painted tiles pick the LUT up. */
114
+ seedGrayWindow(min, max) {
115
+ const ch0 = this.store.currentChannelStates()[0];
116
+ if (ch0 && ch0.min === 0 && ch0.max === 255) {
117
+ this.store.setChannelState(0, { min, max });
118
+ }
119
+ else if (this.host.viewer() && this.colorLut) {
120
+ // Coalesced (and visible-slice-only for multichannel) — not a raw
121
+ // whole-world restore + re-recolor per sampled slice.
122
+ this.scheduleInvalidate();
123
+ }
124
+ }
125
+ /**
126
+ * Hook a freshly opened viewer (and its navigator, a separate mini-viewer with
127
+ * its own tiles that doesn't receive the main viewer's events) into the pixel
128
+ * pipeline, and paint what is already loaded when there is anything to apply.
129
+ */
130
+ attach(viewer) {
131
+ // The handler runs per tile on load (and on requestInvalidate); recoloring
132
+ // is a no-op for RGB images at default display or before the LUT resolves.
133
+ viewer.addHandler('tile-invalidated', (event) => this.recolorTile(event));
134
+ viewer.navigator?.addHandler('tile-invalidated', (event) => this.recolorTile(event));
135
+ if ((this.host.isGrayscale() && this.colorLut) || this.host.isMultiChannel())
136
+ this.invalidateWorld();
137
+ }
138
+ /** Collapse a burst of display-state changes into ONE invalidation on the next
139
+ * frame. Dragging a window slider emits per pixel of travel, and each round
140
+ * restores and re-processes every tile of every channel — so the burst is both
141
+ * wasted work and the race that breaks cache records (see {@link displayToken}).
142
+ * The store write stays live, so the pane itself remains responsive. */
143
+ scheduleInvalidate() {
144
+ if (this.invalidateHandle !== null)
145
+ return; // already queued for this frame
146
+ const raf = typeof requestAnimationFrame === 'function'
147
+ ? requestAnimationFrame
148
+ : (cb) => setTimeout(() => cb(0), 16);
149
+ this.invalidateHandle = raf(() => {
150
+ this.invalidateHandle = null;
151
+ this.invalidateDisplay();
152
+ });
153
+ }
154
+ /** Re-apply the display pipeline (window/gamma/colour/invert) after a state change.
155
+ * Multichannel invalidates ONLY the visible slice's channel images — invalidating
156
+ * the whole world would re-process every hidden/preloaded slice's tiles (hundreds),
157
+ * flooding OSD with "[CacheRecord] … InvalidStateError" and wasting work on tiles
158
+ * that aren't on screen. The other cached slices are marked stale and re-tinted
159
+ * lazily when revealed. Composite/grayscale invalidate the world; serverless
160
+ * multichannel re-composites its cached planes. */
161
+ invalidateDisplay() {
162
+ // Supersede any in-flight recolor round before restarting one (see displayToken).
163
+ this.displayToken++;
164
+ if (!this.host.viewer())
165
+ return;
166
+ if (this.host.isSimpleMultichannel()) {
167
+ this.host.recomposite(this.displayToken);
168
+ return;
169
+ }
170
+ if (this.host.isMultiChannel()) {
171
+ this.host.invalidateChannelDisplay(this.host.currentZ());
172
+ return;
173
+ }
174
+ this.invalidateWorld();
175
+ }
176
+ /** Restore and re-recolor every tile of the main viewer and the navigator. */
177
+ invalidateWorld() {
178
+ const v = this.host.viewer();
179
+ if (!v)
180
+ return;
181
+ quiet(() => v.world.requestInvalidate(true));
182
+ quiet(() => v.navigator?.world?.requestInvalidate(true));
183
+ }
184
+ /**
185
+ * Recolor a grayscale tile through the active colormap LUT, using OSD's
186
+ * tile-invalidated pixel pipeline (OSD 5+/6). Maps each pixel's grayscale
187
+ * value (r==g==b) to the LUT's RGB. No-op for RGB images or until the LUT is
188
+ * built. Handler is async — OSD awaits it (raiseEventAwaiting).
189
+ */
190
+ async recolorTile(event) {
191
+ if (this.host.isMultiChannel()) {
192
+ await this.recolorChannelTile(event);
193
+ return;
194
+ }
195
+ // A serverless multichannel composite is drawn in the display colours already
196
+ // (recomposite): recolouring its tiles as RGB applied the window, gamma and
197
+ // invert a second time.
198
+ if (this.host.isSimpleMultichannel())
199
+ return;
200
+ const token = this.displayToken;
201
+ if (this.host.isGrayscale()) {
202
+ if (!this.colorLut)
203
+ return;
204
+ }
205
+ else if (!this.display.rgbNeedsRecolor()) {
206
+ return; // RGB at default (all visible, full window, γ=1, no invert) → passthrough
207
+ }
208
+ const px = await this.readTilePixels(event);
209
+ if (!px || !this.display.applyToRgba(px.img.data))
210
+ return; // nothing opaque
211
+ await this.writeTilePixels(event, px, token);
212
+ }
213
+ /**
214
+ * Tint a single channel's tile in place. Each channel is its own OpenSeadragon
215
+ * TiledImage (a single-band grayscale tile); OSD composites the N images
216
+ * additively ('lighter') in its drawer — so this just maps the tile's intensity
217
+ * through the channel's window/gamma and its pseudo-colour. Synchronous (no
218
+ * cross-tile fetch) → no race, no seams. Channel is parsed from the tile URL.
219
+ */
220
+ async recolorChannelTile(event) {
221
+ const token = this.displayToken;
222
+ const tile = event?.tile;
223
+ const url = (tile && (typeof tile.getUrl === 'function' ? tile.getUrl() : tile.url)) || '';
224
+ const m = /[?&]channel=(\d+)/.exec(url);
225
+ const ch = m ? parseInt(m[1], 10) : 0;
226
+ const st = this.channelStates[ch];
227
+ const px = await this.readTilePixels(event);
228
+ if (!px)
229
+ return;
230
+ // Precompute lum(0..255) → tinted RGB once, then map each pixel by lookup —
231
+ // the channel tile is single-band, so this turns ~262k per-pixel
232
+ // channelIntensity() (with Math.pow for gamma) calls into 256 — the difference
233
+ // between a snappy and a sluggish slider on a 4-channel stack.
234
+ const { r: rL, g: gL, b: bL } = this.display.channelRgbLut(st);
235
+ const d = px.img.data;
236
+ let changed = false;
237
+ for (let i = 0; i < d.length; i += 4) {
238
+ if (d[i + 3] === 0)
239
+ continue;
240
+ const r = d[i], g = d[i + 1], b = d[i + 2];
241
+ const lum = r >= g ? (r >= b ? r : b) : g >= b ? g : b; // single-band → max
242
+ d[i] = rL[lum];
243
+ d[i + 1] = gL[lum];
244
+ d[i + 2] = bL[lum];
245
+ changed = true;
246
+ }
247
+ if (!changed)
248
+ return;
249
+ await this.writeTilePixels(event, px, token);
250
+ }
251
+ /**
252
+ * Read a tile's pixels for recoloring. Prefers the tile's rendering context,
253
+ * but some tile caches (ajax PNG blobs) convert to an *empty* context2d —
254
+ * recoloring that would blank the tile (white canvas). So if the context has
255
+ * no opaque pixels, the tile's own bitmap/image is drawn to a scratch canvas
256
+ * and read instead. Null when no pixels can be read: leave the tile untouched.
257
+ */
258
+ async readTilePixels(event) {
259
+ let ctx = null;
260
+ try {
261
+ ctx = (await event.getData('context2d'));
262
+ }
263
+ catch {
264
+ /* try the bitmap below */
265
+ }
266
+ if (ctx && ctx.canvas && ctx.canvas.width && ctx.canvas.height) {
267
+ let img = null;
268
+ try {
269
+ img = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
270
+ }
271
+ catch {
272
+ /* tainted/gone */
273
+ }
274
+ if (img && hasOpaque(img.data))
275
+ return { ctx, img };
276
+ }
277
+ let src = null;
278
+ try {
279
+ src = (await event.getData('imageBitmap'));
280
+ }
281
+ catch {
282
+ /* try the image below */
283
+ }
284
+ if (!src || !src.width) {
285
+ try {
286
+ src = (await event.getData('image'));
287
+ }
288
+ catch {
289
+ /* none */
290
+ }
291
+ }
292
+ if (!src || !src.width)
293
+ return null;
294
+ const c = document.createElement('canvas');
295
+ c.width = src.width;
296
+ c.height = src.height;
297
+ const scratch = c.getContext('2d', { willReadFrequently: true });
298
+ if (!scratch)
299
+ return null;
300
+ scratch.drawImage(src, 0, 0);
301
+ return { ctx: scratch, img: scratch.getImageData(0, 0, c.width, c.height) };
302
+ }
303
+ /** Write recolored pixels back to the tile — unless a newer display round
304
+ * (`token`, see {@link displayToken}) has already restored it: writing a
305
+ * superseded context back makes OSD's conversion throw DOMException, which
306
+ * destroys the cache record and unloads the tile. */
307
+ async writeTilePixels(event, px, token) {
308
+ if (token !== this.displayToken)
309
+ return;
310
+ px.ctx.putImageData(px.img, 0, 0);
311
+ // The tile's cache can still be evicted between the awaits and here (a
312
+ // slice change), making setData throw a DOMException on a dead canvas.
313
+ // Swallow it — the tile is gone, so there's nothing to recolor.
314
+ try {
315
+ await event.setData(px.ctx, 'context2d');
316
+ }
317
+ catch {
318
+ /* tile evicted */
319
+ }
320
+ }
321
+ }
322
+ /** True if any pixel in the RGBA buffer is non-transparent. */
323
+ function hasOpaque(d) {
324
+ for (let i = 3; i < d.length; i += 4) {
325
+ if (d[i] !== 0)
326
+ return true;
327
+ }
328
+ return false;
329
+ }
330
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlsZS1yZWNvbG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvb3NkL3RpbGUtcmVjb2xvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdCLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUduRCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQU8sTUFBTSw4QkFBOEIsQ0FBQztBQTRCckU7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQWtDM0IsWUFDbUIsSUFBcUIsRUFDckIsS0FBc0I7UUFEdEIsU0FBSSxHQUFKLElBQUksQ0FBaUI7UUFDckIsVUFBSyxHQUFMLEtBQUssQ0FBaUI7UUFuQ3pDOzttRUFFMkQ7UUFDbEQsWUFBTyxHQUFHLElBQUksZUFBZSxDQUFDO1lBQ3JDLFdBQVcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUMxQyxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVE7WUFDN0IsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxhQUFhO1lBQ3ZDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUTtTQUM5QixDQUFDLENBQUM7UUFDSDs7c0RBRThDO1FBQzlDLGFBQVEsR0FBaUIsSUFBSSxDQUFDO1FBQzlCOzttRUFFMkQ7UUFDM0Qsa0JBQWEsR0FBb0IsRUFBRSxDQUFDO1FBQ3BDOztvREFFNEM7UUFDNUMsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNqQjs7Ozs7O3dEQU1nRDtRQUNoRCxpQkFBWSxHQUFHLENBQUMsQ0FBQztRQUNqQix1RUFBdUU7UUFDL0QscUJBQWdC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RUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0IsT0FBTyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO0lBQzlFLENBQUM7SUFFRDs7OzBEQUdzRDtJQUM5QyxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQWdCLEVBQUUsRUFBYyxFQUFFLEtBQWE7UUFDM0UsSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLFlBQVk7WUFBRSxPQUFPO1FBQ3hDLEVBQUUsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLHVFQUF1RTtRQUN2RSx1RUFBdUU7UUFDdkUsZ0VBQWdFO1FBQ2hFLElBQUksQ0FBQztZQUNILE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxrQkFBa0I7UUFDcEIsQ0FBQztJQUNILENBQUM7Q0FDRjtBQUVELCtEQUErRDtBQUMvRCxTQUFTLFNBQVMsQ0FBQyxDQUFvQjtJQUNyQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTdWJzY3JpcHRpb24sIGNvbWJpbmVMYXRlc3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB0eXBlICogYXMgT3BlblNlYWRyYWdvbiBmcm9tICdvcGVuc2VhZHJhZ29uJztcblxuaW1wb3J0IHsgcXVpZXQgfSBmcm9tICcuL29zZC1saWInO1xuaW1wb3J0IHsgRGlzcGxheVBpcGVsaW5lIH0gZnJvbSAnLi9kaXNwbGF5LXBpcGVsaW5lJztcbmltcG9ydCB7IFZpc3VhbGl6ZXJTdG9yZSB9IGZyb20gJy4uLy4uL3N0b3JlL3Zpc3VhbGl6ZXItc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBidWlsZENvbG9ybWFwTHV0LCBSZ2IgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvY29sb3JtYXAtbHV0JztcbmltcG9ydCB7IElDaGFubmVsU3RhdGUgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvY2hhbm5lbC1oaXN0b2dyYW0tYXBpLmNvbnRyYWN0JztcblxuLyoqIFRoZSBzZXJ2aWNlIHN0YXRlIHRoZSByZWNvbG9yZXIgcmVhZHMg4oCUIGxpdmUsIHNvIGl0IGZvbGxvd3MgYSB2aWV3ZXIgcmVidWlsZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGlsZVJlY29sb3JIb3N0IHtcbiAgdmlld2VyKCk6IE9wZW5TZWFkcmFnb24uVmlld2VyIHwgbnVsbDtcbiAgaXNHcmF5c2NhbGUoKTogYm9vbGVhbjtcbiAgaXNNdWx0aUNoYW5uZWwoKTogYm9vbGVhbjtcbiAgLyoqIFNlcnZlcmxlc3MgbXVsdGljaGFubmVsOiByZWNvbG9yIGJ5IHJlLWNvbXBvc2l0aW5nIHRoZSBjYWNoZWQgcGxhbmVzLiAqL1xuICBpc1NpbXBsZU11bHRpY2hhbm5lbCgpOiBib29sZWFuO1xuICBjdXJyZW50WigpOiBudW1iZXI7XG4gIC8qKiBSZS1hcHBseSB0aGUgY3VycmVudCBzbGljZSdzIHBlci1jaGFubmVsIHZpc2liaWxpdHkgKG11bHRpY2hhbm5lbCkuICovXG4gIHJldmVhbENoYW5uZWxTbGljZSh6OiBudW1iZXIpOiB2b2lkO1xuICAvKiogSW52YWxpZGF0ZSBvbmx5IHRoZSB2aXNpYmxlIHNsaWNlJ3MgY2hhbm5lbCBpbWFnZXMgKG11bHRpY2hhbm5lbCkuICovXG4gIGludmFsaWRhdGVDaGFubmVsRGlzcGxheSh6OiBudW1iZXIpOiB2b2lkO1xuICAvKiogUmUtY29tcG9zaXRlIHRoZSBzZXJ2ZXJsZXNzLW11bHRpY2hhbm5lbCBwbGFuZXMgZm9yIGRpc3BsYXkgcm91bmQgYHRva2VuYC4gKi9cbiAgcmVjb21wb3NpdGUodG9rZW46IG51bWJlcik6IHZvaWQ7XG59XG5cbi8qKiBUaGUgdGlsZS1pbnZhbGlkYXRlZCBldmVudCdzIHBpeGVsIGFjY2Vzc29ycyAoT1NEIDUrLzYpLCBhcyB1c2VkIGhlcmUuICovXG5pbnRlcmZhY2UgVGlsZUV2ZW50IHtcbiAgdGlsZT86IHsgZ2V0VXJsPzogKCkgPT4gc3RyaW5nOyB1cmw/OiBzdHJpbmcgfTtcbiAgZ2V0RGF0YSh0eXBlOiBzdHJpbmcpOiBQcm9taXNlPHVua25vd24+O1xuICBzZXREYXRhKGRhdGE6IHVua25vd24sIHR5cGU6IHN0cmluZyk6IFByb21pc2U8dW5rbm93bj47XG59XG5cbnR5cGUgVGlsZVBpeGVscyA9IHsgY3R4OiBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7IGltZzogSW1hZ2VEYXRhIH07XG5cbi8qKlxuICogQ2xpZW50LXNpZGUgZGlzcGxheSBmb3IgT3BlblNlYWRyYWdvbiB0aWxlczogd2luZG93L2dhbW1hL2NvbG9ybWFwL2ludmVydCBhbmRcbiAqIHBlci1jaGFubmVsIHRpbnRzLCBhcHBsaWVkIHRocm91Z2ggT1NEJ3MgYHRpbGUtaW52YWxpZGF0ZWRgIHBpeGVsIHBpcGVsaW5lLlxuICpcbiAqIE93bnMgdGhlIGRpc3BsYXkgc3RhdGUgbWlycm9yZWQgZnJvbSB0aGUgc2hhcmVkIHtAbGluayBWaXN1YWxpemVyU3RvcmV9ICh0aGVcbiAqIExVVCwgdGhlIGNoYW5uZWwgc3RhdGVzLCBpbnZlcnQpIGFuZCB0aGUgcmVjb2xvciBpbnZhcmlhbnQ6IGludmFsaWRhdGlvbnMgYXJlXG4gKiBjb2FsZXNjZWQgdG8gb25lIHBlciBhbmltYXRpb24gZnJhbWUsIGFuZCBldmVyeSByb3VuZCBjYXB0dXJlc1xuICoge0BsaW5rIGRpc3BsYXlUb2tlbn0g4oCUIGEgcm91bmQgdGhhdCBhIG5ld2VyIG9uZSBoYXMgc3VwZXJzZWRlZCBtdXN0IG5vdCB3cml0ZVxuICogaXRzIHBpeGVscyBiYWNrLlxuICovXG5leHBvcnQgY2xhc3MgT3NkVGlsZVJlY29sb3JlciB7XG4gIC8qKiBQaXhlbCBkaXNwbGF5IHBpcGVsaW5lICh3aW5kb3cvZ2FtbWEvaW52ZXJ0L2NvbG9ybWFwICsgYWRkaXRpdmUgdGludCkg4oCUXG4gICAqICBzaGFyZWQgYnkgdGlsZSByZWNvbG9yaW5nLCB0aGUgc2VydmVybGVzcyBjb21wb3NpdG9yIGFuZCB0aGUgY29tcG9zaXRlXG4gICAqICBleHBvcnQgc28gdGhleSBzdGF5IGlkZW50aWNhbCAoc2VlIERpc3BsYXlQaXBlbGluZSkuICovXG4gIHJlYWRvbmx5IGRpc3BsYXkgPSBuZXcgRGlzcGxheVBpcGVsaW5lKHtcbiAgICBpc0dyYXlzY2FsZTogKCkgPT4gdGhpcy5ob3N0LmlzR3JheXNjYWxlKCksXG4gICAgY29sb3JMdXQ6ICgpID0+IHRoaXMuY29sb3JMdXQsXG4gICAgY2hhbm5lbFN0YXRlczogKCkgPT4gdGhpcy5jaGFubmVsU3RhdGVzLFxuICAgIGludmVydEJnOiAoKSA9PiB0aGlzLmludmVydEJnLFxuICB9KTtcbiAgLyoqIDI1Ni1lbnRyeSBSR0IgTFVUIGZvciB0aGUgYWN0aXZlIGNvbG9ybWFwLCBhcHBsaWVkIHRvIGdyYXlzY2FsZSB0aWxlc1xuICAgKiAgKG1pcnJvcnMgUGxvdGx5J3MgaGVhdG1hcCBjb2xvcnNjYWxlKS4gTnVsbCB3aGlsZSBvcHRpb25zIHJlc29sdmU7XG4gICAqICByZWNvbG9yaW5nIGlzIHNraXBwZWQgdW50aWwgaXQncyBidWlsdC4gKi9cbiAgY29sb3JMdXQ6IFJnYltdIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBMYXRlc3QgcGVyLWNoYW5uZWwgZGlzcGxheSBzdGF0ZSAod2luZG93L2dhbW1hL3Zpc2liaWxpdHkpIGZyb20gdGhlIHN0b3JlLFxuICAgKiAgcmVhZCBzeW5jaHJvbm91c2x5IGJ5IHJlY29sb3JUaWxlLiBDaGFubmVsIDAgZHJpdmVzIGdyYXlzY2FsZSB3aW5kb3dpbmc7XG4gICAqICBSL0cvQiAoaW5kaWNlcyAwLTIpIGRyaXZlIFJHQiBwZXItY2hhbm5lbCB3aW5kb3dpbmcuICovXG4gIGNoYW5uZWxTdGF0ZXM6IElDaGFubmVsU3RhdGVbXSA9IFtdO1xuICAvKiogSW52ZXJ0ZWQgYmFja2dyb3VuZCAod2hpdGUgPSB6ZXJvKTogaW52ZXJ0cyB0aGUgd2luZG93ZWQgdmFsdWUgYmVmb3JlIHRoZVxuICAgKiAgZ2FtbWEgYW5kIHRoZSBMVVQgKGdyYXlzY2FsZSkgLyBwZXIgY2hhbm5lbCBiZWZvcmUgdGhlIGFkZGl0aXZlIG1lcmdlIChSR0JcbiAgICogIGFuZCBtdWx0aWNoYW5uZWwpLCBhcyBuYXBhcmktanMgZG9lcy4gKi9cbiAgaW52ZXJ0QmcgPSBmYWxzZTtcbiAgLyoqIEJ1bXBlZCBieSBldmVyeSBkaXNwbGF5IGludmFsaWRhdGlvbi4gQSByZWNvbG9yIHJvdW5kIGNhcHR1cmVzIGl0IGFuZCwgYWZ0ZXJcbiAgICogIGVhY2ggYGF3YWl0YCwgYWJhbmRvbnMgdGhlIHRpbGUgb25jZSBhIG5ld2VyIHJvdW5kIGhhcyBzdGFydGVkLiBXcml0aW5nIGFcbiAgICogIHN1cGVyc2VkZWQgY29udGV4dCBiYWNrIGlzIG5vdCBtZXJlbHkgd2FzdGVkIHdvcms6IE9TRCdzIGNvbnZlcnNpb24gc2VlcyBhXG4gICAqICBjYW52YXMgdGhlIG5ld2VyIHJvdW5kIGFscmVhZHkgcmVwbGFjZWQsIHRocm93cyBgRE9NRXhjZXB0aW9uYCwgYW5kXG4gICAqICBgX2hhbmRsZUNvbnZlcnNpb25FcnJvcmAgREVTVFJPWVMgdGhlIGNhY2hlIHJlY29yZCBhbmQgdW5sb2FkcyB0aGUgdGlsZVxuICAgKiAgKHVubGlrZSB0aGUgZHJhd2VyJ3MgcmFzdGVyQmxvYiBwYXRoLCBpdCBkb2VzIG5vdCByZS1wcmVwYXJlKS4gRW5vdWdoIG9mXG4gICAqICB0aG9zZSBhbmQgdGhlIHZpZXdlciBnb2VzIHdoaXRlIG1pZC1kcmFnLiAqL1xuICBkaXNwbGF5VG9rZW4gPSAwO1xuICAvKiogUGVuZGluZyBjb2FsZXNjZWQgaW52YWxpZGF0aW9uIChzZWUge0BsaW5rIHNjaGVkdWxlSW52YWxpZGF0ZX0pLiAqL1xuICBwcml2YXRlIGludmFsaWRhdGVIYW5kbGU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHN1YjogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBUaWxlUmVjb2xvckhvc3QsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdG9yZTogVmlzdWFsaXplclN0b3JlLFxuICApIHt9XG5cbiAgLyoqIFdoZXRoZXIgZGlzcGxheSByb3VuZCBgdG9rZW5gIGlzIHN0aWxsIHRoZSBjdXJyZW50IG9uZS4gKi9cbiAgaXNDdXJyZW50KHRva2VuOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdG9rZW4gPT09IHRoaXMuZGlzcGxheVRva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZSB0byB0aGUgc2hhcmVkIFZpc3VhbGl6ZXJTdG9yZSBjb2xvcm1hcC9yZXZlcnNlIHNvIE9TRCByZWNvbG9ycyBpblxuICAgKiBsb2NrLXN0ZXAgd2l0aCBQbG90bHkuIElkZW1wb3RlbnQgYW5kIHNlbGYtaGVhbGluZzogdGhlIHNlcnZpY2UgaXMgYSByb290XG4gICAqIHNpbmdsZXRvbiwgYnV0IGB1bnN1YnNjcmliZSgpYCAoY2FsbGVkIG9uIFZpc3VhbGl6ZXJDb21wb25lbnQgZGVzdHJveSlcbiAgICogdGVhcnMgdGhlIHN1YnNjcmlwdGlvbiBkb3duIOKAlCBhbmQgdGhlIGNvbnN0cnVjdG9yIG5ldmVyIHJ1bnMgYWdhaW4uIFNvXG4gICAqIGBwbG90KClgIGNhbGxzIHRoaXMgdG8gcmUtZXN0YWJsaXNoIGl0IGFmdGVyIGEgY29tcG9uZW50IHRlYXJkb3duL3JlY3JlYXRlXG4gICAqIChlLmcuIHN3aXRjaGluZyBpbWFnZXMpLCBvdGhlcndpc2UgY29sb3JtYXAgY2hhbmdlcyB3b3VsZCBiZSBzaWxlbnRseVxuICAgKiBkcm9wcGVkIG9uIGV2ZXJ5IGltYWdlIGFmdGVyIHRoZSBmaXJzdCBzd2l0Y2guXG4gICAqL1xuICBlbnN1cmVTdWJzY3JpcHRpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc3ViKSByZXR1cm47XG4gICAgLy8gQ29sb3JtYXAvcmV2ZXJzZSArIHBlci1jaGFubmVsIHdpbmRvdy9nYW1tYS92aXNpYmlsaXR5ICsgaW52ZXJ0IGFsbCBsaXZlIGluXG4gICAgLy8gdGhlIHNoYXJlZCBWaXN1YWxpemVyU3RvcmUuIFJlYnVpbGQgdGhlIExVVCBhbmQgcmUtcnVuIHRoZSBwaXhlbCBwaXBlbGluZVxuICAgIC8vIHdoZW5ldmVyIGFueSBvZiB0aGVtIGNoYW5nZXMsIHNvIHRoZSBDaGFubmVscyAmIEhpc3RvZ3JhbSBwYW5lIHVwZGF0ZXMgdGhlXG4gICAgLy8gaW1hZ2UgbGl2ZSBhbmQgT1NEIHN0YXlzIGluIGxvY2stc3RlcCB3aXRoIFBsb3RseS5cbiAgICB0aGlzLnN1YiA9IGNvbWJpbmVMYXRlc3QoW1xuICAgICAgdGhpcy5zdG9yZS5nZXRDb2xvcm1hcCgpLFxuICAgICAgdGhpcy5zdG9yZS5nZXRSZXZlcnNlU2NhbGUoKSxcbiAgICAgIHRoaXMuc3RvcmUuZ2V0Q2hhbm5lbFN0YXRlcygpLFxuICAgICAgdGhpcy5zdG9yZS5nZXRJbnZlcnQoKSxcbiAgICBdKS5zdWJzY3JpYmUoKFtjbSwgcmV2LCBjaGFubmVscywgaW52ZXJ0XSkgPT4ge1xuICAgICAgdGhpcy5jb2xvckx1dCA9IGJ1aWxkQ29sb3JtYXBMdXQoY20/LmRhdGE/LnZhbHVlLCAhIXJldik7XG4gICAgICB0aGlzLmNoYW5uZWxTdGF0ZXMgPSBjaGFubmVscztcbiAgICAgIHRoaXMuaW52ZXJ0QmcgPSAhIWludmVydDtcbiAgICAgIC8vIE11bHRpY2hhbm5lbDogZWFjaCBjaGFubmVsIGlzIGl0cyBvd24gVGlsZWRJbWFnZSDigJQgdmlzaWJpbGl0eSBpcyB0aGVcbiAgICAgIC8vIGltYWdlJ3Mgb3BhY2l0eSAod2luZG93L2dhbW1hL2NvbG91ciBhcmUgYXBwbGllZCBieSByZWNvbG9yQ2hhbm5lbFRpbGVcbiAgICAgIC8vIG9uIHRoZSBpbnZhbGlkYXRlIGJlbG93KS4gUmUtYXBwbHlpbmcgdGhlIGN1cnJlbnQgc2xpY2UncyByZXZlYWwgcGlja3MgdXBcbiAgICAgIC8vIHRoZSBuZXcgcGVyLWNoYW5uZWwgdmlzaWJpbGl0eSAoY2FjaGVkIHNsaWNlcyBzdGF5IGhpZGRlbikuXG4gICAgICBpZiAodGhpcy5ob3N0LmlzTXVsdGlDaGFubmVsKCkpIHtcbiAgICAgICAgdGhpcy5ob3N0LnJldmVhbENoYW5uZWxTbGljZSh0aGlzLmhvc3QuY3VycmVudFooKSk7XG4gICAgICB9XG4gICAgICAvLyByZXF1ZXN0SW52YWxpZGF0ZSh0cnVlKSByZXN0b3JlcyBlYWNoIHRpbGUgdG8gaXRzIG9yaWdpbmFsIGRhdGEgYmVmb3JlXG4gICAgICAvLyByZS1ydW5uaW5nIHJlY29sb3JUaWxlLCBzbyBhIGNoYW5nZSBhbHdheXMgbWFwcyBhZnJlc2ggKG5vIGNvbXBvdW5kaW5nKS5cbiAgICAgIC8vIFJHQiBub3cgcmVjb2xvcnMgdG9vIChwZXItY2hhbm5lbCB3aW5kb3cvdmlzaWJpbGl0eSksIHNvIGRvbid0IGdhdGUgb25cbiAgICAgIC8vIGdyYXlzY2FsZS4gQ29hbGVzY2VkOiBQcmltZU5HJ3Mgc2xpZGVyIGZpcmVzIChvbkNoYW5nZSkgY29udGludW91c2x5LCBzb1xuICAgICAgLy8gYSBzaW5nbGUgZHJhZyB3b3VsZCBvdGhlcndpc2UgcXVldWUgZG96ZW5zIG9mIG92ZXJsYXBwaW5nIHJlc3RvcmUgK1xuICAgICAgLy8gcmUtcHJvY2VzcyByb3VuZHMgb3ZlciBldmVyeSBjaGFubmVsIGltYWdlLiAoU2VydmVybGVzcyBtdWx0aWNoYW5uZWxcbiAgICAgIC8vIHJlLWNvbXBvc2l0ZXMgZnJvbSBpdHMgY2FjaGVkIHBsYW5lcyBpbnN0ZWFkIOKAlCBzZWUgaW52YWxpZGF0ZURpc3BsYXkuKVxuICAgICAgdGhpcy5zY2hlZHVsZUludmFsaWRhdGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBUZWFyIHRoZSBzdG9yZSBzdWJzY3JpcHRpb24gZG93biBhbmQgZHJvcCBhIHF1ZXVlZCBpbnZhbGlkYXRpb24sIHNvIGl0XG4gICAqICBjYW4ndCBmaXJlIGFnYWluc3QgYSB0b3JuLWRvd24gdmlld2VyLiAqL1xuICB1bnN1YnNjcmliZSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1Yj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnN1YiA9IG51bGw7XG4gICAgaWYgKHRoaXMuaW52YWxpZGF0ZUhhbmRsZSAhPT0gbnVsbCkge1xuICAgICAgaWYgKHR5cGVvZiBjYW5jZWxBbmltYXRpb25GcmFtZSA9PT0gJ2Z1bmN0aW9uJykgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5pbnZhbGlkYXRlSGFuZGxlKTtcbiAgICAgIGVsc2UgY2xlYXJUaW1lb3V0KHRoaXMuaW52YWxpZGF0ZUhhbmRsZSBhcyB1bmtub3duIGFzIFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+KTtcbiAgICAgIHRoaXMuaW52YWxpZGF0ZUhhbmRsZSA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqIFNlZWQgdGhlIEludGVuc2l0eSBjaGFubmVsIHdpdGggYSBtZWFzdXJlZCBhdXRvLXdpbmRvdyB3aGlsZSBpdCdzIHN0aWxsXG4gICAqICBhdCBmdWxsIHJhbmdlIChuZXZlciBjbG9iYmVyIHRoZSB1c2VyJ3MgbWFudWFsIHdpbmRvdyk7IGlmIHRoZSB1c2VyXG4gICAqICBhbHJlYWR5IHdpbmRvd2VkLCBqdXN0IHJlLWludmFsaWRhdGUgc28gcGFpbnRlZCB0aWxlcyBwaWNrIHRoZSBMVVQgdXAuICovXG4gIHNlZWRHcmF5V2luZG93KG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGNoMCA9IHRoaXMuc3RvcmUuY3VycmVudENoYW5uZWxTdGF0ZXMoKVswXTtcbiAgICBpZiAoY2gwICYmIGNoMC5taW4gPT09IDAgJiYgY2gwLm1heCA9PT0gMjU1KSB7XG4gICAgICB0aGlzLnN0b3JlLnNldENoYW5uZWxTdGF0ZSgwLCB7IG1pbiwgbWF4IH0pO1xuICAgIH0gZWxzZSBpZiAodGhpcy5ob3N0LnZpZXdlcigpICYmIHRoaXMuY29sb3JMdXQpIHtcbiAgICAgIC8vIENvYWxlc2NlZCAoYW5kIHZpc2libGUtc2xpY2Utb25seSBmb3IgbXVsdGljaGFubmVsKSDigJQgbm90IGEgcmF3XG4gICAgICAvLyB3aG9sZS13b3JsZCByZXN0b3JlICsgcmUtcmVjb2xvciBwZXIgc2FtcGxlZCBzbGljZS5cbiAgICAgIHRoaXMuc2NoZWR1bGVJbnZhbGlkYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhvb2sgYSBmcmVzaGx5IG9wZW5lZCB2aWV3ZXIgKGFuZCBpdHMgbmF2aWdhdG9yLCBhIHNlcGFyYXRlIG1pbmktdmlld2VyIHdpdGhcbiAgICogaXRzIG93biB0aWxlcyB0aGF0IGRvZXNuJ3QgcmVjZWl2ZSB0aGUgbWFpbiB2aWV3ZXIncyBldmVudHMpIGludG8gdGhlIHBpeGVsXG4gICAqIHBpcGVsaW5lLCBhbmQgcGFpbnQgd2hhdCBpcyBhbHJlYWR5IGxvYWRlZCB3aGVuIHRoZXJlIGlzIGFueXRoaW5nIHRvIGFwcGx5LlxuICAgKi9cbiAgYXR0YWNoKHZpZXdlcjogT3BlblNlYWRyYWdvbi5WaWV3ZXIpOiB2b2lkIHtcbiAgICAvLyBUaGUgaGFuZGxlciBydW5zIHBlciB0aWxlIG9uIGxvYWQgKGFuZCBvbiByZXF1ZXN0SW52YWxpZGF0ZSk7IHJlY29sb3JpbmdcbiAgICAvLyBpcyBhIG5vLW9wIGZvciBSR0IgaW1hZ2VzIGF0IGRlZmF1bHQgZGlzcGxheSBvciBiZWZvcmUgdGhlIExVVCByZXNvbHZlcy5cbiAgICB2aWV3ZXIuYWRkSGFuZGxlcigndGlsZS1pbnZhbGlkYXRlZCcsIChldmVudCkgPT4gdGhpcy5yZWNvbG9yVGlsZShldmVudCBhcyB1bmtub3duIGFzIFRpbGVFdmVudCkpO1xuICAgIHZpZXdlci5uYXZpZ2F0b3I/LmFkZEhhbmRsZXIoJ3RpbGUtaW52YWxpZGF0ZWQnLCAoZXZlbnQpID0+IHRoaXMucmVjb2xvclRpbGUoZXZlbnQgYXMgdW5rbm93biBhcyBUaWxlRXZlbnQpKTtcbiAgICBpZiAoKHRoaXMuaG9zdC5pc0dyYXlzY2FsZSgpICYmIHRoaXMuY29sb3JMdXQpIHx8IHRoaXMuaG9zdC5pc011bHRpQ2hhbm5lbCgpKSB0aGlzLmludmFsaWRhdGVXb3JsZCgpO1xuICB9XG5cbiAgLyoqIENvbGxhcHNlIGEgYnVyc3Qgb2YgZGlzcGxheS1zdGF0ZSBjaGFuZ2VzIGludG8gT05FIGludmFsaWRhdGlvbiBvbiB0aGUgbmV4dFxuICAgKiAgZnJhbWUuIERyYWdnaW5nIGEgd2luZG93IHNsaWRlciBlbWl0cyBwZXIgcGl4ZWwgb2YgdHJhdmVsLCBhbmQgZWFjaCByb3VuZFxuICAgKiAgcmVzdG9yZXMgYW5kIHJlLXByb2Nlc3NlcyBldmVyeSB0aWxlIG9mIGV2ZXJ5IGNoYW5uZWwg4oCUIHNvIHRoZSBidXJzdCBpcyBib3RoXG4gICAqICB3YXN0ZWQgd29yayBhbmQgdGhlIHJhY2UgdGhhdCBicmVha3MgY2FjaGUgcmVjb3JkcyAoc2VlIHtAbGluayBkaXNwbGF5VG9rZW59KS5cbiAgICogIFRoZSBzdG9yZSB3cml0ZSBzdGF5cyBsaXZlLCBzbyB0aGUgcGFuZSBpdHNlbGYgcmVtYWlucyByZXNwb25zaXZlLiAqL1xuICBzY2hlZHVsZUludmFsaWRhdGUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW52YWxpZGF0ZUhhbmRsZSAhPT0gbnVsbCkgcmV0dXJuOyAvLyBhbHJlYWR5IHF1ZXVlZCBmb3IgdGhpcyBmcmFtZVxuICAgIGNvbnN0IHJhZiA9XG4gICAgICB0eXBlb2YgcmVxdWVzdEFuaW1hdGlvbkZyYW1lID09PSAnZnVuY3Rpb24nXG4gICAgICAgID8gcmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gICAgICAgIDogKGNiOiBGcmFtZVJlcXVlc3RDYWxsYmFjaykgPT4gc2V0VGltZW91dCgoKSA9PiBjYigwKSwgMTYpIGFzIHVua25vd24gYXMgbnVtYmVyO1xuICAgIHRoaXMuaW52YWxpZGF0ZUhhbmRsZSA9IHJhZigoKSA9PiB7XG4gICAgICB0aGlzLmludmFsaWRhdGVIYW5kbGUgPSBudWxsO1xuICAgICAgdGhpcy5pbnZhbGlkYXRlRGlzcGxheSgpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIFJlLWFwcGx5IHRoZSBkaXNwbGF5IHBpcGVsaW5lICh3aW5kb3cvZ2FtbWEvY29sb3VyL2ludmVydCkgYWZ0ZXIgYSBzdGF0ZSBjaGFuZ2UuXG4gICAqICBNdWx0aWNoYW5uZWwgaW52YWxpZGF0ZXMgT05MWSB0aGUgdmlzaWJsZSBzbGljZSdzIGNoYW5uZWwgaW1hZ2VzIOKAlCBpbnZhbGlkYXRpbmdcbiAgICogIHRoZSB3aG9sZSB3b3JsZCB3b3VsZCByZS1wcm9jZXNzIGV2ZXJ5IGhpZGRlbi9wcmVsb2FkZWQgc2xpY2UncyB0aWxlcyAoaHVuZHJlZHMpLFxuICAgKiAgZmxvb2RpbmcgT1NEIHdpdGggXCJbQ2FjaGVSZWNvcmRdIOKApiBJbnZhbGlkU3RhdGVFcnJvclwiIGFuZCB3YXN0aW5nIHdvcmsgb24gdGlsZXNcbiAgICogIHRoYXQgYXJlbid0IG9uIHNjcmVlbi4gVGhlIG90aGVyIGNhY2hlZCBzbGljZXMgYXJlIG1hcmtlZCBzdGFsZSBhbmQgcmUtdGludGVkXG4gICAqICBsYXppbHkgd2hlbiByZXZlYWxlZC4gQ29tcG9zaXRlL2dyYXlzY2FsZSBpbnZhbGlkYXRlIHRoZSB3b3JsZDsgc2VydmVybGVzc1xuICAgKiAgbXVsdGljaGFubmVsIHJlLWNvbXBvc2l0ZXMgaXRzIGNhY2hlZCBwbGFuZXMuICovXG4gIGludmFsaWRhdGVEaXNwbGF5KCk6IHZvaWQge1xuICAgIC8vIFN1cGVyc2VkZSBhbnkgaW4tZmxpZ2h0IHJlY29sb3Igcm91bmQgYmVmb3JlIHJlc3RhcnRpbmcgb25lIChzZWUgZGlzcGxheVRva2VuKS5cbiAgICB0aGlzLmRpc3BsYXlUb2tlbisrO1xuICAgIGlmICghdGhpcy5ob3N0LnZpZXdlcigpKSByZXR1cm47XG4gICAgaWYgKHRoaXMuaG9zdC5pc1NpbXBsZU11bHRpY2hhbm5lbCgpKSB7XG4gICAgICB0aGlzLmhvc3QucmVjb21wb3NpdGUodGhpcy5kaXNwbGF5VG9rZW4pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy5ob3N0LmlzTXVsdGlDaGFubmVsKCkpIHtcbiAgICAgIHRoaXMuaG9zdC5pbnZhbGlkYXRlQ2hhbm5lbERpc3BsYXkodGhpcy5ob3N0LmN1cnJlbnRaKCkpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmludmFsaWRhdGVXb3JsZCgpO1xuICB9XG5cbiAgLyoqIFJlc3RvcmUgYW5kIHJlLXJlY29sb3IgZXZlcnkgdGlsZSBvZiB0aGUgbWFpbiB2aWV3ZXIgYW5kIHRoZSBuYXZpZ2F0b3IuICovXG4gIGludmFsaWRhdGVXb3JsZCgpOiB2b2lkIHtcbiAgICBjb25zdCB2ID0gdGhpcy5ob3N0LnZpZXdlcigpO1xuICAgIGlmICghdikgcmV0dXJuO1xuICAgIHF1aWV0KCgpID0+IHYud29ybGQucmVxdWVzdEludmFsaWRhdGUodHJ1ZSkpO1xuICAgIHF1aWV0KCgpID0+IHYubmF2aWdhdG9yPy53b3JsZD8ucmVxdWVzdEludmFsaWRhdGUodHJ1ZSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY29sb3IgYSBncmF5c2NhbGUgdGlsZSB0aHJvdWdoIHRoZSBhY3RpdmUgY29sb3JtYXAgTFVULCB1c2luZyBPU0Qnc1xuICAgKiB0aWxlLWludmFsaWRhdGVkIHBpeGVsIHBpcGVsaW5lIChPU0QgNSsvNikuIE1hcHMgZWFjaCBwaXhlbCdzIGdyYXlzY2FsZVxuICAgKiB2YWx1ZSAocj09Zz09YikgdG8gdGhlIExVVCdzIFJHQi4gTm8tb3AgZm9yIFJHQiBpbWFnZXMgb3IgdW50aWwgdGhlIExVVCBpc1xuICAgKiBidWlsdC4gSGFuZGxlciBpcyBhc3luYyDigJQgT1NEIGF3YWl0cyBpdCAocmFpc2VFdmVudEF3YWl0aW5nKS5cbiAgICovXG4gIGFzeW5jIHJlY29sb3JUaWxlKGV2ZW50OiBUaWxlRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5ob3N0LmlzTXVsdGlDaGFubmVsKCkpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVjb2xvckNoYW5uZWxUaWxlKGV2ZW50KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gQSBzZXJ2ZXJsZXNzIG11bHRpY2hhbm5lbCBjb21wb3NpdGUgaXMgZHJhd24gaW4gdGhlIGRpc3BsYXkgY29sb3VycyBhbHJlYWR5XG4gICAgLy8gKHJlY29tcG9zaXRlKTogcmVjb2xvdXJpbmcgaXRzIHRpbGVzIGFzIFJHQiBhcHBsaWVkIHRoZSB3aW5kb3csIGdhbW1hIGFuZFxuICAgIC8vIGludmVydCBhIHNlY29uZCB0aW1lLlxuICAgIGlmICh0aGlzLmhvc3QuaXNTaW1wbGVNdWx0aWNoYW5uZWwoKSkgcmV0dXJuO1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5kaXNwbGF5VG9rZW47XG4gICAgaWYgKHRoaXMuaG9zdC5pc0dyYXlzY2FsZSgpKSB7XG4gICAgICBpZiAoIXRoaXMuY29sb3JMdXQpIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLmRpc3BsYXkucmdiTmVlZHNSZWNvbG9yKCkpIHtcbiAgICAgIHJldHVybjsgLy8gUkdCIGF0IGRlZmF1bHQgKGFsbCB2aXNpYmxlLCBmdWxsIHdpbmRvdywgzrM9MSwgbm8gaW52ZXJ0KSDihpIgcGFzc3Rocm91Z2hcbiAgICB9XG5cbiAgICBjb25zdCBweCA9IGF3YWl0IHRoaXMucmVhZFRpbGVQaXhlbHMoZXZlbnQpO1xuICAgIGlmICghcHggfHwgIXRoaXMuZGlzcGxheS5hcHBseVRvUmdiYShweC5pbWcuZGF0YSkpIHJldHVybjsgLy8gbm90aGluZyBvcGFxdWVcbiAgICBhd2FpdCB0aGlzLndyaXRlVGlsZVBpeGVscyhldmVudCwgcHgsIHRva2VuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaW50IGEgc2luZ2xlIGNoYW5uZWwncyB0aWxlIGluIHBsYWNlLiBFYWNoIGNoYW5uZWwgaXMgaXRzIG93biBPcGVuU2VhZHJhZ29uXG4gICAqIFRpbGVkSW1hZ2UgKGEgc2luZ2xlLWJhbmQgZ3JheXNjYWxlIHRpbGUpOyBPU0QgY29tcG9zaXRlcyB0aGUgTiBpbWFnZXNcbiAgICogYWRkaXRpdmVseSAoJ2xpZ2h0ZXInKSBpbiBpdHMgZHJhd2VyIOKAlCBzbyB0aGlzIGp1c3QgbWFwcyB0aGUgdGlsZSdzIGludGVuc2l0eVxuICAgKiB0aHJvdWdoIHRoZSBjaGFubmVsJ3Mgd2luZG93L2dhbW1hIGFuZCBpdHMgcHNldWRvLWNvbG91ci4gU3luY2hyb25vdXMgKG5vXG4gICAqIGNyb3NzLXRpbGUgZmV0Y2gpIOKGkiBubyByYWNlLCBubyBzZWFtcy4gQ2hhbm5lbCBpcyBwYXJzZWQgZnJvbSB0aGUgdGlsZSBVUkwuXG4gICAqL1xuICBhc3luYyByZWNvbG9yQ2hhbm5lbFRpbGUoZXZlbnQ6IFRpbGVFdmVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5kaXNwbGF5VG9rZW47XG4gICAgY29uc3QgdGlsZSA9IGV2ZW50Py50aWxlO1xuICAgIGNvbnN0IHVybDogc3RyaW5nID0gKHRpbGUgJiYgKHR5cGVvZiB0aWxlLmdldFVybCA9PT0gJ2Z1bmN0aW9uJyA/IHRpbGUuZ2V0VXJsKCkgOiB0aWxlLnVybCkpIHx8ICcnO1xuICAgIGNvbnN0IG0gPSAvWz8mXWNoYW5uZWw9KFxcZCspLy5leGVjKHVybCk7XG4gICAgY29uc3QgY2ggPSBtID8gcGFyc2VJbnQobVsxXSwgMTApIDogMDtcbiAgICBjb25zdCBzdCA9IHRoaXMuY2hhbm5lbFN0YXRlc1tjaF07XG5cbiAgICBjb25zdCBweCA9IGF3YWl0IHRoaXMucmVhZFRpbGVQaXhlbHMoZXZlbnQpO1xuICAgIGlmICghcHgpIHJldHVybjtcblxuICAgIC8vIFByZWNvbXB1dGUgbHVtKDAuLjI1NSkg4oaSIHRpbnRlZCBSR0Igb25jZSwgdGhlbiBtYXAgZWFjaCBwaXhlbCBieSBsb29rdXAg4oCUXG4gICAgLy8gdGhlIGNoYW5uZWwgdGlsZSBpcyBzaW5nbGUtYmFuZCwgc28gdGhpcyB0dXJucyB+MjYyayBwZXItcGl4ZWxcbiAgICAvLyBjaGFubmVsSW50ZW5zaXR5KCkgKHdpdGggTWF0aC5wb3cgZm9yIGdhbW1hKSBjYWxscyBpbnRvIDI1NiDigJQgdGhlIGRpZmZlcmVuY2VcbiAgICAvLyBiZXR3ZWVuIGEgc25hcHB5IGFuZCBhIHNsdWdnaXNoIHNsaWRlciBvbiBhIDQtY2hhbm5lbCBzdGFjay5cbiAgICBjb25zdCB7IHI6IHJMLCBnOiBnTCwgYjogYkwgfSA9IHRoaXMuZGlzcGxheS5jaGFubmVsUmdiTHV0KHN0KTtcbiAgICBjb25zdCBkID0gcHguaW1nLmRhdGE7XG4gICAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGQubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgIGlmIChkW2kgKyAzXSA9PT0gMCkgY29udGludWU7XG4gICAgICBjb25zdCByID0gZFtpXSxcbiAgICAgICAgZyA9IGRbaSArIDFdLFxuICAgICAgICBiID0gZFtpICsgMl07XG4gICAgICBjb25zdCBsdW0gPSByID49IGcgPyAociA+PSBiID8gciA6IGIpIDogZyA+PSBiID8gZyA6IGI7IC8vIHNpbmdsZS1iYW5kIOKGkiBtYXhcbiAgICAgIGRbaV0gPSByTFtsdW1dO1xuICAgICAgZFtpICsgMV0gPSBnTFtsdW1dO1xuICAgICAgZFtpICsgMl0gPSBiTFtsdW1dO1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfVxuICAgIGlmICghY2hhbmdlZCkgcmV0dXJuO1xuICAgIGF3YWl0IHRoaXMud3JpdGVUaWxlUGl4ZWxzKGV2ZW50LCBweCwgdG9rZW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWQgYSB0aWxlJ3MgcGl4ZWxzIGZvciByZWNvbG9yaW5nLiBQcmVmZXJzIHRoZSB0aWxlJ3MgcmVuZGVyaW5nIGNvbnRleHQsXG4gICAqIGJ1dCBzb21lIHRpbGUgY2FjaGVzIChhamF4IFBORyBibG9icykgY29udmVydCB0byBhbiAqZW1wdHkqIGNvbnRleHQyZCDigJRcbiAgICogcmVjb2xvcmluZyB0aGF0IHdvdWxkIGJsYW5rIHRoZSB0aWxlICh3aGl0ZSBjYW52YXMpLiBTbyBpZiB0aGUgY29udGV4dCBoYXNcbiAgICogbm8gb3BhcXVlIHBpeGVscywgdGhlIHRpbGUncyBvd24gYml0bWFwL2ltYWdlIGlzIGRyYXduIHRvIGEgc2NyYXRjaCBjYW52YXNcbiAgICogYW5kIHJlYWQgaW5zdGVhZC4gTnVsbCB3aGVuIG5vIHBpeGVscyBjYW4gYmUgcmVhZDogbGVhdmUgdGhlIHRpbGUgdW50b3VjaGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZWFkVGlsZVBpeGVscyhldmVudDogVGlsZUV2ZW50KTogUHJvbWlzZTxUaWxlUGl4ZWxzIHwgbnVsbD4ge1xuICAgIGxldCBjdHg6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCB8IG51bGwgPSBudWxsO1xuICAgIHRyeSB7XG4gICAgICBjdHggPSAoYXdhaXQgZXZlbnQuZ2V0RGF0YSgnY29udGV4dDJkJykpIGFzIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRDtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8qIHRyeSB0aGUgYml0bWFwIGJlbG93ICovXG4gICAgfVxuICAgIGlmIChjdHggJiYgY3R4LmNhbnZhcyAmJiBjdHguY2FudmFzLndpZHRoICYmIGN0eC5jYW52YXMuaGVpZ2h0KSB7XG4gICAgICBsZXQgaW1nOiBJbWFnZURhdGEgfCBudWxsID0gbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGltZyA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgY3R4LmNhbnZhcy53aWR0aCwgY3R4LmNhbnZhcy5oZWlnaHQpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8qIHRhaW50ZWQvZ29uZSAqL1xuICAgICAgfVxuICAgICAgaWYgKGltZyAmJiBoYXNPcGFxdWUoaW1nLmRhdGEpKSByZXR1cm4geyBjdHgsIGltZyB9O1xuICAgIH1cbiAgICB0eXBlIERyYXdhYmxlID0gQ2FudmFzSW1hZ2VTb3VyY2UgJiB7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH07XG4gICAgbGV0IHNyYzogRHJhd2FibGUgfCBudWxsID0gbnVsbDtcbiAgICB0cnkge1xuICAgICAgc3JjID0gKGF3YWl0IGV2ZW50LmdldERhdGEoJ2ltYWdlQml0bWFwJykpIGFzIERyYXdhYmxlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLyogdHJ5IHRoZSBpbWFnZSBiZWxvdyAqL1xuICAgIH1cbiAgICBpZiAoIXNyYyB8fCAhc3JjLndpZHRoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBzcmMgPSAoYXdhaXQgZXZlbnQuZ2V0RGF0YSgnaW1hZ2UnKSkgYXMgRHJhd2FibGU7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLyogbm9uZSAqL1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXNyYyB8fCAhc3JjLndpZHRoKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBjID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgYy53aWR0aCA9IHNyYy53aWR0aDtcbiAgICBjLmhlaWdodCA9IHNyYy5oZWlnaHQ7XG4gICAgY29uc3Qgc2NyYXRjaCA9IGMuZ2V0Q29udGV4dCgnMmQnLCB7IHdpbGxSZWFkRnJlcXVlbnRseTogdHJ1ZSB9KTtcbiAgICBpZiAoIXNjcmF0Y2gpIHJldHVybiBudWxsO1xuICAgIHNjcmF0Y2guZHJhd0ltYWdlKHNyYywgMCwgMCk7XG4gICAgcmV0dXJuIHsgY3R4OiBzY3JhdGNoLCBpbWc6IHNjcmF0Y2guZ2V0SW1hZ2VEYXRhKDAsIDAsIGMud2lkdGgsIGMuaGVpZ2h0KSB9O1xuICB9XG5cbiAgLyoqIFdyaXRlIHJlY29sb3JlZCBwaXhlbHMgYmFjayB0byB0aGUgdGlsZSDigJQgdW5sZXNzIGEgbmV3ZXIgZGlzcGxheSByb3VuZFxuICAgKiAgKGB0b2tlbmAsIHNlZSB7QGxpbmsgZGlzcGxheVRva2VufSkgaGFzIGFscmVhZHkgcmVzdG9yZWQgaXQ6IHdyaXRpbmcgYVxuICAgKiAgc3VwZXJzZWRlZCBjb250ZXh0IGJhY2sgbWFrZXMgT1NEJ3MgY29udmVyc2lvbiB0aHJvdyBET01FeGNlcHRpb24sIHdoaWNoXG4gICAqICBkZXN0cm95cyB0aGUgY2FjaGUgcmVjb3JkIGFuZCB1bmxvYWRzIHRoZSB0aWxlLiAqL1xuICBwcml2YXRlIGFzeW5jIHdyaXRlVGlsZVBpeGVscyhldmVudDogVGlsZUV2ZW50LCBweDogVGlsZVBpeGVscywgdG9rZW46IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0b2tlbiAhPT0gdGhpcy5kaXNwbGF5VG9rZW4pIHJldHVybjtcbiAgICBweC5jdHgucHV0SW1hZ2VEYXRhKHB4LmltZywgMCwgMCk7XG4gICAgLy8gVGhlIHRpbGUncyBjYWNoZSBjYW4gc3RpbGwgYmUgZXZpY3RlZCBiZXR3ZWVuIHRoZSBhd2FpdHMgYW5kIGhlcmUgKGFcbiAgICAvLyBzbGljZSBjaGFuZ2UpLCBtYWtpbmcgc2V0RGF0YSB0aHJvdyBhIERPTUV4Y2VwdGlvbiBvbiBhIGRlYWQgY2FudmFzLlxuICAgIC8vIFN3YWxsb3cgaXQg4oCUIHRoZSB0aWxlIGlzIGdvbmUsIHNvIHRoZXJlJ3Mgbm90aGluZyB0byByZWNvbG9yLlxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBldmVudC5zZXREYXRhKHB4LmN0eCwgJ2NvbnRleHQyZCcpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLyogdGlsZSBldmljdGVkICovXG4gICAgfVxuICB9XG59XG5cbi8qKiBUcnVlIGlmIGFueSBwaXhlbCBpbiB0aGUgUkdCQSBidWZmZXIgaXMgbm9uLXRyYW5zcGFyZW50LiAqL1xuZnVuY3Rpb24gaGFzT3BhcXVlKGQ6IFVpbnQ4Q2xhbXBlZEFycmF5KTogYm9vbGVhbiB7XG4gIGZvciAobGV0IGkgPSAzOyBpIDwgZC5sZW5ndGg7IGkgKz0gNCkge1xuICAgIGlmIChkW2ldICE9PSAwKSByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG4iXX0=