@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,85 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { IHistogram } from '../../contracts/channel-histogram-api.contract';
|
|
4
|
+
/**
|
|
5
|
+
* Histogram + auto-window sampling for the OSD backend (refactoring plan,
|
|
6
|
+
* Step 4 — a pure move out of the visualizer service). Owns the per-slice
|
|
7
|
+
* 8-bit histograms (sampled from displayed tiles) and the native-bit-depth
|
|
8
|
+
* histograms (fetched from the server `/histogram` endpoint). Read-only with
|
|
9
|
+
* respect to the tile/display pipeline.
|
|
10
|
+
*/
|
|
11
|
+
/** The descriptor fields the samplers read (structurally satisfied by the
|
|
12
|
+
* service's TileDescriptor). */
|
|
13
|
+
export interface SampledDescriptor {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
tileSize: number;
|
|
17
|
+
channels?: number;
|
|
18
|
+
levels?: Array<{
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export interface HistogramSamplerHost {
|
|
24
|
+
/** Real Bio-Formats levels (per-channel tiles exist only there). */
|
|
25
|
+
realLevels(): number;
|
|
26
|
+
/** Channel count for the multichannel sampler. */
|
|
27
|
+
channelCount(d: SampledDescriptor): number;
|
|
28
|
+
/** Grayscale (intensity histogram + auto-window) vs RGB (R/G/B histograms). */
|
|
29
|
+
isGrayscale(): boolean;
|
|
30
|
+
/** Histograms landed — nudge the pane to re-read (its retry window may have
|
|
31
|
+
* lapsed). */
|
|
32
|
+
onChannelHistogramsSampled(): void;
|
|
33
|
+
/** A grayscale auto-window was measured from full-res tiles — seed the
|
|
34
|
+
* Intensity channel (or re-invalidate if the user already windowed). */
|
|
35
|
+
onGrayWindowSampled(min: number, max: number): void;
|
|
36
|
+
}
|
|
37
|
+
export declare class HistogramSampler {
|
|
38
|
+
private http;
|
|
39
|
+
private api;
|
|
40
|
+
private host;
|
|
41
|
+
/** 256-bin intensity histogram per z-slice, from sampled tiles. */
|
|
42
|
+
private sliceHistograms;
|
|
43
|
+
/** Native-bit-depth histograms from `/histogram`, keyed `${z}|${channel}`. */
|
|
44
|
+
private nativeHistograms;
|
|
45
|
+
/** Per-app-load cache-buster for `/histogram` — the server marks the
|
|
46
|
+
* response cacheable for 24h, and a hard refresh can't bust a post-load
|
|
47
|
+
* XHR. A token stable within a session but new on each full load keeps the
|
|
48
|
+
* in-session dedup (via `nativeHistograms`) while always reflecting the
|
|
49
|
+
* live backend after a reload. */
|
|
50
|
+
private readonly histCacheBuster;
|
|
51
|
+
constructor(http: HttpClient, api: string, host: HistogramSamplerHost);
|
|
52
|
+
/** The sampled histogram for one channel of slice z, or null until the
|
|
53
|
+
* async sampling resolves (or if it was skipped). */
|
|
54
|
+
get(z: number, channelIndex: number): IHistogram | null;
|
|
55
|
+
/** Drop everything (teardown / image switch). */
|
|
56
|
+
clear(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Per-channel intensity histograms for multichannel images: sample each
|
|
59
|
+
* channel's single-band tiles at the coarsest real level and bin the
|
|
60
|
+
* luminance. Fire-and-forget.
|
|
61
|
+
*/
|
|
62
|
+
computeMultiChannelHistograms(d: SampledDescriptor, infoB64: string, z: number): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Compute a per-image intensity window [min,max] for grayscale auto-ranging,
|
|
65
|
+
* mirroring the heatmap's auto-stretch. Two constraints force the sampling
|
|
66
|
+
* strategy:
|
|
67
|
+
* - The window MUST be in the same value space as the displayed tiles: the
|
|
68
|
+
* `/preview` endpoint is server-normalized while `/tile` serves raw
|
|
69
|
+
* un-normalized 8-bit — a window from the preview wouldn't match.
|
|
70
|
+
* - It must read FULL-RESOLUTION tiles, not a downsampled overview:
|
|
71
|
+
* averaging sparse low values (label masks) toward 0 wipes the signal.
|
|
72
|
+
* So we sample the full-res level across the whole image — bounded to 64
|
|
73
|
+
* tiles (a huge grayscale image samples the coarsest overview for histograms
|
|
74
|
+
* only). Fire-and-forget; failures leave the window unset (identity 0..255).
|
|
75
|
+
*/
|
|
76
|
+
computeImageWindow(d: SampledDescriptor, infoB64: string, z: number): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Native-bit-depth histogram for >8-bit images, from the server `/histogram`
|
|
79
|
+
* endpoint (the 8-bit canvas tiles can't carry 16-bit values). Cached per
|
|
80
|
+
* slice+channel for the session.
|
|
81
|
+
*/
|
|
82
|
+
native$(infoB64: string, z: number, channel: number, bins: number): Observable<IHistogram | null>;
|
|
83
|
+
/** Fetch + cache one channel's native histogram from `GET /histogram`. */
|
|
84
|
+
private fetchNative;
|
|
85
|
+
}
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { Image } from 'image-js';
|
|
4
|
+
import { VisualizerStore } from '../../store/visualizer-store.service';
|
|
5
|
+
import { RegionStore } from '../../store/region-store.service';
|
|
6
|
+
import { IImageInfo } from '../../contracts/image.contract';
|
|
7
|
+
import { TileAccessPort } from '../../contracts/ports/tile-access.port';
|
|
8
|
+
import { VizConfig } from '../../contracts/viz-config';
|
|
9
|
+
import { PlotType, PlotTypeDescriptor } from '../../contracts/plot-type';
|
|
10
|
+
import { IVisualizer, PixelData, IntensityProfile, IIsosurfaceControls, IIntensityControls, ISurface3dControls } from '../../contracts/visualizer.contract';
|
|
11
|
+
import { ViewerCapabilities } from '../../contracts/capabilities.contract';
|
|
12
|
+
import { IRegionOverlay } from '../../contracts/region-overlay.contract';
|
|
13
|
+
import { BaseStoreVisualizer } from '../base-store-visualizer';
|
|
14
|
+
import { SimpleSliceAccessService } from '../simple-slice-access.service';
|
|
15
|
+
import { WandToolService } from '../../toolbar/wand/wand-tool.service';
|
|
16
|
+
import { BrushToolService } from '../../toolbar/brush/brush-tool.service';
|
|
17
|
+
import { SamToolService } from '../../toolbar/segmentation/sam-tool.service';
|
|
18
|
+
import { SamPointToolService } from '../../toolbar/segmentation/sam-point-tool.service';
|
|
19
|
+
import { CellSegmentToolService } from '../../toolbar/segmentation/cell-segment-tool.service';
|
|
20
|
+
import { ICellSegmenter } from '../../contracts/cell-segmenter.contract';
|
|
21
|
+
import { VertexEraserToolService } from '../../toolbar/vertex-eraser/vertex-eraser-tool.service';
|
|
22
|
+
import { ZoomToBoxToolService } from '../../toolbar/zoom-to-box/zoom-to-box-tool.service';
|
|
23
|
+
import { IHistogram } from '../../contracts/channel-histogram-api.contract';
|
|
24
|
+
import * as i0 from "@angular/core";
|
|
25
|
+
/** One pyramid level from `GET /tiles/info`. */
|
|
26
|
+
interface TileLevel {
|
|
27
|
+
res: number;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}
|
|
31
|
+
/** Tile-source descriptor returned by `GET /tiles/info`. */
|
|
32
|
+
interface TileDescriptor {
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
tileSize: number;
|
|
36
|
+
z: number;
|
|
37
|
+
channels: number;
|
|
38
|
+
/** True only for genuine multi-channel composites (indexed/LUT-bearing
|
|
39
|
+
* fluorescence stacks) the client should split into per-channel layers. The
|
|
40
|
+
* server sets it; an RGB photo read as separated planes has channels>1 but
|
|
41
|
+
* multichannel=false, so it stays a single composite tile source. */
|
|
42
|
+
multichannel?: boolean;
|
|
43
|
+
/** Real Bio-Formats resolution levels at the front of `levels`; the remaining
|
|
44
|
+
* levels are synthetic composited overviews (no per-channel tiles). */
|
|
45
|
+
realLevels?: number;
|
|
46
|
+
/** Per-channel metadata (name/color/bitDepth/min-maxAllowed) for native 16-bit
|
|
47
|
+
* windowing + histogram; null for plain 8-bit/RGB sources. */
|
|
48
|
+
channelInfo?: Array<{
|
|
49
|
+
name?: string;
|
|
50
|
+
color?: string;
|
|
51
|
+
bitDepth?: number;
|
|
52
|
+
minAllowed?: number;
|
|
53
|
+
maxAllowed?: number;
|
|
54
|
+
}> | null;
|
|
55
|
+
levels: TileLevel[];
|
|
56
|
+
/** Physical pixel size in µm (0 when the format doesn't report it). */
|
|
57
|
+
mppX?: number;
|
|
58
|
+
mppY?: number;
|
|
59
|
+
}
|
|
60
|
+
/** What `load()` hands to `plot()`. */
|
|
61
|
+
interface OsdLoaded {
|
|
62
|
+
descriptor: TileDescriptor | null;
|
|
63
|
+
infoB64: string;
|
|
64
|
+
z: number;
|
|
65
|
+
/** Mirrors the loaded image's filename — the diagram's render pipeline
|
|
66
|
+
* guards on `loaded.filename === phaseInfo.fileName` before calling plot(). */
|
|
67
|
+
filename: string | undefined;
|
|
68
|
+
/** Simple (non-tiled) image: `plot()` opens {@link url} directly via OSD's
|
|
69
|
+
* single-image source — no tile pyramid, no server. Set when the image
|
|
70
|
+
* carries `tiled === false` (see {@link IImageInfo.tiled}). */
|
|
71
|
+
simple?: boolean;
|
|
72
|
+
/** The directly-loadable image URL (`blob:`/`data:`/`http`) for simple mode. */
|
|
73
|
+
url?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* OpenSeadragon visualization backend.
|
|
77
|
+
*
|
|
78
|
+
* Renders the *image* plot type as a natively-tiled, zoomable raster, backed by
|
|
79
|
+
* the jit-service tile endpoints (`GET /tiles/info` + `GET /tile`, which reuse
|
|
80
|
+
* the Bio-Formats ROI renderer). Plotly keeps the scientific/data plot types
|
|
81
|
+
* (scalar heatmap, surface, contour, scatter, line, scatter3d, isosurface) —
|
|
82
|
+
* hence this backend advertises only `ImageDisplay`.
|
|
83
|
+
*
|
|
84
|
+
* Wired: load → descriptor, plot → mount viewer with a custom tile source,
|
|
85
|
+
* zoom/pan → viewport API. NOT wired yet (follow-ups): region overlays + tools
|
|
86
|
+
* (a positioned canvas/SVG overlay or Annotorious), pixel readback, and the
|
|
87
|
+
* per-tile LUT/contrast params. Not registered in DI providers — `PlotlyService`
|
|
88
|
+
* is still the only active backend; this proves the contract supports a second
|
|
89
|
+
* implementation against real endpoints.
|
|
90
|
+
*/
|
|
91
|
+
export declare class OpenSeadragonVisualizerService extends BaseStoreVisualizer implements IVisualizer {
|
|
92
|
+
private http;
|
|
93
|
+
private tiles;
|
|
94
|
+
private wandTool;
|
|
95
|
+
private brushTool;
|
|
96
|
+
private samTool;
|
|
97
|
+
private samPointTool;
|
|
98
|
+
private cellSegmentTool;
|
|
99
|
+
private cellSegmenter;
|
|
100
|
+
private eraserTool;
|
|
101
|
+
private zoomToBoxTool;
|
|
102
|
+
private simpleStack;
|
|
103
|
+
/** OSD's strength is displaying a large zoomable image — nothing else here. */
|
|
104
|
+
readonly capabilities: ViewerCapabilities;
|
|
105
|
+
private readonly api;
|
|
106
|
+
private viewer;
|
|
107
|
+
private overlay;
|
|
108
|
+
private scaleBar;
|
|
109
|
+
private descriptor;
|
|
110
|
+
/** Base64 RawFileInfo + current z-slice, kept so setZIndex can rebuild the
|
|
111
|
+
* tile source and swap slices live (stack navigation). */
|
|
112
|
+
private infoB64;
|
|
113
|
+
private currentZ;
|
|
114
|
+
/** True while the current image is "simple" (tiled:false — self-contained
|
|
115
|
+
* per-slice URLs, no tile server; e.g. a numbered image series assembled
|
|
116
|
+
* client-side into a stack). setZIndex swaps the single-image source for
|
|
117
|
+
* the new slice's URL instead of updating a tiled z-param. */
|
|
118
|
+
private simpleMode;
|
|
119
|
+
/** urls[] for the current simple-mode image, so setZIndex can look up the
|
|
120
|
+
* slice being scrubbed to (via {@link SimpleSliceAccessService.urlFor}).
|
|
121
|
+
* Unused (and left stale, harmlessly) in tiled mode. */
|
|
122
|
+
private simpleUrls;
|
|
123
|
+
/** preview blob URL → full-res upscaled blob URL (see toFullResUrl), so
|
|
124
|
+
* re-visiting a simple-mode slice doesn't re-upscale. Revoked on file change. */
|
|
125
|
+
private readonly simpleFullResUrls;
|
|
126
|
+
/** Skip the full-res upscale above this longest-side dimension — a folder
|
|
127
|
+
* stack is per-file previews (well under this); this only guards against an
|
|
128
|
+
* accidental enormous canvas allocation. */
|
|
129
|
+
private readonly SIMPLE_UPSCALE_MAX_DIM;
|
|
130
|
+
private coordTransform;
|
|
131
|
+
private wandHost;
|
|
132
|
+
private eraserHost;
|
|
133
|
+
/** Wand sampling matrix read back from the rendered viewport; cached until
|
|
134
|
+
* the viewport changes (see readbackViewport). */
|
|
135
|
+
private viewportPixels;
|
|
136
|
+
/** The DOM id of the element OSD is mounted in (shared with Plotly); the
|
|
137
|
+
* on-canvas tools attach their overlays here. */
|
|
138
|
+
private plotDiv;
|
|
139
|
+
/** Current file name, tagged onto wand-created shapes. */
|
|
140
|
+
private currentFileName;
|
|
141
|
+
/** 256-entry RGB LUT for the active colormap, applied to grayscale tiles via
|
|
142
|
+
* the tile-invalidated pixel pipeline (mirrors Plotly's heatmap colorscale).
|
|
143
|
+
* Null while options resolve; recoloring is skipped until it's built. */
|
|
144
|
+
private colorLut;
|
|
145
|
+
/** Only grayscale images get a colormap (RGB tiles pass through untouched). */
|
|
146
|
+
private isGrayscaleImage;
|
|
147
|
+
private colormapSub;
|
|
148
|
+
/** Latest per-channel display state (window/gamma/visibility) from the store,
|
|
149
|
+
* read synchronously by recolorTile. Channel 0 drives grayscale windowing;
|
|
150
|
+
* R/G/B (indices 0-2) drive RGB per-channel windowing. */
|
|
151
|
+
private channelStates;
|
|
152
|
+
/** True for multichannel fluorescence (channelCount > 1, not RGB): tiles are
|
|
153
|
+
* composited client-side from per-channel single-band fetches (see
|
|
154
|
+
* recolorMultiChannelTile) rather than recolored in place. */
|
|
155
|
+
private isMultiChannel;
|
|
156
|
+
/** Count of real Bio-Formats resolution levels (per-channel tiles exist only
|
|
157
|
+
* here). For multichannel images the tile source is built from these alone so
|
|
158
|
+
* every displayed tile supports a per-channel fetch. */
|
|
159
|
+
private realLevels;
|
|
160
|
+
/** Inverted background (white = zero): inverts the display value before the
|
|
161
|
+
* LUT (grayscale) / per channel (RGB). */
|
|
162
|
+
private invertBg;
|
|
163
|
+
/** Bearer token for OSD's own tile fetches (HttpClient calls get it via the
|
|
164
|
+
* interceptor; OSD's loader does not, so we pass it as an ajax header). */
|
|
165
|
+
private authHeaders;
|
|
166
|
+
/** Whether the overview navigator (minimap) is shown. Read at viewer creation;
|
|
167
|
+
* a consumer that doesn't want it (e.g. a small embedded preview) sets it off
|
|
168
|
+
* via {@link setNavigatorVisible} before the first render. */
|
|
169
|
+
private navigatorVisible;
|
|
170
|
+
/** Image smoothing (bilinear). `false` → nearest-neighbour, so zoomed-in pixels
|
|
171
|
+
* render as crisp blocks (pixel inspection). Defaults to `false` so the image
|
|
172
|
+
* opens showing raw pixels. Read at viewer creation; toggled via
|
|
173
|
+
* {@link setImageSmoothingEnabled}. */
|
|
174
|
+
private smoothingEnabled;
|
|
175
|
+
/** Overall deadline for the /tiles/info poll loop. An uncached whole-slide
|
|
176
|
+
* image (e.g. .ndpi) is cached server-side first (GCS->PVC), which can take
|
|
177
|
+
* several minutes — we poll (short requests; the cache-progress overlay
|
|
178
|
+
* shows the wait) until it's ready. Generous because each poll is cheap; on
|
|
179
|
+
* expiry the render pipeline gives up and the router falls back to Plotly. */
|
|
180
|
+
private readonly tilesInfoTimeoutMs;
|
|
181
|
+
/** Per-channel fit-view tile budget (tiles at the coarsest real level × channels).
|
|
182
|
+
* Above it, a multichannel image renders server-composited instead of per-channel
|
|
183
|
+
* — its full-res reads (it has no overview pyramid) would be too many × N channels.
|
|
184
|
+
* 64 (e.g. a 4x4 single-FOV z-stack × 4ch) stays per-channel; a whole-slide
|
|
185
|
+
* (hundreds–thousands) falls back. */
|
|
186
|
+
private readonly MAX_MULTICHANNEL_FIT_TILES;
|
|
187
|
+
/** Pixel display pipeline (window/gamma/invert/colormap + additive tint) —
|
|
188
|
+
* shared by tile recoloring and the composite export so they stay identical
|
|
189
|
+
* (see DisplayPipeline). Host closures read the service's live fields. */
|
|
190
|
+
private readonly display;
|
|
191
|
+
/** Histogram + auto-window sampling (see HistogramSampler). Constructed in
|
|
192
|
+
* the ctor body because it captures the resolved API base URL. */
|
|
193
|
+
private sampler;
|
|
194
|
+
/** Stack-slice cache + background preloader (see SliceCache — refactoring
|
|
195
|
+
* plan Step 3). The host accessors are live closures, so the cache always
|
|
196
|
+
* reads the service's current viewer/descriptor/z — exactly the fields the
|
|
197
|
+
* moved code used to read directly. */
|
|
198
|
+
private readonly cache;
|
|
199
|
+
constructor(http: HttpClient, tiles: TileAccessPort, wandTool: WandToolService, brushTool: BrushToolService, samTool: SamToolService, samPointTool: SamPointToolService, cellSegmentTool: CellSegmentToolService, cellSegmenter: ICellSegmenter | null, eraserTool: VertexEraserToolService, zoomToBoxTool: ZoomToBoxToolService, store: VisualizerStore, regionStore: RegionStore, simpleStack: SimpleSliceAccessService, config: VizConfig);
|
|
200
|
+
private readonly stackLoading$;
|
|
201
|
+
private readonly stackLoadingProgress$;
|
|
202
|
+
private readonly autoscaleEvent$;
|
|
203
|
+
/** Visible image region (full-image pixel coords) emitted when the view
|
|
204
|
+
* settles, so the intensity inset can re-sample at the current zoom level. */
|
|
205
|
+
private readonly viewportChange$;
|
|
206
|
+
private readonly intensityProfile$;
|
|
207
|
+
/**
|
|
208
|
+
* Subscribe to the shared VisualizerStore colormap/reverse so OSD recolors in
|
|
209
|
+
* lock-step with Plotly. Idempotent and self-healing: this service is a root
|
|
210
|
+
* singleton, but `unsubscribe()` (called on VisualizerComponent destroy)
|
|
211
|
+
* tears the subscription down — and the constructor never runs again. So
|
|
212
|
+
* `plot()` calls this to re-establish it after a component teardown/recreate
|
|
213
|
+
* (e.g. switching images), otherwise colormap changes would be silently
|
|
214
|
+
* dropped on every image after the first switch.
|
|
215
|
+
*/
|
|
216
|
+
private ensureColormapSubscription;
|
|
217
|
+
/** Seed the Intensity channel with a measured auto-window while it's still
|
|
218
|
+
* at full range (never clobber the user's manual window); if the user
|
|
219
|
+
* already windowed, just re-invalidate so painted tiles pick the LUT up. */
|
|
220
|
+
private seedGrayWindow;
|
|
221
|
+
/**
|
|
222
|
+
* Fetch the tile-source descriptor for the selected file. The `info` param is
|
|
223
|
+
* the base64 RawFileInfo the rest of the API uses; the GET goes through the
|
|
224
|
+
* auth interceptor (Bearer). We also grab a token here for OSD's own tile
|
|
225
|
+
* fetches (its loader bypasses HttpClient).
|
|
226
|
+
*/
|
|
227
|
+
load(imageInfo: IImageInfo, zIndex: number): Promise<OsdLoaded>;
|
|
228
|
+
/** Build the `plot()` payload for a simple (tiled:false) image: a single-level
|
|
229
|
+
* descriptor sized from `trueImageSize`, plus the directly-loadable URL —
|
|
230
|
+
* resolved and fetched via {@link SimpleSliceAccessService} (shared with
|
|
231
|
+
* napari-js; see its docs for why this can't be a raw `fetch()`/`<img>`). */
|
|
232
|
+
private loadSimple;
|
|
233
|
+
/**
|
|
234
|
+
* OSD's `{type:'image'}` source sizes its coordinate world to the image's
|
|
235
|
+
* NATURAL pixels. A folder-stack slice is a server `/preview` whose pixel size
|
|
236
|
+
* needn't match the full-resolution image — it may be downscaled (large
|
|
237
|
+
* images) OR larger than the dimensions `/metadata` reports. Either way OSD's
|
|
238
|
+
* world would differ from the full-res ROI coordinate space (QuPath geojson,
|
|
239
|
+
* in level-0 pixels): a smaller preview renders ROIs oversized, a larger one
|
|
240
|
+
* renders them undersized/offset. Resample the preview to EXACTLY the
|
|
241
|
+
* full-resolution dimensions (blurry but positionally exact — scaling up or
|
|
242
|
+
* down as needed) so OSD's world matches the ROI coordinate space, while still
|
|
243
|
+
* using OSD's reliable single-image renderer. Cached per preview URL (revoked
|
|
244
|
+
* on file change); a no-op when the preview is already exactly full-res (small
|
|
245
|
+
* images, in-memory pipeline blobs), when the dims are unknown, or when
|
|
246
|
+
* they're implausibly large (guards against an enormous canvas). (jit-ui#93)
|
|
247
|
+
*/
|
|
248
|
+
private toFullResUrl;
|
|
249
|
+
/** Load a URL into an HTMLImageElement (resolves once decoded). Uses
|
|
250
|
+
* document.createElement rather than `new Image()` because this file's
|
|
251
|
+
* `Image` import is image-js's decoder, not the DOM element. */
|
|
252
|
+
private loadImageEl;
|
|
253
|
+
private revokeSimpleFullResUrls;
|
|
254
|
+
/** Mount the viewer with a custom tile source pointing at `GET /tile`. */
|
|
255
|
+
plot(plotDiv: string, imageLoaded: any, imageInfo: IImageInfo, _screenHeight: number, _plotType: PlotType, inPlace?: boolean): Promise<boolean>;
|
|
256
|
+
/**
|
|
257
|
+
* Fit-to-home once `el` first has a non-zero size. If it's already sized we
|
|
258
|
+
* rely on the timed refits the caller scheduled; otherwise a one-shot
|
|
259
|
+
* ResizeObserver runs `refit` the moment the container is laid out (then
|
|
260
|
+
* disconnects), so the initial fit doesn't depend on the render's start time
|
|
261
|
+
* relative to the diagram container's layout. No-op without a container or
|
|
262
|
+
* ResizeObserver (the timed refits remain the fallback). One-shot + only
|
|
263
|
+
* attached on a fresh mount, so slice-scrub re-opens keep the user's zoom.
|
|
264
|
+
*/
|
|
265
|
+
private fitWhenContainerSized;
|
|
266
|
+
/**
|
|
267
|
+
* Custom tile source built from the descriptor. OSD numbers levels
|
|
268
|
+
* coarsest-first; the backend numbers resolutions full-res-first, so
|
|
269
|
+
* `res = (levels-1) - osdLevel`. Overriding getLevelScale/getNumTiles lets us
|
|
270
|
+
* honour Bio-Formats' actual per-level dimensions (not assume power-of-two).
|
|
271
|
+
*/
|
|
272
|
+
private buildTileSource;
|
|
273
|
+
/** Re-apply the display pipeline (window/gamma/colour/invert) after a state change.
|
|
274
|
+
* Multichannel invalidates ONLY the visible slice's channel images — invalidating
|
|
275
|
+
* the whole world would re-process every hidden/preloaded slice's tiles (hundreds),
|
|
276
|
+
* flooding OSD with "[CacheRecord] … InvalidStateError" and wasting work on tiles
|
|
277
|
+
* that aren't on screen. The other cached slices are marked stale and re-tinted
|
|
278
|
+
* lazily when revealed. Composite/grayscale invalidate the world as before. */
|
|
279
|
+
private invalidateDisplay;
|
|
280
|
+
private destroyViewer;
|
|
281
|
+
/** This backend's region renderer (the SVG overlay), once a plot is mounted. */
|
|
282
|
+
getRegionOverlay(): IRegionOverlay | null;
|
|
283
|
+
/** OSD renders only the image type — no isosurface, so no controls. */
|
|
284
|
+
getIsosurfaceControls(): IIsosurfaceControls | null;
|
|
285
|
+
/** OSD renders only the image type — no 3D scenes, so no controls. */
|
|
286
|
+
getSurface3dControls(): ISurface3dControls | null;
|
|
287
|
+
/** OSD renders only the image type — no LINE intensity ROIs, so no controls. */
|
|
288
|
+
getIntensityControls(): IIntensityControls | null;
|
|
289
|
+
private toOverlayMode;
|
|
290
|
+
reloadAndPlot(): void;
|
|
291
|
+
reset(): void;
|
|
292
|
+
relayout(_trueImageSize?: number[]): void;
|
|
293
|
+
resetAxes(): void;
|
|
294
|
+
autoscale(): void;
|
|
295
|
+
zoomIn(): void;
|
|
296
|
+
zoomOut(): void;
|
|
297
|
+
setDragMode(mode: string | false): void;
|
|
298
|
+
setShowStack(_showstack: boolean): void;
|
|
299
|
+
/** Show/hide the overview navigator. Stored for the next viewer creation, and
|
|
300
|
+
* applied live when a viewer is already mounted (hides/reveals its element —
|
|
301
|
+
* the navigator instance itself only exists when created with showNavigator). */
|
|
302
|
+
setNavigatorVisible(visible: boolean): void;
|
|
303
|
+
/** Toggle bilinear smoothing vs nearest-neighbour (crisp pixels). Stored for the
|
|
304
|
+
* next viewer creation, and applied live (with a redraw) to a mounted viewer. */
|
|
305
|
+
setImageSmoothingEnabled(enabled: boolean): void;
|
|
306
|
+
/**
|
|
307
|
+
* Swap the displayed z-slice live. Slices are kept as separate tiled images in
|
|
308
|
+
* the world, so switching is just an opacity toggle: a previously-visited slice
|
|
309
|
+
* shows instantly (its decoded + recolored tiles are still resident), and a
|
|
310
|
+
* never-seen slice is added once. The region overlay, coordinate transform,
|
|
311
|
+
* scale bar, colormap pipeline and current zoom/pan all persist — the x/y
|
|
312
|
+
* geometry is identical across slices.
|
|
313
|
+
*
|
|
314
|
+
* Simple mode (tiled:false — a numbered image series assembled client-side,
|
|
315
|
+
* each slice its own complete image with no shared tile server) has no
|
|
316
|
+
* pyramid to toggle opacity on, so it re-opens the viewer on the new
|
|
317
|
+
* slice's URL instead. preserveViewport (viewer option, see plot()) keeps
|
|
318
|
+
* the current zoom/pan across that reopen.
|
|
319
|
+
*/
|
|
320
|
+
setZIndex(zIndex: number): void;
|
|
321
|
+
setStackLoading(stackLoading: boolean): void;
|
|
322
|
+
isStackLoading(): Observable<boolean>;
|
|
323
|
+
getStackLoadingProgress(): Observable<number>;
|
|
324
|
+
getTrueImageSize(): {
|
|
325
|
+
width: number;
|
|
326
|
+
height: number;
|
|
327
|
+
} | null;
|
|
328
|
+
getCurrentImage(): Promise<Image | null>;
|
|
329
|
+
/**
|
|
330
|
+
* The currently displayed pixels — the rendered viewport (what the user sees,
|
|
331
|
+
* including the current zoom and any colormap recolor), as RGBA. Feeds the
|
|
332
|
+
* processing-pipeline dialog's "use current view". Returns null until tiles
|
|
333
|
+
* are drawn.
|
|
334
|
+
*/
|
|
335
|
+
getDisplayedPixelData(): PixelData | null;
|
|
336
|
+
/**
|
|
337
|
+
* Image-pixel rectangle the drawer canvas (what {@link getDisplayedPixelData}
|
|
338
|
+
* reads) currently covers. Unlike {@link emitViewportChange}, this is NOT
|
|
339
|
+
* clamped to the image bounds: the canvas maps 1:1 to the viewport rectangle,
|
|
340
|
+
* so leaving it unclamped keeps `canvasPx -> imagePx` an exact affine map
|
|
341
|
+
* (clamping would skew coordinates near the image edges). Routed through world
|
|
342
|
+
* item 0 (see {@link viewportRectToImage}) for multi-layer accuracy.
|
|
343
|
+
*/
|
|
344
|
+
getDisplayedSourceRect(): {
|
|
345
|
+
x: number;
|
|
346
|
+
y: number;
|
|
347
|
+
width: number;
|
|
348
|
+
height: number;
|
|
349
|
+
} | null;
|
|
350
|
+
downloadImage(): void;
|
|
351
|
+
setPlotType(_plotType: PlotType): void;
|
|
352
|
+
setSurfaceDragMode(_mode: string): void;
|
|
353
|
+
resetSurfaceCamera(): void;
|
|
354
|
+
getAutoscaleEvent(): Observable<any>;
|
|
355
|
+
/** Visible image region (full-image pixel coords), emitted when the view
|
|
356
|
+
* settles. The intensity inset re-samples this region at the zoom resolution. */
|
|
357
|
+
getViewportChange$(): Observable<{
|
|
358
|
+
x: number;
|
|
359
|
+
y: number;
|
|
360
|
+
width: number;
|
|
361
|
+
height: number;
|
|
362
|
+
}>;
|
|
363
|
+
/** {@link IIntensitySampling} stub — intensity sampling lives in the Plotly
|
|
364
|
+
* backend (it owns pixel readback). OSD feeds it only via getViewportChange$;
|
|
365
|
+
* the sampling-cache priming itself is a no-op here. */
|
|
366
|
+
ensureIntensitySampling(_imageInfo: IImageInfo, _zIndex: number): Promise<void>;
|
|
367
|
+
/** {@link IIntensitySampling} stub — see {@link ensureIntensitySampling}. */
|
|
368
|
+
refreshIntensitySamplingForRoi(_x: number, _y: number, _width: number, _height: number, _zIndex: number): void;
|
|
369
|
+
/** Compute the current viewport's image-pixel rectangle (clamped to the image)
|
|
370
|
+
* and broadcast it. */
|
|
371
|
+
private emitViewportChange;
|
|
372
|
+
/** OSD targets the image display; the scalar/3D plot types belong to Plotly. */
|
|
373
|
+
getPlotTypeDescriptors(): PlotTypeDescriptor[];
|
|
374
|
+
getIntensityProfile$(): Observable<IntensityProfile[]>;
|
|
375
|
+
/** OSD only renders the image type; the LINE intensity inset is Plotly-only. */
|
|
376
|
+
renderIntensityInset(_divId: string, _profiles: IntensityProfile[]): void;
|
|
377
|
+
setWandMode(active: boolean, options?: any): void;
|
|
378
|
+
setWandOptions(options: any): void;
|
|
379
|
+
clearActiveWandRegion(): void;
|
|
380
|
+
setBrushMode(active: boolean, options?: any): void;
|
|
381
|
+
setBrushOptions(options: any): void;
|
|
382
|
+
setVertexEraserMode(active: boolean): void;
|
|
383
|
+
setVertexEraserRadius(radius: number): void;
|
|
384
|
+
setZoomToBoxMode(active: boolean): void;
|
|
385
|
+
/** Box-prompted SAM: segment the drawn rectangles. The SAM tool reuses the
|
|
386
|
+
* wand host (viewport readback + coordinate transform + region store). */
|
|
387
|
+
segmentRectangles(): Promise<number>;
|
|
388
|
+
segmentRectanglesCellpose(): Promise<number>;
|
|
389
|
+
setSamModel(id: string): void;
|
|
390
|
+
setSamPointMode(active: boolean): void;
|
|
391
|
+
commitSamPoints(): void;
|
|
392
|
+
clearSamPoints(): void;
|
|
393
|
+
/** Build the wand/eraser host objects bound to this backend. Both tools run
|
|
394
|
+
* over OSD via the shared coordinate transform + a viewport pixel readback,
|
|
395
|
+
* and read/write regions directly on the shared RegionStore (neutral model). */
|
|
396
|
+
private buildToolHosts;
|
|
397
|
+
/** The element the on-canvas tool overlays attach to (OSD is mounted here). */
|
|
398
|
+
private getOverlayContainer;
|
|
399
|
+
/** Size the navigator from the CURRENT container (navigatorSizeRatio of the
|
|
400
|
+
* viewer element) and keep it pinned to the corner. OSD computes the size
|
|
401
|
+
* once in the Viewer constructor — before the host flex layout settles —
|
|
402
|
+
* and never corrects it, leaving a stale-size element whose visible minimap
|
|
403
|
+
* floats above the bottom-right corner. */
|
|
404
|
+
private resizeNavigator;
|
|
405
|
+
/** Force the docked toolbar to repaint after an OSD zoom. Chrome leaves it
|
|
406
|
+
* laid-out-but-unpainted (the canvas's compositing churn strands the toolbar's
|
|
407
|
+
* raster). A synchronous display toggle re-rasters it with no visible gone-frame
|
|
408
|
+
* and no layout shift. Located via the DOM since this service doesn't own the
|
|
409
|
+
* toolbar; a no-op when there's no toolbar (e.g. embedded without one). */
|
|
410
|
+
private nudgeToolbarRepaint;
|
|
411
|
+
/** Host for the (shared) zoom-to-box tool: convert overlay pixels to image
|
|
412
|
+
* coords via the viewport, and fit the viewport to the chosen rectangle. */
|
|
413
|
+
private zoomBoxHost;
|
|
414
|
+
/** Fit the OSD viewport to an image-space rectangle (coords ordered
|
|
415
|
+
* [xMin, xMax, yMax, yMin]). */
|
|
416
|
+
private applyZoomToBox;
|
|
417
|
+
/**
|
|
418
|
+
* Read back the *currently rendered* OSD canvas as the wand's pixel matrix.
|
|
419
|
+
* The matrix covers only the visible viewport at screen resolution, so when
|
|
420
|
+
* the user is zoomed into a sub-region the wand samples that region's detail
|
|
421
|
+
* (rather than the whole image at preview resolution). `originX/originY` and
|
|
422
|
+
* `ratios` map image coords <-> readback-pixel coords for the wand's
|
|
423
|
+
* data/ratio/origin model. Cached until the viewport changes.
|
|
424
|
+
*/
|
|
425
|
+
private readbackViewport;
|
|
426
|
+
/**
|
|
427
|
+
* Recolor a grayscale tile through the active colormap LUT, using OSD's
|
|
428
|
+
* tile-invalidated pixel pipeline (OSD 5+/6). Maps each pixel's grayscale
|
|
429
|
+
* value (r==g==b) to the LUT's RGB. No-op for RGB images or until the LUT is
|
|
430
|
+
* built. Handler is async — OSD awaits it (raiseEventAwaiting).
|
|
431
|
+
*/
|
|
432
|
+
private recolorTile;
|
|
433
|
+
/**
|
|
434
|
+
* Tint a single channel's tile in place. Each channel is its own OpenSeadragon
|
|
435
|
+
* TiledImage (a single-band grayscale tile); OSD composites the N images
|
|
436
|
+
* additively ('lighter') in its drawer — so this just maps the tile's intensity
|
|
437
|
+
* through the channel's window/gamma and its pseudo-colour. Synchronous (no
|
|
438
|
+
* cross-tile fetch) → no race, no seams. Channel is parsed from the tile URL.
|
|
439
|
+
*/
|
|
440
|
+
private recolorChannelTile;
|
|
441
|
+
/** Per-channel histogram for the Channels & Histogram pane, from the current
|
|
442
|
+
* slice's sampled tiles (grayscale → channel 0; RGB → R/G/B). Null until the
|
|
443
|
+
* async sampling resolves or if it was skipped. */
|
|
444
|
+
getHistogram(channelIndex: number, _bins: number): IHistogram | null;
|
|
445
|
+
/** Native bit depth of a channel from the tile descriptor (8 when unknown). */
|
|
446
|
+
private channelBitDepth;
|
|
447
|
+
/**
|
|
448
|
+
* Async histogram for the Channels & Histogram pane. For >8-bit images it
|
|
449
|
+
* fetches the **native** distribution from the server `/histogram` endpoint
|
|
450
|
+
* (the 8-bit canvas tiles can't carry 16-bit values) and caches it per
|
|
451
|
+
* slice+channel; for 8-bit/RGB it returns the existing client-sampled 8-bit
|
|
452
|
+
* histogram. Read-only — it never touches the tile/display pipeline.
|
|
453
|
+
*/
|
|
454
|
+
getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
|
|
455
|
+
/**
|
|
456
|
+
* Export the underlying image data as a data-preserving multi-band TIFF at
|
|
457
|
+
* native bit depth via `GET /export/tiff` (the server reads the raw 16-bit
|
|
458
|
+
* planes — the client never sees them). Sends only the visible channels; the
|
|
459
|
+
* existing 8-bit composite PNG export is unaffected.
|
|
460
|
+
*/
|
|
461
|
+
exportData(): Promise<void>;
|
|
462
|
+
/**
|
|
463
|
+
* Export the current slice as a publication-ready PNG composited with the
|
|
464
|
+
* active display settings (window / gamma / colormap or per-channel pseudo-
|
|
465
|
+
* colours / invert). Picks the largest pyramid level under a pixel cap (the
|
|
466
|
+
* coarser overview for huge whole-slides), fetches that level's tile grid,
|
|
467
|
+
* stitches it into one canvas, runs the shared display pipeline, and saves it.
|
|
468
|
+
*/
|
|
469
|
+
exportComposite(): Promise<void>;
|
|
470
|
+
/** True if any pixel in the RGBA buffer is non-transparent. */
|
|
471
|
+
private hasOpaque;
|
|
472
|
+
unsubscribe(): void;
|
|
473
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<OpenSeadragonVisualizerService, [null, null, null, null, null, null, null, { optional: true; }, null, null, null, null, null, null]>;
|
|
474
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<OpenSeadragonVisualizerService>;
|
|
475
|
+
}
|
|
476
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ICoordinateTransform } from '../../contracts/coordinate-transform.contract';
|
|
2
|
+
/**
|
|
3
|
+
* OpenSeadragon implementation of {@link ICoordinateTransform}. "Data coords"
|
|
4
|
+
* here are image-pixel coordinates (OSD's native shape space), obtained from the
|
|
5
|
+
* viewport API. This is the reason the tools can run over OSD at all: the
|
|
6
|
+
* viewport gives a clean screen<->image mapping that holds across pan/zoom.
|
|
7
|
+
*/
|
|
8
|
+
export declare class OsdCoordinateTransform implements ICoordinateTransform {
|
|
9
|
+
private viewer;
|
|
10
|
+
constructor(viewer: any);
|
|
11
|
+
isReady(): boolean;
|
|
12
|
+
clientToData(clientX: number, clientY: number): {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
};
|
|
16
|
+
dataLengthToScreen(dataLength: number): number;
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Viewer-element pixel -> image (data) coordinates. */
|
|
2
|
+
export declare function elementToImage(viewer: any, x: number, y: number): {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
};
|
|
6
|
+
/** Image (data) coordinates -> viewer-element pixel point. */
|
|
7
|
+
export declare function imageToElement(viewer: any, x: number, y: number): {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
11
|
+
/** Image-space rectangle -> viewport rectangle (for fitBounds). */
|
|
12
|
+
export declare function imageRectToViewport(viewer: any, x: number, y: number, w: number, h: number): any;
|
|
13
|
+
/** Viewport rectangle -> image (data) rectangle. Routes through world item 0 so
|
|
14
|
+
* it stays accurate when the world holds multiple images (stack slices /
|
|
15
|
+
* per-channel layers); falls back to the viewport when the world is empty. */
|
|
16
|
+
export declare function viewportRectToImage(viewer: any, vpRect: any): any;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as OpenSeadragon from 'openseadragon';
|
|
2
|
+
/**
|
|
3
|
+
* The real OpenSeadragon object, normalized for the packaged (FESM) build.
|
|
4
|
+
*
|
|
5
|
+
* OpenSeadragon ships as plain CommonJS (`module.exports = OpenSeadragon`, no
|
|
6
|
+
* `__esModule` flag). Bundled into this library's FESM and re-bundled by a
|
|
7
|
+
* consuming app, `import * as OpenSeadragon` resolves to a synthesized ES
|
|
8
|
+
* namespace whose only reliable slot is `.default` (the real `module.exports`).
|
|
9
|
+
* The factory itself and every static member (Viewer, Point, Rect, TileSource, …)
|
|
10
|
+
* live on that object, NOT on the namespace — so `OpenSeadragon(...)` or
|
|
11
|
+
* `new OpenSeadragon.Point()` against the namespace fail once packaged
|
|
12
|
+
* ("is not a function" / "not a constructor"). Normalize ONCE here and import
|
|
13
|
+
* { OSD } wherever a runtime VALUE is needed; import the `openseadragon` namespace
|
|
14
|
+
* directly only for its TYPES (e.g. `OpenSeadragon.Viewer`).
|
|
15
|
+
*
|
|
16
|
+
* (plotly.js-dist-min needs no equivalent: it sets `__esModule`, so webpack gives
|
|
17
|
+
* it real named exports and plain member access works.)
|
|
18
|
+
*/
|
|
19
|
+
export declare const OSD: typeof OpenSeadragon;
|