@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.
- package/README.md +201 -460
- package/esm2022/index.mjs +28 -15
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +163 -91
- package/esm2022/lib/contracts/capabilities.contract.mjs +4 -3
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +5 -1
- package/esm2022/lib/contracts/color.mjs +60 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +213 -57
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +1 -1
- package/esm2022/lib/contracts/display-types.mjs +11 -1
- package/esm2022/lib/contracts/instance-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/intensity.mjs +48 -5
- package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
- package/esm2022/lib/contracts/plot-type.mjs +134 -17
- package/esm2022/lib/contracts/ports/image-state.port.mjs +4 -1
- package/esm2022/lib/contracts/ports/preferences.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/region-io.port.mjs +2 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +5 -1
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +2 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-overlay.contract.mjs +1 -1
- package/esm2022/lib/contracts/sam.contract.mjs +1 -1
- package/esm2022/lib/contracts/semantic-segmenter.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
- package/esm2022/lib/contracts/toolbar-tool.contract.mjs +6 -4
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/contracts/viz-config.mjs +2 -1
- package/esm2022/lib/geometry/contour.mjs +63 -0
- package/esm2022/lib/geometry/raster.mjs +98 -0
- package/esm2022/lib/geometry/ring.mjs +201 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +202 -102
- package/esm2022/lib/implementations/base-store-visualizer.mjs +201 -48
- package/esm2022/lib/implementations/napari-js/napari-axes-gizmo.mjs +65 -0
- package/esm2022/lib/implementations/napari-js/napari-display-state.mjs +136 -0
- package/esm2022/lib/implementations/napari-js/napari-helpers.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-image-2d-scene.mjs +602 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +3 -4
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +66 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +157 -591
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +2 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +614 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +769 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +199 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +263 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +159 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +106 -1408
- package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +2 -2
- package/esm2022/lib/implementations/napari-js/napari-surface-scene.mjs +271 -0
- package/esm2022/lib/implementations/napari-js/napari-tile-client.mjs +562 -0
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +344 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +358 -4218
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +439 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +6 -6
- package/esm2022/lib/implementations/napari-js/region-overlay/overlay-projection.mjs +96 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-edit.mjs +35 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +182 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/categorical-lookup.mjs +30 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +274 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/density-layer.mjs +144 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/layer-groups.mjs +165 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/plan-context.mjs +78 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-hover.mjs +182 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-jobs.mjs +369 -0
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +306 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +102 -40
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +56 -31
- package/esm2022/lib/implementations/osd/openseadragon-viewer-options.mjs +128 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +333 -1685
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/osd/osd-coords.mjs +5 -6
- package/esm2022/lib/implementations/osd/osd-export.mjs +122 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +15 -1
- package/esm2022/lib/implementations/osd/osd-navigator-chrome.mjs +205 -0
- package/esm2022/lib/implementations/osd/osd-pixel-readback.mjs +68 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +153 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +185 -718
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +52 -60
- package/esm2022/lib/implementations/osd/osd-tile-source.mjs +105 -0
- package/esm2022/lib/implementations/osd/osd-viewer-like.mjs +2 -0
- package/esm2022/lib/implementations/osd/osd-viewer-mount.mjs +44 -0
- package/esm2022/lib/implementations/osd/osd-viewport.mjs +184 -0
- package/esm2022/lib/implementations/osd/osd-zoom.mjs +7 -1
- package/esm2022/lib/implementations/osd/simple-source.mjs +395 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +53 -48
- package/esm2022/lib/implementations/osd/tile-client.mjs +32 -11
- package/esm2022/lib/implementations/osd/tile-recolor.mjs +330 -0
- package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +161 -73
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +1 -1
- package/esm2022/lib/implementations/plotly/plotly-image-loader.mjs +112 -0
- package/esm2022/lib/implementations/plotly/plotly-image-recolor.mjs +178 -0
- package/esm2022/lib/implementations/plotly/plotly-intensity-inset.mjs +33 -0
- package/esm2022/lib/implementations/plotly/plotly-isosurface-controls.mjs +83 -0
- package/esm2022/lib/implementations/plotly/plotly-layouts.mjs +121 -0
- package/esm2022/lib/implementations/plotly/plotly-readback.mjs +117 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +19 -10
- package/esm2022/lib/implementations/plotly/plotly-shape-projection.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +79 -19
- package/esm2022/lib/implementations/plotly/plotly-zoom-controller.mjs +223 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +439 -1655
- package/esm2022/lib/implementations/region-centroids.mjs +47 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +22 -12
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +172 -92
- package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +103 -22
- package/esm2022/lib/implementations/tile-server/index.mjs +6 -0
- package/esm2022/lib/implementations/tile-server/native-histogram.mjs +30 -0
- package/esm2022/lib/implementations/tile-server/poll-descriptor.mjs +65 -0
- package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +42 -0
- package/esm2022/lib/implementations/tile-server/transport.mjs +135 -0
- package/esm2022/lib/intensity/intensity-profile.mjs +107 -0
- package/esm2022/lib/intensity/intensity-profile.service.mjs +223 -0
- package/esm2022/lib/intensity-inset/intensity-inset.component.mjs +133 -0
- package/esm2022/lib/models/bezier.mjs +1 -11
- package/esm2022/lib/models/class-preset.mjs +41 -3
- package/esm2022/lib/models/geometry.mjs +27 -164
- package/esm2022/lib/models/polygon-edit.mjs +254 -0
- package/esm2022/lib/models/polygon-factory.mjs +118 -0
- package/esm2022/lib/models/region-clone.mjs +68 -0
- package/esm2022/lib/models/region-geojson.mjs +373 -0
- package/esm2022/lib/models/region.mjs +34 -33
- package/esm2022/lib/models/shape.mjs +18 -16
- package/esm2022/lib/plot-mode/contribution-host.mjs +297 -0
- package/esm2022/lib/plot-mode/plot-mode-controller.mjs +9 -6
- package/esm2022/lib/plot-mode/plot-type-menu.mjs +85 -0
- package/esm2022/lib/plot-mode/tool-params-model.mjs +87 -0
- package/esm2022/lib/plot.utilities.mjs +296 -473
- package/esm2022/lib/processing/image-crop.mjs +1 -1
- package/esm2022/lib/processing/processing-image.mjs +28 -15
- package/esm2022/lib/provide-visualization.mjs +40 -14
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +99 -0
- package/esm2022/lib/region-editor/file-stem.mjs +13 -0
- package/esm2022/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.mjs +118 -0
- package/esm2022/lib/region-editor/mask-export.service.mjs +98 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +11 -5
- package/esm2022/lib/region-editor/region-color-dialog/region-color-dialog.component.mjs +56 -0
- package/esm2022/lib/region-editor/region-editor-help/region-editor-help.component.mjs +28 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +402 -651
- package/esm2022/lib/region-editor/region-metrics.mjs +68 -0
- package/esm2022/lib/region-editor/region-persistence.service.mjs +134 -0
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +153 -0
- package/esm2022/lib/region-editor/save-mask-dialog/save-mask-dialog.component.mjs +91 -0
- package/esm2022/lib/region-editor/save-regions-dialog/save-regions-dialog.component.mjs +92 -0
- package/esm2022/lib/region-ops.service.mjs +28 -70
- package/esm2022/lib/region-overlay/region-geometry.mjs +360 -0
- package/esm2022/lib/region-overlay/region-hit-test.mjs +103 -0
- package/esm2022/lib/region-overlay/svg-region-renderer.mjs +228 -0
- package/esm2022/lib/render-orchestrator.mjs +14 -11
- package/esm2022/lib/render-session.mjs +207 -0
- package/esm2022/lib/routing-visualizer.service.mjs +459 -411
- package/esm2022/lib/spatial/density-raster.mjs +14 -0
- package/esm2022/lib/spatial/embedding-compute-coordinator.mjs +239 -0
- package/esm2022/lib/spatial/embedding-compute.mjs +43 -10
- package/esm2022/lib/spatial/gene-search.mjs +1 -1
- package/esm2022/lib/spatial/glyphs.mjs +97 -0
- package/esm2022/lib/spatial/lod.mjs +187 -0
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +200 -0
- package/esm2022/lib/spatial/spatial-density.mjs +25 -16
- package/esm2022/lib/spatial/spatial-encoding.mjs +26 -82
- package/esm2022/lib/spatial/spatial-expression.mjs +43 -42
- package/esm2022/lib/spatial/spatial-framing.mjs +1 -1
- package/esm2022/lib/spatial/spatial-heatmap.mjs +6 -3
- package/esm2022/lib/spatial/spatial-hover.mjs +5 -33
- package/esm2022/lib/spatial/spatial-panel-model.mjs +282 -0
- package/esm2022/lib/spatial/spatial-sections.mjs +1 -1
- package/esm2022/lib/spatial/spatial-selection.mjs +33 -46
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +219 -0
- package/esm2022/lib/spatial/spatial-tiles.mjs +12 -648
- package/esm2022/lib/spatial/spatial-volume-image.mjs +2 -4
- package/esm2022/lib/spatial/stats.mjs +71 -0
- package/esm2022/lib/spatial/transcript-grouping.mjs +307 -0
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +150 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-data-model.mjs +309 -0
- package/esm2022/lib/spatial-controls/spatial-charts/chart-help.mjs +145 -0
- package/esm2022/lib/spatial-controls/spatial-charts/plotly-chart-host.mjs +158 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.mjs +47 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +297 -802
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.mjs +89 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.mjs +52 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +143 -1238
- package/esm2022/lib/spatial-controls/spatial-gene-picker.mjs +153 -0
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +241 -0
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +193 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +132 -0
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.model.mjs +67 -0
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +147 -0
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +300 -0
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +370 -0
- package/esm2022/lib/store/class-color.util.mjs +46 -3
- package/esm2022/lib/store/region-history.mjs +146 -0
- package/esm2022/lib/store/region-scope-cache.mjs +140 -0
- package/esm2022/lib/store/region-selection.mjs +82 -0
- package/esm2022/lib/store/region-store.service.mjs +279 -675
- package/esm2022/lib/store/spatial-selection.service.mjs +2 -2
- package/esm2022/lib/store/visualizer-store.service.mjs +49 -71
- package/esm2022/lib/toast-outlets.mjs +5 -4
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +92 -434
- package/esm2022/lib/toolbar/canvas-tools.mjs +20 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +26 -42
- package/esm2022/lib/toolbar/plot-type-selector/plot-type-selector.component.mjs +85 -0
- package/esm2022/lib/toolbar/region-tools/region-tool-buttons.mjs +74 -0
- package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +114 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +74 -78
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +50 -8
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +61 -42
- package/esm2022/lib/toolbar/segmentation/pending-calls.mjs +47 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +12 -4
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +70 -14
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +135 -172
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +9 -90
- package/esm2022/lib/toolbar/segmentation/sam-session.service.mjs +183 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +95 -150
- package/esm2022/lib/toolbar/segmentation/segmentation-commit.mjs +12 -0
- package/esm2022/lib/toolbar/segmentation/segmentation-runner.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation-tools/segmentation-tools.component.mjs +155 -0
- package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +81 -0
- package/esm2022/lib/toolbar/tool-kit/async-tool-status.mjs +37 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool-manager.mjs +63 -0
- package/esm2022/lib/toolbar/tool-kit/canvas-tool.mjs +2 -0
- package/esm2022/lib/toolbar/tool-kit/frame-pixels.mjs +108 -0
- package/esm2022/lib/toolbar/tool-kit/mask-stroke-editor.mjs +306 -0
- package/esm2022/lib/toolbar/tool-kit/matrix-frame.mjs +61 -0
- package/esm2022/lib/toolbar/tool-kit/tool-overlay.mjs +140 -0
- package/esm2022/lib/toolbar/tool-kit/undo-gesture.mjs +24 -0
- package/esm2022/lib/toolbar/tool-slider/tool-slider.component.mjs +63 -0
- package/esm2022/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.mjs +50 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +68 -117
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +93 -115
- package/esm2022/lib/toolbar/view-controls/view-controls.component.mjs +107 -0
- package/esm2022/lib/toolbar/wand/wand-region-grow.mjs +321 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +121 -416
- package/esm2022/lib/toolbar/wand/wand.service.mjs +30 -894
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +48 -90
- package/esm2022/lib/util/mark-for-check.mjs +17 -0
- package/esm2022/lib/util/supersede.mjs +56 -0
- package/esm2022/lib/visualization.module.mjs +39 -141
- package/esm2022/lib/visualizer/floating-drag.directive.mjs +58 -0
- package/esm2022/lib/visualizer/region-actions.mjs +149 -0
- package/esm2022/lib/visualizer/region-load.mjs +60 -0
- package/esm2022/lib/visualizer/spatial-dataset-binder.mjs +163 -0
- package/esm2022/lib/visualizer/tool-modes.mjs +113 -0
- package/esm2022/lib/visualizer/viewer-shortcuts.mjs +167 -0
- package/esm2022/lib/visualizer/visualizer-context-menu.mjs +119 -0
- package/esm2022/lib/visualizer.component.mjs +480 -1902
- package/esm2022/lib/workers/spatial-math-ops.mjs +43 -0
- package/esm2022/lib/workers/spatial-math-worker.mjs +10 -0
- package/esm2022/lib/workers/spatial-math.mjs +190 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs +41083 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs +238 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-spatial-math-worker-BzVFFqGS.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +41 -34467
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
- package/fesm2022/mask.worker.js +36 -917
- package/fesm2022/onnx-sam.worker.js +52 -16
- package/fesm2022/spatial-math.worker.js +471 -0
- package/fesm2022/tsne.worker.js +32 -15
- package/index.d.ts +13 -10
- package/lib/channel-histogram/channel-histogram.component.d.ts +53 -43
- package/lib/contracts/capabilities.contract.d.ts +4 -2
- package/lib/contracts/cell-segmenter.contract.d.ts +1 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +4 -0
- package/lib/contracts/color.d.ts +27 -0
- package/lib/contracts/colormap-lut.d.ts +19 -4
- package/lib/contracts/coordinate-transform.contract.d.ts +3 -3
- package/lib/contracts/display-types.d.ts +21 -0
- package/lib/contracts/instance-segmenter.contract.d.ts +5 -0
- package/lib/contracts/intensity.d.ts +13 -2
- package/lib/contracts/plot-type.d.ts +3 -1
- package/lib/contracts/ports/image-state.port.d.ts +6 -2
- package/lib/contracts/ports/preferences.port.d.ts +4 -0
- package/lib/contracts/ports/region-io.port.d.ts +1 -0
- package/lib/contracts/ports/spatial-data.port.d.ts +4 -10
- package/lib/contracts/ports/tile-access.port.d.ts +1 -0
- package/lib/contracts/region-editor-api.contract.d.ts +1 -1
- package/lib/contracts/region-overlay.contract.d.ts +5 -0
- package/lib/contracts/sam.contract.d.ts +7 -0
- package/lib/contracts/semantic-segmenter.contract.d.ts +6 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +19 -6
- package/lib/contracts/toolbar-tool.contract.d.ts +1 -0
- package/lib/contracts/visualizer.contract.d.ts +221 -54
- package/lib/contracts/viz-config.d.ts +1 -0
- package/lib/geometry/contour.d.ts +24 -0
- package/lib/geometry/raster.d.ts +42 -0
- package/lib/geometry/ring.d.ts +67 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +61 -27
- package/lib/implementations/base-store-visualizer.d.ts +61 -15
- package/lib/implementations/napari-js/napari-axes-gizmo.d.ts +36 -0
- package/lib/implementations/napari-js/napari-display-state.d.ts +76 -0
- package/lib/implementations/napari-js/napari-helpers.d.ts +129 -0
- package/lib/implementations/napari-js/napari-image-2d-scene.d.ts +162 -0
- package/lib/implementations/napari-js/napari-loading-badge.d.ts +0 -1
- package/lib/implementations/napari-js/napari-loading-state.d.ts +30 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +62 -70
- package/lib/implementations/napari-js/napari-scene.d.ts +93 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +163 -0
- package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +212 -0
- package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +114 -0
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +89 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +118 -0
- package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +56 -263
- package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +1 -1
- package/lib/implementations/napari-js/napari-surface-scene.d.ts +76 -0
- package/lib/implementations/napari-js/napari-tile-client.d.ts +214 -0
- package/lib/implementations/napari-js/napari-tool-bridge.d.ts +179 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +121 -883
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +104 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +8 -12
- package/lib/implementations/napari-js/region-overlay/overlay-projection.d.ts +59 -0
- package/lib/implementations/napari-js/region-overlay/region-edit.d.ts +15 -0
- package/lib/implementations/napari-js/region-overlay/region-svg-renderer.d.ts +54 -0
- package/lib/implementations/napari-js/spatial-tiles/categorical-lookup.d.ts +26 -0
- package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +70 -0
- package/lib/implementations/napari-js/spatial-tiles/density-layer.d.ts +61 -0
- package/lib/implementations/napari-js/spatial-tiles/layer-groups.d.ts +67 -0
- package/lib/implementations/napari-js/spatial-tiles/plan-context.d.ts +38 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-hover.d.ts +71 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-jobs.d.ts +105 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +56 -0
- package/lib/implementations/osd/display-pipeline.d.ts +38 -9
- package/lib/implementations/osd/histogram-sampler.d.ts +22 -12
- package/lib/implementations/osd/openseadragon-viewer-options.d.ts +35 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +78 -354
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +2 -1
- package/lib/implementations/osd/osd-coords.d.ts +6 -4
- package/lib/implementations/osd/osd-export.d.ts +36 -0
- package/lib/implementations/osd/osd-lib.d.ts +7 -0
- package/lib/implementations/osd/osd-navigator-chrome.d.ts +69 -0
- package/lib/implementations/osd/osd-pixel-readback.d.ts +22 -0
- package/lib/implementations/osd/osd-region-overlay-draw.d.ts +37 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +36 -48
- package/lib/implementations/osd/osd-scale-bar.d.ts +8 -6
- package/lib/implementations/osd/osd-tile-source.d.ts +49 -0
- package/lib/implementations/osd/osd-viewer-like.d.ts +100 -0
- package/lib/implementations/osd/osd-viewer-mount.d.ts +14 -0
- package/lib/implementations/osd/osd-viewport.d.ts +77 -0
- package/lib/implementations/osd/osd-zoom.d.ts +6 -0
- package/lib/implementations/osd/simple-source.d.ts +161 -0
- package/lib/implementations/osd/slice-cache.d.ts +12 -3
- package/lib/implementations/osd/tile-client.d.ts +11 -14
- package/lib/implementations/osd/tile-recolor.d.ts +141 -0
- package/lib/implementations/plotly/omics-trace-builders.d.ts +32 -20
- package/lib/implementations/plotly/plotly-image-loader.d.ts +49 -0
- package/lib/implementations/plotly/plotly-image-recolor.d.ts +75 -0
- package/lib/implementations/plotly/plotly-intensity-inset.d.ts +8 -0
- package/lib/implementations/plotly/plotly-isosurface-controls.d.ts +38 -0
- package/lib/implementations/plotly/plotly-layouts.d.ts +188 -0
- package/lib/implementations/plotly/plotly-readback.d.ts +41 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +2 -2
- package/lib/implementations/plotly/plotly-shape-projection.d.ts +92 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +23 -12
- package/lib/implementations/plotly/plotly-zoom-controller.d.ts +86 -0
- package/lib/implementations/plotly/plotly.service.d.ts +136 -401
- package/lib/implementations/region-centroids.d.ts +14 -0
- package/lib/implementations/simple-slice-access.service.d.ts +7 -4
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +42 -18
- package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -9
- package/lib/implementations/tile-server/index.d.ts +5 -0
- package/lib/implementations/tile-server/native-histogram.d.ts +25 -0
- package/lib/implementations/tile-server/poll-descriptor.d.ts +39 -0
- package/lib/implementations/tile-server/tile-protocol.d.ts +80 -0
- package/lib/implementations/tile-server/transport.d.ts +62 -0
- package/lib/intensity/intensity-profile.d.ts +66 -0
- package/lib/intensity/intensity-profile.service.d.ts +108 -0
- package/lib/intensity-inset/intensity-inset.component.d.ts +58 -0
- package/lib/models/bezier.d.ts +0 -5
- package/lib/models/class-preset.d.ts +18 -0
- package/lib/models/geometry.d.ts +14 -48
- package/lib/models/polygon-edit.d.ts +72 -0
- package/lib/models/polygon-factory.d.ts +40 -0
- package/lib/models/region-clone.d.ts +20 -0
- package/lib/models/region-geojson.d.ts +17 -0
- package/lib/models/region.d.ts +40 -4
- package/lib/models/shape.d.ts +8 -0
- package/lib/plot-mode/contribution-host.d.ts +125 -0
- package/lib/plot-mode/plot-type-menu.d.ts +60 -0
- package/lib/plot-mode/tool-params-model.d.ts +49 -0
- package/lib/plot.utilities.d.ts +19 -30
- package/lib/processing/processing-image.d.ts +5 -2
- package/lib/provide-visualization.d.ts +19 -2
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +56 -0
- package/lib/region-editor/file-stem.d.ts +7 -0
- package/lib/region-editor/manage-classes-dialog/manage-classes-dialog.component.d.ts +45 -0
- package/lib/region-editor/mask-export.service.d.ts +54 -0
- package/lib/region-editor/mask-raster.d.ts +2 -8
- package/lib/region-editor/region-color-dialog/region-color-dialog.component.d.ts +29 -0
- package/lib/region-editor/region-editor-help/region-editor-help.component.d.ts +11 -0
- package/lib/region-editor/region-editor.component.d.ts +166 -199
- package/lib/region-editor/region-metrics.d.ts +26 -0
- package/lib/region-editor/region-persistence.service.d.ts +69 -0
- package/lib/region-editor/region-table/region-table.component.d.ts +83 -0
- package/lib/region-editor/save-mask-dialog/save-mask-dialog.component.d.ts +36 -0
- package/lib/region-editor/save-regions-dialog/save-regions-dialog.component.d.ts +37 -0
- package/lib/region-ops.service.d.ts +1 -7
- package/lib/region-overlay/region-geometry.d.ts +157 -0
- package/lib/region-overlay/region-hit-test.d.ts +38 -0
- package/lib/region-overlay/svg-region-renderer.d.ts +110 -0
- package/lib/render-orchestrator.d.ts +6 -2
- package/lib/render-session.d.ts +75 -0
- package/lib/routing-visualizer.service.d.ts +110 -58
- package/lib/spatial/density-raster.d.ts +6 -0
- package/lib/spatial/embedding-compute-coordinator.d.ts +123 -0
- package/lib/spatial/embedding-compute.d.ts +21 -2
- package/lib/spatial/glyphs.d.ts +16 -0
- package/lib/spatial/lod.d.ts +94 -0
- package/lib/spatial/spatial-controls.facade.d.ts +64 -0
- package/lib/spatial/spatial-density.d.ts +15 -5
- package/lib/spatial/spatial-encoding.d.ts +11 -44
- package/lib/spatial/spatial-expression.d.ts +40 -22
- package/lib/spatial/spatial-framing.d.ts +1 -0
- package/lib/spatial/spatial-heatmap.d.ts +2 -0
- package/lib/spatial/spatial-hover.d.ts +4 -16
- package/lib/spatial/spatial-panel-model.d.ts +135 -0
- package/lib/spatial/spatial-selection.d.ts +21 -26
- package/lib/spatial/spatial-tile-merge.d.ts +41 -0
- package/lib/spatial/spatial-tiles.d.ts +9 -256
- package/lib/spatial/stats.d.ts +38 -0
- package/lib/spatial/transcript-grouping.d.ts +119 -0
- package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-charts/chart-data-model.d.ts +153 -0
- package/lib/spatial-controls/spatial-charts/chart-help.d.ts +69 -0
- package/lib/spatial-controls/spatial-charts/plotly-chart-host.d.ts +98 -0
- package/lib/spatial-controls/spatial-charts/spatial-chart-window/spatial-chart-window.component.d.ts +26 -0
- package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +101 -260
- package/lib/spatial-controls/spatial-charts/spatial-embedding-controls/spatial-embedding-controls.component.d.ts +43 -0
- package/lib/spatial-controls/spatial-charts/spatial-heatmap-controls/spatial-heatmap-controls.component.d.ts +27 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +68 -448
- package/lib/spatial-controls/spatial-gene-picker.d.ts +86 -0
- package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +102 -0
- package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +72 -0
- package/lib/spatial-controls/spatial-key/spatial-key.component.d.ts +66 -0
- package/lib/spatial-controls/spatial-key/spatial-key.model.d.ts +33 -0
- package/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +117 -0
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +142 -0
- package/lib/store/class-color.util.d.ts +35 -1
- package/lib/store/region-history.d.ts +66 -0
- package/lib/store/region-scope-cache.d.ts +63 -0
- package/lib/store/region-selection.d.ts +36 -0
- package/lib/store/region-store.service.d.ts +104 -112
- package/lib/store/visualizer-store.service.d.ts +22 -33
- package/lib/toast-outlets.d.ts +4 -3
- package/lib/toolbar/brush/brush-tool.service.d.ts +31 -98
- package/lib/toolbar/canvas-tools.d.ts +20 -0
- package/lib/toolbar/crop/slide-crop.d.ts +10 -4
- package/lib/toolbar/plot-type-selector/plot-type-selector.component.d.ts +38 -0
- package/lib/toolbar/region-tools/region-tool-buttons.d.ts +21 -0
- package/lib/toolbar/region-tools/region-tools.component.d.ts +60 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +10 -14
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +12 -2
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +22 -3
- package/lib/toolbar/segmentation/pending-calls.d.ts +31 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +9 -3
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +18 -5
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +46 -32
- package/lib/toolbar/segmentation/sam-prompt.d.ts +7 -31
- package/lib/toolbar/segmentation/sam-session.service.d.ts +74 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +23 -30
- package/lib/toolbar/segmentation/segmentation-commit.d.ts +8 -0
- package/lib/toolbar/segmentation/segmentation-runner.d.ts +52 -0
- package/lib/toolbar/segmentation-tools/segmentation-tools.component.d.ts +87 -0
- package/lib/toolbar/stack-controls/stack-controls.component.d.ts +40 -0
- package/lib/toolbar/tool-kit/async-tool-status.d.ts +21 -0
- package/lib/toolbar/tool-kit/canvas-tool-manager.d.ts +36 -0
- package/lib/toolbar/tool-kit/canvas-tool.d.ts +86 -0
- package/lib/toolbar/tool-kit/frame-pixels.d.ts +45 -0
- package/lib/toolbar/tool-kit/mask-stroke-editor.d.ts +125 -0
- package/lib/toolbar/tool-kit/matrix-frame.d.ts +40 -0
- package/lib/toolbar/tool-kit/tool-overlay.d.ts +60 -0
- package/lib/toolbar/tool-kit/undo-gesture.d.ts +17 -0
- package/lib/toolbar/tool-slider/tool-slider.component.d.ts +33 -0
- package/lib/toolbar/toolbar-help-dialog/toolbar-help-dialog.component.d.ts +24 -0
- package/lib/toolbar/toolbar.component.d.ts +47 -83
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +33 -40
- package/lib/toolbar/view-controls/view-controls.component.d.ts +54 -0
- package/lib/toolbar/wand/wand-region-grow.d.ts +49 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +39 -124
- package/lib/toolbar/wand/wand.service.d.ts +22 -116
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +17 -37
- package/lib/util/mark-for-check.d.ts +11 -0
- package/lib/util/supersede.d.ts +53 -0
- package/lib/visualization.module.d.ts +18 -39
- package/lib/visualizer/floating-drag.directive.d.ts +30 -0
- package/lib/visualizer/region-actions.d.ts +54 -0
- package/lib/visualizer/region-load.d.ts +27 -0
- package/lib/visualizer/spatial-dataset-binder.d.ts +74 -0
- package/lib/visualizer/tool-modes.d.ts +49 -0
- package/lib/visualizer/viewer-shortcuts.d.ts +71 -0
- package/lib/visualizer/visualizer-context-menu.d.ts +55 -0
- package/lib/visualizer.component.d.ts +201 -447
- package/lib/workers/spatial-math-ops.d.ts +65 -0
- package/lib/workers/spatial-math-worker.d.ts +7 -0
- package/lib/workers/spatial-math.d.ts +74 -0
- package/package.json +12 -3
- package/src/lib/styles/_viz-icons-rules.scss +73 -0
- package/src/lib/styles/viz-icons.scss +14 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +0 -97
- package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +0 -195
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +0 -92
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs +0 -329
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map +0 -1
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +0 -49
- package/lib/implementations/napari-js/napari-navigator.d.ts +0 -72
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +0 -35
- package/src/lib/assets/cell-detection.svg +0 -37
- package/src/lib/assets/click.svg +0 -1
- package/src/lib/assets/colormap-luts.json +0 -1
- package/src/lib/assets/edit-selection-white.svg +0 -47
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +0 -1
- package/src/lib/assets/picture-segmentation.svg +0 -43
- package/src/lib/assets/test/download-379.svg +0 -1
- package/src/lib/assets/test/download-98.svg +0 -1
- package/src/lib/assets/test/json-1.svg +0 -1
- package/src/lib/assets/test/load-53.svg +0 -1
- package/src/lib/assets/test/mask-44.svg +0 -1
- package/src/lib/assets/test/mask-download-44.svg +0 -15
- package/src/lib/assets/test/mask-save-44.svg +0 -11
- package/src/lib/assets/test/overlay-1.svg +0 -1
- package/src/lib/assets/test/overlay-4.svg +0 -1
- package/src/lib/assets/test/region-26.svg +0 -1
- package/src/lib/assets/test/save-56.svg +0 -1
- 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=
|