@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,274 @@
|
|
|
1
|
+
import { colormapFromLut } from 'napari-js';
|
|
2
|
+
import { NO_CATEGORY, isCategoricalColumn, } from '../../../contracts/spatial-dataset.contract';
|
|
3
|
+
import { DEFAULT_CATEGORICAL_PALETTE, MISSING_COLOR, contrastWindow, parseHex, resolveCategoryColors, } from '../../../spatial/spatial-encoding';
|
|
4
|
+
import { POLYGON_LEVEL_MIN_CELL_PX, cellTypeColumnFor, cellsShown, polygonLevelFor, tileId, tilesInRect, typicalCellDiameter, } from '../../../spatial/lod';
|
|
5
|
+
import { filterRings, mergePolygonTiles } from '../../../spatial/spatial-tile-merge';
|
|
6
|
+
import { ContrastWindowCache } from '../napari-spatial-encoding';
|
|
7
|
+
const MAX_CELL_TILES = 48;
|
|
8
|
+
/**
|
|
9
|
+
* The cell outlines of the 2D spatial view, at the polygon level the zoom calls for: a fill,
|
|
10
|
+
* an outline or both (plus nucleus outlines for the "both" cell set), coloured by the view's
|
|
11
|
+
* cell-colour mode, with switched-off groups left out of the geometry.
|
|
12
|
+
*
|
|
13
|
+
* Geometry and style are keyed apart, so a recolour (a new cell-type column, a selection)
|
|
14
|
+
* rewrites the per-shape values of the existing layers and never re-expands the rings.
|
|
15
|
+
*/
|
|
16
|
+
export class CellLayers {
|
|
17
|
+
constructor(port, groups, lookup, host) {
|
|
18
|
+
this.port = port;
|
|
19
|
+
this.groups = groups;
|
|
20
|
+
this.lookup = lookup;
|
|
21
|
+
this.host = host;
|
|
22
|
+
this.polygonsShown = false;
|
|
23
|
+
/** Rings currently drawn and the (dataset, set, tiles) they came from. */
|
|
24
|
+
this.currentRings = null;
|
|
25
|
+
this.cellGeometryKey = null;
|
|
26
|
+
this.currentNuclei = null;
|
|
27
|
+
this.cellStyleKey = null;
|
|
28
|
+
/** Selection identity → revision, so a change key can name a selection cheaply. */
|
|
29
|
+
this.lastSelection = null;
|
|
30
|
+
this.selectionRevision = 0;
|
|
31
|
+
/** Continuous colourings' windows, per (vector, clip, log): `contrastWindow` sorts every
|
|
32
|
+
* value, and a selection or opacity change recolours with the vector unchanged (SPATIAL-12). */
|
|
33
|
+
this.contrastWindows = new ContrastWindowCache();
|
|
34
|
+
}
|
|
35
|
+
/** True while outlines are on screen — the service hides its dots then. */
|
|
36
|
+
get outlinesShown() {
|
|
37
|
+
return this.polygonsShown;
|
|
38
|
+
}
|
|
39
|
+
/** The viewer went away (its layers with it): the outlines are no longer shown. */
|
|
40
|
+
detached() {
|
|
41
|
+
this.setPolygonsShown(false);
|
|
42
|
+
}
|
|
43
|
+
/** Draw the cells covering `rect` at the level `pxPerUnit` calls for, or drop them. */
|
|
44
|
+
async plan(dataset, view, selection, rect, pxPerUnit, ctx) {
|
|
45
|
+
const tiled = dataset.polygonTiles;
|
|
46
|
+
const whole = !tiled && dataset.polygons && this.port.getPolygons;
|
|
47
|
+
if (!cellsShown(dataset, view) || (!tiled && !whole)) {
|
|
48
|
+
this.drop();
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const diameter = typicalCellDiameter(dataset.observations.radius);
|
|
52
|
+
// Whole-dataset rings have one level and no coarser fallback, so they are drawn as
|
|
53
|
+
// soon as a cell is big enough to read as a shape rather than a dot.
|
|
54
|
+
const level = tiled
|
|
55
|
+
? polygonLevelFor(pxPerUnit, diameter, tiled.levels.length)
|
|
56
|
+
: pxPerUnit * diameter >= POLYGON_LEVEL_MIN_CELL_PX[2]
|
|
57
|
+
? 0
|
|
58
|
+
: -1;
|
|
59
|
+
if (level < 0) {
|
|
60
|
+
this.drop();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Groups switched off in the list: their cells are left out of the geometry.
|
|
64
|
+
const hidden = await this.lookup.hiddenCodes(dataset, view);
|
|
65
|
+
if (ctx.stale())
|
|
66
|
+
return;
|
|
67
|
+
const label = view.cellSet === 'both' ? 'Cells and nuclei' : view.cellSet === 'nucleus' ? 'Nuclei' : 'Cells';
|
|
68
|
+
const geometry = await ctx.track(label, this.cellGeometry(dataset, view, rect, level, hidden, ctx));
|
|
69
|
+
if (!geometry)
|
|
70
|
+
return;
|
|
71
|
+
const { rings, nuclei, geometryKey } = geometry;
|
|
72
|
+
const geometryChanged = geometryKey !== this.cellGeometryKey;
|
|
73
|
+
const styleKey = [
|
|
74
|
+
geometryKey,
|
|
75
|
+
view.cellColorMode,
|
|
76
|
+
view.cellColorGene,
|
|
77
|
+
view.cellSingleColor,
|
|
78
|
+
cellTypeColumnFor(dataset, view),
|
|
79
|
+
this.selectionRev(selection),
|
|
80
|
+
view.logScale,
|
|
81
|
+
view.percentileClip.join(),
|
|
82
|
+
JSON.stringify(view.continuousColormap),
|
|
83
|
+
view.cellDraw,
|
|
84
|
+
view.cellOpacity,
|
|
85
|
+
].join('|');
|
|
86
|
+
const present = ['cellFill', 'cellOutline', 'nucleusOutline'].some((g) => this.groups.shown(g));
|
|
87
|
+
if (!geometryChanged && styleKey === this.cellStyleKey && present) {
|
|
88
|
+
this.setPolygonsShown(true);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const colors = await this.cellColors(dataset, view, selection, rings.observation);
|
|
92
|
+
if (ctx.stale())
|
|
93
|
+
return;
|
|
94
|
+
this.currentRings = rings;
|
|
95
|
+
this.currentNuclei = nuclei;
|
|
96
|
+
// A geometry missing a failed tile is drawn but not remembered, so the retry refetches it.
|
|
97
|
+
this.cellGeometryKey = ctx.incomplete ? null : geometryKey;
|
|
98
|
+
this.cellStyleKey = styleKey;
|
|
99
|
+
this.drawCells(dataset, view, geometry, colors, geometryChanged);
|
|
100
|
+
this.setPolygonsShown(true);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The cell layers: the fill and the outline the view's draw mode asks for, and with "both" the
|
|
104
|
+
* nucleus outlines over them. A geometry change builds new layers; a style change restyles them.
|
|
105
|
+
*/
|
|
106
|
+
drawCells(dataset, view, { rings, nuclei }, colors, geometryChanged) {
|
|
107
|
+
const ref = dataset.imageRef;
|
|
108
|
+
const common = { scale: ref?.scale ?? [1, 1], translate: ref?.translate ?? [0, 0] };
|
|
109
|
+
const fill = view.cellDraw !== 'outline';
|
|
110
|
+
const outline = view.cellDraw !== 'fill';
|
|
111
|
+
this.groups.upsertShapes('cellFill', fill, geometryChanged, rings, {
|
|
112
|
+
name: 'cells',
|
|
113
|
+
draw: 'fill',
|
|
114
|
+
opacity: view.cellOpacity,
|
|
115
|
+
...colors,
|
|
116
|
+
...common,
|
|
117
|
+
});
|
|
118
|
+
this.groups.upsertShapes('cellOutline', outline, geometryChanged, rings, fill
|
|
119
|
+
? // Over a fill, a dark outline separates neighbours of the same type.
|
|
120
|
+
{ name: 'cell outlines', draw: 'outline', color: [0.08, 0.08, 0.1, 1], opacity: 0.7, ...common }
|
|
121
|
+
: { name: 'cell outlines', draw: 'outline', opacity: 1, ...colors, ...common });
|
|
122
|
+
// "Both": nuclei outlined over the cells, light so they read against any fill.
|
|
123
|
+
if (nuclei) {
|
|
124
|
+
this.groups.upsertShapes('nucleusOutline', true, geometryChanged, nuclei, {
|
|
125
|
+
name: 'nucleus outlines',
|
|
126
|
+
draw: 'outline',
|
|
127
|
+
color: [0.95, 0.95, 0.98, 1],
|
|
128
|
+
opacity: 0.8,
|
|
129
|
+
...common,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this.groups.drop('nucleusOutline');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
selectionRev(selection) {
|
|
137
|
+
if (selection !== this.lastSelection) {
|
|
138
|
+
this.lastSelection = selection;
|
|
139
|
+
this.selectionRevision++;
|
|
140
|
+
}
|
|
141
|
+
return this.selectionRevision;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The rings' colours by their owners, by the view's cell-colour mode (Xenium Explorer's "Cell
|
|
145
|
+
* Color"): one RGBA per shape for a grouping, values + colormap for a measurement, one colour
|
|
146
|
+
* for "single". A selection mutes what it leaves out.
|
|
147
|
+
*/
|
|
148
|
+
async cellColors(dataset, view, selection, owners) {
|
|
149
|
+
const muted = selection.count > 0 ? selection.mask : null;
|
|
150
|
+
const mode = view.cellColorMode;
|
|
151
|
+
if (mode === 'single') {
|
|
152
|
+
const [r, g, b] = parseHex(view.cellSingleColor);
|
|
153
|
+
return { color: [r / 255, g / 255, b / 255, 1] };
|
|
154
|
+
}
|
|
155
|
+
const continuous = async (raw, log) => {
|
|
156
|
+
const values = new Float32Array(owners.length);
|
|
157
|
+
for (let i = 0; i < owners.length; i++) {
|
|
158
|
+
const v = raw[owners[i]] ?? NaN;
|
|
159
|
+
values[i] = log ? Math.log1p(Math.max(0, v)) : v;
|
|
160
|
+
}
|
|
161
|
+
const [clipLo, clipHi] = view.percentileClip;
|
|
162
|
+
// Keyed by the SOURCE vector (the log copy would be new on every call), as the 3D cloud's.
|
|
163
|
+
const [lo, hi] = this.contrastWindows.get(raw, clipLo, clipHi, log, () => contrastWindow(log ? raw.map((v) => Math.log1p(Math.max(0, v))) : raw, clipLo, clipHi));
|
|
164
|
+
return {
|
|
165
|
+
values,
|
|
166
|
+
colormap: colormapFromLut('spatial-continuous', this.host.continuousLut(view)),
|
|
167
|
+
contrastLimits: [lo, hi],
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
if (mode === 'gene' && view.cellColorGene) {
|
|
171
|
+
return continuous(await this.port.getFeatureVector(view.cellColorGene), true);
|
|
172
|
+
}
|
|
173
|
+
if (mode === 'transcriptDensity' && dataset.columns.some((c) => c.name === 'transcript_density')) {
|
|
174
|
+
const column = await this.port.getColumn('transcript_density');
|
|
175
|
+
if (!isCategoricalColumn(column))
|
|
176
|
+
return continuous(column.values, false);
|
|
177
|
+
}
|
|
178
|
+
const name = mode === 'segmentation' && dataset.columns.some((c) => c.name === 'segmentation_method')
|
|
179
|
+
? 'segmentation_method'
|
|
180
|
+
: cellTypeColumnFor(dataset, view);
|
|
181
|
+
const codes = name ? await this.lookup.codes(name) : null;
|
|
182
|
+
const palette = categoryRgba(codes?.meta ?? null);
|
|
183
|
+
const missing = rgba01(MISSING_COLOR);
|
|
184
|
+
// One RGBA per shape (napari Shapes' `face_color`): any number of categories keeps its own
|
|
185
|
+
// colour, where a colormap band per category ran out of LUT entries past ~127.
|
|
186
|
+
const faceColor = new Float32Array(owners.length * 4);
|
|
187
|
+
for (let i = 0; i < owners.length; i++) {
|
|
188
|
+
const o = owners[i];
|
|
189
|
+
const code = !codes || (muted && !muted[o]) ? NO_CATEGORY : codes.codes[o];
|
|
190
|
+
faceColor.set(palette[code] ?? missing, i * 4);
|
|
191
|
+
}
|
|
192
|
+
return { faceColor };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The cell rings (and, for "both", the nucleus rings) covering `rect` at `level`, minus
|
|
196
|
+
* the hidden groups — reused when nothing that decides them changed. Null when the
|
|
197
|
+
* view went stale or the dataset has no set to draw.
|
|
198
|
+
*/
|
|
199
|
+
async cellGeometry(dataset, view, rect, level, hidden, ctx) {
|
|
200
|
+
const tiled = dataset.polygonTiles;
|
|
201
|
+
const hiddenKey = view.hiddenGroups.join('\u0001');
|
|
202
|
+
let rings;
|
|
203
|
+
let nuclei = null;
|
|
204
|
+
let geometryKey;
|
|
205
|
+
if (tiled) {
|
|
206
|
+
const both = view.cellSet === 'both';
|
|
207
|
+
const set = !both && view.cellSet && tiled.sets.some((s) => s.name === view.cellSet)
|
|
208
|
+
? view.cellSet
|
|
209
|
+
: (tiled.defaultSet ?? tiled.sets[0]?.name);
|
|
210
|
+
if (!set)
|
|
211
|
+
return null;
|
|
212
|
+
const nucleusSet = both ? tiled.sets.find((s) => s.name !== set)?.name : undefined;
|
|
213
|
+
const keys = tilesInRect(rect, level, tiled.levels, tiled.bounds, MAX_CELL_TILES);
|
|
214
|
+
geometryKey = `${dataset.id}|${set}|${nucleusSet ?? ''}|${hiddenKey}|${keys.map(tileId).join(',')}`;
|
|
215
|
+
if (geometryKey === this.cellGeometryKey && this.currentRings) {
|
|
216
|
+
rings = this.currentRings;
|
|
217
|
+
nuclei = this.currentNuclei;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const [tiles, nucleusTiles] = await Promise.all([
|
|
221
|
+
ctx.fetchAll(keys, (k) => this.port.getPolygonTile(set, k.level, k.gx, k.gy)),
|
|
222
|
+
nucleusSet
|
|
223
|
+
? ctx.fetchAll(keys, (k) => this.port.getPolygonTile(nucleusSet, k.level, k.gx, k.gy))
|
|
224
|
+
: Promise.resolve(null),
|
|
225
|
+
]);
|
|
226
|
+
if (ctx.stale())
|
|
227
|
+
return null;
|
|
228
|
+
rings = filterRings(mergePolygonTiles(tiles), hidden);
|
|
229
|
+
nuclei = nucleusTiles ? filterRings(mergePolygonTiles(nucleusTiles), hidden) : null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
geometryKey = `${dataset.id}|whole|${hiddenKey}`;
|
|
234
|
+
if (geometryKey === this.cellGeometryKey && this.currentRings) {
|
|
235
|
+
rings = this.currentRings;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const polys = await this.port.getPolygons();
|
|
239
|
+
if (ctx.stale())
|
|
240
|
+
return null;
|
|
241
|
+
// Whole-dataset rings are index-aligned with the observations.
|
|
242
|
+
rings = filterRings({ ...polys, observation: Uint32Array.from({ length: polys.count }, (_v, i) => i) }, hidden);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return { rings, nuclei, geometryKey };
|
|
246
|
+
}
|
|
247
|
+
/** Remove the cell layers and forget what they showed. */
|
|
248
|
+
drop() {
|
|
249
|
+
this.groups.drop('cellFill');
|
|
250
|
+
this.groups.drop('cellOutline');
|
|
251
|
+
this.groups.drop('nucleusOutline');
|
|
252
|
+
this.currentNuclei = null;
|
|
253
|
+
this.cellGeometryKey = null;
|
|
254
|
+
this.cellStyleKey = null;
|
|
255
|
+
this.currentRings = null;
|
|
256
|
+
this.setPolygonsShown(false);
|
|
257
|
+
}
|
|
258
|
+
setPolygonsShown(shown) {
|
|
259
|
+
if (shown === this.polygonsShown)
|
|
260
|
+
return;
|
|
261
|
+
this.polygonsShown = shown;
|
|
262
|
+
this.host.polygonsShownChanged(shown);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** An 8-bit RGB as an opaque 0..1 RGBA. */
|
|
266
|
+
function rgba01([r, g, b]) {
|
|
267
|
+
return [r / 255, g / 255, b / 255, 1];
|
|
268
|
+
}
|
|
269
|
+
/** A grouping's category colours, as 0..1 RGBA by category code (one default without a grouping). */
|
|
270
|
+
function categoryRgba(meta) {
|
|
271
|
+
const hex = meta && meta.kind === 'categorical' ? resolveCategoryColors(meta) : [DEFAULT_CATEGORICAL_PALETTE[0]];
|
|
272
|
+
return hex.map((h) => rgba01(parseHex(h)));
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VsbC1sYXllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9uYXBhcmktanMvc3BhdGlhbC10aWxlcy9jZWxsLWxheWVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBTTVDLE9BQU8sRUFDTCxXQUFXLEVBS1gsbUJBQW1CLEdBQ3BCLE1BQU0sNkNBQTZDLENBQUM7QUFDckQsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixhQUFhLEVBQ2IsY0FBYyxFQUNkLFFBQVEsRUFDUixxQkFBcUIsR0FDdEIsTUFBTSxtQ0FBbUMsQ0FBQztBQUUzQyxPQUFPLEVBRUwseUJBQXlCLEVBQ3pCLGlCQUFpQixFQUNqQixVQUFVLEVBQ1YsZUFBZSxFQUNmLE1BQU0sRUFDTixXQUFXLEVBQ1gsbUJBQW1CLEdBQ3BCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3JGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBS2pFLE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQztBQW9CMUI7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxVQUFVO0lBY3JCLFlBQ21CLElBQXFCLEVBQ3JCLE1BQXFDLEVBQ3JDLE1BQXlCLEVBQ3pCLElBQW9CO1FBSHBCLFNBQUksR0FBSixJQUFJLENBQWlCO1FBQ3JCLFdBQU0sR0FBTixNQUFNLENBQStCO1FBQ3JDLFdBQU0sR0FBTixNQUFNLENBQW1CO1FBQ3pCLFNBQUksR0FBSixJQUFJLENBQWdCO1FBakIvQixrQkFBYSxHQUFHLEtBQUssQ0FBQztRQUM5QiwwRUFBMEU7UUFDbEUsaUJBQVksR0FBOEIsSUFBSSxDQUFDO1FBQy9DLG9CQUFlLEdBQWtCLElBQUksQ0FBQztRQUN0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cG9ydCB7IGNvbG9ybWFwRnJvbUx1dCB9IGZyb20gJ25hcGFyaS1qcyc7XG5pbXBvcnQgdHlwZSB7IENvbG9ybWFwLCBSR0JBIH0gZnJvbSAnbmFwYXJpLWpzJztcblxuaW1wb3J0IHR5cGUgeyBSZ2IgfSBmcm9tICcuLi8uLi8uLi9jb250cmFjdHMvY29sb3JtYXAtbHV0JztcbmltcG9ydCB0eXBlIHsgU3BhdGlhbERhdGFQb3J0IH0gZnJvbSAnLi4vLi4vLi4vY29udHJhY3RzL3BvcnRzL3NwYXRpYWwtZGF0YS5wb3J0JztcbmltcG9ydCB0eXBlIHsgU3BhdGlhbFZpZXdTdGF0ZSB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9kaXNwbGF5LXR5cGVzJztcbmltcG9ydCB7XG4gIE5PX0NBVEVHT1JZLFxuICBTcGF0aWFsQ29sdW1uLFxuICBTcGF0aWFsRGF0YXNldCxcbiAgU3BhdGlhbFBvbHlnb25UaWxlLFxuICBTcGF0aWFsUG9seWdvbnMsXG4gIGlzQ2F0ZWdvcmljYWxDb2x1bW4sXG59IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9zcGF0aWFsLWRhdGFzZXQuY29udHJhY3QnO1xuaW1wb3J0IHtcbiAgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFLFxuICBNSVNTSU5HX0NPTE9SLFxuICBjb250cmFzdFdpbmRvdyxcbiAgcGFyc2VIZXgsXG4gIHJlc29sdmVDYXRlZ29yeUNvbG9ycyxcbn0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB7IFNwYXRpYWxTZWxlY3Rpb25NYXNrIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXNlbGVjdGlvbic7XG5pbXBvcnQge1xuICBEYXRhUmVjdCxcbiAgUE9MWUdPTl9MRVZFTF9NSU5fQ0VMTF9QWCxcbiAgY2VsbFR5cGVDb2x1bW5Gb3IsXG4gIGNlbGxzU2hvd24sXG4gIHBvbHlnb25MZXZlbEZvcixcbiAgdGlsZUlkLFxuICB0aWxlc0luUmVjdCxcbiAgdHlwaWNhbENlbGxEaWFtZXRlcixcbn0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9sb2QnO1xuaW1wb3J0IHsgZmlsdGVyUmluZ3MsIG1lcmdlUG9seWdvblRpbGVzIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXRpbGUtbWVyZ2UnO1xuaW1wb3J0IHsgQ29udHJhc3RXaW5kb3dDYWNoZSB9IGZyb20gJy4uL25hcGFyaS1zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB0eXBlIHsgQ2F0ZWdvcmljYWxMb29rdXAsIEhpZGRlbkNvZGVzIH0gZnJvbSAnLi9jYXRlZ29yaWNhbC1sb29rdXAnO1xuaW1wb3J0IHR5cGUgeyBPcmRlcmVkTGF5ZXJHcm91cHMsIFRpbGVHcm91cCB9IGZyb20gJy4vbGF5ZXItZ3JvdXBzJztcbmltcG9ydCB0eXBlIHsgUGxhbkNvbnRleHQgfSBmcm9tICcuL3BsYW4tY29udGV4dCc7XG5cbmNvbnN0IE1BWF9DRUxMX1RJTEVTID0gNDg7XG5cbi8qKiBUaGUgY2VsbHMnIGNvbG91cnMgYXMgYSBzaGFwZXMgbGF5ZXIgdGFrZXMgdGhlbTogcGVyLXNoYXBlIFJHQkEsIHZhbHVlcyBvdmVyIGEgY29sb3JtYXAsIG9yXG4gKiAgb25lIGNvbG91ci4gKi9cbmludGVyZmFjZSBDZWxsQ29sb3JzIHtcbiAgdmFsdWVzPzogRmxvYXQzMkFycmF5O1xuICBjb2xvcm1hcD86IENvbG9ybWFwO1xuICBjb250cmFzdExpbWl0cz86IFtudW1iZXIsIG51bWJlcl07XG4gIGNvbG9yPzogUkdCQTtcbiAgZmFjZUNvbG9yPzogRmxvYXQzMkFycmF5O1xufVxuXG4vKiogV2hhdCB0aGUgY2VsbCBsYXllcnMgbmVlZCBmcm9tIHRoZSBzZXJ2aWNlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDZWxsTGF5ZXJzSG9zdCB7XG4gIC8qKiBUaGUgY29udGludW91cyBMVVQgdGhlIHZpZXcgaXMgdXNpbmcgKHNvIGNlbGxzIGNvbG91cmVkIGJ5IGEgZ2VuZSBtYXRjaCB0aGUgbWFya2VycykuICovXG4gIGNvbnRpbnVvdXNMdXQodmlldzogU3BhdGlhbFZpZXdTdGF0ZSk6IFJnYltdO1xuICAvKiogT3V0bGluZXMgYXBwZWFyZWQgb3IgZGlzYXBwZWFyZWQ6IHRoZSBtYXJrZXJzJyB2aXNpYmlsaXR5IGZvbGxvd3MuICovXG4gIHBvbHlnb25zU2hvd25DaGFuZ2VkKHNob3duOiBib29sZWFuKTogdm9pZDtcbn1cblxuLyoqXG4gKiBUaGUgY2VsbCBvdXRsaW5lcyBvZiB0aGUgMkQgc3BhdGlhbCB2aWV3LCBhdCB0aGUgcG9seWdvbiBsZXZlbCB0aGUgem9vbSBjYWxscyBmb3I6IGEgZmlsbCxcbiAqIGFuIG91dGxpbmUgb3IgYm90aCAocGx1cyBudWNsZXVzIG91dGxpbmVzIGZvciB0aGUgXCJib3RoXCIgY2VsbCBzZXQpLCBjb2xvdXJlZCBieSB0aGUgdmlldydzXG4gKiBjZWxsLWNvbG91ciBtb2RlLCB3aXRoIHN3aXRjaGVkLW9mZiBncm91cHMgbGVmdCBvdXQgb2YgdGhlIGdlb21ldHJ5LlxuICpcbiAqIEdlb21ldHJ5IGFuZCBzdHlsZSBhcmUga2V5ZWQgYXBhcnQsIHNvIGEgcmVjb2xvdXIgKGEgbmV3IGNlbGwtdHlwZSBjb2x1bW4sIGEgc2VsZWN0aW9uKVxuICogcmV3cml0ZXMgdGhlIHBlci1zaGFwZSB2YWx1ZXMgb2YgdGhlIGV4aXN0aW5nIGxheWVycyBhbmQgbmV2ZXIgcmUtZXhwYW5kcyB0aGUgcmluZ3MuXG4gKi9cbmV4cG9ydCBjbGFzcyBDZWxsTGF5ZXJzIHtcbiAgcHJpdmF0ZSBwb2x5Z29uc1Nob3duID0gZmFsc2U7XG4gIC8qKiBSaW5ncyBjdXJyZW50bHkgZHJhd24gYW5kIHRoZSAoZGF0YXNldCwgc2V0LCB0aWxlcykgdGhleSBjYW1lIGZyb20uICovXG4gIHByaXZhdGUgY3VycmVudFJpbmdzOiBTcGF0aWFsUG9seWdvblRpbGUgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjZWxsR2VvbWV0cnlLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGN1cnJlbnROdWNsZWk6IFNwYXRpYWxQb2x5Z29uVGlsZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGNlbGxTdHlsZUtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBTZWxlY3Rpb24gaWRlbnRpdHkg4oaSIHJldmlzaW9uLCBzbyBhIGNoYW5nZSBrZXkgY2FuIG5hbWUgYSBzZWxlY3Rpb24gY2hlYXBseS4gKi9cbiAgcHJpdmF0ZSBsYXN0U2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHNlbGVjdGlvblJldmlzaW9uID0gMDtcbiAgLyoqIENvbnRpbnVvdXMgY29sb3VyaW5ncycgd2luZG93cywgcGVyICh2ZWN0b3IsIGNsaXAsIGxvZyk6IGBjb250cmFzdFdpbmRvd2Agc29ydHMgZXZlcnlcbiAgICogIHZhbHVlLCBhbmQgYSBzZWxlY3Rpb24gb3Igb3BhY2l0eSBjaGFuZ2UgcmVjb2xvdXJzIHdpdGggdGhlIHZlY3RvciB1bmNoYW5nZWQgKFNQQVRJQUwtMTIpLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbnRyYXN0V2luZG93cyA9IG5ldyBDb250cmFzdFdpbmRvd0NhY2hlKCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwb3J0OiBTcGF0aWFsRGF0YVBvcnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSBncm91cHM6IE9yZGVyZWRMYXllckdyb3VwczxUaWxlR3JvdXA+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgbG9va3VwOiBDYXRlZ29yaWNhbExvb2t1cCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGhvc3Q6IENlbGxMYXllcnNIb3N0LFxuICApIHt9XG5cbiAgLyoqIFRydWUgd2hpbGUgb3V0bGluZXMgYXJlIG9uIHNjcmVlbiDigJQgdGhlIHNlcnZpY2UgaGlkZXMgaXRzIGRvdHMgdGhlbi4gKi9cbiAgZ2V0IG91dGxpbmVzU2hvd24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucG9seWdvbnNTaG93bjtcbiAgfVxuXG4gIC8qKiBUaGUgdmlld2VyIHdlbnQgYXdheSAoaXRzIGxheWVycyB3aXRoIGl0KTogdGhlIG91dGxpbmVzIGFyZSBubyBsb25nZXIgc2hvd24uICovXG4gIGRldGFjaGVkKCk6IHZvaWQge1xuICAgIHRoaXMuc2V0UG9seWdvbnNTaG93bihmYWxzZSk7XG4gIH1cblxuICAvKiogRHJhdyB0aGUgY2VsbHMgY292ZXJpbmcgYHJlY3RgIGF0IHRoZSBsZXZlbCBgcHhQZXJVbml0YCBjYWxscyBmb3IsIG9yIGRyb3AgdGhlbS4gKi9cbiAgYXN5bmMgcGxhbihcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCxcbiAgICB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLFxuICAgIHNlbGVjdGlvbjogU3BhdGlhbFNlbGVjdGlvbk1hc2ssXG4gICAgcmVjdDogRGF0YVJlY3QsXG4gICAgcHhQZXJVbml0OiBudW1iZXIsXG4gICAgY3R4OiBQbGFuQ29udGV4dCxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdGlsZWQgPSBkYXRhc2V0LnBvbHlnb25UaWxlcztcbiAgICBjb25zdCB3aG9sZSA9ICF0aWxlZCAmJiBkYXRhc2V0LnBvbHlnb25zICYmIHRoaXMucG9ydC5nZXRQb2x5Z29ucztcbiAgICBpZiAoIWNlbGxzU2hvd24oZGF0YXNldCwgdmlldykgfHwgKCF0aWxlZCAmJiAhd2hvbGUpKSB7XG4gICAgICB0aGlzLmRyb3AoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZGlhbWV0ZXIgPSB0eXBpY2FsQ2VsbERpYW1ldGVyKGRhdGFzZXQub2JzZXJ2YXRpb25zLnJhZGl1cyk7XG4gICAgLy8gV2hvbGUtZGF0YXNldCByaW5ncyBoYXZlIG9uZSBsZXZlbCBhbmQgbm8gY29hcnNlciBmYWxsYmFjaywgc28gdGhleSBhcmUgZHJhd24gYXNcbiAgICAvLyBzb29uIGFzIGEgY2VsbCBpcyBiaWcgZW5vdWdoIHRvIHJlYWQgYXMgYSBzaGFwZSByYXRoZXIgdGhhbiBhIGRvdC5cbiAgICBjb25zdCBsZXZlbCA9IHRpbGVkXG4gICAgICA/IHBvbHlnb25MZXZlbEZvcihweFBlclVuaXQsIGRpYW1ldGVyLCB0aWxlZC5sZXZlbHMubGVuZ3RoKVxuICAgICAgOiBweFBlclVuaXQgKiBkaWFtZXRlciA+PSBQT0xZR09OX0xFVkVMX01JTl9DRUxMX1BYWzJdXG4gICAgICAgID8gMFxuICAgICAgICA6IC0xO1xuICAgIGlmIChsZXZlbCA8IDApIHtcbiAgICAgIHRoaXMuZHJvcCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEdyb3VwcyBzd2l0Y2hlZCBvZmYgaW4gdGhlIGxpc3Q6IHRoZWlyIGNlbGxzIGFyZSBsZWZ0IG91dCBvZiB0aGUgZ2VvbWV0cnkuXG4gICAgY29uc3QgaGlkZGVuID0gYXdhaXQgdGhpcy5sb29rdXAuaGlkZGVuQ29kZXMoZGF0YXNldCwgdmlldyk7XG4gICAgaWYgKGN0eC5zdGFsZSgpKSByZXR1cm47XG4gICAgY29uc3QgbGFiZWwgPSB2aWV3LmNlbGxTZXQgPT09ICdib3RoJyA/ICdDZWxscyBhbmQgbnVjbGVpJyA6IHZpZXcuY2VsbFNldCA9PT0gJ251Y2xldXMnID8gJ051Y2xlaScgOiAnQ2VsbHMnO1xuICAgIGNvbnN0IGdlb21ldHJ5ID0gYXdhaXQgY3R4LnRyYWNrKGxhYmVsLCB0aGlzLmNlbGxHZW9tZXRyeShkYXRhc2V0LCB2aWV3LCByZWN0LCBsZXZlbCwgaGlkZGVuLCBjdHgpKTtcbiAgICBpZiAoIWdlb21ldHJ5KSByZXR1cm47XG4gICAgY29uc3QgeyByaW5ncywgbnVjbGVpLCBnZW9tZXRyeUtleSB9ID0gZ2VvbWV0cnk7XG5cbiAgICBjb25zdCBnZW9tZXRyeUNoYW5nZWQgPSBnZW9tZXRyeUtleSAhPT0gdGhpcy5jZWxsR2VvbWV0cnlLZXk7XG4gICAgY29uc3Qgc3R5bGVLZXkgPSBbXG4gICAgICBnZW9tZXRyeUtleSxcbiAgICAgIHZpZXcuY2VsbENvbG9yTW9kZSxcbiAgICAgIHZpZXcuY2VsbENvbG9yR2VuZSxcbiAgICAgIHZpZXcuY2VsbFNpbmdsZUNvbG9yLFxuICAgICAgY2VsbFR5cGVDb2x1bW5Gb3IoZGF0YXNldCwgdmlldyksXG4gICAgICB0aGlzLnNlbGVjdGlvblJldihzZWxlY3Rpb24pLFxuICAgICAgdmlldy5sb2dTY2FsZSxcbiAgICAgIHZpZXcucGVyY2VudGlsZUNsaXAuam9pbigpLFxuICAgICAgSlNPTi5zdHJpbmdpZnkodmlldy5jb250aW51b3VzQ29sb3JtYXApLFxuICAgICAgdmlldy5jZWxsRHJhdyxcbiAgICAgIHZpZXcuY2VsbE9wYWNpdHksXG4gICAgXS5qb2luKCd8Jyk7XG4gICAgY29uc3QgcHJlc2VudCA9IChbJ2NlbGxGaWxsJywgJ2NlbGxPdXRsaW5lJywgJ251Y2xldXNPdXRsaW5lJ10gYXMgY29uc3QpLnNvbWUoKGcpID0+IHRoaXMuZ3JvdXBzLnNob3duKGcpKTtcbiAgICBpZiAoIWdlb21ldHJ5Q2hhbmdlZCAmJiBzdHlsZUtleSA9PT0gdGhpcy5jZWxsU3R5bGVLZXkgJiYgcHJlc2VudCkge1xuICAgICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjb2xvcnMgPSBhd2FpdCB0aGlzLmNlbGxDb2xvcnMoZGF0YXNldCwgdmlldywgc2VsZWN0aW9uLCByaW5ncy5vYnNlcnZhdGlvbik7XG4gICAgaWYgKGN0eC5zdGFsZSgpKSByZXR1cm47XG5cbiAgICB0aGlzLmN1cnJlbnRSaW5ncyA9IHJpbmdzO1xuICAgIHRoaXMuY3VycmVudE51Y2xlaSA9IG51Y2xlaTtcbiAgICAvLyBBIGdlb21ldHJ5IG1pc3NpbmcgYSBmYWlsZWQgdGlsZSBpcyBkcmF3biBidXQgbm90IHJlbWVtYmVyZWQsIHNvIHRoZSByZXRyeSByZWZldGNoZXMgaXQuXG4gICAgdGhpcy5jZWxsR2VvbWV0cnlLZXkgPSBjdHguaW5jb21wbGV0ZSA/IG51bGwgOiBnZW9tZXRyeUtleTtcbiAgICB0aGlzLmNlbGxTdHlsZUtleSA9IHN0eWxlS2V5O1xuICAgIHRoaXMuZHJhd0NlbGxzKGRhdGFzZXQsIHZpZXcsIGdlb21ldHJ5LCBjb2xvcnMsIGdlb21ldHJ5Q2hhbmdlZCk7XG4gICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjZWxsIGxheWVyczogdGhlIGZpbGwgYW5kIHRoZSBvdXRsaW5lIHRoZSB2aWV3J3MgZHJhdyBtb2RlIGFza3MgZm9yLCBhbmQgd2l0aCBcImJvdGhcIiB0aGVcbiAgICogbnVjbGV1cyBvdXRsaW5lcyBvdmVyIHRoZW0uIEEgZ2VvbWV0cnkgY2hhbmdlIGJ1aWxkcyBuZXcgbGF5ZXJzOyBhIHN0eWxlIGNoYW5nZSByZXN0eWxlcyB0aGVtLlxuICAgKi9cbiAgcHJpdmF0ZSBkcmF3Q2VsbHMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICB7IHJpbmdzLCBudWNsZWkgfTogeyByaW5nczogU3BhdGlhbFBvbHlnb25UaWxlOyBudWNsZWk6IFNwYXRpYWxQb2x5Z29uVGlsZSB8IG51bGwgfSxcbiAgICBjb2xvcnM6IENlbGxDb2xvcnMsXG4gICAgZ2VvbWV0cnlDaGFuZ2VkOiBib29sZWFuLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCByZWYgPSBkYXRhc2V0LmltYWdlUmVmO1xuICAgIGNvbnN0IGNvbW1vbiA9IHsgc2NhbGU6IHJlZj8uc2NhbGUgPz8gWzEsIDFdLCB0cmFuc2xhdGU6IHJlZj8udHJhbnNsYXRlID8/IFswLCAwXSB9IGFzIGNvbnN0O1xuICAgIGNvbnN0IGZpbGwgPSB2aWV3LmNlbGxEcmF3ICE9PSAnb3V0bGluZSc7XG4gICAgY29uc3Qgb3V0bGluZSA9IHZpZXcuY2VsbERyYXcgIT09ICdmaWxsJztcblxuICAgIHRoaXMuZ3JvdXBzLnVwc2VydFNoYXBlcygnY2VsbEZpbGwnLCBmaWxsLCBnZW9tZXRyeUNoYW5nZWQsIHJpbmdzLCB7XG4gICAgICBuYW1lOiAnY2VsbHMnLFxuICAgICAgZHJhdzogJ2ZpbGwnLFxuICAgICAgb3BhY2l0eTogdmlldy5jZWxsT3BhY2l0eSxcbiAgICAgIC4uLmNvbG9ycyxcbiAgICAgIC4uLmNvbW1vbixcbiAgICB9KTtcbiAgICB0aGlzLmdyb3Vwcy51cHNlcnRTaGFwZXMoXG4gICAgICAnY2VsbE91dGxpbmUnLFxuICAgICAgb3V0bGluZSxcbiAgICAgIGdlb21ldHJ5Q2hhbmdlZCxcbiAgICAgIHJpbmdzLFxuICAgICAgZmlsbFxuICAgICAgICA/IC8vIE92ZXIgYSBmaWxsLCBhIGRhcmsgb3V0bGluZSBzZXBhcmF0ZXMgbmVpZ2hib3VycyBvZiB0aGUgc2FtZSB0eXBlLlxuICAgICAgICAgIHsgbmFtZTogJ2NlbGwgb3V0bGluZXMnLCBkcmF3OiAnb3V0bGluZScsIGNvbG9yOiBbMC4wOCwgMC4wOCwgMC4xLCAxXSwgb3BhY2l0eTogMC43LCAuLi5jb21tb24gfVxuICAgICAgICA6IHsgbmFtZTogJ2NlbGwgb3V0bGluZXMnLCBkcmF3OiAnb3V0bGluZScsIG9wYWNpdHk6IDEsIC4uLmNvbG9ycywgLi4uY29tbW9uIH0sXG4gICAgKTtcbiAgICAvLyBcIkJvdGhcIjogbnVjbGVpIG91dGxpbmVkIG92ZXIgdGhlIGNlbGxzLCBsaWdodCBzbyB0aGV5IHJlYWQgYWdhaW5zdCBhbnkgZmlsbC5cbiAgICBpZiAobnVjbGVpKSB7XG4gICAgICB0aGlzLmdyb3Vwcy51cHNlcnRTaGFwZXMoJ251Y2xldXNPdXRsaW5lJywgdHJ1ZSwgZ2VvbWV0cnlDaGFuZ2VkLCBudWNsZWksIHtcbiAgICAgICAgbmFtZTogJ251Y2xldXMgb3V0bGluZXMnLFxuICAgICAgICBkcmF3OiAnb3V0bGluZScsXG4gICAgICAgIGNvbG9yOiBbMC45NSwgMC45NSwgMC45OCwgMV0sXG4gICAgICAgIG9wYWNpdHk6IDAuOCxcbiAgICAgICAgLi4uY29tbW9uLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZ3JvdXBzLmRyb3AoJ251Y2xldXNPdXRsaW5lJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZWxlY3Rpb25SZXYoc2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayk6IG51bWJlciB7XG4gICAgaWYgKHNlbGVjdGlvbiAhPT0gdGhpcy5sYXN0U2VsZWN0aW9uKSB7XG4gICAgICB0aGlzLmxhc3RTZWxlY3Rpb24gPSBzZWxlY3Rpb247XG4gICAgICB0aGlzLnNlbGVjdGlvblJldmlzaW9uKys7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNlbGVjdGlvblJldmlzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByaW5ncycgY29sb3VycyBieSB0aGVpciBvd25lcnMsIGJ5IHRoZSB2aWV3J3MgY2VsbC1jb2xvdXIgbW9kZSAoWGVuaXVtIEV4cGxvcmVyJ3MgXCJDZWxsXG4gICAqIENvbG9yXCIpOiBvbmUgUkdCQSBwZXIgc2hhcGUgZm9yIGEgZ3JvdXBpbmcsIHZhbHVlcyArIGNvbG9ybWFwIGZvciBhIG1lYXN1cmVtZW50LCBvbmUgY29sb3VyXG4gICAqIGZvciBcInNpbmdsZVwiLiBBIHNlbGVjdGlvbiBtdXRlcyB3aGF0IGl0IGxlYXZlcyBvdXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNlbGxDb2xvcnMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICBzZWxlY3Rpb246IFNwYXRpYWxTZWxlY3Rpb25NYXNrLFxuICAgIG93bmVyczogVWludDMyQXJyYXksXG4gICk6IFByb21pc2U8Q2VsbENvbG9ycz4ge1xuICAgIGNvbnN0IG11dGVkID0gc2VsZWN0aW9uLmNvdW50ID4gMCA/IHNlbGVjdGlvbi5tYXNrIDogbnVsbDtcbiAgICBjb25zdCBtb2RlID0gdmlldy5jZWxsQ29sb3JNb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdzaW5nbGUnKSB7XG4gICAgICBjb25zdCBbciwgZywgYl0gPSBwYXJzZUhleCh2aWV3LmNlbGxTaW5nbGVDb2xvcik7XG4gICAgICByZXR1cm4geyBjb2xvcjogW3IgLyAyNTUsIGcgLyAyNTUsIGIgLyAyNTUsIDFdIH07XG4gICAgfVxuXG4gICAgY29uc3QgY29udGludW91cyA9IGFzeW5jIChyYXc6IEZsb2F0MzJBcnJheSwgbG9nOiBib29sZWFuKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KG93bmVycy5sZW5ndGgpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvd25lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgdiA9IHJhd1tvd25lcnNbaV1dID8/IE5hTjtcbiAgICAgICAgdmFsdWVzW2ldID0gbG9nID8gTWF0aC5sb2cxcChNYXRoLm1heCgwLCB2KSkgOiB2O1xuICAgICAgfVxuICAgICAgY29uc3QgW2NsaXBMbywgY2xpcEhpXSA9IHZpZXcucGVyY2VudGlsZUNsaXA7XG4gICAgICAvLyBLZXllZCBieSB0aGUgU09VUkNFIHZlY3RvciAodGhlIGxvZyBjb3B5IHdvdWxkIGJlIG5ldyBvbiBldmVyeSBjYWxsKSwgYXMgdGhlIDNEIGNsb3VkJ3MuXG4gICAgICBjb25zdCBbbG8sIGhpXSA9IHRoaXMuY29udHJhc3RXaW5kb3dzLmdldChyYXcsIGNsaXBMbywgY2xpcEhpLCBsb2csICgpID0+XG4gICAgICAgIGNvbnRyYXN0V2luZG93KGxvZyA/IHJhdy5tYXAoKHYpID0+IE1hdGgubG9nMXAoTWF0aC5tYXgoMCwgdikpKSA6IHJhdywgY2xpcExvLCBjbGlwSGkpLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlcyxcbiAgICAgICAgY29sb3JtYXA6IGNvbG9ybWFwRnJvbUx1dCgnc3BhdGlhbC1jb250aW51b3VzJywgdGhpcy5ob3N0LmNvbnRpbnVvdXNMdXQodmlldykpLFxuICAgICAgICBjb250cmFzdExpbWl0czogW2xvLCBoaV0gYXMgW251bWJlciwgbnVtYmVyXSxcbiAgICAgIH07XG4gICAgfTtcbiAgICBpZiAobW9kZSA9PT0gJ2dlbmUnICYmIHZpZXcuY2VsbENvbG9yR2VuZSkge1xuICAgICAgcmV0dXJuIGNvbnRpbnVvdXMoYXdhaXQgdGhpcy5wb3J0LmdldEZlYXR1cmVWZWN0b3Iodmlldy5jZWxsQ29sb3JHZW5lKSwgdHJ1ZSk7XG4gICAgfVxuICAgIGlmIChtb2RlID09PSAndHJhbnNjcmlwdERlbnNpdHknICYmIGRhdGFzZXQuY29sdW1ucy5zb21lKChjKSA9PiBjLm5hbWUgPT09ICd0cmFuc2NyaXB0X2RlbnNpdHknKSkge1xuICAgICAgY29uc3QgY29sdW1uID0gYXdhaXQgdGhpcy5wb3J0LmdldENvbHVtbigndHJhbnNjcmlwdF9kZW5zaXR5Jyk7XG4gICAgICBpZiAoIWlzQ2F0ZWdvcmljYWxDb2x1bW4oY29sdW1uKSkgcmV0dXJuIGNvbnRpbnVvdXMoY29sdW1uLnZhbHVlcywgZmFsc2UpO1xuICAgIH1cblxuICAgIGNvbnN0IG5hbWUgPVxuICAgICAgbW9kZSA9PT0gJ3NlZ21lbnRhdGlvbicgJiYgZGF0YXNldC5jb2x1bW5zLnNvbWUoKGMpID0+IGMubmFtZSA9PT0gJ3NlZ21lbnRhdGlvbl9tZXRob2QnKVxuICAgICAgICA/ICdzZWdtZW50YXRpb25fbWV0aG9kJ1xuICAgICAgICA6IGNlbGxUeXBlQ29sdW1uRm9yKGRhdGFzZXQsIHZpZXcpO1xuICAgIGNvbnN0IGNvZGVzID0gbmFtZSA/IGF3YWl0IHRoaXMubG9va3VwLmNvZGVzKG5hbWUpIDogbnVsbDtcbiAgICBjb25zdCBwYWxldHRlID0gY2F0ZWdvcnlSZ2JhKGNvZGVzPy5tZXRhID8/IG51bGwpO1xuICAgIGNvbnN0IG1pc3NpbmcgPSByZ2JhMDEoTUlTU0lOR19DT0xPUik7XG4gICAgLy8gT25lIFJHQkEgcGVyIHNoYXBlIChuYXBhcmkgU2hhcGVzJyBgZmFjZV9jb2xvcmApOiBhbnkgbnVtYmVyIG9mIGNhdGVnb3JpZXMga2VlcHMgaXRzIG93blxuICAgIC8vIGNvbG91ciwgd2hlcmUgYSBjb2xvcm1hcCBiYW5kIHBlciBjYXRlZ29yeSByYW4gb3V0IG9mIExVVCBlbnRyaWVzIHBhc3QgfjEyNy5cbiAgICBjb25zdCBmYWNlQ29sb3IgPSBuZXcgRmxvYXQzMkFycmF5KG93bmVycy5sZW5ndGggKiA0KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG93bmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbyA9IG93bmVyc1tpXTtcbiAgICAgIGNvbnN0IGNvZGUgPSAhY29kZXMgfHwgKG11dGVkICYmICFtdXRlZFtvXSkgPyBOT19DQVRFR09SWSA6IGNvZGVzLmNvZGVzW29dO1xuICAgICAgZmFjZUNvbG9yLnNldChwYWxldHRlW2NvZGVdID8/IG1pc3NpbmcsIGkgKiA0KTtcbiAgICB9XG4gICAgcmV0dXJuIHsgZmFjZUNvbG9yIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNlbGwgcmluZ3MgKGFuZCwgZm9yIFwiYm90aFwiLCB0aGUgbnVjbGV1cyByaW5ncykgY292ZXJpbmcgYHJlY3RgIGF0IGBsZXZlbGAsIG1pbnVzXG4gICAqIHRoZSBoaWRkZW4gZ3JvdXBzIOKAlCByZXVzZWQgd2hlbiBub3RoaW5nIHRoYXQgZGVjaWRlcyB0aGVtIGNoYW5nZWQuIE51bGwgd2hlbiB0aGVcbiAgICogdmlldyB3ZW50IHN0YWxlIG9yIHRoZSBkYXRhc2V0IGhhcyBubyBzZXQgdG8gZHJhdy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY2VsbEdlb21ldHJ5KFxuICAgIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICAgcmVjdDogRGF0YVJlY3QsXG4gICAgbGV2ZWw6IG51bWJlcixcbiAgICBoaWRkZW46IEhpZGRlbkNvZGVzIHwgbnVsbCxcbiAgICBjdHg6IFBsYW5Db250ZXh0LFxuICApOiBQcm9taXNlPHsgcmluZ3M6IFNwYXRpYWxQb2x5Z29uVGlsZTsgbnVjbGVpOiBTcGF0aWFsUG9seWdvblRpbGUgfCBudWxsOyBnZW9tZXRyeUtleTogc3RyaW5nIH0gfCBudWxsPiB7XG4gICAgY29uc3QgdGlsZWQgPSBkYXRhc2V0LnBvbHlnb25UaWxlcztcbiAgICBjb25zdCBoaWRkZW5LZXkgPSB2aWV3LmhpZGRlbkdyb3Vwcy5qb2luKCdcXHUwMDAxJyk7XG4gICAgbGV0IHJpbmdzOiBTcGF0aWFsUG9seWdvblRpbGU7XG4gICAgbGV0IG51Y2xlaTogU3BhdGlhbFBvbHlnb25UaWxlIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGdlb21ldHJ5S2V5OiBzdHJpbmc7XG4gICAgaWYgKHRpbGVkKSB7XG4gICAgICBjb25zdCBib3RoID0gdmlldy5jZWxsU2V0ID09PSAnYm90aCc7XG4gICAgICBjb25zdCBzZXQgPVxuICAgICAgICAhYm90aCAmJiB2aWV3LmNlbGxTZXQgJiYgdGlsZWQuc2V0cy5zb21lKChzKSA9PiBzLm5hbWUgPT09IHZpZXcuY2VsbFNldClcbiAgICAgICAgICA/IHZpZXcuY2VsbFNldFxuICAgICAgICAgIDogKHRpbGVkLmRlZmF1bHRTZXQgPz8gdGlsZWQuc2V0c1swXT8ubmFtZSk7XG4gICAgICBpZiAoIXNldCkgcmV0dXJuIG51bGw7XG4gICAgICBjb25zdCBudWNsZXVzU2V0ID0gYm90aCA/IHRpbGVkLnNldHMuZmluZCgocykgPT4gcy5uYW1lICE9PSBzZXQpPy5uYW1lIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3Qga2V5cyA9IHRpbGVzSW5SZWN0KHJlY3QsIGxldmVsLCB0aWxlZC5sZXZlbHMsIHRpbGVkLmJvdW5kcywgTUFYX0NFTExfVElMRVMpO1xuICAgICAgZ2VvbWV0cnlLZXkgPSBgJHtkYXRhc2V0LmlkfXwke3NldH18JHtudWNsZXVzU2V0ID8/ICcnfXwke2hpZGRlbktleX18JHtrZXlzLm1hcCh0aWxlSWQpLmpvaW4oJywnKX1gO1xuICAgICAgaWYgKGdlb21ldHJ5S2V5ID09PSB0aGlzLmNlbGxHZW9tZXRyeUtleSAmJiB0aGlzLmN1cnJlbnRSaW5ncykge1xuICAgICAgICByaW5ncyA9IHRoaXMuY3VycmVudFJpbmdzO1xuICAgICAgICBudWNsZWkgPSB0aGlzLmN1cnJlbnROdWNsZWk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBbdGlsZXMsIG51Y2xldXNUaWxlc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgY3R4LmZldGNoQWxsKGtleXMsIChrKSA9PiB0aGlzLnBvcnQuZ2V0UG9seWdvblRpbGUhKHNldCwgay5sZXZlbCwgay5neCwgay5neSkpLFxuICAgICAgICAgIG51Y2xldXNTZXRcbiAgICAgICAgICAgID8gY3R4LmZldGNoQWxsKGtleXMsIChrKSA9PiB0aGlzLnBvcnQuZ2V0UG9seWdvblRpbGUhKG51Y2xldXNTZXQsIGsubGV2ZWwsIGsuZ3gsIGsuZ3kpKVxuICAgICAgICAgICAgOiBQcm9taXNlLnJlc29sdmUobnVsbCksXG4gICAgICAgIF0pO1xuICAgICAgICBpZiAoY3R4LnN0YWxlKCkpIHJldHVybiBudWxsO1xuICAgICAgICByaW5ncyA9IGZpbHRlclJpbmdzKG1lcmdlUG9seWdvblRpbGVzKHRpbGVzKSwgaGlkZGVuKTtcbiAgICAgICAgbnVjbGVpID0gbnVjbGV1c1RpbGVzID8gZmlsdGVyUmluZ3MobWVyZ2VQb2x5Z29uVGlsZXMobnVjbGV1c1RpbGVzKSwgaGlkZGVuKSA6IG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGdlb21ldHJ5S2V5ID0gYCR7ZGF0YXNldC5pZH18d2hvbGV8JHtoaWRkZW5LZXl9YDtcbiAgICAgIGlmIChnZW9tZXRyeUtleSA9PT0gdGhpcy5jZWxsR2VvbWV0cnlLZXkgJiYgdGhpcy5jdXJyZW50UmluZ3MpIHtcbiAgICAgICAgcmluZ3MgPSB0aGlzLmN1cnJlbnRSaW5ncztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHBvbHlzOiBTcGF0aWFsUG9seWdvbnMgPSBhd2FpdCB0aGlzLnBvcnQuZ2V0UG9seWdvbnMhKCk7XG4gICAgICAgIGlmIChjdHguc3RhbGUoKSkgcmV0dXJuIG51bGw7XG4gICAgICAgIC8vIFdob2xlLWRhdGFzZXQgcmluZ3MgYXJlIGluZGV4LWFsaWduZWQgd2l0aCB0aGUgb2JzZXJ2YXRpb25zLlxuICAgICAgICByaW5ncyA9IGZpbHRlclJpbmdzKFxuICAgICAgICAgIHsgLi4ucG9seXMsIG9ic2VydmF0aW9uOiBVaW50MzJBcnJheS5mcm9tKHsgbGVuZ3RoOiBwb2x5cy5jb3VudCB9LCAoX3YsIGkpID0+IGkpIH0sXG4gICAgICAgICAgaGlkZGVuLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyByaW5ncywgbnVjbGVpLCBnZW9tZXRyeUtleSB9O1xuICB9XG5cbiAgLyoqIFJlbW92ZSB0aGUgY2VsbCBsYXllcnMgYW5kIGZvcmdldCB3aGF0IHRoZXkgc2hvd2VkLiAqL1xuICBkcm9wKCk6IHZvaWQge1xuICAgIHRoaXMuZ3JvdXBzLmRyb3AoJ2NlbGxGaWxsJyk7XG4gICAgdGhpcy5ncm91cHMuZHJvcCgnY2VsbE91dGxpbmUnKTtcbiAgICB0aGlzLmdyb3Vwcy5kcm9wKCdudWNsZXVzT3V0bGluZScpO1xuICAgIHRoaXMuY3VycmVudE51Y2xlaSA9IG51bGw7XG4gICAgdGhpcy5jZWxsR2VvbWV0cnlLZXkgPSBudWxsO1xuICAgIHRoaXMuY2VsbFN0eWxlS2V5ID0gbnVsbDtcbiAgICB0aGlzLmN1cnJlbnRSaW5ncyA9IG51bGw7XG4gICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0UG9seWdvbnNTaG93bihzaG93bjogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChzaG93biA9PT0gdGhpcy5wb2x5Z29uc1Nob3duKSByZXR1cm47XG4gICAgdGhpcy5wb2x5Z29uc1Nob3duID0gc2hvd247XG4gICAgdGhpcy5ob3N0LnBvbHlnb25zU2hvd25DaGFuZ2VkKHNob3duKTtcbiAgfVxufVxuXG4vKiogQW4gOC1iaXQgUkdCIGFzIGFuIG9wYXF1ZSAwLi4xIFJHQkEuICovXG5mdW5jdGlvbiByZ2JhMDEoW3IsIGcsIGJdOiByZWFkb25seSBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pOiBSR0JBIHtcbiAgcmV0dXJuIFtyIC8gMjU1LCBnIC8gMjU1LCBiIC8gMjU1LCAxXTtcbn1cblxuLyoqIEEgZ3JvdXBpbmcncyBjYXRlZ29yeSBjb2xvdXJzLCBhcyAwLi4xIFJHQkEgYnkgY2F0ZWdvcnkgY29kZSAob25lIGRlZmF1bHQgd2l0aG91dCBhIGdyb3VwaW5nKS4gKi9cbmZ1bmN0aW9uIGNhdGVnb3J5UmdiYShtZXRhOiBTcGF0aWFsQ29sdW1uWydtZXRhJ10gfCBudWxsKTogUkdCQVtdIHtcbiAgY29uc3QgaGV4ID0gbWV0YSAmJiBtZXRhLmtpbmQgPT09ICdjYXRlZ29yaWNhbCcgPyByZXNvbHZlQ2F0ZWdvcnlDb2xvcnMobWV0YSkgOiBbREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFWzBdXTtcbiAgcmV0dXJuIGhleC5tYXAoKGgpID0+IHJnYmEwMShwYXJzZUhleChoKSkpO1xufVxuIl19
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { colormapFromLut } from 'napari-js';
|
|
2
|
+
import { INFERNO_LUT } from 'napari-js/colormaps';
|
|
3
|
+
import { ALL_GENES } from '../../../contracts/ports/spatial-data.port';
|
|
4
|
+
import { lutFor } from '../../../spatial/spatial-encoding';
|
|
5
|
+
import { visibleArea, visibleDataRect } from '../../../spatial/lod';
|
|
6
|
+
import { densityAutoRange } from '../../../spatial/density-raster';
|
|
7
|
+
/**
|
|
8
|
+
* The transcript density image of the 2D spatial view: the visible genes' summed density
|
|
9
|
+
* raster, one scalar layer in the `density` group, windowed and coloured on the GPU.
|
|
10
|
+
*
|
|
11
|
+
* Bins at or below the window's low end are transparent (`transparentBelow`), so a window,
|
|
12
|
+
* colormap or opacity change is a uniform or LUT update of the same layer: only new genes or a
|
|
13
|
+
* new bin size fetch and upload a raster.
|
|
14
|
+
*/
|
|
15
|
+
export class DensityLayer {
|
|
16
|
+
constructor(port, groups, changed) {
|
|
17
|
+
this.port = port;
|
|
18
|
+
this.groups = groups;
|
|
19
|
+
this.changed = changed;
|
|
20
|
+
/** The density window in use and the densest bin, for the panel's threshold control. */
|
|
21
|
+
this.stats = null;
|
|
22
|
+
/** The drawn raster in transcripts per unit area, its densest bin and its auto window. */
|
|
23
|
+
this.raster = null;
|
|
24
|
+
/** The colormap the layer was given, so an unchanged one does not rebuild its LUT. */
|
|
25
|
+
this.colormapKey = null;
|
|
26
|
+
}
|
|
27
|
+
/** Draw the view's density, or drop it; an unchanged (genes, bin, window, colormap) is a no-op. */
|
|
28
|
+
async plan(dataset, view, ctx) {
|
|
29
|
+
const hiddenGenes = new Set(view.transcriptHiddenGenes);
|
|
30
|
+
const genes = view.transcriptAllGenes ? [ALL_GENES] : view.transcriptGenes.filter((g) => !hiddenGenes.has(g));
|
|
31
|
+
if (!dataset.density || !this.port.getDensity || view.transcriptMode !== 'density' || !genes.length) {
|
|
32
|
+
this.groups.drop('density');
|
|
33
|
+
this.stats = null;
|
|
34
|
+
this.raster = null;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// The raster's key: what it is a raster OF. Window, colormap and opacity are the layer's style.
|
|
38
|
+
const key = [dataset.id, genes.join(','), view.densityBin].join('|');
|
|
39
|
+
// `shown`, not `has`: a stitched slice re-render clears the layer list, and the key alone
|
|
40
|
+
// would call the cleared layer drawn.
|
|
41
|
+
if (key !== this.groups.key('density') || !this.groups.shown('density') || !this.raster) {
|
|
42
|
+
const raster = await ctx.track('Transcript density', this.port.getDensity(genes, view.densityBin));
|
|
43
|
+
if (ctx.stale())
|
|
44
|
+
return;
|
|
45
|
+
// Bins drawn as squares, as Xenium Explorer does; the window is in transcripts/µm².
|
|
46
|
+
const meta = raster.meta;
|
|
47
|
+
const area = meta.gridSize[0] * meta.gridSize[1];
|
|
48
|
+
const perArea = raster.values.map((v) => v / area);
|
|
49
|
+
this.raster = {
|
|
50
|
+
perArea,
|
|
51
|
+
max: perArea.reduce((m, v) => (v > m ? v : m), 0),
|
|
52
|
+
auto: densityAutoRange(perArea),
|
|
53
|
+
};
|
|
54
|
+
const ref = dataset.imageRef;
|
|
55
|
+
const sx = ref?.scale?.[0] ?? 1;
|
|
56
|
+
const sy = ref?.scale?.[1] ?? 1;
|
|
57
|
+
const layer = this.groups.viewer.addImage({ kind: 'typed', width: meta.cols, height: meta.rows, channels: 1, dtype: 'float32', data: perArea }, {
|
|
58
|
+
name: `density · ${view.transcriptAllGenes ? 'all genes' : genes.join(', ')}`,
|
|
59
|
+
scale: [meta.gridSize[0] * sx, meta.gridSize[1] * sy],
|
|
60
|
+
translate: [
|
|
61
|
+
meta.origin[0] * sx + (ref?.translate?.[0] ?? 0),
|
|
62
|
+
meta.origin[1] * sy + (ref?.translate?.[1] ?? 0),
|
|
63
|
+
],
|
|
64
|
+
// Xenium Explorer's "scale threshold": empty tissue shows the image under it.
|
|
65
|
+
transparentBelow: true,
|
|
66
|
+
blending: 'translucent',
|
|
67
|
+
interpolation: 'nearest',
|
|
68
|
+
});
|
|
69
|
+
this.colormapKey = null;
|
|
70
|
+
this.groups.setKey('density', key);
|
|
71
|
+
this.groups.replace('density', layer);
|
|
72
|
+
}
|
|
73
|
+
this.restyle(this.groups.layer('density'), view);
|
|
74
|
+
}
|
|
75
|
+
/** Window, colour and opacity onto the drawn layer: uniforms and a LUT, no re-upload. */
|
|
76
|
+
restyle(layer, view) {
|
|
77
|
+
const raster = this.raster;
|
|
78
|
+
const [lo, hi] = view.densityRange ?? raster.auto;
|
|
79
|
+
layer.contrastLimits = [lo, hi];
|
|
80
|
+
layer.opacity = view.densityOpacity;
|
|
81
|
+
const colormapKey = JSON.stringify(view.densityColormap ?? null);
|
|
82
|
+
if (colormapKey !== this.colormapKey) {
|
|
83
|
+
this.colormapKey = colormapKey;
|
|
84
|
+
layer.colormap = colormapFromLut('transcript-density', lutFor(view.densityColormap ?? INFERNO_LUT));
|
|
85
|
+
}
|
|
86
|
+
this.groups.viewer.requestRender();
|
|
87
|
+
const stats = { lo, hi, max: raster.max };
|
|
88
|
+
if (this.stats?.lo === lo && this.stats.hi === hi && this.stats.max === raster.max)
|
|
89
|
+
return;
|
|
90
|
+
this.stats = stats;
|
|
91
|
+
this.changed(stats);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Transcripts in view for the visible genes, against the marker budget — it tells the user
|
|
96
|
+
* whether the budget will force grouping. Caches the per-gene dataset totals for the latest
|
|
97
|
+
* gene set.
|
|
98
|
+
*/
|
|
99
|
+
export class TranscriptEstimator {
|
|
100
|
+
constructor(port, changed) {
|
|
101
|
+
this.port = port;
|
|
102
|
+
this.changed = changed;
|
|
103
|
+
/** Per-gene dataset totals for the in-view estimate, for the latest gene set. */
|
|
104
|
+
this.countsCache = null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Transcripts in view for the visible genes: each gene's dataset total times the share
|
|
108
|
+
* of the tissue on screen. An estimate — expression is not uniform — which is also what
|
|
109
|
+
* Xenium Explorer shows; it tells the user whether the budget will force grouping.
|
|
110
|
+
*/
|
|
111
|
+
async plan(dataset, view, viewer, w, h, ctx) {
|
|
112
|
+
const tiles = dataset.transcriptTiles;
|
|
113
|
+
if (!tiles || !this.port.getTranscriptCounts || view.transcriptMode === 'off') {
|
|
114
|
+
this.changed(null);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const hiddenGenes = new Set(view.transcriptHiddenGenes);
|
|
118
|
+
const genes = view.transcriptAllGenes ? [] : view.transcriptGenes.filter((g) => !hiddenGenes.has(g));
|
|
119
|
+
const key = `${dataset.id}|${genes.join(',')}`;
|
|
120
|
+
if (this.countsCache?.key !== key) {
|
|
121
|
+
this.countsCache = { key, counts: this.port.getTranscriptCounts(genes) };
|
|
122
|
+
}
|
|
123
|
+
let counts;
|
|
124
|
+
try {
|
|
125
|
+
counts = await this.countsCache.counts;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
this.countsCache = null;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (ctx.stale())
|
|
132
|
+
return;
|
|
133
|
+
const inView = visibleDataRect(viewer.camera.center, viewer.camera.zoom, w, h, dataset.imageRef, 0);
|
|
134
|
+
if (!inView)
|
|
135
|
+
return;
|
|
136
|
+
const b = counts.bounds;
|
|
137
|
+
const share = Math.min(1, visibleArea(inView, b) / Math.max(1, (b[2] - b[0]) * (b[3] - b[1])));
|
|
138
|
+
const selected = view.transcriptAllGenes
|
|
139
|
+
? counts.total
|
|
140
|
+
: genes.reduce((sum, g) => sum + (counts.counts[g] ?? 0), 0);
|
|
141
|
+
this.changed({ points: Math.round(selected * share), max: view.transcriptBudget });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVuc2l0eS1sYXllci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvaW1wbGVtZW50YXRpb25zL25hcGFyaS1qcy9zcGF0aWFsLXRpbGVzL2RlbnNpdHktbGF5ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUU1QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbEQsT0FBTyxFQUFFLFNBQVMsRUFBd0IsTUFBTSw0Q0FBNEMsQ0FBQztBQUc3RixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDM0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQW1CbkU7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxZQUFZO0lBUXZCLFlBQ21CLElBQXFCLEVBQ3JCLE1BQXFDLEVBQ3JDLE9BQXNDO1FBRnRDLFNBQUksR0FBSixJQUFJLENBQWlCO1FBQ3JCLFdBQU0sR0FBTixNQUFNLENBQStCO1FBQ3JDLFlBQU8sR0FBUCxPQUFPLENBQStCO1FBVnpELHdGQUF3RjtRQUN4RixVQUFLLEdBQXdCLElBQUksQ0FBQztRQUNsQywwRkFBMEY7UUFDbEYsV0FBTSxHQUEwRSxJQUFJLENBQUM7UUFDN0Ysc0ZBQXNGO1FBQzlFLGdCQUFXLEdBQWtCLElBQUksQ0FBQztJQU12QyxDQUFDO0lBRUosbUdBQW1HO0lBQ25HLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBdUIsRUFBRSxJQUFzQixFQUFFLEdBQWdCO1FBQzFFLE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxrQkFB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RUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsQ0FBQztJQUNyRixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjb2xvcm1hcEZyb21MdXQgfSBmcm9tICduYXBhcmktanMnO1xuaW1wb3J0IHR5cGUgeyBJbWFnZUxheWVyLCBWaWV3ZXIgfSBmcm9tICduYXBhcmktanMnO1xuaW1wb3J0IHsgSU5GRVJOT19MVVQgfSBmcm9tICduYXBhcmktanMvY29sb3JtYXBzJztcblxuaW1wb3J0IHsgQUxMX0dFTkVTLCB0eXBlIFNwYXRpYWxEYXRhUG9ydCB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9wb3J0cy9zcGF0aWFsLWRhdGEucG9ydCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxWaWV3U3RhdGUgfSBmcm9tICcuLi8uLi8uLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0LCBTcGF0aWFsVHJhbnNjcmlwdENvdW50cyB9IGZyb20gJy4uLy4uLy4uL2NvbnRyYWN0cy9zcGF0aWFsLWRhdGFzZXQuY29udHJhY3QnO1xuaW1wb3J0IHsgbHV0Rm9yIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB7IHZpc2libGVBcmVhLCB2aXNpYmxlRGF0YVJlY3QgfSBmcm9tICcuLi8uLi8uLi9zcGF0aWFsL2xvZCc7XG5pbXBvcnQgeyBkZW5zaXR5QXV0b1JhbmdlIH0gZnJvbSAnLi4vLi4vLi4vc3BhdGlhbC9kZW5zaXR5LXJhc3Rlcic7XG5pbXBvcnQgdHlwZSB7IE9yZGVyZWRMYXllckdyb3VwcywgVGlsZUdyb3VwIH0gZnJvbSAnLi9sYXllci1ncm91cHMnO1xuaW1wb3J0IHR5cGUgeyBQbGFuQ29udGV4dCB9IGZyb20gJy4vcGxhbi1jb250ZXh0JztcblxuLyoqIFRoZSBkZW5zaXR5IHdpbmRvdyBpbiB1c2UgYW5kIHRoZSBkZW5zZXN0IGJpbiAodHJhbnNjcmlwdHMgcGVyIHVuaXQgYXJlYSkuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbnNpdHlTdGF0cyB7XG4gIGxvOiBudW1iZXI7XG4gIGhpOiBudW1iZXI7XG4gIG1heDogbnVtYmVyO1xufVxuXG4vKiogWGVuaXVtIEV4cGxvcmVyJ3MgXCJFc3RpbWF0ZWQgVHJhbnNjcmlwdCBQb2ludHNcIi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVHJhbnNjcmlwdEVzdGltYXRlIHtcbiAgLyoqIFRyYW5zY3JpcHRzIG9mIHRoZSB2aXNpYmxlIGdlbmVzIGVzdGltYXRlZCB0byBiZSBpbiB2aWV3LiAqL1xuICBwb2ludHM6IG51bWJlcjtcbiAgLyoqIFRoZSBtYXJrZXIgYnVkZ2V0LiAqL1xuICBtYXg6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBUaGUgdHJhbnNjcmlwdCBkZW5zaXR5IGltYWdlIG9mIHRoZSAyRCBzcGF0aWFsIHZpZXc6IHRoZSB2aXNpYmxlIGdlbmVzJyBzdW1tZWQgZGVuc2l0eVxuICogcmFzdGVyLCBvbmUgc2NhbGFyIGxheWVyIGluIHRoZSBgZGVuc2l0eWAgZ3JvdXAsIHdpbmRvd2VkIGFuZCBjb2xvdXJlZCBvbiB0aGUgR1BVLlxuICpcbiAqIEJpbnMgYXQgb3IgYmVsb3cgdGhlIHdpbmRvdydzIGxvdyBlbmQgYXJlIHRyYW5zcGFyZW50IChgdHJhbnNwYXJlbnRCZWxvd2ApLCBzbyBhIHdpbmRvdyxcbiAqIGNvbG9ybWFwIG9yIG9wYWNpdHkgY2hhbmdlIGlzIGEgdW5pZm9ybSBvciBMVVQgdXBkYXRlIG9mIHRoZSBzYW1lIGxheWVyOiBvbmx5IG5ldyBnZW5lcyBvciBhXG4gKiBuZXcgYmluIHNpemUgZmV0Y2ggYW5kIHVwbG9hZCBhIHJhc3Rlci5cbiAqL1xuZXhwb3J0IGNsYXNzIERlbnNpdHlMYXllciB7XG4gIC8qKiBUaGUgZGVuc2l0eSB3aW5kb3cgaW4gdXNlIGFuZCB0aGUgZGVuc2VzdCBiaW4sIGZvciB0aGUgcGFuZWwncyB0aHJlc2hvbGQgY29udHJvbC4gKi9cbiAgc3RhdHM6IERlbnNpdHlTdGF0cyB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIGRyYXduIHJhc3RlciBpbiB0cmFuc2NyaXB0cyBwZXIgdW5pdCBhcmVhLCBpdHMgZGVuc2VzdCBiaW4gYW5kIGl0cyBhdXRvIHdpbmRvdy4gKi9cbiAgcHJpdmF0ZSByYXN0ZXI6IHsgcGVyQXJlYTogRmxvYXQzMkFycmF5OyBtYXg6IG51bWJlcjsgYXV0bzogW251bWJlciwgbnVtYmVyXSB9IHwgbnVsbCA9IG51bGw7XG4gIC8qKiBUaGUgY29sb3JtYXAgdGhlIGxheWVyIHdhcyBnaXZlbiwgc28gYW4gdW5jaGFuZ2VkIG9uZSBkb2VzIG5vdCByZWJ1aWxkIGl0cyBMVVQuICovXG4gIHByaXZhdGUgY29sb3JtYXBLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcG9ydDogU3BhdGlhbERhdGFQb3J0LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZ3JvdXBzOiBPcmRlcmVkTGF5ZXJHcm91cHM8VGlsZUdyb3VwPixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoYW5nZWQ6IChzdGF0czogRGVuc2l0eVN0YXRzKSA9PiB2b2lkLFxuICApIHt9XG5cbiAgLyoqIERyYXcgdGhlIHZpZXcncyBkZW5zaXR5LCBvciBkcm9wIGl0OyBhbiB1bmNoYW5nZWQgKGdlbmVzLCBiaW4sIHdpbmRvdywgY29sb3JtYXApIGlzIGEgbm8tb3AuICovXG4gIGFzeW5jIHBsYW4oZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIGN0eDogUGxhbkNvbnRleHQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBoaWRkZW5HZW5lcyA9IG5ldyBTZXQodmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMpO1xuICAgIGNvbnN0IGdlbmVzID0gdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyBbQUxMX0dFTkVTXSA6IHZpZXcudHJhbnNjcmlwdEdlbmVzLmZpbHRlcigoZykgPT4gIWhpZGRlbkdlbmVzLmhhcyhnKSk7XG4gICAgaWYgKCFkYXRhc2V0LmRlbnNpdHkgfHwgIXRoaXMucG9ydC5nZXREZW5zaXR5IHx8IHZpZXcudHJhbnNjcmlwdE1vZGUgIT09ICdkZW5zaXR5JyB8fCAhZ2VuZXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmdyb3Vwcy5kcm9wKCdkZW5zaXR5Jyk7XG4gICAgICB0aGlzLnN0YXRzID0gbnVsbDtcbiAgICAgIHRoaXMucmFzdGVyID0gbnVsbDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gVGhlIHJhc3RlcidzIGtleTogd2hhdCBpdCBpcyBhIHJhc3RlciBPRi4gV2luZG93LCBjb2xvcm1hcCBhbmQgb3BhY2l0eSBhcmUgdGhlIGxheWVyJ3Mgc3R5bGUuXG4gICAgY29uc3Qga2V5ID0gW2RhdGFzZXQuaWQsIGdlbmVzLmpvaW4oJywnKSwgdmlldy5kZW5zaXR5QmluXS5qb2luKCd8Jyk7XG4gICAgLy8gYHNob3duYCwgbm90IGBoYXNgOiBhIHN0aXRjaGVkIHNsaWNlIHJlLXJlbmRlciBjbGVhcnMgdGhlIGxheWVyIGxpc3QsIGFuZCB0aGUga2V5IGFsb25lXG4gICAgLy8gd291bGQgY2FsbCB0aGUgY2xlYXJlZCBsYXllciBkcmF3bi5cbiAgICBpZiAoa2V5ICE9PSB0aGlzLmdyb3Vwcy5rZXkoJ2RlbnNpdHknKSB8fCAhdGhpcy5ncm91cHMuc2hvd24oJ2RlbnNpdHknKSB8fCAhdGhpcy5yYXN0ZXIpIHtcbiAgICAgIGNvbnN0IHJhc3RlciA9IGF3YWl0IGN0eC50cmFjaygnVHJhbnNjcmlwdCBkZW5zaXR5JywgdGhpcy5wb3J0LmdldERlbnNpdHkoZ2VuZXMsIHZpZXcuZGVuc2l0eUJpbikpO1xuICAgICAgaWYgKGN0eC5zdGFsZSgpKSByZXR1cm47XG5cbiAgICAgIC8vIEJpbnMgZHJhd24gYXMgc3F1YXJlcywgYXMgWGVuaXVtIEV4cGxvcmVyIGRvZXM7IHRoZSB3aW5kb3cgaXMgaW4gdHJhbnNjcmlwdHMvwrVtwrIuXG4gICAgICBjb25zdCBtZXRhID0gcmFzdGVyLm1ldGE7XG4gICAgICBjb25zdCBhcmVhID0gbWV0YS5ncmlkU2l6ZVswXSAqIG1ldGEuZ3JpZFNpemVbMV07XG4gICAgICBjb25zdCBwZXJBcmVhID0gcmFzdGVyLnZhbHVlcy5tYXAoKHYpID0+IHYgLyBhcmVhKTtcbiAgICAgIHRoaXMucmFzdGVyID0ge1xuICAgICAgICBwZXJBcmVhLFxuICAgICAgICBtYXg6IHBlckFyZWEucmVkdWNlKChtLCB2KSA9PiAodiA+IG0gPyB2IDogbSksIDApLFxuICAgICAgICBhdXRvOiBkZW5zaXR5QXV0b1JhbmdlKHBlckFyZWEpLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlZiA9IGRhdGFzZXQuaW1hZ2VSZWY7XG4gICAgICBjb25zdCBzeCA9IHJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICAgICAgY29uc3Qgc3kgPSByZWY/LnNjYWxlPy5bMV0gPz8gMTtcbiAgICAgIGNvbnN0IGxheWVyOiBJbWFnZUxheWVyID0gdGhpcy5ncm91cHMudmlld2VyIS5hZGRJbWFnZShcbiAgICAgICAgeyBraW5kOiAndHlwZWQnLCB3aWR0aDogbWV0YS5jb2xzLCBoZWlnaHQ6IG1ldGEucm93cywgY2hhbm5lbHM6IDEsIGR0eXBlOiAnZmxvYXQzMicsIGRhdGE6IHBlckFyZWEgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IGBkZW5zaXR5IMK3ICR7dmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyAnYWxsIGdlbmVzJyA6IGdlbmVzLmpvaW4oJywgJyl9YCxcbiAgICAgICAgICBzY2FsZTogW21ldGEuZ3JpZFNpemVbMF0gKiBzeCwgbWV0YS5ncmlkU2l6ZVsxXSAqIHN5XSxcbiAgICAgICAgICB0cmFuc2xhdGU6IFtcbiAgICAgICAgICAgIG1ldGEub3JpZ2luWzBdICogc3ggKyAocmVmPy50cmFuc2xhdGU/LlswXSA/PyAwKSxcbiAgICAgICAgICAgIG1ldGEub3JpZ2luWzFdICogc3kgKyAocmVmPy50cmFuc2xhdGU/LlsxXSA/PyAwKSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIC8vIFhlbml1bSBFeHBsb3JlcidzIFwic2NhbGUgdGhyZXNob2xkXCI6IGVtcHR5IHRpc3N1ZSBzaG93cyB0aGUgaW1hZ2UgdW5kZXIgaXQuXG4gICAgICAgICAgdHJhbnNwYXJlbnRCZWxvdzogdHJ1ZSxcbiAgICAgICAgICBibGVuZGluZzogJ3RyYW5zbHVjZW50JyxcbiAgICAgICAgICBpbnRlcnBvbGF0aW9uOiAnbmVhcmVzdCcsXG4gICAgICAgIH0sXG4gICAgICApO1xuICAgICAgdGhpcy5jb2xvcm1hcEtleSA9IG51bGw7XG4gICAgICB0aGlzLmdyb3Vwcy5zZXRLZXkoJ2RlbnNpdHknLCBrZXkpO1xuICAgICAgdGhpcy5ncm91cHMucmVwbGFjZSgnZGVuc2l0eScsIGxheWVyKTtcbiAgICB9XG4gICAgdGhpcy5yZXN0eWxlKHRoaXMuZ3JvdXBzLmxheWVyKCdkZW5zaXR5JykgYXMgSW1hZ2VMYXllciwgdmlldyk7XG4gIH1cblxuICAvKiogV2luZG93LCBjb2xvdXIgYW5kIG9wYWNpdHkgb250byB0aGUgZHJhd24gbGF5ZXI6IHVuaWZvcm1zIGFuZCBhIExVVCwgbm8gcmUtdXBsb2FkLiAqL1xuICBwcml2YXRlIHJlc3R5bGUobGF5ZXI6IEltYWdlTGF5ZXIsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUpOiB2b2lkIHtcbiAgICBjb25zdCByYXN0ZXIgPSB0aGlzLnJhc3RlciE7XG4gICAgY29uc3QgW2xvLCBoaV0gPSB2aWV3LmRlbnNpdHlSYW5nZSA/PyByYXN0ZXIuYXV0bztcbiAgICBsYXllci5jb250cmFzdExpbWl0cyA9IFtsbywgaGldO1xuICAgIGxheWVyLm9wYWNpdHkgPSB2aWV3LmRlbnNpdHlPcGFjaXR5O1xuICAgIGNvbnN0IGNvbG9ybWFwS2V5ID0gSlNPTi5zdHJpbmdpZnkodmlldy5kZW5zaXR5Q29sb3JtYXAgPz8gbnVsbCk7XG4gICAgaWYgKGNvbG9ybWFwS2V5ICE9PSB0aGlzLmNvbG9ybWFwS2V5KSB7XG4gICAgICB0aGlzLmNvbG9ybWFwS2V5ID0gY29sb3JtYXBLZXk7XG4gICAgICBsYXllci5jb2xvcm1hcCA9IGNvbG9ybWFwRnJvbUx1dCgndHJhbnNjcmlwdC1kZW5zaXR5JywgbHV0Rm9yKHZpZXcuZGVuc2l0eUNvbG9ybWFwID8/IElORkVSTk9fTFVUKSk7XG4gICAgfVxuICAgIHRoaXMuZ3JvdXBzLnZpZXdlciEucmVxdWVzdFJlbmRlcigpO1xuICAgIGNvbnN0IHN0YXRzID0geyBsbywgaGksIG1heDogcmFzdGVyLm1heCB9O1xuICAgIGlmICh0aGlzLnN0YXRzPy5sbyA9PT0gbG8gJiYgdGhpcy5zdGF0cy5oaSA9PT0gaGkgJiYgdGhpcy5zdGF0cy5tYXggPT09IHJhc3Rlci5tYXgpIHJldHVybjtcbiAgICB0aGlzLnN0YXRzID0gc3RhdHM7XG4gICAgdGhpcy5jaGFuZ2VkKHN0YXRzKTtcbiAgfVxufVxuXG4vKipcbiAqIFRyYW5zY3JpcHRzIGluIHZpZXcgZm9yIHRoZSB2aXNpYmxlIGdlbmVzLCBhZ2FpbnN0IHRoZSBtYXJrZXIgYnVkZ2V0IOKAlCBpdCB0ZWxscyB0aGUgdXNlclxuICogd2hldGhlciB0aGUgYnVkZ2V0IHdpbGwgZm9yY2UgZ3JvdXBpbmcuIENhY2hlcyB0aGUgcGVyLWdlbmUgZGF0YXNldCB0b3RhbHMgZm9yIHRoZSBsYXRlc3RcbiAqIGdlbmUgc2V0LlxuICovXG5leHBvcnQgY2xhc3MgVHJhbnNjcmlwdEVzdGltYXRvciB7XG4gIC8qKiBQZXItZ2VuZSBkYXRhc2V0IHRvdGFscyBmb3IgdGhlIGluLXZpZXcgZXN0aW1hdGUsIGZvciB0aGUgbGF0ZXN0IGdlbmUgc2V0LiAqL1xuICBwcml2YXRlIGNvdW50c0NhY2hlOiB7IGtleTogc3RyaW5nOyBjb3VudHM6IFByb21pc2U8U3BhdGlhbFRyYW5zY3JpcHRDb3VudHM+IH0gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IHBvcnQ6IFNwYXRpYWxEYXRhUG9ydCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNoYW5nZWQ6IChlc3RpbWF0ZTogVHJhbnNjcmlwdEVzdGltYXRlIHwgbnVsbCkgPT4gdm9pZCxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBUcmFuc2NyaXB0cyBpbiB2aWV3IGZvciB0aGUgdmlzaWJsZSBnZW5lczogZWFjaCBnZW5lJ3MgZGF0YXNldCB0b3RhbCB0aW1lcyB0aGUgc2hhcmVcbiAgICogb2YgdGhlIHRpc3N1ZSBvbiBzY3JlZW4uIEFuIGVzdGltYXRlIOKAlCBleHByZXNzaW9uIGlzIG5vdCB1bmlmb3JtIOKAlCB3aGljaCBpcyBhbHNvIHdoYXRcbiAgICogWGVuaXVtIEV4cGxvcmVyIHNob3dzOyBpdCB0ZWxscyB0aGUgdXNlciB3aGV0aGVyIHRoZSBidWRnZXQgd2lsbCBmb3JjZSBncm91cGluZy5cbiAgICovXG4gIGFzeW5jIHBsYW4oXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsXG4gICAgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICB2aWV3ZXI6IFZpZXdlcixcbiAgICB3OiBudW1iZXIsXG4gICAgaDogbnVtYmVyLFxuICAgIGN0eDogUGxhbkNvbnRleHQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRpbGVzID0gZGF0YXNldC50cmFuc2NyaXB0VGlsZXM7XG4gICAgaWYgKCF0aWxlcyB8fCAhdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRDb3VudHMgfHwgdmlldy50cmFuc2NyaXB0TW9kZSA9PT0gJ29mZicpIHtcbiAgICAgIHRoaXMuY2hhbmdlZChudWxsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaGlkZGVuR2VuZXMgPSBuZXcgU2V0KHZpZXcudHJhbnNjcmlwdEhpZGRlbkdlbmVzKTtcbiAgICBjb25zdCBnZW5lcyA9IHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gW10gOiB2aWV3LnRyYW5zY3JpcHRHZW5lcy5maWx0ZXIoKGcpID0+ICFoaWRkZW5HZW5lcy5oYXMoZykpO1xuICAgIGNvbnN0IGtleSA9IGAke2RhdGFzZXQuaWR9fCR7Z2VuZXMuam9pbignLCcpfWA7XG4gICAgaWYgKHRoaXMuY291bnRzQ2FjaGU/LmtleSAhPT0ga2V5KSB7XG4gICAgICB0aGlzLmNvdW50c0NhY2hlID0geyBrZXksIGNvdW50czogdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRDb3VudHMoZ2VuZXMpIH07XG4gICAgfVxuICAgIGxldCBjb3VudHM6IFNwYXRpYWxUcmFuc2NyaXB0Q291bnRzO1xuICAgIHRyeSB7XG4gICAgICBjb3VudHMgPSBhd2FpdCB0aGlzLmNvdW50c0NhY2hlLmNvdW50cztcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRoaXMuY291bnRzQ2FjaGUgPSBudWxsO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoY3R4LnN0YWxlKCkpIHJldHVybjtcbiAgICBjb25zdCBpblZpZXcgPSB2aXNpYmxlRGF0YVJlY3Qodmlld2VyLmNhbWVyYS5jZW50ZXIsIHZpZXdlci5jYW1lcmEuem9vbSwgdywgaCwgZGF0YXNldC5pbWFnZVJlZiwgMCk7XG4gICAgaWYgKCFpblZpZXcpIHJldHVybjtcbiAgICBjb25zdCBiID0gY291bnRzLmJvdW5kcztcbiAgICBjb25zdCBzaGFyZSA9IE1hdGgubWluKDEsIHZpc2libGVBcmVhKGluVmlldywgYikgLyBNYXRoLm1heCgxLCAoYlsyXSAtIGJbMF0pICogKGJbM10gLSBiWzFdKSkpO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdmlldy50cmFuc2NyaXB0QWxsR2VuZXNcbiAgICAgID8gY291bnRzLnRvdGFsXG4gICAgICA6IGdlbmVzLnJlZHVjZSgoc3VtLCBnKSA9PiBzdW0gKyAoY291bnRzLmNvdW50c1tnXSA/PyAwKSwgMCk7XG4gICAgdGhpcy5jaGFuZ2VkKHsgcG9pbnRzOiBNYXRoLnJvdW5kKHNlbGVjdGVkICogc2hhcmUpLCBtYXg6IHZpZXcudHJhbnNjcmlwdEJ1ZGdldCB9KTtcbiAgfVxufVxuIl19
|