@jax-data-science/sci-image-visualizer 0.1.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/LICENSE +21 -0
- package/README.md +404 -0
- package/esm2022/index.mjs +52 -0
- package/esm2022/jax-data-science-sci-image-visualizer.mjs +5 -0
- package/esm2022/lib/channel-histogram/channel-histogram.component.mjs +398 -0
- package/esm2022/lib/contracts/capabilities.contract.mjs +32 -0
- package/esm2022/lib/contracts/cell-segmenter.contract.mjs +12 -0
- package/esm2022/lib/contracts/channel-histogram-api.contract.mjs +14 -0
- package/esm2022/lib/contracts/colormap-lut.mjs +95 -0
- package/esm2022/lib/contracts/coordinate-transform.contract.mjs +2 -0
- package/esm2022/lib/contracts/display-types.mjs +8 -0
- package/esm2022/lib/contracts/image.contract.mjs +11 -0
- package/esm2022/lib/contracts/intensity.mjs +28 -0
- package/esm2022/lib/contracts/plot-type.mjs +112 -0
- package/esm2022/lib/contracts/ports/image-state.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/preferences.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/region-io.port.mjs +3 -0
- package/esm2022/lib/contracts/ports/tile-access.port.mjs +3 -0
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +4 -0
- package/esm2022/lib/contracts/region-overlay.contract.mjs +2 -0
- package/esm2022/lib/contracts/region-store.contract.mjs +2 -0
- package/esm2022/lib/contracts/sam.contract.mjs +12 -0
- package/esm2022/lib/contracts/toolbar-config.mjs +8 -0
- package/esm2022/lib/contracts/visualizer.contract.mjs +10 -0
- package/esm2022/lib/contracts/viz-config.mjs +3 -0
- package/esm2022/lib/hex-color-picker/hex-color-picker.component.mjs +260 -0
- package/esm2022/lib/implementations/base-store-visualizer.mjs +76 -0
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +106 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +847 -0
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +92 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2283 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-z-handle.mjs +126 -0
- package/esm2022/lib/implementations/osd/display-pipeline.mjs +143 -0
- package/esm2022/lib/implementations/osd/histogram-sampler.mjs +217 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +1780 -0
- package/esm2022/lib/implementations/osd/osd-coordinate-transform.mjs +25 -0
- package/esm2022/lib/implementations/osd/osd-coords.mjs +53 -0
- package/esm2022/lib/implementations/osd/osd-lib.mjs +20 -0
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +1237 -0
- package/esm2022/lib/implementations/osd/osd-scale-bar.mjs +88 -0
- package/esm2022/lib/implementations/osd/slice-cache.mjs +488 -0
- package/esm2022/lib/implementations/osd/tile-client.mjs +29 -0
- package/esm2022/lib/implementations/plotly/plotly-coordinate-transform.mjs +37 -0
- package/esm2022/lib/implementations/plotly/plotly-region-overlay.mjs +31 -0
- package/esm2022/lib/implementations/plotly/plotly-trace-builders.mjs +183 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +2137 -0
- package/esm2022/lib/implementations/simple-slice-access.service.mjs +99 -0
- package/esm2022/lib/models/bezier.mjs +120 -0
- package/esm2022/lib/models/class-preset.mjs +46 -0
- package/esm2022/lib/models/geometry.mjs +198 -0
- package/esm2022/lib/models/region.mjs +166 -0
- package/esm2022/lib/models/shape.mjs +53 -0
- package/esm2022/lib/plot.utilities.mjs +693 -0
- package/esm2022/lib/processing/image-converter.service.mjs +90 -0
- package/esm2022/lib/processing/image-crop.mjs +62 -0
- package/esm2022/lib/processing/processing-image.mjs +50 -0
- package/esm2022/lib/provide-visualization.mjs +63 -0
- package/esm2022/lib/region-editor/mask-raster.mjs +95 -0
- package/esm2022/lib/region-editor/mask-worker.mjs +10 -0
- package/esm2022/lib/region-editor/region-editor.component.mjs +1190 -0
- package/esm2022/lib/region-ops.service.mjs +301 -0
- package/esm2022/lib/render-orchestrator.mjs +87 -0
- package/esm2022/lib/routing-visualizer.service.mjs +533 -0
- package/esm2022/lib/store/class-color.util.mjs +52 -0
- package/esm2022/lib/store/region-store.service.mjs +1029 -0
- package/esm2022/lib/store/visualizer-store.service.mjs +352 -0
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +546 -0
- package/esm2022/lib/toolbar/crop/slide-crop.mjs +57 -0
- package/esm2022/lib/toolbar/segmentation/cell-segment-tool.service.mjs +115 -0
- package/esm2022/lib/toolbar/segmentation/cellpose-segmenter.service.mjs +84 -0
- package/esm2022/lib/toolbar/segmentation/onnx-sam-session.mjs +133 -0
- package/esm2022/lib/toolbar/segmentation/ort-runtime-config.mjs +31 -0
- package/esm2022/lib/toolbar/segmentation/sam-model-registry.mjs +108 -0
- package/esm2022/lib/toolbar/segmentation/sam-onnx-core.mjs +159 -0
- package/esm2022/lib/toolbar/segmentation/sam-point-tool.service.mjs +255 -0
- package/esm2022/lib/toolbar/segmentation/sam-prompt.mjs +94 -0
- package/esm2022/lib/toolbar/segmentation/sam-tool.service.mjs +188 -0
- package/esm2022/lib/toolbar/toolbar.component.mjs +311 -0
- package/esm2022/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.mjs +234 -0
- package/esm2022/lib/toolbar/wand/wand-tool.service.mjs +499 -0
- package/esm2022/lib/toolbar/wand/wand.service.mjs +921 -0
- package/esm2022/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.mjs +157 -0
- package/esm2022/lib/visualization.module.mjs +162 -0
- package/esm2022/lib/visualizer.component.mjs +1597 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-mask-worker-uhepXUhM.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs +327 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +21314 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -0
- package/fesm2022/mask.worker.js +989 -0
- package/fesm2022/onnx-sam.worker.js +202 -0
- package/index.d.ts +39 -0
- package/lib/channel-histogram/channel-histogram.component.d.ts +112 -0
- package/lib/contracts/capabilities.contract.d.ts +30 -0
- package/lib/contracts/cell-segmenter.contract.d.ts +40 -0
- package/lib/contracts/channel-histogram-api.contract.d.ts +98 -0
- package/lib/contracts/colormap-lut.d.ts +21 -0
- package/lib/contracts/coordinate-transform.contract.d.ts +43 -0
- package/lib/contracts/display-types.d.ts +41 -0
- package/lib/contracts/image.contract.d.ts +72 -0
- package/lib/contracts/intensity.d.ts +18 -0
- package/lib/contracts/plot-type.d.ts +108 -0
- package/lib/contracts/ports/image-state.port.d.ts +29 -0
- package/lib/contracts/ports/preferences.port.d.ts +19 -0
- package/lib/contracts/ports/region-io.port.d.ts +29 -0
- package/lib/contracts/ports/tile-access.port.d.ts +27 -0
- package/lib/contracts/region-editor-api.contract.d.ts +83 -0
- package/lib/contracts/region-overlay.contract.d.ts +47 -0
- package/lib/contracts/region-store.contract.d.ts +74 -0
- package/lib/contracts/sam.contract.d.ts +98 -0
- package/lib/contracts/toolbar-config.d.ts +24 -0
- package/lib/contracts/visualizer.contract.d.ts +346 -0
- package/lib/contracts/viz-config.d.ts +25 -0
- package/lib/hex-color-picker/hex-color-picker.component.d.ts +47 -0
- package/lib/implementations/base-store-visualizer.d.ts +71 -0
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +47 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +115 -0
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +31 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +455 -0
- package/lib/implementations/napari-js/napari-volume-z-handle.d.ts +46 -0
- package/lib/implementations/osd/display-pipeline.d.ts +47 -0
- package/lib/implementations/osd/histogram-sampler.d.ts +85 -0
- package/lib/implementations/osd/openseadragon-visualizer.service.d.ts +476 -0
- package/lib/implementations/osd/osd-coordinate-transform.d.ts +17 -0
- package/lib/implementations/osd/osd-coords.d.ts +16 -0
- package/lib/implementations/osd/osd-lib.d.ts +19 -0
- package/lib/implementations/osd/osd-region-overlay.d.ts +191 -0
- package/lib/implementations/osd/osd-scale-bar.d.ts +17 -0
- package/lib/implementations/osd/slice-cache.d.ts +161 -0
- package/lib/implementations/osd/tile-client.d.ts +32 -0
- package/lib/implementations/plotly/plotly-coordinate-transform.d.ts +19 -0
- package/lib/implementations/plotly/plotly-region-overlay.d.ts +23 -0
- package/lib/implementations/plotly/plotly-trace-builders.d.ts +60 -0
- package/lib/implementations/plotly/plotly.service.d.ts +594 -0
- package/lib/implementations/simple-slice-access.service.d.ts +64 -0
- package/lib/models/bezier.d.ts +59 -0
- package/lib/models/class-preset.d.ts +39 -0
- package/lib/models/geometry.d.ts +66 -0
- package/lib/models/region.d.ts +132 -0
- package/lib/models/shape.d.ts +44 -0
- package/lib/plot.utilities.d.ts +107 -0
- package/lib/processing/image-converter.service.d.ts +28 -0
- package/lib/processing/image-crop.d.ts +18 -0
- package/lib/processing/processing-image.d.ts +17 -0
- package/lib/provide-visualization.d.ts +34 -0
- package/lib/region-editor/mask-raster.d.ts +61 -0
- package/lib/region-editor/mask-worker.d.ts +7 -0
- package/lib/region-editor/region-editor.component.d.ts +305 -0
- package/lib/region-ops.service.d.ts +92 -0
- package/lib/render-orchestrator.d.ts +59 -0
- package/lib/routing-visualizer.service.d.ts +227 -0
- package/lib/store/class-color.util.d.ts +26 -0
- package/lib/store/region-store.service.d.ts +315 -0
- package/lib/store/visualizer-store.service.d.ts +123 -0
- package/lib/toolbar/brush/brush-tool.service.d.ts +143 -0
- package/lib/toolbar/crop/slide-crop.d.ts +30 -0
- package/lib/toolbar/segmentation/cell-segment-tool.service.d.ts +32 -0
- package/lib/toolbar/segmentation/cellpose-segmenter.service.d.ts +39 -0
- package/lib/toolbar/segmentation/onnx-sam-session.d.ts +25 -0
- package/lib/toolbar/segmentation/ort-runtime-config.d.ts +4 -0
- package/lib/toolbar/segmentation/sam-model-registry.d.ts +36 -0
- package/lib/toolbar/segmentation/sam-onnx-core.d.ts +48 -0
- package/lib/toolbar/segmentation/sam-point-tool.service.d.ts +59 -0
- package/lib/toolbar/segmentation/sam-prompt.d.ts +34 -0
- package/lib/toolbar/segmentation/sam-tool.service.d.ts +50 -0
- package/lib/toolbar/toolbar.component.d.ts +167 -0
- package/lib/toolbar/vertex-eraser/vertex-eraser-tool.service.d.ts +64 -0
- package/lib/toolbar/wand/wand-tool.service.d.ts +149 -0
- package/lib/toolbar/wand/wand.service.d.ts +133 -0
- package/lib/toolbar/zoom-to-box/zoom-to-box-tool.service.d.ts +49 -0
- package/lib/visualization.module.d.ts +45 -0
- package/lib/visualizer.component.d.ts +378 -0
- package/package.json +73 -0
- package/src/lib/assets/3d-coordinates.svg +49 -0
- package/src/lib/assets/cells.svg +1 -0
- package/src/lib/assets/click.svg +1 -0
- package/src/lib/assets/colormap-luts.json +1 -0
- package/src/lib/assets/contour.svg +48 -0
- package/src/lib/assets/cube-3d.svg +1 -0
- package/src/lib/assets/edit-selection-white.svg +47 -0
- package/src/lib/assets/heatmap.svg +1 -0
- package/src/lib/assets/icons/colormap-Pastel1.png +0 -0
- package/src/lib/assets/icons/colormap-accent.png +0 -0
- package/src/lib/assets/icons/colormap-afmhot.png +0 -0
- package/src/lib/assets/icons/colormap-autumn.png +0 -0
- package/src/lib/assets/icons/colormap-berlin.png +0 -0
- package/src/lib/assets/icons/colormap-binary.png +0 -0
- package/src/lib/assets/icons/colormap-blackbody.png +0 -0
- package/src/lib/assets/icons/colormap-bluered.png +0 -0
- package/src/lib/assets/icons/colormap-blues.png +0 -0
- package/src/lib/assets/icons/colormap-bone.png +0 -0
- package/src/lib/assets/icons/colormap-brbg.png +0 -0
- package/src/lib/assets/icons/colormap-brg.png +0 -0
- package/src/lib/assets/icons/colormap-bugn.png +0 -0
- package/src/lib/assets/icons/colormap-bupu.png +0 -0
- package/src/lib/assets/icons/colormap-bwr.png +0 -0
- package/src/lib/assets/icons/colormap-cividis.png +0 -0
- package/src/lib/assets/icons/colormap-cmrmap.png +0 -0
- package/src/lib/assets/icons/colormap-cool.png +0 -0
- package/src/lib/assets/icons/colormap-coolwarm.png +0 -0
- package/src/lib/assets/icons/colormap-copper.png +0 -0
- package/src/lib/assets/icons/colormap-cubehelix.png +0 -0
- package/src/lib/assets/icons/colormap-dark2.png +0 -0
- package/src/lib/assets/icons/colormap-earth.png +0 -0
- package/src/lib/assets/icons/colormap-electric.png +0 -0
- package/src/lib/assets/icons/colormap-flag.png +0 -0
- package/src/lib/assets/icons/colormap-gist_earth.png +0 -0
- package/src/lib/assets/icons/colormap-gist_gray.png +0 -0
- package/src/lib/assets/icons/colormap-gist_heat.png +0 -0
- package/src/lib/assets/icons/colormap-gist_ncar.png +0 -0
- package/src/lib/assets/icons/colormap-gist_rainbow.png +0 -0
- package/src/lib/assets/icons/colormap-gist_stern.png +0 -0
- package/src/lib/assets/icons/colormap-gist_yarg.png +0 -0
- package/src/lib/assets/icons/colormap-gnbu.png +0 -0
- package/src/lib/assets/icons/colormap-gnuplot.png +0 -0
- package/src/lib/assets/icons/colormap-gnuplot2.png +0 -0
- package/src/lib/assets/icons/colormap-gray.png +0 -0
- package/src/lib/assets/icons/colormap-greens-inv.png +0 -0
- package/src/lib/assets/icons/colormap-greens.png +0 -0
- package/src/lib/assets/icons/colormap-greys-inv.png +0 -0
- package/src/lib/assets/icons/colormap-greys.png +0 -0
- package/src/lib/assets/icons/colormap-hot.png +0 -0
- package/src/lib/assets/icons/colormap-hsv.png +0 -0
- package/src/lib/assets/icons/colormap-inferno.png +0 -0
- package/src/lib/assets/icons/colormap-jet.png +0 -0
- package/src/lib/assets/icons/colormap-magma.png +0 -0
- package/src/lib/assets/icons/colormap-managua.png +0 -0
- package/src/lib/assets/icons/colormap-nipy_spectral.png +0 -0
- package/src/lib/assets/icons/colormap-ocean.png +0 -0
- package/src/lib/assets/icons/colormap-oranges.png +0 -0
- package/src/lib/assets/icons/colormap-orrd.png +0 -0
- package/src/lib/assets/icons/colormap-pastel2.png +0 -0
- package/src/lib/assets/icons/colormap-picnic.png +0 -0
- package/src/lib/assets/icons/colormap-pink.png +0 -0
- package/src/lib/assets/icons/colormap-piyg.png +0 -0
- package/src/lib/assets/icons/colormap-placeholder.png +0 -0
- package/src/lib/assets/icons/colormap-plasma.png +0 -0
- package/src/lib/assets/icons/colormap-portland.png +0 -0
- package/src/lib/assets/icons/colormap-prgn.png +0 -0
- package/src/lib/assets/icons/colormap-prism.png +0 -0
- package/src/lib/assets/icons/colormap-pubu.png +0 -0
- package/src/lib/assets/icons/colormap-pubugn.png +0 -0
- package/src/lib/assets/icons/colormap-puor.png +0 -0
- package/src/lib/assets/icons/colormap-purd.png +0 -0
- package/src/lib/assets/icons/colormap-purples.png +0 -0
- package/src/lib/assets/icons/colormap-rainbow.png +0 -0
- package/src/lib/assets/icons/colormap-rdbu.png +0 -0
- package/src/lib/assets/icons/colormap-rdgy.png +0 -0
- package/src/lib/assets/icons/colormap-rdpu.png +0 -0
- package/src/lib/assets/icons/colormap-rdylbu.png +0 -0
- package/src/lib/assets/icons/colormap-rdylgn.png +0 -0
- package/src/lib/assets/icons/colormap-reds.png +0 -0
- package/src/lib/assets/icons/colormap-seismic.png +0 -0
- package/src/lib/assets/icons/colormap-set1.png +0 -0
- package/src/lib/assets/icons/colormap-set2.png +0 -0
- package/src/lib/assets/icons/colormap-set3.png +0 -0
- package/src/lib/assets/icons/colormap-spectral.png +0 -0
- package/src/lib/assets/icons/colormap-spring.png +0 -0
- package/src/lib/assets/icons/colormap-summer.png +0 -0
- package/src/lib/assets/icons/colormap-tab10.png +0 -0
- package/src/lib/assets/icons/colormap-tab20.png +0 -0
- package/src/lib/assets/icons/colormap-tab20b.png +0 -0
- package/src/lib/assets/icons/colormap-tab20c.png +0 -0
- package/src/lib/assets/icons/colormap-terrain.png +0 -0
- package/src/lib/assets/icons/colormap-turbo.png +0 -0
- package/src/lib/assets/icons/colormap-twilight.png +0 -0
- package/src/lib/assets/icons/colormap-twilight_shifted.png +0 -0
- package/src/lib/assets/icons/colormap-vanimo.png +0 -0
- package/src/lib/assets/icons/colormap-viridis.png +0 -0
- package/src/lib/assets/icons/colormap-winter.png +0 -0
- package/src/lib/assets/icons/colormap-wistia.png +0 -0
- package/src/lib/assets/icons/colormap-ylgn.png +0 -0
- package/src/lib/assets/icons/colormap-ylgnbu-inv.png +0 -0
- package/src/lib/assets/icons/colormap-ylgnbu.png +0 -0
- package/src/lib/assets/icons/colormap-ylorbr.png +0 -0
- package/src/lib/assets/icons/colormap-ylorrd-inv.png +0 -0
- package/src/lib/assets/icons/colormap-ylorrd.png +0 -0
- package/src/lib/assets/interactive-segmentation-cursor.svg +1 -0
- package/src/lib/assets/invert.svg +1 -0
- package/src/lib/assets/isosurface.svg +7 -0
- package/src/lib/assets/mask.svg +1 -0
- package/src/lib/assets/paintbrush.svg +1 -0
- package/src/lib/assets/picture-segmentation.svg +43 -0
- package/src/lib/assets/polygon-vertices.svg +13 -0
- package/src/lib/assets/polyline.svg +3 -0
- package/src/lib/assets/redo.svg +39 -0
- package/src/lib/assets/region-editor.svg +37 -0
- package/src/lib/assets/region-move.svg +7 -0
- package/src/lib/assets/smooth.svg +56 -0
- package/src/lib/assets/spline-chart.svg +7 -0
- package/src/lib/assets/surface.svg +37 -0
- package/src/lib/assets/test/download-379.svg +1 -0
- package/src/lib/assets/test/download-98.svg +1 -0
- package/src/lib/assets/test/json-1.svg +1 -0
- package/src/lib/assets/test/load-53.svg +1 -0
- package/src/lib/assets/test/mask-44.svg +1 -0
- package/src/lib/assets/test/mask-download-44.svg +15 -0
- package/src/lib/assets/test/mask-save-44.svg +11 -0
- package/src/lib/assets/test/overlay-1.svg +1 -0
- package/src/lib/assets/test/overlay-4.svg +1 -0
- package/src/lib/assets/test/region-26.svg +1 -0
- package/src/lib/assets/test/save-56.svg +1 -0
- package/src/lib/assets/test/upload-43.svg +1 -0
- package/src/lib/assets/to-bezier.svg +15 -0
- package/src/lib/assets/to-polygon.svg +11 -0
- package/src/lib/assets/undo.svg +38 -0
- package/src/lib/assets/vertex-add.svg +12 -0
- package/src/lib/assets/vertex-delete.svg +12 -0
- package/src/lib/assets/wand.svg +54 -0
- package/src/lib/assets/zoom-box.svg +10 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plotly implementation of {@link ICoordinateTransform}. Wraps the axis objects
|
|
3
|
+
* on the plot's `_fullLayout`. This is the exact math the wand / vertex-eraser
|
|
4
|
+
* used inline before they were decoupled — lifted here verbatim so Plotly
|
|
5
|
+
* behaviour is unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export class PlotlyCoordinateTransform {
|
|
8
|
+
constructor(getGraphDiv, getContainer) {
|
|
9
|
+
this.getGraphDiv = getGraphDiv;
|
|
10
|
+
this.getContainer = getContainer;
|
|
11
|
+
}
|
|
12
|
+
axes() {
|
|
13
|
+
const layout = this.getGraphDiv()?._fullLayout;
|
|
14
|
+
return { xaxis: layout?.xaxis, yaxis: layout?.yaxis };
|
|
15
|
+
}
|
|
16
|
+
isReady() {
|
|
17
|
+
const { xaxis, yaxis } = this.axes();
|
|
18
|
+
return !!(xaxis && yaxis);
|
|
19
|
+
}
|
|
20
|
+
clientToData(clientX, clientY) {
|
|
21
|
+
const { xaxis, yaxis } = this.axes();
|
|
22
|
+
const rect = this.getContainer()?.getBoundingClientRect();
|
|
23
|
+
if (!xaxis || !yaxis || !rect)
|
|
24
|
+
return { x: NaN, y: NaN };
|
|
25
|
+
return {
|
|
26
|
+
x: xaxis.p2d(clientX - rect.left - xaxis._offset),
|
|
27
|
+
y: yaxis.p2d(clientY - rect.top - yaxis._offset),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
dataLengthToScreen(dataLength) {
|
|
31
|
+
const { xaxis } = this.axes();
|
|
32
|
+
if (!xaxis)
|
|
33
|
+
return 0;
|
|
34
|
+
return Math.abs(xaxis.l2p(dataLength) - xaxis.l2p(0));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LWNvb3JkaW5hdGUtdHJhbnNmb3JtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1jb29yZGluYXRlLXRyYW5zZm9ybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQTs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyx5QkFBeUI7SUFFcEMsWUFDVSxXQUFzQixFQUN0QixZQUFzQztRQUR0QyxnQkFBVyxHQUFYLFdBQVcsQ0FBVztRQUN0QixpQkFBWSxHQUFaLFlBQVksQ0FBMEI7SUFDN0MsQ0FBQztJQUVJLElBQUk7UUFDVixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsV0FBVyxDQUFDO1FBQy9DLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3hELENBQUM7SUFFRCxPQUFPO1FBQ0wsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLENBQUM7SUFDNUIsQ0FBQztJQUVELFlBQVksQ0FBQyxPQUFlLEVBQUUsT0FBZTtRQUMzQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFLEVBQUUscUJBQXFCLEVBQUUsQ0FBQztRQUMxRCxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUN6RCxPQUFPO1lBQ0wsQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQztZQUNqRCxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1NBQ2pELENBQUM7SUFDSixDQUFDO0lBRUQsa0JBQWtCLENBQUMsVUFBa0I7UUFDbkMsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5QixJQUFJLENBQUMsS0FBSztZQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJQ29vcmRpbmF0ZVRyYW5zZm9ybSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9jb29yZGluYXRlLXRyYW5zZm9ybS5jb250cmFjdCc7XG5cbi8qKlxuICogUGxvdGx5IGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJQ29vcmRpbmF0ZVRyYW5zZm9ybX0uIFdyYXBzIHRoZSBheGlzIG9iamVjdHNcbiAqIG9uIHRoZSBwbG90J3MgYF9mdWxsTGF5b3V0YC4gVGhpcyBpcyB0aGUgZXhhY3QgbWF0aCB0aGUgd2FuZCAvIHZlcnRleC1lcmFzZXJcbiAqIHVzZWQgaW5saW5lIGJlZm9yZSB0aGV5IHdlcmUgZGVjb3VwbGVkIOKAlCBsaWZ0ZWQgaGVyZSB2ZXJiYXRpbSBzbyBQbG90bHlcbiAqIGJlaGF2aW91ciBpcyB1bmNoYW5nZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbG90bHlDb29yZGluYXRlVHJhbnNmb3JtIGltcGxlbWVudHMgSUNvb3JkaW5hdGVUcmFuc2Zvcm0ge1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZ2V0R3JhcGhEaXY6ICgpID0+IGFueSxcbiAgICBwcml2YXRlIGdldENvbnRhaW5lcjogKCkgPT4gSFRNTEVsZW1lbnQgfCBudWxsLFxuICApIHt9XG5cbiAgcHJpdmF0ZSBheGVzKCk6IHsgeGF4aXM6IGFueTsgeWF4aXM6IGFueSB9IHtcbiAgICBjb25zdCBsYXlvdXQgPSB0aGlzLmdldEdyYXBoRGl2KCk/Ll9mdWxsTGF5b3V0O1xuICAgIHJldHVybiB7IHhheGlzOiBsYXlvdXQ/LnhheGlzLCB5YXhpczogbGF5b3V0Py55YXhpcyB9O1xuICB9XG5cbiAgaXNSZWFkeSgpOiBib29sZWFuIHtcbiAgICBjb25zdCB7IHhheGlzLCB5YXhpcyB9ID0gdGhpcy5heGVzKCk7XG4gICAgcmV0dXJuICEhKHhheGlzICYmIHlheGlzKTtcbiAgfVxuXG4gIGNsaWVudFRvRGF0YShjbGllbnRYOiBudW1iZXIsIGNsaWVudFk6IG51bWJlcik6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB7XG4gICAgY29uc3QgeyB4YXhpcywgeWF4aXMgfSA9IHRoaXMuYXhlcygpO1xuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmdldENvbnRhaW5lcigpPy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBpZiAoIXhheGlzIHx8ICF5YXhpcyB8fCAhcmVjdCkgcmV0dXJuIHsgeDogTmFOLCB5OiBOYU4gfTtcbiAgICByZXR1cm4ge1xuICAgICAgeDogeGF4aXMucDJkKGNsaWVudFggLSByZWN0LmxlZnQgLSB4YXhpcy5fb2Zmc2V0KSxcbiAgICAgIHk6IHlheGlzLnAyZChjbGllbnRZIC0gcmVjdC50b3AgLSB5YXhpcy5fb2Zmc2V0KSxcbiAgICB9O1xuICB9XG5cbiAgZGF0YUxlbmd0aFRvU2NyZWVuKGRhdGFMZW5ndGg6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgeyB4YXhpcyB9ID0gdGhpcy5heGVzKCk7XG4gICAgaWYgKCF4YXhpcykgcmV0dXJuIDA7XG4gICAgcmV0dXJuIE1hdGguYWJzKHhheGlzLmwycChkYXRhTGVuZ3RoKSAtIHhheGlzLmwycCgwKSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plotly implementation of {@link IRegionOverlay}.
|
|
3
|
+
*
|
|
4
|
+
* Plotly renders region shapes natively in its plot layout and edits them via
|
|
5
|
+
* its own drag modes, so this adapter is thin: it maps the neutral
|
|
6
|
+
* {@link RegionToolMode} onto Plotly drag modes and lets Plotly draw. `redraw`
|
|
7
|
+
* is a no-op because Plotly re-renders its shapes itself on relayout.
|
|
8
|
+
*
|
|
9
|
+
* It is the symmetric counterpart to {@link OsdRegionOverlay}: both render the
|
|
10
|
+
* same shared `IRegionStore`, each onto its own backend's canvas.
|
|
11
|
+
*/
|
|
12
|
+
export class PlotlyRegionOverlay {
|
|
13
|
+
constructor(plotly) {
|
|
14
|
+
this.plotly = plotly;
|
|
15
|
+
}
|
|
16
|
+
setMode(mode) {
|
|
17
|
+
// 'select' is a neutral mode for Plotly (no drag mode); region selection is
|
|
18
|
+
// driven by the table / active-shape sampling, so just clear the drag mode.
|
|
19
|
+
const dragMode = mode === 'drawrect' ? 'drawrect' :
|
|
20
|
+
mode === 'drawclosedpath' ? 'drawclosedpath' :
|
|
21
|
+
mode === 'drawopenpath' ? 'drawopenpath' :
|
|
22
|
+
false;
|
|
23
|
+
this.plotly.setDragMode(dragMode);
|
|
24
|
+
}
|
|
25
|
+
redraw() { }
|
|
26
|
+
/** Bezier regions are an OpenSeadragon-only feature (Plotly has no native
|
|
27
|
+
* curved-shape rendering), so this is a no-op here. */
|
|
28
|
+
setSelectedBezier(_bezier) { }
|
|
29
|
+
destroy() { }
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXJlZ2lvbi1vdmVybGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS1yZWdpb24tb3ZlcmxheS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxPQUFPLG1CQUFtQjtJQUU5QixZQUFvQixNQUFxQjtRQUFyQixXQUFNLEdBQU4sTUFBTSxDQUFlO0lBQUcsQ0FBQztJQUU3QyxPQUFPLENBQUMsSUFBb0I7UUFDMUIsNEVBQTRFO1FBQzVFLDRFQUE0RTtRQUM1RSxNQUFNLFFBQVEsR0FDWixJQUFJLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNsQyxJQUFJLEtBQUssZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUM7Z0JBQzlDLElBQUksS0FBSyxjQUFjLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDO29CQUMxQyxLQUFLLENBQUM7UUFDUixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsTUFBTSxLQUFtRSxDQUFDO0lBRTFFOzREQUN3RDtJQUN4RCxpQkFBaUIsQ0FBQyxPQUFnQixJQUF5QixDQUFDO0lBRTVELE9BQU8sS0FBeUUsQ0FBQztDQUNsRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBsb3RseVNlcnZpY2UgfSBmcm9tICcuL3Bsb3RseS5zZXJ2aWNlJztcbmltcG9ydCB7IElSZWdpb25PdmVybGF5LCBSZWdpb25Ub29sTW9kZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9yZWdpb24tb3ZlcmxheS5jb250cmFjdCc7XG5cbi8qKlxuICogUGxvdGx5IGltcGxlbWVudGF0aW9uIG9mIHtAbGluayBJUmVnaW9uT3ZlcmxheX0uXG4gKlxuICogUGxvdGx5IHJlbmRlcnMgcmVnaW9uIHNoYXBlcyBuYXRpdmVseSBpbiBpdHMgcGxvdCBsYXlvdXQgYW5kIGVkaXRzIHRoZW0gdmlhXG4gKiBpdHMgb3duIGRyYWcgbW9kZXMsIHNvIHRoaXMgYWRhcHRlciBpcyB0aGluOiBpdCBtYXBzIHRoZSBuZXV0cmFsXG4gKiB7QGxpbmsgUmVnaW9uVG9vbE1vZGV9IG9udG8gUGxvdGx5IGRyYWcgbW9kZXMgYW5kIGxldHMgUGxvdGx5IGRyYXcuIGByZWRyYXdgXG4gKiBpcyBhIG5vLW9wIGJlY2F1c2UgUGxvdGx5IHJlLXJlbmRlcnMgaXRzIHNoYXBlcyBpdHNlbGYgb24gcmVsYXlvdXQuXG4gKlxuICogSXQgaXMgdGhlIHN5bW1ldHJpYyBjb3VudGVycGFydCB0byB7QGxpbmsgT3NkUmVnaW9uT3ZlcmxheX06IGJvdGggcmVuZGVyIHRoZVxuICogc2FtZSBzaGFyZWQgYElSZWdpb25TdG9yZWAsIGVhY2ggb250byBpdHMgb3duIGJhY2tlbmQncyBjYW52YXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbG90bHlSZWdpb25PdmVybGF5IGltcGxlbWVudHMgSVJlZ2lvbk92ZXJsYXkge1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcGxvdGx5OiBQbG90bHlTZXJ2aWNlKSB7fVxuXG4gIHNldE1vZGUobW9kZTogUmVnaW9uVG9vbE1vZGUpOiB2b2lkIHtcbiAgICAvLyAnc2VsZWN0JyBpcyBhIG5ldXRyYWwgbW9kZSBmb3IgUGxvdGx5IChubyBkcmFnIG1vZGUpOyByZWdpb24gc2VsZWN0aW9uIGlzXG4gICAgLy8gZHJpdmVuIGJ5IHRoZSB0YWJsZSAvIGFjdGl2ZS1zaGFwZSBzYW1wbGluZywgc28ganVzdCBjbGVhciB0aGUgZHJhZyBtb2RlLlxuICAgIGNvbnN0IGRyYWdNb2RlID1cbiAgICAgIG1vZGUgPT09ICdkcmF3cmVjdCcgPyAnZHJhd3JlY3QnIDpcbiAgICAgIG1vZGUgPT09ICdkcmF3Y2xvc2VkcGF0aCcgPyAnZHJhd2Nsb3NlZHBhdGgnIDpcbiAgICAgIG1vZGUgPT09ICdkcmF3b3BlbnBhdGgnID8gJ2RyYXdvcGVucGF0aCcgOlxuICAgICAgZmFsc2U7XG4gICAgdGhpcy5wbG90bHkuc2V0RHJhZ01vZGUoZHJhZ01vZGUpO1xuICB9XG5cbiAgcmVkcmF3KCk6IHZvaWQgeyAvKiBQbG90bHkgcmUtcmVuZGVycyBpdHMgc2hhcGVzIG5hdGl2ZWx5IG9uIHJlbGF5b3V0ICovIH1cblxuICAvKiogQmV6aWVyIHJlZ2lvbnMgYXJlIGFuIE9wZW5TZWFkcmFnb24tb25seSBmZWF0dXJlIChQbG90bHkgaGFzIG5vIG5hdGl2ZVxuICAgKiAgY3VydmVkLXNoYXBlIHJlbmRlcmluZyksIHNvIHRoaXMgaXMgYSBuby1vcCBoZXJlLiAqL1xuICBzZXRTZWxlY3RlZEJlemllcihfYmV6aWVyOiBib29sZWFuKTogdm9pZCB7IC8qIE9TRC1vbmx5ICovIH1cblxuICBkZXN0cm95KCk6IHZvaWQgeyAvKiBub3RoaW5nIHRvIHRlYXIgZG93biDigJQgc2hhcGVzIGxpdmUgaW4gdGhlIFBsb3RseSBsYXlvdXQgKi8gfVxufVxuIl19
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { PlotType } from '../../contracts/plot-type';
|
|
2
|
+
import { bt601Luminance } from '../../contracts/intensity';
|
|
3
|
+
// ── helpers ──────────────────────────────────────────────────────────────
|
|
4
|
+
/** Scalar value of a frame cell: `[r, g, b]` → BT.601 luminance, scalar as-is. */
|
|
5
|
+
function luminance(cell) {
|
|
6
|
+
if (Array.isArray(cell)) {
|
|
7
|
+
return bt601Luminance(cell[0], cell[1], cell[2]);
|
|
8
|
+
}
|
|
9
|
+
return cell;
|
|
10
|
+
}
|
|
11
|
+
/** Project a frame to a scalar matrix (RGB → luminance, grayscale → as-is). */
|
|
12
|
+
function toScalarFrame(frame, isGrayscale) {
|
|
13
|
+
if (isGrayscale)
|
|
14
|
+
return frame;
|
|
15
|
+
return frame.map((row) => row.map(luminance));
|
|
16
|
+
}
|
|
17
|
+
/** Even stride that keeps an axis under `maxSamples` sample points. */
|
|
18
|
+
function strideFor(length, maxSamples) {
|
|
19
|
+
return Math.max(1, Math.ceil(length / maxSamples));
|
|
20
|
+
}
|
|
21
|
+
// ── builders ─────────────────────────────────────────────────────────────
|
|
22
|
+
/** Max cells per axis the contour grid is downsampled to. The heatmap trace can
|
|
23
|
+
* raster the full preview cheaply, but contour runs CPU marching-squares over
|
|
24
|
+
* every cell, so a full-resolution preview (~1000²) costs seconds. Contours
|
|
25
|
+
* interpolate, so a coarser grid looks the same while rendering near-instantly. */
|
|
26
|
+
const CONTOUR_MAX_SAMPLES = 400;
|
|
27
|
+
/** Every `sx`-th column / `sy`-th row of a scalar matrix. */
|
|
28
|
+
function downsampleMatrix(matrix, sx, sy) {
|
|
29
|
+
if (sx <= 1 && sy <= 1)
|
|
30
|
+
return matrix;
|
|
31
|
+
const out = [];
|
|
32
|
+
for (let r = 0; r < matrix.length; r += sy) {
|
|
33
|
+
const row = matrix[r];
|
|
34
|
+
if (sx <= 1) {
|
|
35
|
+
out.push(row);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const sampled = [];
|
|
39
|
+
for (let c = 0; c < row.length; c += sx)
|
|
40
|
+
sampled.push(row[c]);
|
|
41
|
+
out.push(sampled);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
/** CONTOUR — per-frame iso-contours over a downsampled scalar matrix. Mirrors
|
|
46
|
+
* the heatmap trace geometry (x0/dx/y0/dy) so it lines up with the image axes;
|
|
47
|
+
* the stride scales dx/dy so the coarser grid still spans the true extent. */
|
|
48
|
+
function buildContourTraces(input) {
|
|
49
|
+
const [x0, , y0] = [input.trueImageSize[0], input.trueImageSize[1], input.trueImageSize[2]];
|
|
50
|
+
return input.frames.map((frame, index) => {
|
|
51
|
+
const scalar = toScalarFrame(frame, input.isGrayscale);
|
|
52
|
+
const height = scalar.length;
|
|
53
|
+
const width = height > 0 ? scalar[0].length : 0;
|
|
54
|
+
const sx = strideFor(width, CONTOUR_MAX_SAMPLES);
|
|
55
|
+
const sy = strideFor(height, CONTOUR_MAX_SAMPLES);
|
|
56
|
+
return {
|
|
57
|
+
x0,
|
|
58
|
+
dx: input.ratios[0] * sx,
|
|
59
|
+
y0,
|
|
60
|
+
dy: input.ratios[0] * sy,
|
|
61
|
+
z: downsampleMatrix(scalar, sx, sy),
|
|
62
|
+
type: 'contour',
|
|
63
|
+
hoverinfo: 'none',
|
|
64
|
+
colorscale: input.colorscale,
|
|
65
|
+
reversescale: input.reversescale,
|
|
66
|
+
contours: { coloring: 'heatmap' },
|
|
67
|
+
// Cap the level count so it doesn't scale with the (now coarser) grid.
|
|
68
|
+
ncontours: 15,
|
|
69
|
+
name: `Slice ${index + 1}`,
|
|
70
|
+
visible: index === 0,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** SCATTER — region centroids as labelled markers (region-sourced). */
|
|
75
|
+
function buildScatterTraces(input) {
|
|
76
|
+
const xs = [];
|
|
77
|
+
const ys = [];
|
|
78
|
+
const text = [];
|
|
79
|
+
input.regions.forEach((poly, i) => {
|
|
80
|
+
const n = poly.xpoints.length;
|
|
81
|
+
if (n === 0)
|
|
82
|
+
return;
|
|
83
|
+
const cx = poly.xpoints.reduce((a, b) => a + b, 0) / n;
|
|
84
|
+
const cy = poly.ypoints.reduce((a, b) => a + b, 0) / n;
|
|
85
|
+
xs.push(cx);
|
|
86
|
+
ys.push(cy);
|
|
87
|
+
text.push(`R${i + 1}`);
|
|
88
|
+
});
|
|
89
|
+
return [{
|
|
90
|
+
x: xs,
|
|
91
|
+
y: ys,
|
|
92
|
+
text,
|
|
93
|
+
type: 'scatter',
|
|
94
|
+
mode: 'markers+text',
|
|
95
|
+
textposition: 'top center',
|
|
96
|
+
marker: { size: 10, color: input.shapeColor, line: { color: '#000', width: 1 } },
|
|
97
|
+
name: 'Region centroids',
|
|
98
|
+
}];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Collect a downsampled regular grid of voxels across the z-stack.
|
|
102
|
+
* Returns parallel flat arrays suitable for both scatter3d and isosurface.
|
|
103
|
+
* A single-frame image is thickened to two z-planes so 3D traces render.
|
|
104
|
+
*/
|
|
105
|
+
function sampleVolume(input, maxXY, maxZ) {
|
|
106
|
+
let frames = input.frames.map(f => toScalarFrame(f, input.isGrayscale));
|
|
107
|
+
if (frames.length < 2)
|
|
108
|
+
frames = [frames[0] || [], frames[0] || []];
|
|
109
|
+
const height = frames[0].length;
|
|
110
|
+
const width = height > 0 ? frames[0][0].length : 0;
|
|
111
|
+
const sx = strideFor(width, maxXY);
|
|
112
|
+
const sy = strideFor(height, maxXY);
|
|
113
|
+
const sz = strideFor(frames.length, maxZ);
|
|
114
|
+
const x = [];
|
|
115
|
+
const y = [];
|
|
116
|
+
const z = [];
|
|
117
|
+
const value = [];
|
|
118
|
+
for (let zi = 0; zi < frames.length; zi += sz) {
|
|
119
|
+
for (let yi = 0; yi < height; yi += sy) {
|
|
120
|
+
const rowArr = frames[zi][yi] || [];
|
|
121
|
+
for (let xi = 0; xi < width; xi += sx) {
|
|
122
|
+
x.push(xi * input.ratios[0]);
|
|
123
|
+
y.push(yi * input.ratios[0]);
|
|
124
|
+
z.push(zi);
|
|
125
|
+
value.push(rowArr[xi]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { x, y, z, value };
|
|
130
|
+
}
|
|
131
|
+
/** SCATTER3D — downsampled voxels as intensity-coloured 3D markers. */
|
|
132
|
+
function buildScatter3dTraces(input) {
|
|
133
|
+
const { x, y, z, value } = sampleVolume(input, 48, 40);
|
|
134
|
+
return [{
|
|
135
|
+
type: 'scatter3d',
|
|
136
|
+
mode: 'markers',
|
|
137
|
+
x, y, z,
|
|
138
|
+
marker: {
|
|
139
|
+
size: 2,
|
|
140
|
+
color: value,
|
|
141
|
+
colorscale: input.colorscale,
|
|
142
|
+
reversescale: input.reversescale,
|
|
143
|
+
opacity: 0.8,
|
|
144
|
+
},
|
|
145
|
+
name: 'Voxels',
|
|
146
|
+
}];
|
|
147
|
+
}
|
|
148
|
+
/** ISOSURFACE — iso-intensity surfaces over the downsampled volume grid.
|
|
149
|
+
* isomin/isomax come straight from the toolbar range slider (0–255). */
|
|
150
|
+
function buildIsosurfaceTraces(input) {
|
|
151
|
+
const { x, y, z, value } = sampleVolume(input, 40, 40);
|
|
152
|
+
// The caller (PlotlyService) maps the 0–255 slider onto the volume's real
|
|
153
|
+
// intensity range before this runs, so the band always sits inside the data.
|
|
154
|
+
// We only guard ordering here.
|
|
155
|
+
const isoMin = Math.min(input.isoMin, input.isoMax);
|
|
156
|
+
const isoMax = Math.max(input.isoMin, input.isoMax);
|
|
157
|
+
return [{
|
|
158
|
+
type: 'isosurface',
|
|
159
|
+
x, y, z, value,
|
|
160
|
+
isomin: isoMin,
|
|
161
|
+
isomax: isoMax,
|
|
162
|
+
// A few nested levels (not just the two band extremes): even if an extreme
|
|
163
|
+
// grazes the data edge and draws nothing, an interior level still renders,
|
|
164
|
+
// so the volume is never silently empty.
|
|
165
|
+
surface: { count: 3 },
|
|
166
|
+
colorscale: input.colorscale,
|
|
167
|
+
reversescale: input.reversescale,
|
|
168
|
+
opacity: 0.6,
|
|
169
|
+
caps: { x: { show: false }, y: { show: false }, z: { show: false } },
|
|
170
|
+
name: 'Isosurface',
|
|
171
|
+
}];
|
|
172
|
+
}
|
|
173
|
+
/** Registry of the pluggable (non-original) plot types. */
|
|
174
|
+
export const PLOTLY_PLOT_TYPE_IMPLS = {
|
|
175
|
+
[PlotType.CONTOUR]: { buildTraces: buildContourTraces, layoutKind: '2d-image', threeD: false },
|
|
176
|
+
[PlotType.SCATTER]: { buildTraces: buildScatterTraces, layoutKind: '2d-overlay', threeD: false },
|
|
177
|
+
[PlotType.SCATTER3D]: { buildTraces: buildScatter3dTraces, layoutKind: '3d-volume', threeD: true },
|
|
178
|
+
[PlotType.ISOSURFACE]: { buildTraces: buildIsosurfaceTraces, layoutKind: '3d-volume', threeD: true },
|
|
179
|
+
};
|
|
180
|
+
export function getPlotTypeImpl(type) {
|
|
181
|
+
return PLOTLY_PLOT_TYPE_IMPLS[type];
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxvdGx5LXRyYWNlLWJ1aWxkZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9pbXBsZW1lbnRhdGlvbnMvcGxvdGx5L3Bsb3RseS10cmFjZS1idWlsZGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBNEQzRCw0RUFBNEU7QUFFNUUsa0ZBQWtGO0FBQ2xGLFNBQVMsU0FBUyxDQUFDLElBQVM7SUFDMUIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDeEIsT0FBTyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBQ0QsT0FBTyxJQUFjLENBQUM7QUFDeEIsQ0FBQztBQUVELCtFQUErRTtBQUMvRSxTQUFTLGFBQWEsQ0FBQyxLQUFZLEVBQUUsV0FBb0I7SUFDdkQsSUFBSSxXQUFXO1FBQUUsT0FBTyxLQUFtQixDQUFDO0lBQzVDLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQVUsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFFRCx1RUFBdUU7QUFDdkUsU0FBUyxTQUFTLENBQUMsTUFBYyxFQUFFLFVBQWtCO0lBQ25ELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBRUQsNEVBQTRFO0FBRTVFOzs7b0ZBR29GO0FBQ3BGLE1BQU0sbUJBQW1CLEdBQUcsR0FB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QUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3BFLElBQUksRUFBRSxZQUFZO1NBQ25CLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCwyREFBMkQ7QUFDM0QsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQWtEO0lBQ25GLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFLLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixFQUFLLFVBQVUsRUFBRSxVQUFVLEVBQUksTUFBTSxFQUFFLEtBQUssRUFBRTtJQUN0RyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBSyxFQUFFLFdBQVcsRUFBRSxrQkFBa0IsRUFBSyxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7SUFDdEcsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUcsRUFBRSxXQUFXLEVBQUUsb0JBQW9CLEVBQUcsVUFBVSxFQUFFLFdBQVcsRUFBRyxNQUFNLEVBQUUsSUFBSSxFQUFFO0lBQ3JHLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLHFCQUFxQixFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUcsTUFBTSxFQUFFLElBQUksRUFBRTtDQUN0RyxDQUFDO0FBRUYsTUFBTSxVQUFVLGVBQWUsQ0FBQyxJQUFjO0lBQzVDLE9BQU8sc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDdEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBsb3RUeXBlIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3Bsb3QtdHlwZSc7XG5pbXBvcnQgeyBidDYwMUx1bWluYW5jZSB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9pbnRlbnNpdHknO1xuXG4vKipcbiAqIFBsdWdnYWJsZSBQbG90bHkgdHJhY2UgYnVpbGRlcnMgZm9yIHRoZSBwbG90IHR5cGVzIGFkZGVkIG9uIHRvcCBvZiB0aGVcbiAqIG9yaWdpbmFsIEhFQVRNQVAgLyBTVVJGQUNFIC8gUkdCLWltYWdlIHJlbmRlcmVycy5cbiAqXG4gKiBERVNJR04gLyBFWFRSQUNUSU9OIEFMSUdOTUVOVFxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEV2ZXJ5IGZ1bmN0aW9uIGhlcmUgaXMgKipwdXJlKiog4oCUIGl0IHRha2VzIGEgYFRyYWNlQnVpbGRJbnB1dGAgYW5kIHJldHVybnNcbiAqIFBsb3RseSB0cmFjZSBkaWN0cy4gVGhlcmUgaXMgbm8gQW5ndWxhciwgbm8gUnhKUywgbm8gaG9zdC1zdGF0ZSBjb3VwbGluZ1xuICogKGBNYWluU3RhdGVgLCBgRmlsZXNTZXJ2aWNlYCwg4oCmKS4gVGhhdCBrZWVwcyB0aGUgbW9kdWxlIHJlbG9jYXRhYmxlIGludG8gdGhlXG4gKiBmdXR1cmUgYEBqYXgtZGF0YS1zY2llbmNlL2ltYWdlLXZpc3VhbGl6YXRpb25gIGxpYnJhcnkgY29yZSAoc2VlIHRoZVxuICogYHNrZXRjaC9qaXQtcGxvdHRpbmctZXh0cmFjdGlvbmAgU09XKSB3aXRob3V0IHBvcnQgc3VyZ2VyeS5cbiAqXG4gKiBMYXlvdXQgYnVpbGRpbmcgc3RheXMgaW4gYFBsb3RseVNlcnZpY2VgIChpdCBuZWVkcyBsaXZlIHNlcnZpY2Ugc3RhdGUgc3VjaFxuICogYXMgc2NyZWVuIGhlaWdodCwgc2NhbGUgcmF0aW8gYW5kIHRoZSBjdXJyZW50IHNoYXBlcyk7IG9ubHkgVFJBQ0UgYnVpbGRpbmdcbiAqIGlzIHBsdWdnYWJsZSBoZXJlLiBUbyBhZGQgYSBuZXcgcGxvdCB0eXBlOiB3cml0ZSBhIGJ1aWxkZXIsIHJlZ2lzdGVyIGl0IGluXG4gKiBgUExPVExZX1BMT1RfVFlQRV9JTVBMU2AsIGFuZCBhZGQgYSBkZXNjcmlwdG9yIGluIGBjb250cmFjdHMvcGxvdC10eXBlLnRzYC5cbiAqXG4gKiBUaGUgb3JpZ2luYWwgSEVBVE1BUC9TVVJGQUNFL1JHQiB0eXBlcyBpbnRlbnRpb25hbGx5IGtlZXAgdGhlaXIgZGVkaWNhdGVkXG4gKiByZW5kZXJlcnMgaW4gYFBsb3RseVNlcnZpY2VgICh0aGV5IGFyZSBhbHNvIHJldXNlZCBieSB0aGUgaGlnaC1kZWYgem9vbVxuICogcmUtZmV0Y2ggcGF0aCksIHNvIHRoZXkgYXJlIE5PVCByZWdpc3RlcmVkIGhlcmUuXG4gKi9cblxuLyoqIE5vcm1hbGlzZWQgaW5wdXQgZm9yIGEgdHJhY2UgYnVpbGRlci4gRnJhbWVzIGFyZSBwZXItei1wbGFuZSBtYXRyaWNlczpcbiAqICBncmF5c2NhbGUgY2VsbHMgYXJlIHNjYWxhcnMsIFJHQiBjZWxscyBhcmUgYFtyLCBnLCBiXWAuICovXG5leHBvcnQgaW50ZXJmYWNlIFRyYWNlQnVpbGRJbnB1dCB7XG4gIGZyYW1lczogYW55W107XG4gIHdpZHRoOiBudW1iZXI7XG4gIGhlaWdodDogbnVtYmVyO1xuICAvKiogW3hSYXRpbywgeVJhdGlvXSDigJQgZGF0YSB1bml0cyBwZXIgcGl4ZWwuICovXG4gIHJhdGlvczogbnVtYmVyW107XG4gIC8qKiBbeDAsIHgxLCB5MCwgeTFdIOKAlCB0cnVlIGltYWdlIGV4dGVudCBpbiBkYXRhIHVuaXRzLiAqL1xuICB0cnVlSW1hZ2VTaXplOiBudW1iZXJbXTtcbiAgaXNHcmF5c2NhbGU6IGJvb2xlYW47XG4gIC8qKiBQbG90bHkgY29sb3JzY2FsZSB2YWx1ZSAoZS5nLiBmcm9tIHRoZSBhY3RpdmUgY29sb3JtYXApLiAqL1xuICBjb2xvcnNjYWxlOiBhbnk7XG4gIHJldmVyc2VzY2FsZTogYm9vbGVhbjtcbiAgLyoqIFJlZ2lvbiBwb2x5Z29ucyBpbiBkYXRhIGNvb3JkcywgZm9yIHJlZ2lvbi1zb3VyY2VkIHBsb3RzIChTQ0FUVEVSKS4gKi9cbiAgcmVnaW9uczogeyB4cG9pbnRzOiBudW1iZXJbXTsgeXBvaW50czogbnVtYmVyW10gfVtdO1xuICAvKiogRGVmYXVsdCBtYXJrZXIvbGluZSBjb2xvdXIgZm9yIGRlcml2ZWQgKG5vbi1pbWFnZS1MVVQpIHRyYWNlcy4gKi9cbiAgc2hhcGVDb2xvcjogc3RyaW5nO1xuICAvKiogSVNPU1VSRkFDRSBpbnRlbnNpdHkgYm91bmRzICgw4oCTMjU1KTogc3VyZmFjZXMgYXJlIGRyYXduIGZvciB2YWx1ZXMgaW5cbiAgICogIFtpc29NaW4sIGlzb01heF0sIG1hcHBlZCBzdHJhaWdodCBvbnRvIFBsb3RseSdzIGlzb21pbi9pc29tYXguICovXG4gIGlzb01pbjogbnVtYmVyO1xuICBpc29NYXg6IG51bWJlcjtcbn1cblxuZXhwb3J0IHR5cGUgVHJhY2VCdWlsZGVyID0gKGlucHV0OiBUcmFjZUJ1aWxkSW5wdXQpID0+IGFueVtdO1xuXG5leHBvcnQgdHlwZSBQbG90TGF5b3V0S2luZCA9ICcyZC1pbWFnZScgfCAnMmQtb3ZlcmxheScgfCAnMmQtY2hhcnQnIHwgJzNkLXZvbHVtZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGxvdGx5UGxvdFR5cGVJbXBsIHtcbiAgYnVpbGRUcmFjZXM6IFRyYWNlQnVpbGRlcjtcbiAgLyoqIFdoaWNoIGxheW91dCBgUGxvdGx5U2VydmljZWAgc2hvdWxkIGJ1aWxkIGZvciB0aGlzIHR5cGUuICovXG4gIGxheW91dEtpbmQ6IFBsb3RMYXlvdXRLaW5kO1xuICAvKiogVHJ1ZSBmb3Igc2NlbmUtYmFzZWQgKDNEKSB0cmFjZXMg4oCUIHBpY2tzIHRoZSAzRCBQbG90bHkgY29uZmlnLiAqL1xuICB0aHJlZUQ6IGJvb2xlYW47XG59XG5cbi8vIOKUgOKUgCBoZWxwZXJzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogU2NhbGFyIHZhbHVlIG9mIGEgZnJhbWUgY2VsbDogYFtyLCBnLCBiXWAg4oaSIEJULjYwMSBsdW1pbmFuY2UsIHNjYWxhciBhcy1pcy4gKi9cbmZ1bmN0aW9uIGx1bWluYW5jZShjZWxsOiBhbnkpOiBudW1iZXIge1xuICBpZiAoQXJyYXkuaXNBcnJheShjZWxsKSkge1xuICAgIHJldHVybiBidDYwMUx1bWluYW5jZShjZWxsWzBdLCBjZWxsWzFdLCBjZWxsWzJdKTtcbiAgfVxuICByZXR1cm4gY2VsbCBhcyBudW1iZXI7XG59XG5cbi8qKiBQcm9qZWN0IGEgZnJhbWUgdG8gYSBzY2FsYXIgbWF0cml4IChSR0Ig4oaSIGx1bWluYW5jZSwgZ3JheXNjYWxlIOKGkiBhcy1pcykuICovXG5mdW5jdGlvbiB0b1NjYWxhckZyYW1lKGZyYW1lOiBhbnlbXSwgaXNHcmF5c2NhbGU6IGJvb2xlYW4pOiBudW1iZXJbXVtdIHtcbiAgaWYgKGlzR3JheXNjYWxlKSByZXR1cm4gZnJhbWUgYXMgbnVtYmVyW11bXTtcbiAgcmV0dXJuIGZyYW1lLm1hcCgocm93OiBhbnlbXSkgPT4gcm93Lm1hcChsdW1pbmFuY2UpKTtcbn1cblxuLyoqIEV2ZW4gc3RyaWRlIHRoYXQga2VlcHMgYW4gYXhpcyB1bmRlciBgbWF4U2FtcGxlc2Agc2FtcGxlIHBvaW50cy4gKi9cbmZ1bmN0aW9uIHN0cmlkZUZvcihsZW5ndGg6IG51bWJlciwgbWF4U2FtcGxlczogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgubWF4KDEsIE1hdGguY2VpbChsZW5ndGggLyBtYXhTYW1wbGVzKSk7XG59XG5cbi8vIOKUgOKUgCBidWlsZGVycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqIE1heCBjZWxscyBwZXIgYXhpcyB0aGUgY29udG91ciBncmlkIGlzIGRvd25zYW1wbGVkIHRvLiBUaGUgaGVhdG1hcCB0cmFjZSBjYW5cbiAqICByYXN0ZXIgdGhlIGZ1bGwgcHJldmlldyBjaGVhcGx5LCBidXQgY29udG91ciBydW5zIENQVSBtYXJjaGluZy1zcXVhcmVzIG92ZXJcbiAqICBldmVyeSBjZWxsLCBzbyBhIGZ1bGwtcmVzb2x1dGlvbiBwcmV2aWV3ICh+MTAwMMKyKSBjb3N0cyBzZWNvbmRzLiBDb250b3Vyc1xuICogIGludGVycG9sYXRlLCBzbyBhIGNvYXJzZXIgZ3JpZCBsb29rcyB0aGUgc2FtZSB3aGlsZSByZW5kZXJpbmcgbmVhci1pbnN0YW50bHkuICovXG5jb25zdCBDT05UT1VSX01BWF9TQU1QTEVTID0gNDAwO1xuXG4vKiogRXZlcnkgYHN4YC10aCBjb2x1bW4gLyBgc3lgLXRoIHJvdyBvZiBhIHNjYWxhciBtYXRyaXguICovXG5mdW5jdGlvbiBkb3duc2FtcGxlTWF0cml4KG1hdHJpeDogbnVtYmVyW11bXSwgc3g6IG51bWJlciwgc3k6IG51bWJlcik6IG51bWJlcltdW10ge1xuICBpZiAoc3ggPD0gMSAmJiBzeSA8PSAxKSByZXR1cm4gbWF0cml4O1xuICBjb25zdCBvdXQ6IG51bWJlcltdW10gPSBbXTtcbiAgZm9yIChsZXQgciA9IDA7IHIgPCBtYXRyaXgubGVuZ3RoOyByICs9IHN5KSB7XG4gICAgY29uc3Qgcm93ID0gbWF0cml4W3JdO1xuICAgIGlmIChzeCA8PSAxKSB7IG91dC5wdXNoKHJvdyk7IGNvbnRpbnVlOyB9XG4gICAgY29uc3Qgc2FtcGxlZDogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBjID0gMDsgYyA8IHJvdy5sZW5ndGg7IGMgKz0gc3gpIHNhbXBsZWQucHVzaChyb3dbY10pO1xuICAgIG91dC5wdXNoKHNhbXBsZWQpO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBDT05UT1VSIOKAlCBwZXItZnJhbWUgaXNvLWNvbnRvdXJzIG92ZXIgYSBkb3duc2FtcGxlZCBzY2FsYXIgbWF0cml4LiBNaXJyb3JzXG4gKiAgdGhlIGhlYXRtYXAgdHJhY2UgZ2VvbWV0cnkgKHgwL2R4L3kwL2R5KSBzbyBpdCBsaW5lcyB1cCB3aXRoIHRoZSBpbWFnZSBheGVzO1xuICogIHRoZSBzdHJpZGUgc2NhbGVzIGR4L2R5IHNvIHRoZSBjb2Fyc2VyIGdyaWQgc3RpbGwgc3BhbnMgdGhlIHRydWUgZXh0ZW50LiAqL1xuZnVuY3Rpb24gYnVpbGRDb250b3VyVHJhY2VzKGlucHV0OiBUcmFjZUJ1aWxkSW5wdXQpOiBhbnlbXSB7XG4gIGNvbnN0IFt4MCwgLCB5MF0gPSBbaW5wdXQudHJ1ZUltYWdlU2l6ZVswXSwgaW5wdXQudHJ1ZUltYWdlU2l6ZVsxXSwgaW5wdXQudHJ1ZUltYWdlU2l6ZVsyXV07XG4gIHJldHVybiBpbnB1dC5mcmFtZXMubWFwKChmcmFtZSwgaW5kZXgpID0+IHtcbiAgICBjb25zdCBzY2FsYXIgPSB0b1NjYWxhckZyYW1lKGZyYW1lLCBpbnB1dC5pc0dyYXlzY2FsZSk7XG4gICAgY29uc3QgaGVpZ2h0ID0gc2NhbGFyLmxlbmd0aDtcbiAgICBjb25zdCB3aWR0aCA9IGhlaWdodCA+IDAgPyBzY2FsYXJbMF0ubGVuZ3RoIDogMDtcbiAgICBjb25zdCBzeCA9IHN0cmlkZUZvcih3aWR0aCwgQ09OVE9VUl9NQVhfU0FNUExFUyk7XG4gICAgY29uc3Qgc3kgPSBzdHJpZGVGb3IoaGVpZ2h0LCBDT05UT1VSX01BWF9TQU1QTEVTKTtcbiAgICByZXR1cm4ge1xuICAgICAgeDAsXG4gICAgICBkeDogaW5wdXQucmF0aW9zWzBdICogc3gsXG4gICAgICB5MCxcbiAgICAgIGR5OiBpbnB1dC5yYXRpb3NbMF0gKiBzeSxcbiAgICAgIHo6IGRvd25zYW1wbGVNYXRyaXgoc2NhbGFyLCBzeCwgc3kpLFxuICAgICAgdHlwZTogJ2NvbnRvdXInLFxuICAgICAgaG92ZXJpbmZvOiAnbm9uZScsXG4gICAgICBjb2xvcnNjYWxlOiBpbnB1dC5jb2xvcnNjYWxlLFxuICAgICAgcmV2ZXJzZXNjYWxlOiBpbnB1dC5yZXZlcnNlc2NhbGUsXG4gICAgICBjb250b3VyczogeyBjb2xvcmluZzogJ2hlYXRtYXAnIH0sXG4gICAgICAvLyBDYXAgdGhlIGxldmVsIGNvdW50IHNvIGl0IGRvZXNuJ3Qgc2NhbGUgd2l0aCB0aGUgKG5vdyBjb2Fyc2VyKSBncmlkLlxuICAgICAgbmNvbnRvdXJzOiAxNSxcbiAgICAgIG5hbWU6IGBTbGljZSAke2luZGV4ICsgMX1gLFxuICAgICAgdmlzaWJsZTogaW5kZXggPT09IDAsXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKiBTQ0FUVEVSIOKAlCByZWdpb24gY2VudHJvaWRzIGFzIGxhYmVsbGVkIG1hcmtlcnMgKHJlZ2lvbi1zb3VyY2VkKS4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2NhdHRlclRyYWNlcyhpbnB1dDogVHJhY2VCdWlsZElucHV0KTogYW55W10ge1xuICBjb25zdCB4czogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgeXM6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHRleHQ6IHN0cmluZ1tdID0gW107XG4gIGlucHV0LnJlZ2lvbnMuZm9yRWFjaCgocG9seSwgaSkgPT4ge1xuICAgIGNvbnN0IG4gPSBwb2x5Lnhwb2ludHMubGVuZ3RoO1xuICAgIGlmIChuID09PSAwKSByZXR1cm47XG4gICAgY29uc3QgY3ggPSBwb2x5Lnhwb2ludHMucmVkdWNlKChhLCBiKSA9PiBhICsgYiwgMCkgLyBuO1xuICAgIGNvbnN0IGN5ID0gcG9seS55cG9pbnRzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApIC8gbjtcbiAgICB4cy5wdXNoKGN4KTtcbiAgICB5cy5wdXNoKGN5KTtcbiAgICB0ZXh0LnB1c2goYFIke2kgKyAxfWApO1xuICB9KTtcbiAgcmV0dXJuIFt7XG4gICAgeDogeHMsXG4gICAgeTogeXMsXG4gICAgdGV4dCxcbiAgICB0eXBlOiAnc2NhdHRlcicsXG4gICAgbW9kZTogJ21hcmtlcnMrdGV4dCcsXG4gICAgdGV4dHBvc2l0aW9uOiAndG9wIGNlbnRlcicsXG4gICAgbWFya2VyOiB7IHNpemU6IDEwLCBjb2xvcjogaW5wdXQuc2hhcGVDb2xvciwgbGluZTogeyBjb2xvcjogJyMwMDAnLCB3aWR0aDogMSB9IH0sXG4gICAgbmFtZTogJ1JlZ2lvbiBjZW50cm9pZHMnLFxuICB9XTtcbn1cblxuLyoqXG4gKiBDb2xsZWN0IGEgZG93bnNhbXBsZWQgcmVndWxhciBncmlkIG9mIHZveGVscyBhY3Jvc3MgdGhlIHotc3RhY2suXG4gKiBSZXR1cm5zIHBhcmFsbGVsIGZsYXQgYXJyYXlzIHN1aXRhYmxlIGZvciBib3RoIHNjYXR0ZXIzZCBhbmQgaXNvc3VyZmFjZS5cbiAqIEEgc2luZ2xlLWZyYW1lIGltYWdlIGlzIHRoaWNrZW5lZCB0byB0d28gei1wbGFuZXMgc28gM0QgdHJhY2VzIHJlbmRlci5cbiAqL1xuZnVuY3Rpb24gc2FtcGxlVm9sdW1lKGlucHV0OiBUcmFjZUJ1aWxkSW5wdXQsIG1heFhZOiBudW1iZXIsIG1heFo6IG51bWJlcikge1xuICBsZXQgZnJhbWVzID0gaW5wdXQuZnJhbWVzLm1hcChmID0+IHRvU2NhbGFyRnJhbWUoZiwgaW5wdXQuaXNHcmF5c2NhbGUpKTtcbiAgaWYgKGZyYW1lcy5sZW5ndGggPCAyKSBmcmFtZXMgPSBbZnJhbWVzWzBdIHx8IFtdLCBmcmFtZXNbMF0gfHwgW11dO1xuXG4gIGNvbnN0IGhlaWdodCA9IGZyYW1lc1swXS5sZW5ndGg7XG4gIGNvbnN0IHdpZHRoID0gaGVpZ2h0ID4gMCA/IGZyYW1lc1swXVswXS5sZW5ndGggOiAwO1xuICBjb25zdCBzeCA9IHN0cmlkZUZvcih3aWR0aCwgbWF4WFkpO1xuICBjb25zdCBzeSA9IHN0cmlkZUZvcihoZWlnaHQsIG1heFhZKTtcbiAgY29uc3Qgc3ogPSBzdHJpZGVGb3IoZnJhbWVzLmxlbmd0aCwgbWF4Wik7XG5cbiAgY29uc3QgeDogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgeTogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgejogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgdmFsdWU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IHppID0gMDsgemkgPCBmcmFtZXMubGVuZ3RoOyB6aSArPSBzeikge1xuICAgIGZvciAobGV0IHlpID0gMDsgeWkgPCBoZWlnaHQ7IHlpICs9IHN5KSB7XG4gICAgICBjb25zdCByb3dBcnIgPSBmcmFtZXNbemldW3lpXSB8fCBbXTtcbiAgICAgIGZvciAobGV0IHhpID0gMDsgeGkgPCB3aWR0aDsgeGkgKz0gc3gpIHtcbiAgICAgICAgeC5wdXNoKHhpICogaW5wdXQucmF0aW9zWzBdKTtcbiAgICAgICAgeS5wdXNoKHlpICogaW5wdXQucmF0aW9zWzBdKTtcbiAgICAgICAgei5wdXNoKHppKTtcbiAgICAgICAgdmFsdWUucHVzaChyb3dBcnJbeGldKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHsgeCwgeSwgeiwgdmFsdWUgfTtcbn1cblxuLyoqIFNDQVRURVIzRCDigJQgZG93bnNhbXBsZWQgdm94ZWxzIGFzIGludGVuc2l0eS1jb2xvdXJlZCAzRCBtYXJrZXJzLiAqL1xuZnVuY3Rpb24gYnVpbGRTY2F0dGVyM2RUcmFjZXMoaW5wdXQ6IFRyYWNlQnVpbGRJbnB1dCk6IGFueVtdIHtcbiAgY29uc3QgeyB4LCB5LCB6LCB2YWx1ZSB9ID0gc2FtcGxlVm9sdW1lKGlucHV0LCA0OCwgNDApO1xuICByZXR1cm4gW3tcbiAgICB0eXBlOiAnc2NhdHRlcjNkJyxcbiAgICBtb2RlOiAnbWFya2VycycsXG4gICAgeCwgeSwgeixcbiAgICBtYXJrZXI6IHtcbiAgICAgIHNpemU6IDIsXG4gICAgICBjb2xvcjogdmFsdWUsXG4gICAgICBjb2xvcnNjYWxlOiBpbnB1dC5jb2xvcnNjYWxlLFxuICAgICAgcmV2ZXJzZXNjYWxlOiBpbnB1dC5yZXZlcnNlc2NhbGUsXG4gICAgICBvcGFjaXR5OiAwLjgsXG4gICAgfSxcbiAgICBuYW1lOiAnVm94ZWxzJyxcbiAgfV07XG59XG5cbi8qKiBJU09TVVJGQUNFIOKAlCBpc28taW50ZW5zaXR5IHN1cmZhY2VzIG92ZXIgdGhlIGRvd25zYW1wbGVkIHZvbHVtZSBncmlkLlxuICogIGlzb21pbi9pc29tYXggY29tZSBzdHJhaWdodCBmcm9tIHRoZSB0b29sYmFyIHJhbmdlIHNsaWRlciAoMOKAkzI1NSkuICovXG5mdW5jdGlvbiBidWlsZElzb3N1cmZhY2VUcmFjZXMoaW5wdXQ6IFRyYWNlQnVpbGRJbnB1dCk6IGFueVtdIHtcbiAgY29uc3QgeyB4LCB5LCB6LCB2YWx1ZSB9ID0gc2FtcGxlVm9sdW1lKGlucHV0LCA0MCwgNDApO1xuICAvLyBUaGUgY2FsbGVyIChQbG90bHlTZXJ2aWNlKSBtYXBzIHRoZSAw4oCTMjU1IHNsaWRlciBvbnRvIHRoZSB2b2x1bWUncyByZWFsXG4gIC8vIGludGVuc2l0eSByYW5nZSBiZWZvcmUgdGhpcyBydW5zLCBzbyB0aGUgYmFuZCBhbHdheXMgc2l0cyBpbnNpZGUgdGhlIGRhdGEuXG4gIC8vIFdlIG9ubHkgZ3VhcmQgb3JkZXJpbmcgaGVyZS5cbiAgY29uc3QgaXNvTWluID0gTWF0aC5taW4oaW5wdXQuaXNvTWluLCBpbnB1dC5pc29NYXgpO1xuICBjb25zdCBpc29NYXggPSBNYXRoLm1heChpbnB1dC5pc29NaW4sIGlucHV0Lmlzb01heCk7XG4gIHJldHVybiBbe1xuICAgIHR5cGU6ICdpc29zdXJmYWNlJyxcbiAgICB4LCB5LCB6LCB2YWx1ZSxcbiAgICBpc29taW46IGlzb01pbixcbiAgICBpc29tYXg6IGlzb01heCxcbiAgICAvLyBBIGZldyBuZXN0ZWQgbGV2ZWxzIChub3QganVzdCB0aGUgdHdvIGJhbmQgZXh0cmVtZXMpOiBldmVuIGlmIGFuIGV4dHJlbWVcbiAgICAvLyBncmF6ZXMgdGhlIGRhdGEgZWRnZSBhbmQgZHJhd3Mgbm90aGluZywgYW4gaW50ZXJpb3IgbGV2ZWwgc3RpbGwgcmVuZGVycyxcbiAgICAvLyBzbyB0aGUgdm9sdW1lIGlzIG5ldmVyIHNpbGVudGx5IGVtcHR5LlxuICAgIHN1cmZhY2U6IHsgY291bnQ6IDMgfSxcbiAgICBjb2xvcnNjYWxlOiBpbnB1dC5jb2xvcnNjYWxlLFxuICAgIHJldmVyc2VzY2FsZTogaW5wdXQucmV2ZXJzZXNjYWxlLFxuICAgIG9wYWNpdHk6IDAuNixcbiAgICBjYXBzOiB7IHg6IHsgc2hvdzogZmFsc2UgfSwgeTogeyBzaG93OiBmYWxzZSB9LCB6OiB7IHNob3c6IGZhbHNlIH0gfSxcbiAgICBuYW1lOiAnSXNvc3VyZmFjZScsXG4gIH1dO1xufVxuXG4vKiogUmVnaXN0cnkgb2YgdGhlIHBsdWdnYWJsZSAobm9uLW9yaWdpbmFsKSBwbG90IHR5cGVzLiAqL1xuZXhwb3J0IGNvbnN0IFBMT1RMWV9QTE9UX1RZUEVfSU1QTFM6IFBhcnRpYWw8UmVjb3JkPFBsb3RUeXBlLCBQbG90bHlQbG90VHlwZUltcGw+PiA9IHtcbiAgW1Bsb3RUeXBlLkNPTlRPVVJdOiAgICB7IGJ1aWxkVHJhY2VzOiBidWlsZENvbnRvdXJUcmFjZXMsICAgIGxheW91dEtpbmQ6ICcyZC1pbWFnZScsICAgdGhyZWVEOiBmYWxzZSB9LFxuICBbUGxvdFR5cGUuU0NBVFRFUl06ICAgIHsgYnVpbGRUcmFjZXM6IGJ1aWxkU2NhdHRlclRyYWNlcywgICAgbGF5b3V0S2luZDogJzJkLW92ZXJsYXknLCB0aHJlZUQ6IGZhbHNlIH0sXG4gIFtQbG90VHlwZS5TQ0FUVEVSM0RdOiAgeyBidWlsZFRyYWNlczogYnVpbGRTY2F0dGVyM2RUcmFjZXMsICBsYXlvdXRLaW5kOiAnM2Qtdm9sdW1lJywgIHRocmVlRDogdHJ1ZSB9LFxuICBbUGxvdFR5cGUuSVNPU1VSRkFDRV06IHsgYnVpbGRUcmFjZXM6IGJ1aWxkSXNvc3VyZmFjZVRyYWNlcywgbGF5b3V0S2luZDogJzNkLXZvbHVtZScsICB0aHJlZUQ6IHRydWUgfSxcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQbG90VHlwZUltcGwodHlwZTogUGxvdFR5cGUpOiBQbG90bHlQbG90VHlwZUltcGwgfCB1bmRlZmluZWQge1xuICByZXR1cm4gUExPVExZX1BMT1RfVFlQRV9JTVBMU1t0eXBlXTtcbn1cbiJdfQ==
|