@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,346 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { Image } from 'image-js';
|
|
4
|
+
import { IImageInfo, IImageMetadata } from './image.contract';
|
|
5
|
+
import { Region } from '../models/region';
|
|
6
|
+
import { PlotType, PlotTypeDescriptor } from './plot-type';
|
|
7
|
+
import { ViewerCapabilities } from './capabilities.contract';
|
|
8
|
+
import { IRegionOverlay } from './region-overlay.contract';
|
|
9
|
+
import { IHistogram } from './channel-histogram-api.contract';
|
|
10
|
+
import { ColormapNode, IWandOptions, IBrushOptions } from './display-types';
|
|
11
|
+
/**
|
|
12
|
+
* Backend-neutral visualization contract. Plotly is one implementation;
|
|
13
|
+
* OpenSeadragon is another (for the image plot type). The abstraction renders
|
|
14
|
+
* data — a raster image OR a scientific plot (heatmap, surface, contour,
|
|
15
|
+
* scatter, line, isosurface) — draws regions on it, and drives on-canvas tools.
|
|
16
|
+
*
|
|
17
|
+
* Split into role interfaces so a consumer can depend only on the slice it
|
|
18
|
+
* uses, then composed into `IVisualizer`.
|
|
19
|
+
*
|
|
20
|
+
* Types are intentionally permissive (`any` where the current Plotly service
|
|
21
|
+
* is untyped) so `PlotlyService` satisfies the contract without a typing
|
|
22
|
+
* rewrite — tightening is a follow-up, not part of standing the interface up.
|
|
23
|
+
*/
|
|
24
|
+
/** Pixel readback shape returned by `getDisplayedPixelData`. */
|
|
25
|
+
export interface PixelData {
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
channels: number;
|
|
29
|
+
data: Uint8ClampedArray;
|
|
30
|
+
}
|
|
31
|
+
/** Intensity sampled along a line ROI (PlotType.LINE over image data). */
|
|
32
|
+
export interface IntensityProfile {
|
|
33
|
+
/** Distance along the line. In microns when the image carries a physical
|
|
34
|
+
* pixel size (mpp); otherwise in image pixels. See {@link unit}. */
|
|
35
|
+
positions: number[];
|
|
36
|
+
/** Sampled intensity (grayscale value or RGB luminance). */
|
|
37
|
+
values: number[];
|
|
38
|
+
/** Unit of {@link positions}: 'µm' when scaled by the image's mpp, else 'px'. */
|
|
39
|
+
unit?: 'µm' | 'px';
|
|
40
|
+
/** Stable id of the line ROI this profile came from (multi-line support). */
|
|
41
|
+
id?: number;
|
|
42
|
+
/** Colour of the line ROI — the inset trace is drawn in the same colour. */
|
|
43
|
+
color?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The render/viewport role: load data, render it (image or plot), and handle
|
|
47
|
+
* zoom, stack navigation, and pixel readback.
|
|
48
|
+
*/
|
|
49
|
+
export interface IDataRenderer {
|
|
50
|
+
load(imageInfo: IImageInfo, zIndex: number): Promise<any>;
|
|
51
|
+
/** `imageLoaded` is the backend-specific handle returned by `load()` —
|
|
52
|
+
* treat it as opaque and pass it straight through. */
|
|
53
|
+
plot(plotDiv: string, imageLoaded: unknown, imageInfo: IImageInfo, screenHeight: number, plotType: PlotType, inPlace?: boolean): Promise<boolean>;
|
|
54
|
+
/** @deprecated Plotly-specific re-render; the OSD backend no-ops it. The host
|
|
55
|
+
* re-drives `plot()` from its image stream instead. */
|
|
56
|
+
reloadAndPlot(): void;
|
|
57
|
+
reset(): void;
|
|
58
|
+
relayout(trueImageSize?: number[]): void;
|
|
59
|
+
/** @deprecated Plotly-specific (axis reset); the OSD backend no-ops it. Gate
|
|
60
|
+
* on {@link ViewerCapabilities} before calling. */
|
|
61
|
+
resetAxes(): void;
|
|
62
|
+
/** @deprecated Plotly-specific (autoscale); the OSD backend no-ops it. Gate
|
|
63
|
+
* on {@link ViewerCapabilities} before calling. */
|
|
64
|
+
autoscale(): void;
|
|
65
|
+
zoomIn(): void;
|
|
66
|
+
zoomOut(): void;
|
|
67
|
+
setDragMode(mode: string | false): void;
|
|
68
|
+
/** Show/hide the overview navigator (the minimap). OpenSeadragon only — Plotly
|
|
69
|
+
* no-ops it (it has no navigator). Applied when the viewer is (re)created, and
|
|
70
|
+
* toggled live when one is already mounted. */
|
|
71
|
+
setNavigatorVisible(visible: boolean): void;
|
|
72
|
+
/** Image smoothing (bilinear interpolation). `false` = nearest-neighbour, so
|
|
73
|
+
* zooming past 1:1 shows crisp pixel blocks (pixel-level inspection).
|
|
74
|
+
* OpenSeadragon only — Plotly no-ops it. Applied at viewer creation and live
|
|
75
|
+
* (with a redraw) when one is mounted. */
|
|
76
|
+
setImageSmoothingEnabled(enabled: boolean): void;
|
|
77
|
+
setShowStack(showstack: boolean): void;
|
|
78
|
+
setZIndex(zIndex: number): void;
|
|
79
|
+
setStackLoading(stackLoading: boolean): void;
|
|
80
|
+
isStackLoading(): Observable<boolean>;
|
|
81
|
+
getStackLoadingProgress(): Observable<number>;
|
|
82
|
+
/** Cancel any in-flight multi-frame loading (volume-assembly / surface preload) so it stops
|
|
83
|
+
* fetching more frames and clears the loading state. Optional — only backends that stream a
|
|
84
|
+
* z-stack (napari-js WebGPU) do real work here; others no-op. */
|
|
85
|
+
cancelLoading?(): void;
|
|
86
|
+
getTrueImageSize(): {
|
|
87
|
+
width: number;
|
|
88
|
+
height: number;
|
|
89
|
+
} | null;
|
|
90
|
+
getCurrentImage(): Promise<Image | null>;
|
|
91
|
+
getDisplayedPixelData(): PixelData | null;
|
|
92
|
+
/**
|
|
93
|
+
* The region of the original, full-resolution image that the pixels returned
|
|
94
|
+
* by {@link getDisplayedPixelData} currently cover — `{ x, y, width, height }`
|
|
95
|
+
* in full-image pixel coordinates. When zoomed/panned into a sub-area this is
|
|
96
|
+
* the crop's origin + extent; when zoomed out/panned beyond the edges, the
|
|
97
|
+
* rectangle may extend outside the image bounds (matching the pixel readback
|
|
98
|
+
* canvas). Lets a consumer map displayed-pixel coordinates back to the original
|
|
99
|
+
* image via `origin + displayedPx * (extent / displayedDim)`.
|
|
100
|
+
*
|
|
101
|
+
* Returns `null` when the viewport isn't laid out yet or the backend can't
|
|
102
|
+
* report it — callers should then fall back to the full-image scale (treat
|
|
103
|
+
* the displayed pixels as a downsample of the whole image).
|
|
104
|
+
*/
|
|
105
|
+
getDisplayedSourceRect(): {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
} | null;
|
|
111
|
+
downloadImage(): void;
|
|
112
|
+
setPlotType(plotType: PlotType): void;
|
|
113
|
+
/** Set the napari 3D decimate factor (1 = full … 8 = ⅛). Optional — only the napari-js WebGPU
|
|
114
|
+
* backend honors it; changing it re-loads the current 3D plot at the coarser/finer sampling. */
|
|
115
|
+
setResolutionScale?(scale: number): void;
|
|
116
|
+
/** The current napari 3D decimate factor (to initialize the Resolution control). Optional. */
|
|
117
|
+
getResolutionScale?(): number;
|
|
118
|
+
/** @deprecated Use `getSurface3dControls()` — 3D scene controls only exist on
|
|
119
|
+
* a backend that renders 3D plot types; this method silently no-ops on OSD. */
|
|
120
|
+
setSurfaceDragMode(mode: string): void;
|
|
121
|
+
/** @deprecated Use `getSurface3dControls()` — see {@link setSurfaceDragMode}. */
|
|
122
|
+
resetSurfaceCamera(): void;
|
|
123
|
+
getAutoscaleEvent(): Observable<any>;
|
|
124
|
+
/** Plot types this backend advertises (drives the UI selector). */
|
|
125
|
+
getPlotTypeDescriptors(): PlotTypeDescriptor[];
|
|
126
|
+
/** Intensity along the line ROIs; emits the full set as any line is added,
|
|
127
|
+
* moved, or removed (PlotType.LINE). One entry per line ROI. */
|
|
128
|
+
getIntensityProfile$(): Observable<IntensityProfile[]>;
|
|
129
|
+
/** Render the floating intensity-profile inset chart into `divId` from the
|
|
130
|
+
* given profiles (one trace per line ROI, coloured to match its line).
|
|
131
|
+
* Owned by the backend so consumers never reach a charting library directly. */
|
|
132
|
+
renderIntensityInset(divId: string, profiles: IntensityProfile[]): void;
|
|
133
|
+
}
|
|
134
|
+
/** Region/shape state: CRUD, selection, classification colours, GeoJSON I/O. */
|
|
135
|
+
export interface IRegionStore {
|
|
136
|
+
setRegions(regions: Region[], showRegionLabel?: boolean, isRegionSaveOn?: boolean, fillColor?: string, append?: boolean): void;
|
|
137
|
+
/** Framework-neutral accessor — the canonical way to read current regions. */
|
|
138
|
+
getRegions(): Region[];
|
|
139
|
+
getRegionPolygons(): any[];
|
|
140
|
+
getRegionUpdateEvent(): Observable<any[]>;
|
|
141
|
+
setSelectedShapeIndices(indices: number[]): void;
|
|
142
|
+
getSelectedShapeIndices$(): Observable<number[]>;
|
|
143
|
+
/** Select a specific region (by identity), highlighting it on whichever
|
|
144
|
+
* backend is rendering — Plotly sets its active-shape handles, OpenSeadragon
|
|
145
|
+
* highlights the SVG element. No-op if the region isn't in the store. */
|
|
146
|
+
selectRegion(region: Region): void;
|
|
147
|
+
deleteActiveShape(): void;
|
|
148
|
+
getShowShapeLabel(): boolean;
|
|
149
|
+
getShapeColor(): string;
|
|
150
|
+
getFillColor(): string;
|
|
151
|
+
getClassificationColors(): Map<string, string>;
|
|
152
|
+
setClassificationColor(label: string, color: string): void;
|
|
153
|
+
plotPreviousShapes(): void;
|
|
154
|
+
setPreviousShapes(shapes: any[]): void;
|
|
155
|
+
getPreviousShapes(): any[];
|
|
156
|
+
/** Undo the most recent region action (jit-ui#85). Restores the region set to
|
|
157
|
+
* the state before that action; up to a small fixed depth (10) is retained,
|
|
158
|
+
* so it can be invoked up to 10 times in a row. No-op when nothing is left to
|
|
159
|
+
* undo. */
|
|
160
|
+
undo(): void;
|
|
161
|
+
/** Re-apply the most recently undone region action. No-op when there's
|
|
162
|
+
* nothing to redo (any fresh region action clears the redo future). */
|
|
163
|
+
redo(): void;
|
|
164
|
+
/** Synchronous read of {@link getCanUndo$}. */
|
|
165
|
+
canUndo(): boolean;
|
|
166
|
+
/** Synchronous read of {@link getCanRedo$}. */
|
|
167
|
+
canRedo(): boolean;
|
|
168
|
+
/** Emits whether an undo step is currently available — drives the toolbar
|
|
169
|
+
* Undo button's enabled (greyed-out) state. */
|
|
170
|
+
getCanUndo$(): Observable<boolean>;
|
|
171
|
+
/** Emits whether a redo step is currently available — drives the toolbar
|
|
172
|
+
* Redo button's enabled (greyed-out) state. */
|
|
173
|
+
getCanRedo$(): Observable<boolean>;
|
|
174
|
+
/** Clear the undo/redo history (e.g. on image load/switch). */
|
|
175
|
+
resetUndoHistory(): void;
|
|
176
|
+
importRegions(geoJsonStr: string): Region[];
|
|
177
|
+
exportRegions(regions: Region[]): void;
|
|
178
|
+
getGeoJsonString(regions: Region[]): string;
|
|
179
|
+
/** Begin a per-slice z-stack region session (jit-ui#93). `slices` maps each
|
|
180
|
+
* zero-based slice index to that slice's regions; the store shows `initialZ`
|
|
181
|
+
* live while holding the rest, so scrubbing swaps region sets and edits on a
|
|
182
|
+
* slice persist. `saveLayout` records how the stack persists — `combined`
|
|
183
|
+
* (one z-indexed geojson, single-file z-stack) or `per-slice-file` (folder
|
|
184
|
+
* stack). See {@link setDisplaySlice}, {@link getSliceRegions}. */
|
|
185
|
+
enterStackMode(slices: Map<number, Region[]>, initialZ?: number, saveLayout?: 'combined' | 'per-slice-file'): void;
|
|
186
|
+
/** End the per-slice session (single-plane image, or the stack was closed). */
|
|
187
|
+
exitStackMode(): void;
|
|
188
|
+
/** True while a per-slice z-stack session is active. */
|
|
189
|
+
isStackMode(): boolean;
|
|
190
|
+
/** How the current stack persists to disk (jit-ui#93). */
|
|
191
|
+
getStackSaveLayout(): 'combined' | 'per-slice-file';
|
|
192
|
+
/** Swap the live region set to slice `z` (stack mode only), capturing the
|
|
193
|
+
* current slice's edits first. Called on every committed slice scrub. */
|
|
194
|
+
setDisplaySlice(z: number): void;
|
|
195
|
+
/** Every slice's regions for save/export, each tagged with its zero-based
|
|
196
|
+
* {@link Region.z}; the flat set outside stack mode. */
|
|
197
|
+
getSliceRegions(): Region[];
|
|
198
|
+
/** Slices to write on a per-slice-file save (folder stack, jit-ui#93): each
|
|
199
|
+
* slice with regions, plus slices cleared since load (empty, to overwrite).
|
|
200
|
+
* Keyed by zero-based slice index; regions tagged with their z. */
|
|
201
|
+
getStackSaveSlices(): Map<number, Region[]>;
|
|
202
|
+
}
|
|
203
|
+
/** On-canvas tool modes (wand, brush, vertex eraser, zoom-to-box). */
|
|
204
|
+
export interface IToolController {
|
|
205
|
+
setWandMode(active: boolean, options?: IWandOptions): void;
|
|
206
|
+
setWandOptions(options: IWandOptions): void;
|
|
207
|
+
clearActiveWandRegion(): void;
|
|
208
|
+
/** Brush region tool. `size` (matrix-pixel diameter) sizes the painted disc. */
|
|
209
|
+
setBrushMode(active: boolean, options?: IBrushOptions): void;
|
|
210
|
+
setBrushOptions(options: IBrushOptions): void;
|
|
211
|
+
setVertexEraserMode(active: boolean): void;
|
|
212
|
+
setVertexEraserRadius(radius: number): void;
|
|
213
|
+
setZoomToBoxMode(active: boolean): void;
|
|
214
|
+
/** Box-prompted SAM segmentation: segment every rectangle region into masks.
|
|
215
|
+
* Returns the number of mask regions added. (jit-ui#90) */
|
|
216
|
+
segmentRectangles(): Promise<number>;
|
|
217
|
+
/** Cellpose-on-crop: client slide-crop each rectangle and segment cells in it
|
|
218
|
+
* (cellpose-SAM via the host's CELL_SEGMENTER). Returns regions added. */
|
|
219
|
+
segmentRectanglesCellpose(): Promise<number>;
|
|
220
|
+
/** Choose the registered SAM model the segment tools use (jit-ui#90 P1). */
|
|
221
|
+
setSamModel(id: string): void;
|
|
222
|
+
/** Toggle the interactive SAM point-prompt tool (click = +point, Shift = -). */
|
|
223
|
+
setSamPointMode(active: boolean): void;
|
|
224
|
+
/** Finalise / discard the in-progress SAM point object. */
|
|
225
|
+
commitSamPoints(): void;
|
|
226
|
+
clearSamPoints(): void;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Controls specific to the ISOSURFACE plot type. Optional and capability-gated
|
|
230
|
+
* (`ViewerFeature.Isosurface`): only a backend that renders isosurfaces exposes
|
|
231
|
+
* it, via `IVisualizer.getIsosurfaceControls()`. Kept off the always-on
|
|
232
|
+
* contract so consumers never call a control that's meaningless for the current
|
|
233
|
+
* plot type / backend.
|
|
234
|
+
*/
|
|
235
|
+
export interface IIsosurfaceControls {
|
|
236
|
+
/** Live-update the isosurface intensity band [isomin, isomax] over 0–255. */
|
|
237
|
+
setIsoRange(isoMin: number, isoMax: number): void;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Controls specific to the 3D plot types (SURFACE / SCATTER3D / ISOSURFACE
|
|
241
|
+
* scenes). Capability-gated like {@link IIsosurfaceControls}: only a backend
|
|
242
|
+
* that renders 3D scenes exposes it, via `IVisualizer.getSurface3dControls()` —
|
|
243
|
+
* the deprecated top-level `setSurfaceDragMode`/`resetSurfaceCamera` silently
|
|
244
|
+
* no-op on 2D-only backends.
|
|
245
|
+
*/
|
|
246
|
+
export interface ISurface3dControls {
|
|
247
|
+
/** Switch the 3D scene interaction mode (orbit / turntable / pan / zoom). */
|
|
248
|
+
setSurfaceDragMode(mode: string): void;
|
|
249
|
+
/** Reset the 3D scene camera to its default eye position. */
|
|
250
|
+
resetSurfaceCamera(): void;
|
|
251
|
+
/** Toggle the 3D coordinate-axes / scale gizmo on/off. Optional — only the napari-js WebGPU
|
|
252
|
+
* volume/isosurface backend renders one (jit-ui#102). */
|
|
253
|
+
setAxesVisible?(visible: boolean): void;
|
|
254
|
+
/** Whether the axes gizmo is currently shown (for initializing the toggle UI). Optional. */
|
|
255
|
+
axesVisible?(): boolean;
|
|
256
|
+
/** Render the surface as a wireframe (edges) instead of a filled surface. Optional — only the
|
|
257
|
+
* napari-js WebGPU surface backend supports it (jit-ui#102). */
|
|
258
|
+
setWireframe?(on: boolean): void;
|
|
259
|
+
/** Whether the surface is currently drawn as a wireframe (for initializing the toggle UI). */
|
|
260
|
+
wireframe?(): boolean;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Controls specific to the LINE (intensity-profile) plot type. Capability-gated
|
|
264
|
+
* like {@link IIsosurfaceControls}: only a backend that renders the line-ROI /
|
|
265
|
+
* inset exposes it, via `IVisualizer.getIntensityControls()`.
|
|
266
|
+
*/
|
|
267
|
+
export interface IIntensityControls {
|
|
268
|
+
/** Add another line ROI (next bright palette colour) and its inset trace.
|
|
269
|
+
* Returns the created region so the caller can select it on the active
|
|
270
|
+
* backend, or null if no image extent is known yet. */
|
|
271
|
+
addProfileLine(): Region | null;
|
|
272
|
+
}
|
|
273
|
+
/** Display options (colormap/LUT, reverse scale, image metadata). */
|
|
274
|
+
export interface IDisplayOptions {
|
|
275
|
+
getColormap(): Observable<ColormapNode | null>;
|
|
276
|
+
setColormap(colormap: ColormapNode): void;
|
|
277
|
+
getColormapOptions(): ColormapNode[];
|
|
278
|
+
getReverseScale(): Observable<boolean>;
|
|
279
|
+
setReverseScale(reverscale: any): void;
|
|
280
|
+
setImageMeta(imageMeta: IImageMetadata[]): void;
|
|
281
|
+
getImageMeta(): Observable<IImageMetadata[]>;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Intensity-profile sampling (PlotType.LINE). The sampling *source* lives in the
|
|
285
|
+
* Plotly backend (it owns pixel readback); OpenSeadragon contributes only the
|
|
286
|
+
* viewport-change signal that drives re-sampling at the current zoom. Each
|
|
287
|
+
* backend implements the part it owns and no-ops the rest — mirroring the
|
|
288
|
+
* deprecated no-op pattern on {@link IDataRenderer} — so the contract is uniform
|
|
289
|
+
* and a consumer can depend on `IVisualizer` alone (no concrete-type reach-in).
|
|
290
|
+
*/
|
|
291
|
+
export interface IIntensitySampling {
|
|
292
|
+
/** Populate the intensity-sampling cache for the current image/slice so the
|
|
293
|
+
* line-ROI profiles have pixel data. Real on Plotly; no-op on OSD. */
|
|
294
|
+
ensureIntensitySampling(imageInfo: IImageInfo, zIndex: number): Promise<void>;
|
|
295
|
+
/** Re-sample the profiles from a fresh crop of the given image-pixel ROI at
|
|
296
|
+
* display resolution. Real on Plotly; no-op on OSD. */
|
|
297
|
+
refreshIntensitySamplingForRoi(x: number, y: number, width: number, height: number, zIndex: number): void;
|
|
298
|
+
/** Visible-region changes (image-pixel coords), emitted when the view settles,
|
|
299
|
+
* so the inset can re-sample at the current zoom. Real on OSD; empty on Plotly
|
|
300
|
+
* (its high-def zoom updates the sampling cache inline instead). */
|
|
301
|
+
getViewportChange$(): Observable<{
|
|
302
|
+
x: number;
|
|
303
|
+
y: number;
|
|
304
|
+
width: number;
|
|
305
|
+
height: number;
|
|
306
|
+
}>;
|
|
307
|
+
}
|
|
308
|
+
/** Composite contract a visualization backend implements. */
|
|
309
|
+
export interface IVisualizer extends IDataRenderer, IRegionStore, IToolController, IDisplayOptions, IIntensitySampling {
|
|
310
|
+
readonly capabilities: ViewerCapabilities;
|
|
311
|
+
/** This backend's region renderer. May be null until a plot is mounted
|
|
312
|
+
* (OpenSeadragon). Drives region draw/select modes uniformly. */
|
|
313
|
+
getRegionOverlay(): IRegionOverlay | null;
|
|
314
|
+
/** Isosurface controls when this backend advertises `ViewerFeature.Isosurface`,
|
|
315
|
+
* else null — so consumers gate on the returned object, not a no-op method. */
|
|
316
|
+
getIsosurfaceControls(): IIsosurfaceControls | null;
|
|
317
|
+
/** Intensity (line-ROI) controls when the backend renders the LINE plot type,
|
|
318
|
+
* else null. */
|
|
319
|
+
getIntensityControls(): IIntensityControls | null;
|
|
320
|
+
/** 3D scene controls when this backend renders 3D plot types, else null —
|
|
321
|
+
* the capability-gated replacement for the deprecated top-level
|
|
322
|
+
* `setSurfaceDragMode`/`resetSurfaceCamera`. */
|
|
323
|
+
getSurface3dControls(): ISurface3dControls | null;
|
|
324
|
+
/** Binned intensity histogram for a channel from the currently-displayed
|
|
325
|
+
* pixels, or null when none are available. Feeds the Channels & Histogram
|
|
326
|
+
* pane. */
|
|
327
|
+
getHistogram(channelIndex: number, bins: number): IHistogram | null;
|
|
328
|
+
/** Async histogram stream — native bit depth for >8-bit images (server), else
|
|
329
|
+
* the 8-bit client histogram. */
|
|
330
|
+
getHistogram$(channelIndex: number, bins: number): Observable<IHistogram | null>;
|
|
331
|
+
/** Export the displayed image, composited with the current display settings,
|
|
332
|
+
* as a publication-ready PNG download. */
|
|
333
|
+
exportComposite(): void;
|
|
334
|
+
/** Export the underlying image data as a data-preserving multi-band TIFF
|
|
335
|
+
* (native bit depth). No-op on backends that can't provide it. */
|
|
336
|
+
exportData(): void;
|
|
337
|
+
unsubscribe(): void;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* DI token for the active visualization backend. Bind it (`useExisting`) to the
|
|
341
|
+
* `RoutingVisualizerService`, which selects Plotly vs OpenSeadragon per plot
|
|
342
|
+
* type. Consumers — including this library's own `VisualizerComponent` —
|
|
343
|
+
* inject `IVisualizer` through this token rather than the concrete router, so
|
|
344
|
+
* the routing/fallback implementation can change without touching constructors.
|
|
345
|
+
*/
|
|
346
|
+
export declare const VISUALIZER: InjectionToken<IVisualizer>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Static configuration the visualization library needs from the host, supplied
|
|
4
|
+
* via DI so the library never imports the app's `environment`.
|
|
5
|
+
*/
|
|
6
|
+
export interface VizConfig {
|
|
7
|
+
/** Base URL of the tile/crop server (`/tile`, `/tiles/info`, zoom). */
|
|
8
|
+
slideCropServer: string;
|
|
9
|
+
/**
|
|
10
|
+
* Optional CSS selector for a host element whose current width the Region
|
|
11
|
+
* Editor dialog should match when it first opens (e.g. the app's right
|
|
12
|
+
* panel). Measured once per open — it does not track later resizes. When
|
|
13
|
+
* absent or the element isn't found, the dialog falls back to a quarter of
|
|
14
|
+
* the page width (25vw).
|
|
15
|
+
*/
|
|
16
|
+
regionEditorWidthSelector?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Opt in to the experimental WebGPU **napari-js** backend for the IMAGE plot type
|
|
19
|
+
* (jit-ui#102). When `true`, the router renders images through napari-js with OpenSeadragon
|
|
20
|
+
* as the fallback; when absent/false, OpenSeadragon remains the default. Other plot types
|
|
21
|
+
* are unaffected.
|
|
22
|
+
*/
|
|
23
|
+
useNapariRenderer?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare const VIZ_CONFIG: InjectionToken<VizConfig>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, Renderer2 } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class HexColorPickerComponent implements OnDestroy {
|
|
4
|
+
private elRef;
|
|
5
|
+
private renderer;
|
|
6
|
+
private cdr;
|
|
7
|
+
private static readonly DROPDOWN_WIDTH;
|
|
8
|
+
private _color;
|
|
9
|
+
colorChange: EventEmitter<string>;
|
|
10
|
+
open: boolean;
|
|
11
|
+
swatchBtn: ElementRef<HTMLButtonElement>;
|
|
12
|
+
dropdownRef: ElementRef<HTMLDivElement>;
|
|
13
|
+
hue: number;
|
|
14
|
+
saturation: number;
|
|
15
|
+
lightness: number;
|
|
16
|
+
red: number;
|
|
17
|
+
green: number;
|
|
18
|
+
blue: number;
|
|
19
|
+
readonly colorRows: string[][];
|
|
20
|
+
private normalizeHexColor;
|
|
21
|
+
get color(): string;
|
|
22
|
+
set color(val: string);
|
|
23
|
+
constructor(elRef: ElementRef, renderer: Renderer2, cdr: ChangeDetectorRef);
|
|
24
|
+
ngOnDestroy(): void;
|
|
25
|
+
toggle(): void;
|
|
26
|
+
private appendDropdownToBody;
|
|
27
|
+
private removeDropdownFromBody;
|
|
28
|
+
selectColor(hex: string): void;
|
|
29
|
+
selectAndClose(hex: string): void;
|
|
30
|
+
close(): void;
|
|
31
|
+
onHexInput(value: string): void;
|
|
32
|
+
onHslChange(): void;
|
|
33
|
+
onRgbChange(): void;
|
|
34
|
+
get hueGradient(): string;
|
|
35
|
+
get satGradient(): string;
|
|
36
|
+
get lightGradient(): string;
|
|
37
|
+
onDocumentClick(event: Event): void;
|
|
38
|
+
private syncFromHex;
|
|
39
|
+
private syncRgbFromHex;
|
|
40
|
+
private syncHslFromRgb;
|
|
41
|
+
private hexToRgb;
|
|
42
|
+
private rgbToHex;
|
|
43
|
+
private rgbToHsl;
|
|
44
|
+
private hslToHex;
|
|
45
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<HexColorPickerComponent, never>;
|
|
46
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<HexColorPickerComponent, "hex-color-picker", never, { "color": { "alias": "color"; "required": false; }; }, { "colorChange": "colorChange"; }, never, never, false, never>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { IDisplayOptions, IRegionStore } from '../contracts/visualizer.contract';
|
|
3
|
+
import { Region } from '../models/region';
|
|
4
|
+
import { ColormapNode } from '../contracts/display-types';
|
|
5
|
+
import { IImageMetadata } from '../contracts/image.contract';
|
|
6
|
+
import { RegionStore } from '../store/region-store.service';
|
|
7
|
+
import { VisualizerStore } from '../store/visualizer-store.service';
|
|
8
|
+
/**
|
|
9
|
+
* Shared store-delegation base for the OpenSeadragon and napari-js
|
|
10
|
+
* `IVisualizer` backends. The entire `IRegionStore` and `IDisplayOptions`
|
|
11
|
+
* surfaces (plus the two classification-colour members) are pure forwarders to
|
|
12
|
+
* the shared `RegionStore` / `VisualizerStore` in BOTH backends — so they live
|
|
13
|
+
* here once, as a single source of truth, rather than being copied per backend.
|
|
14
|
+
* (This is the "cross-backend behaviour that isn't rendering belongs in a
|
|
15
|
+
* shared abstraction" convention from CLAUDE.md; the extraction closes
|
|
16
|
+
* SHARED-BACKEND-REFACTOR.md.)
|
|
17
|
+
*
|
|
18
|
+
* Backend-specific members — `load`/`plot`/`reset`/zoom/`setZIndex`/readback,
|
|
19
|
+
* the region OVERLAY, tool wiring, histograms, scale bar, tiling, colormap LUT
|
|
20
|
+
* application — deliberately stay in each subclass.
|
|
21
|
+
*
|
|
22
|
+
* NOT `@Injectable`: an abstract base doesn't participate in Angular DI. Each
|
|
23
|
+
* subclass stays `@Injectable`, declares its own injected dependencies
|
|
24
|
+
* (including the two stores), and passes them to `super(...)`. Plotly is
|
|
25
|
+
* intentionally not a subclass — it has its own region model.
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class BaseStoreVisualizer implements IRegionStore, IDisplayOptions {
|
|
28
|
+
protected readonly regionStore: RegionStore;
|
|
29
|
+
protected readonly store: VisualizerStore;
|
|
30
|
+
protected constructor(regionStore: RegionStore, store: VisualizerStore);
|
|
31
|
+
setRegions(regions: Region[], showRegionLabel?: boolean, isRegionSaveOn?: boolean, fillColor?: string, append?: boolean): void;
|
|
32
|
+
getRegions(): Region[];
|
|
33
|
+
getRegionPolygons(): any[];
|
|
34
|
+
getRegionUpdateEvent(): Observable<any[]>;
|
|
35
|
+
setSelectedShapeIndices(indices: number[]): void;
|
|
36
|
+
getSelectedShapeIndices$(): Observable<number[]>;
|
|
37
|
+
selectRegion(region: Region): void;
|
|
38
|
+
deleteActiveShape(): void;
|
|
39
|
+
getShowShapeLabel(): boolean;
|
|
40
|
+
getShapeColor(): string;
|
|
41
|
+
getFillColor(): string;
|
|
42
|
+
plotPreviousShapes(): void;
|
|
43
|
+
setPreviousShapes(shapes: any[]): void;
|
|
44
|
+
getPreviousShapes(): any[];
|
|
45
|
+
undo(): void;
|
|
46
|
+
redo(): void;
|
|
47
|
+
canUndo(): boolean;
|
|
48
|
+
canRedo(): boolean;
|
|
49
|
+
getCanUndo$(): Observable<boolean>;
|
|
50
|
+
getCanRedo$(): Observable<boolean>;
|
|
51
|
+
resetUndoHistory(): void;
|
|
52
|
+
importRegions(geoJsonStr: string): Region[];
|
|
53
|
+
exportRegions(regions: Region[]): void;
|
|
54
|
+
getGeoJsonString(regions: Region[]): string;
|
|
55
|
+
enterStackMode(slices: Map<number, Region[]>, initialZ?: number, saveLayout?: 'combined' | 'per-slice-file'): void;
|
|
56
|
+
exitStackMode(): void;
|
|
57
|
+
isStackMode(): boolean;
|
|
58
|
+
getStackSaveLayout(): 'combined' | 'per-slice-file';
|
|
59
|
+
setDisplaySlice(z: number): void;
|
|
60
|
+
getSliceRegions(): Region[];
|
|
61
|
+
getStackSaveSlices(): Map<number, Region[]>;
|
|
62
|
+
getClassificationColors(): Map<string, string>;
|
|
63
|
+
setClassificationColor(label: string, color: string): void;
|
|
64
|
+
getColormap(): Observable<ColormapNode | null>;
|
|
65
|
+
setColormap(colormap: ColormapNode): void;
|
|
66
|
+
getColormapOptions(): ColormapNode[];
|
|
67
|
+
getReverseScale(): Observable<boolean>;
|
|
68
|
+
setReverseScale(reverscale: any): void;
|
|
69
|
+
setImageMeta(imageMeta: IImageMetadata[]): void;
|
|
70
|
+
getImageMeta(): Observable<IImageMetadata[]>;
|
|
71
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM text labels for the napari-js 3D axes gizmo (jit-ui#102). The {@link AxesLayer} draws the
|
|
3
|
+
* axis lines/ticks/box in WebGPU; this overlay adds the crisp X/Y/Z + scale text on top, projected
|
|
4
|
+
* with the 3D camera's view-projection so each label tracks its anchor as the volume orbits.
|
|
5
|
+
* Mirrors the {@link NapariScaleBar} overlay pattern (absolute-positioned over the host, updated on
|
|
6
|
+
* every `camera3d.changed`). Falls back to pixel/slice counts when no physical µm/pixel is known.
|
|
7
|
+
*/
|
|
8
|
+
/** One axis label: a world-space anchor (the axis end, in the volume's centred box), the text to
|
|
9
|
+
* show, and its colour (matching the WebGPU axis colour). */
|
|
10
|
+
export interface AxisLabelSpec {
|
|
11
|
+
anchor: [number, number, number];
|
|
12
|
+
text: string;
|
|
13
|
+
color: string;
|
|
14
|
+
}
|
|
15
|
+
/** The slice of napari's Camera3D this overlay reads. `viewProjection` is column-major (gl-matrix). */
|
|
16
|
+
export interface AxesLabelCamera3D {
|
|
17
|
+
viewProjection(vw: number, vh: number): ArrayLike<number>;
|
|
18
|
+
readonly changed: {
|
|
19
|
+
connect(listener: () => void): () => void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Project a world point through a column-major 4×4 MVP to CSS-pixel screen coordinates.
|
|
24
|
+
* Returns `visible: false` when the point is at/behind the camera (w ≤ 0). Pure — unit-tested.
|
|
25
|
+
*/
|
|
26
|
+
export declare function projectPoint(mvp: ArrayLike<number>, p: [number, number, number], vw: number, vh: number): {
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
visible: boolean;
|
|
30
|
+
};
|
|
31
|
+
export declare class NapariAxesLabels {
|
|
32
|
+
private readonly host;
|
|
33
|
+
private readonly camera3d;
|
|
34
|
+
private readonly labels;
|
|
35
|
+
private readonly els;
|
|
36
|
+
private readonly disconnectCamera;
|
|
37
|
+
private readonly resizeObserver?;
|
|
38
|
+
private visible;
|
|
39
|
+
constructor(host: HTMLElement, camera3d: AxesLabelCamera3D, labels: AxisLabelSpec[]);
|
|
40
|
+
setVisible(visible: boolean): void;
|
|
41
|
+
/** Replace the label anchors/text in place (same count) and reproject — lets a host move the
|
|
42
|
+
* labels when the box geometry changes live (e.g. a Z-height gizmo restretching the volume)
|
|
43
|
+
* without tearing down and recreating the DOM elements (which would flicker). */
|
|
44
|
+
updateAnchors(labels: AxisLabelSpec[]): void;
|
|
45
|
+
private update;
|
|
46
|
+
destroy(): void;
|
|
47
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { IRegionOverlay, RegionToolMode } from '../../contracts/region-overlay.contract';
|
|
2
|
+
import { RegionStore } from '../../store/region-store.service';
|
|
3
|
+
/** The slice of the napari Viewer the overlay needs (coord transforms + control gating). */
|
|
4
|
+
interface OverlayViewer {
|
|
5
|
+
canvasToWorld(clientX: number, clientY: number): [number, number];
|
|
6
|
+
worldToCanvas(worldX: number, worldY: number): [number, number];
|
|
7
|
+
setControlsEnabled(enabled: boolean): void;
|
|
8
|
+
readonly camera: {
|
|
9
|
+
readonly changed: {
|
|
10
|
+
connect(listener: () => void): () => void;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* SVG region overlay for the napari-js WebGPU image view (jit-ui#102), mirroring the OSD backend's
|
|
16
|
+
* {@link OsdRegionOverlay} but driven by napari's `canvasToWorld`/`worldToCanvas` transforms.
|
|
17
|
+
* Vector shapes are drawn in an absolutely-positioned `<svg>` over the canvas (no need to push
|
|
18
|
+
* them through WebGPU). It writes completed shapes to the shared {@link RegionStore} (so save /
|
|
19
|
+
* undo / export work identically to OSD) and re-renders from the store on every camera move,
|
|
20
|
+
* region change, and selection change.
|
|
21
|
+
*
|
|
22
|
+
* Supports (jit-ui#102): rectangle / polygon / freehand path drawing, click-select and rubber-band
|
|
23
|
+
* marquee select, pan/zoom gating via `setControlsEnabled`, body move, vertex move/add/delete,
|
|
24
|
+
* bezier handle editing, and donut holes (including hole vertex + hole-bezier-handle editing) —
|
|
25
|
+
* full parity with {@link OsdRegionOverlay}.
|
|
26
|
+
*/
|
|
27
|
+
export declare class NapariRegionOverlay implements IRegionOverlay {
|
|
28
|
+
private readonly host;
|
|
29
|
+
private readonly viewer;
|
|
30
|
+
private readonly store;
|
|
31
|
+
private readonly svg;
|
|
32
|
+
private readonly subs;
|
|
33
|
+
private readonly disconnectCamera;
|
|
34
|
+
private mode;
|
|
35
|
+
private selected;
|
|
36
|
+
/** In-progress drawing state (image-space). */
|
|
37
|
+
private draftRect;
|
|
38
|
+
/** In-progress rubber-band selection marquee (select mode), image-space. */
|
|
39
|
+
private marquee;
|
|
40
|
+
/** Dedicated marquee rect element, updated directly during the drag (no full region redraw). */
|
|
41
|
+
private marqueeEl;
|
|
42
|
+
private draftPath;
|
|
43
|
+
private drawing;
|
|
44
|
+
/** In-progress manipulation (select/move modes): dragging a body, a polygon vertex, or a
|
|
45
|
+
* rectangle corner. `anchor` is the fixed opposite corner for a rectangle resize. */
|
|
46
|
+
private edit;
|
|
47
|
+
constructor(host: HTMLElement, viewer: OverlayViewer, store: RegionStore);
|
|
48
|
+
setMode(mode: RegionToolMode): void;
|
|
49
|
+
setSelectedBezier(bezier: boolean): void;
|
|
50
|
+
destroy(): void;
|
|
51
|
+
/** Pointer client coords → rounded image coords. */
|
|
52
|
+
private toImage;
|
|
53
|
+
/** Image coords → SVG-local px (the svg overlays the canvas at the same client rect). */
|
|
54
|
+
private toLocal;
|
|
55
|
+
private readonly onPointerDown;
|
|
56
|
+
private readonly onPointerMove;
|
|
57
|
+
private readonly onPointerUp;
|
|
58
|
+
/** Click-to-place polygon: add a vertex, or close when clicking near the first one. */
|
|
59
|
+
private handlePolygonClick;
|
|
60
|
+
private readonly onDblClick;
|
|
61
|
+
/** The currently-selected region (single selection), or null. */
|
|
62
|
+
private selectedRegion;
|
|
63
|
+
/** Screen distance (px) between a client point and an image coord. */
|
|
64
|
+
private screenDist;
|
|
65
|
+
/**
|
|
66
|
+
* Start a select/move interaction: grab a handle (rectangle corner) or vertex of the already-
|
|
67
|
+
* selected region first; otherwise select the topmost region under the cursor and drag its body.
|
|
68
|
+
*/
|
|
69
|
+
private beginManipulation;
|
|
70
|
+
/** Create/update the marquee rect element directly (avoids a full region redraw per move). */
|
|
71
|
+
private updateMarqueeEl;
|
|
72
|
+
/** Remove the marquee element from the SVG. */
|
|
73
|
+
private clearMarqueeEl;
|
|
74
|
+
/** Test whether a client point grabs a rectangle corner or a polygon vertex of `region`. */
|
|
75
|
+
private hitHandle;
|
|
76
|
+
/** Apply the live drag for the active manipulation (image coords `ix,iy`). */
|
|
77
|
+
private applyManipulation;
|
|
78
|
+
/** addpoint mode: insert a vertex on the selected polygon's nearest edge at the click. */
|
|
79
|
+
private handleAddPoint;
|
|
80
|
+
/** deletepoint mode: remove the selected polygon's vertex nearest the click. */
|
|
81
|
+
private handleDeletePoint;
|
|
82
|
+
/** Distance from point (px,py) to segment (ax,ay)-(bx,by), in image units. */
|
|
83
|
+
private pointSegDist;
|
|
84
|
+
/** Finalize a rubber-band marquee: select every region whose bounding box it overlaps (a tiny
|
|
85
|
+
* marquee is treated as a click on empty space → clear the selection). */
|
|
86
|
+
private finishMarquee;
|
|
87
|
+
/** A region's bounding box in image coords (rectangle, polygon, or multipolygon), or null. */
|
|
88
|
+
private regionBBox;
|
|
89
|
+
private commitRectangle;
|
|
90
|
+
private commitPolygon;
|
|
91
|
+
private hitTest;
|
|
92
|
+
redraw(): void;
|
|
93
|
+
/** Draw a region's classification label at its top-left, when labels are enabled (matches OSD). */
|
|
94
|
+
private drawLabel;
|
|
95
|
+
/** Draw grab handles for the selected region: rectangle corners or polygon vertices. */
|
|
96
|
+
private drawHandles;
|
|
97
|
+
/** Draw one bezier control point (anchor + handle offset) as a small circle connected to its
|
|
98
|
+
* anchor by a tangent line. `handle` is the [dx,dy] offset from the anchor in image space. */
|
|
99
|
+
private drawBezierHandle;
|
|
100
|
+
private buildRegionEl;
|
|
101
|
+
/** Path data for a polygon: the exterior ring (bezier or straight) plus any holes (bezier when
|
|
102
|
+
* the donut carries hole handles, else straight) as sub-paths — even-odd fill cuts them out. */
|
|
103
|
+
private polygonPathData;
|
|
104
|
+
/** SVG path data for a straight ring/polyline in image coords (closed appends `Z`). */
|
|
105
|
+
private straightPath;
|
|
106
|
+
/** SVG cubic-bezier path data for any ring (exterior or hole): anchors joined by cubic segments
|
|
107
|
+
* whose control points are `anchor + handleOut` (leaving) and `nextAnchor + handleIn` (arriving),
|
|
108
|
+
* in image space. Used for both the exterior and (donut) hole rings. */
|
|
109
|
+
private ringBezierPath;
|
|
110
|
+
private style;
|
|
111
|
+
/** Draw the in-progress rectangle / path preview. */
|
|
112
|
+
private drawDraft;
|
|
113
|
+
private styleDraft;
|
|
114
|
+
}
|
|
115
|
+
export {};
|