@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,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library-owned data interfaces for the image the visualization renders.
|
|
3
|
+
*
|
|
4
|
+
* The visualization package must not import the host app's concrete models
|
|
5
|
+
* (`main/models/file-info`), or it can't become a standalone library. These
|
|
6
|
+
* slim interfaces declare only the fields the library reads/writes; the host's
|
|
7
|
+
* `ImageInfo`/`ImageMetadata` classes are pure data holders that satisfy them
|
|
8
|
+
* structurally, so the host keeps passing its own instances unchanged.
|
|
9
|
+
*/
|
|
10
|
+
/** Per-channel metadata from the server descriptor (issue #76). */
|
|
11
|
+
export interface IChannelInfo {
|
|
12
|
+
name: string;
|
|
13
|
+
/** Suggested display tint as "#RRGGBB". */
|
|
14
|
+
color: string;
|
|
15
|
+
/** Embedded 256-entry display LUT as "#RRGGBB" (intensity→color), or
|
|
16
|
+
* null/undefined when the file has no palette for this channel. */
|
|
17
|
+
lut?: string[] | null;
|
|
18
|
+
bitDepth?: number;
|
|
19
|
+
/** Pixel-type minimum (e.g. 0 for unsigned). Native-unit floor of the window. */
|
|
20
|
+
minAllowed?: number;
|
|
21
|
+
/** Pixel-type maximum (e.g. 65535 for unsigned 16-bit). Native-unit ceiling. */
|
|
22
|
+
maxAllowed?: number;
|
|
23
|
+
}
|
|
24
|
+
/** Per-series image metadata (physical size + dimensions). */
|
|
25
|
+
export interface IImageMetadata {
|
|
26
|
+
channelCount: number;
|
|
27
|
+
rgbChannels: number;
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
z: number;
|
|
31
|
+
/** Physical pixel size in µm; null/undefined when the format reports none. */
|
|
32
|
+
mppX?: number | null;
|
|
33
|
+
mppY?: number | null;
|
|
34
|
+
/** Per-channel name/color/LUT for multichannel (non-RGB) images, when known. */
|
|
35
|
+
channelInfo?: IChannelInfo[] | null;
|
|
36
|
+
}
|
|
37
|
+
/** The image currently being visualized. Field optionality mirrors the host's
|
|
38
|
+
* `ImageInfo` so its instances are assignable to this interface. */
|
|
39
|
+
export interface IImageInfo {
|
|
40
|
+
isGrayscale: boolean;
|
|
41
|
+
trueImageSize: number[];
|
|
42
|
+
urls: string[];
|
|
43
|
+
/** Optional small-tier URLs (fast blurry placeholder), 1:1 with `urls`. */
|
|
44
|
+
smallUrls?: string[];
|
|
45
|
+
isStack: boolean;
|
|
46
|
+
showStack: boolean;
|
|
47
|
+
scaleRatio: boolean;
|
|
48
|
+
fileName: string;
|
|
49
|
+
roiJsonStr?: string;
|
|
50
|
+
/** Per-slice ROI GeoJSON, aligned 1:1 with `urls`, for a folder stack where
|
|
51
|
+
* each slice is a separate file with its own sibling `<stem>.geojson`
|
|
52
|
+
* (`null` for slices without one). When present, the component applies
|
|
53
|
+
* `roiJsonStrs[z]` for the displayed slice and swaps it on scrub — as
|
|
54
|
+
* opposed to the scalar `roiJsonStr`, which is one ROI set for the whole
|
|
55
|
+
* image (a single file or a server z-stack). (jit-ui#93) */
|
|
56
|
+
roiJsonStrs?: (string | null)[];
|
|
57
|
+
imageMeta: IImageMetadata[];
|
|
58
|
+
/** How the OpenSeadragon backend should source this image.
|
|
59
|
+
* - `true`/absent (default): server-tiled — OSD polls `/tiles/info` for a
|
|
60
|
+
* pyramid and fetches tiles from the slide-crop server (whole-slide path).
|
|
61
|
+
* - `false`: a self-contained, directly-loadable image — `urls[zIndex]` is a
|
|
62
|
+
* complete image (e.g. a `blob:` URL built from a client-side pixel buffer),
|
|
63
|
+
* opened via OSD's single-image source with no tile server. Lets in-memory
|
|
64
|
+
* images (the processing pipeline) use the OSD viewer without a round-trip. */
|
|
65
|
+
tiled?: boolean;
|
|
66
|
+
/** One-shot hint: open the stack on this slice instead of slice 0 (e.g. the
|
|
67
|
+
* host clicked a specific file within a numbered image series). The
|
|
68
|
+
* component consumes and clears this the first time it sees the object, so
|
|
69
|
+
* re-delivering the same ImageInfo (e.g. a plot-type switch) doesn't reset
|
|
70
|
+
* the user's current scrub position. */
|
|
71
|
+
initialZIndex?: number;
|
|
72
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IHistogram } from './channel-histogram-api.contract';
|
|
2
|
+
/**
|
|
3
|
+
* Shared intensity helpers (refactoring plan, Step 5). The two backends use
|
|
4
|
+
* two DIFFERENT scalar projections by design — do not unify them:
|
|
5
|
+
* - Plotly projects `[r,g,b]` frame cells with ITU-R BT.601 luminance (matches
|
|
6
|
+
* what its heatmap has always rendered);
|
|
7
|
+
* - the OSD tile path takes the max of the decoded RGBA channels (single-band
|
|
8
|
+
* tiles encode gray as r=g=b, so max is exact; it also tolerates tinted
|
|
9
|
+
* pixels).
|
|
10
|
+
*/
|
|
11
|
+
/** ITU-R BT.601 luminance for an RGB pixel (Plotly's scalar projection). */
|
|
12
|
+
export declare function bt601Luminance(r: number, g: number, b: number): number;
|
|
13
|
+
/** Max of the three channels (the OSD tile path's scalar projection).
|
|
14
|
+
* NOTE: the per-pixel recolor loop in `osd/display-pipeline.ts` keeps this
|
|
15
|
+
* inlined on purpose — it runs ~262k times per tile. */
|
|
16
|
+
export declare function maxRgb(r: number, g: number, b: number): number;
|
|
17
|
+
/** Wrap 256 raw bin counts as an IHistogram (0..255 left edges + max). */
|
|
18
|
+
export declare function histogram256(counts: number[]): IHistogram;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind of rendering a viewer backend should produce for the loaded data.
|
|
3
|
+
*
|
|
4
|
+
* Lives in `contracts/` (rather than inside a specific backend) because it is
|
|
5
|
+
* part of the backend-neutral plotting contract: both the Plotly backend and
|
|
6
|
+
* any future backend (e.g. OpenSeadragon) accept a `PlotType` on `plot()`.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: a backend may not support every type — 3D types (`SURFACE`,
|
|
9
|
+
* `SCATTER3D`, `ISOSURFACE`) are gated behind `ViewerFeature.Surface3D` in the
|
|
10
|
+
* capabilities contract, so a 2D-only backend can advertise that it can't
|
|
11
|
+
* render them and the UI can hide the option.
|
|
12
|
+
*/
|
|
13
|
+
export declare enum PlotType {
|
|
14
|
+
/** Natively-tiled, zoomable raster rendered by OpenSeadragon (the default
|
|
15
|
+
* view for an image). Heatmap remains the Plotly scalar-image rendering. */
|
|
16
|
+
IMAGE = "image",
|
|
17
|
+
HEATMAP = "heatmap",
|
|
18
|
+
SURFACE = "surface",
|
|
19
|
+
CONTOUR = "contour",
|
|
20
|
+
SCATTER = "scatter",
|
|
21
|
+
LINE = "line",
|
|
22
|
+
SCATTER3D = "scatter3d",
|
|
23
|
+
ISOSURFACE = "isosurface",
|
|
24
|
+
/** WebGPU napari-js renderings (jit-ui#102), selectable alongside the OSD/Plotly types. The 3D
|
|
25
|
+
* types take a runtime decimate factor (Full / ½ / ¼ / ⅛) instead of fixed hi/lo-res variants. */
|
|
26
|
+
NAPARI_IMAGE = "napari-image",
|
|
27
|
+
NAPARI_VOLUME = "napari-volume",
|
|
28
|
+
NAPARI_ISOSURFACE = "napari-isosurface",
|
|
29
|
+
/** WebGPU height-field surface mesh (z = intensity), the napari-js analog of Plotly SURFACE. */
|
|
30
|
+
NAPARI_SURFACE = "napari-surface",
|
|
31
|
+
/** WebGPU 2D scatter of region centroids (napari-js analog of Plotly SCATTER). */
|
|
32
|
+
NAPARI_SCATTER = "napari-scatter",
|
|
33
|
+
/** WebGPU 3D scatter of the downsampled voxel cloud (napari-js analog of Plotly SCATTER3D). */
|
|
34
|
+
NAPARI_SCATTER3D = "napari-scatter3d"
|
|
35
|
+
}
|
|
36
|
+
/** How many spatial dimensions a plot type renders in. */
|
|
37
|
+
export type PlotDimensions = '2d' | '3d';
|
|
38
|
+
/**
|
|
39
|
+
* Where a plot type pulls its data from:
|
|
40
|
+
* - `image` — the loaded pixel matrices / z-stack (HEATMAP, SURFACE, …)
|
|
41
|
+
* - `regions` — the drawn/derived regions (SCATTER of region centroids, …)
|
|
42
|
+
*/
|
|
43
|
+
export type PlotDataSource = 'image' | 'regions';
|
|
44
|
+
/**
|
|
45
|
+
* Backend-neutral metadata about a plot type. Drives UI affordances (which
|
|
46
|
+
* types are 3D, which need an image stack, how to label them in a dropdown)
|
|
47
|
+
* without any backend's trace-building logic leaking into the contract.
|
|
48
|
+
*/
|
|
49
|
+
export interface PlotTypeDescriptor {
|
|
50
|
+
type: PlotType;
|
|
51
|
+
/** Human-readable label for menus/dropdowns. Shown in **test mode**, where
|
|
52
|
+
* every backend's type is offered, so it carries the backend suffix (e.g.
|
|
53
|
+
* "Surface (napari · WebGPU)") to disambiguate same-named modes. */
|
|
54
|
+
label: string;
|
|
55
|
+
/**
|
|
56
|
+
* Label shown in the **default (non-test) selector**, where a single curated
|
|
57
|
+
* mode owns each name — so it drops the backend suffix (e.g. just "Surface").
|
|
58
|
+
* A type WITHOUT a `productionLabel` is **test-only**: hidden from the default
|
|
59
|
+
* selector and shown only when the host enables test mode. This is the single
|
|
60
|
+
* knob that curates the default plot-mode list (jax-image-visualization).
|
|
61
|
+
*/
|
|
62
|
+
productionLabel?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Icon shown to the left of the label in the plot-type selector. Either a
|
|
65
|
+
* PrimeNG icon class (starts with `pi `, e.g. `pi pi-image`) rendered as a
|
|
66
|
+
* font glyph, or a served SVG asset path (e.g. `assets/plotting/surface.svg`)
|
|
67
|
+
* rendered as an `<img>`. Both are tinted to the toolbar's primary blue.
|
|
68
|
+
*/
|
|
69
|
+
icon?: string;
|
|
70
|
+
dimensions: PlotDimensions;
|
|
71
|
+
source: PlotDataSource;
|
|
72
|
+
/** True when the type only makes sense over a multi-frame z-stack. */
|
|
73
|
+
requiresStack?: boolean;
|
|
74
|
+
/** True when the type maps a single scalar intensity per pixel (contour,
|
|
75
|
+
* surface, intensity profile, isosurface) — only meaningful for grayscale.
|
|
76
|
+
* Image/Heatmap render RGB fine; Scatter uses regions. */
|
|
77
|
+
requiresGrayscale?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Single source of truth for plot-type metadata. LINE is intentionally absent —
|
|
81
|
+
* intensity profiles are now Region-based line ROIs (available in Heatmap/Image
|
|
82
|
+
* mode), so LINE is no longer offered in the selector (the enum member is kept
|
|
83
|
+
* for future use). Hence the `Partial` record.
|
|
84
|
+
*/
|
|
85
|
+
export declare const PLOT_TYPE_DESCRIPTORS: Partial<Record<PlotType, PlotTypeDescriptor>>;
|
|
86
|
+
export declare function getPlotTypeDescriptor(type: PlotType): PlotTypeDescriptor | undefined;
|
|
87
|
+
export declare function isThreeDimensional(type: PlotType): boolean;
|
|
88
|
+
/** napari-js volume. */
|
|
89
|
+
export declare function isNapariVolume(type: PlotType): boolean;
|
|
90
|
+
/** napari-js isosurface. */
|
|
91
|
+
export declare function isNapariIsosurface(type: PlotType): boolean;
|
|
92
|
+
/** napari-js height-field surface mesh. */
|
|
93
|
+
export declare function isNapariSurface(type: PlotType): boolean;
|
|
94
|
+
/** napari-js 2D scatter (region centroids). */
|
|
95
|
+
export declare function isNapariScatter(type: PlotType): boolean;
|
|
96
|
+
/** napari-js 3D scatter (voxel point cloud). */
|
|
97
|
+
export declare function isNapariScatter3d(type: PlotType): boolean;
|
|
98
|
+
/** Any napari-js 3D plot type (volume, isosurface, surface, or 3D scatter). Resolution is a runtime
|
|
99
|
+
* decimate factor (Full / ½ / ¼ / ⅛) — see the service's `resolutionScale`. */
|
|
100
|
+
export declare function isNapari3d(type: PlotType): boolean;
|
|
101
|
+
/** Decimate factors offered by the Resolution control (1 = Full … 8 = ⅛). */
|
|
102
|
+
export declare const NAPARI_DECIMATE_OPTIONS: {
|
|
103
|
+
label: string;
|
|
104
|
+
value: number;
|
|
105
|
+
}[];
|
|
106
|
+
/** Default decimate factor: ¼. The caps are set so ¼ is a sensible default resolution while ½ and
|
|
107
|
+
* Full offer 2× and 4× the detail for opt-in high-resolution renders. */
|
|
108
|
+
export declare const NAPARI_DEFAULT_DECIMATE = 4;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { IImageInfo } from '../image.contract';
|
|
4
|
+
/**
|
|
5
|
+
* Host image/loading/zoom state, inverted as a port so the visualization library
|
|
6
|
+
* doesn't import the app's `MainState`/`MainFacade`. The host supplies an adapter
|
|
7
|
+
* that delegates to those. Read methods return the host's live streams; write
|
|
8
|
+
* methods push state back to the host (e.g. loading flags, the updated image).
|
|
9
|
+
*/
|
|
10
|
+
export interface ImageStatePort {
|
|
11
|
+
getFilename$(): Observable<string | undefined>;
|
|
12
|
+
isImageCached$(): Observable<boolean>;
|
|
13
|
+
getImageInfo$(): Observable<IImageInfo | null>;
|
|
14
|
+
getImageLoadingMessage$(): Observable<string>;
|
|
15
|
+
getCacheProgress$(): Observable<number | null>;
|
|
16
|
+
getPanelWidth$(): Observable<number>;
|
|
17
|
+
isImageLoading$(): Observable<boolean>;
|
|
18
|
+
isZoom$(): Observable<boolean>;
|
|
19
|
+
/** Push an updated image descriptor to the host (partial — only set fields). */
|
|
20
|
+
setImageInfo(info: Partial<IImageInfo>): void;
|
|
21
|
+
setImageLoading(loading: boolean): void;
|
|
22
|
+
setImageLoadingMessage(message: string): void;
|
|
23
|
+
setZoom(zoom: boolean): void;
|
|
24
|
+
setImageCached(cached: boolean): void;
|
|
25
|
+
setLoadingError(error: boolean): void;
|
|
26
|
+
/** Register the active diagram/visualization component with the host. */
|
|
27
|
+
setDiagram(diagram: unknown): void;
|
|
28
|
+
}
|
|
29
|
+
export declare const IMAGE_STATE_PORT: InjectionToken<ImageStatePort>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { PresetSet } from '../../models/class-preset';
|
|
4
|
+
/**
|
|
5
|
+
* Port for persisting the per-user annotation-class preset set (jit-ui#70).
|
|
6
|
+
*
|
|
7
|
+
* The library defines the contract; the app supplies an adapter that talks to the
|
|
8
|
+
* jit-service `/api/preferences/annotation-classes` endpoint. The user is keyed
|
|
9
|
+
* server-side from the authenticated JWT, so no user id is passed here.
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `RegionIoPort` / `REGION_IO_PORT`.
|
|
12
|
+
*/
|
|
13
|
+
export interface PreferencesPort {
|
|
14
|
+
/** Load the current user's preset set; resolves to `null` if none has been saved yet. */
|
|
15
|
+
loadPresetSet(): Observable<PresetSet | null>;
|
|
16
|
+
/** Persist (upsert) the current user's preset set. */
|
|
17
|
+
savePresetSet(set: PresetSet): Observable<void>;
|
|
18
|
+
}
|
|
19
|
+
export declare const PREFERENCES_PORT: InjectionToken<PreferencesPort>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* Region file I/O, inverted as a port so the visualization library's region
|
|
5
|
+
* editor doesn't import the app's `FilesService` (the library performs no backend
|
|
6
|
+
* requests itself). The host supplies an adapter that delegates to its file
|
|
7
|
+
* service; the editor only needs the selected file's name (to derive default ROI
|
|
8
|
+
* filenames), an existence check, and a save. Bound to {@link REGION_IO_PORT}.
|
|
9
|
+
*/
|
|
10
|
+
export interface RegionIoPort {
|
|
11
|
+
/** Name of the currently selected file (e.g. "image.tif"), or undefined when
|
|
12
|
+
* none is selected. Used to derive a default ROI filename stem. */
|
|
13
|
+
getSelectedFileName(): string | undefined;
|
|
14
|
+
/** Whether an ROI file named `name` already exists for the selected file. */
|
|
15
|
+
roiFileExists(name: string): Observable<boolean>;
|
|
16
|
+
/** Persist the regions (already serialized to a GeoJSON string) as `filename`. */
|
|
17
|
+
saveGeoJson(geoJsonStr: string, filename: string): Observable<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Persist a folder-stack's regions as one geojson per slice-file (jit-ui#93).
|
|
20
|
+
* Each entry's `z` is the zero-based slice index; the host maps it to that
|
|
21
|
+
* slice-file's sibling `<stem>.geojson` in the same folder. Completes once
|
|
22
|
+
* every slice has been written. (jit-ui#93)
|
|
23
|
+
*/
|
|
24
|
+
saveSliceGeoJsons(slices: {
|
|
25
|
+
z: number;
|
|
26
|
+
geoJsonStr: string;
|
|
27
|
+
}[]): Observable<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare const REGION_IO_PORT: InjectionToken<RegionIoPort>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { Rectangle } from '../../models/region';
|
|
4
|
+
/**
|
|
5
|
+
* File/tile/zoom backend, inverted as a port so the visualization library doesn't
|
|
6
|
+
* import the app's `FilesService` (nor its `ZoomRequest`/`DisplayType` request
|
|
7
|
+
* models). The host supplies an adapter that builds the concrete request from
|
|
8
|
+
* these library-native arguments and the currently-selected file.
|
|
9
|
+
*/
|
|
10
|
+
export interface TileAccessPort {
|
|
11
|
+
/** Base64-encoded info for the currently-selected file (used for `/tile` and
|
|
12
|
+
* `/tiles/info` requests), or null when nothing is selected. Collapses the
|
|
13
|
+
* host's `getSelectedFileInfo()` + `encode(rawData)`. */
|
|
14
|
+
getSelectedInfoB64(): string | null;
|
|
15
|
+
/** Server-side crop/zoom of the current image to `roi`; resolves to raw image
|
|
16
|
+
* bytes. `screen` is the on-screen diagram rectangle. The host builds the
|
|
17
|
+
* request (including the selected file) internally. */
|
|
18
|
+
zoomOnRegion(roi: Rectangle, screen: Rectangle, zIndex: number): Observable<ArrayBuffer>;
|
|
19
|
+
/** Switch the host's display back to the diagram view (replaces the app's
|
|
20
|
+
* `selectDisplayType(DisplayType.Diagram)`). */
|
|
21
|
+
selectDiagramDisplay(): void;
|
|
22
|
+
/** Auth headers (e.g. `Authorization: Bearer …`) for OSD's own tile fetches
|
|
23
|
+
* (its AJAX loader + prefetch bypass Angular's HttpClient interceptor, so the
|
|
24
|
+
* host supplies them). Hides the app's Auth0 dependency from the library. */
|
|
25
|
+
getAuthHeaders(): Promise<Record<string, string>>;
|
|
26
|
+
}
|
|
27
|
+
export declare const TILE_ACCESS_PORT: InjectionToken<TileAccessPort>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { Region } from '../models/region';
|
|
4
|
+
import { ClassPreset, PresetSet } from '../models/class-preset';
|
|
5
|
+
import { IImageMetadata } from './image.contract';
|
|
6
|
+
/**
|
|
7
|
+
* Public, implementation-agnostic surface that the Region Editor (an *external*
|
|
8
|
+
* consumer of the visualization package) depends on. It deals only in
|
|
9
|
+
* **annotation** regions — intensity-profile lines (`Region.isProfile()`) are
|
|
10
|
+
* owned by the intensity tool and are filtered out / preserved internally, so
|
|
11
|
+
* the editor never sees or disturbs them.
|
|
12
|
+
*
|
|
13
|
+
* The editor injects this via {@link REGION_EDITOR_API} (bound to the concrete
|
|
14
|
+
* `RoutingVisualizerService` with `useExisting`) instead of importing the
|
|
15
|
+
* service class, so it cannot reach the implementation. This is the boundary
|
|
16
|
+
* that lets `services/visualization` become a library whose only public surface
|
|
17
|
+
* is the contracts.
|
|
18
|
+
*
|
|
19
|
+
* Selection is expressed in terms of {@link Region}s, not array indices — the
|
|
20
|
+
* index space (which includes profile lines) stays internal to the package.
|
|
21
|
+
*/
|
|
22
|
+
export interface IRegionEditorApi {
|
|
23
|
+
getShowShapeLabel(): boolean;
|
|
24
|
+
getShapeColor(): string;
|
|
25
|
+
getFillColor(): string;
|
|
26
|
+
/** Annotation regions for the current image. Intensity-profile lines are
|
|
27
|
+
* never included. */
|
|
28
|
+
getAnnotationRegions(): Region[];
|
|
29
|
+
/** Replace the annotation regions. Intensity-profile lines in the store are
|
|
30
|
+
* preserved (the editor must not be able to drop them). */
|
|
31
|
+
setAnnotationRegions(regions: Region[], showRegionLabel?: boolean, isRegionSaveOn?: boolean, fillColor?: string): void;
|
|
32
|
+
/** Change signal — fires whenever regions change on any backend. */
|
|
33
|
+
getRegionUpdateEvent(): Observable<any[]>;
|
|
34
|
+
/** The currently-selected annotation regions (profile lines never appear). */
|
|
35
|
+
getSelectedRegions$(): Observable<Region[]>;
|
|
36
|
+
/** Set the selection to these regions. */
|
|
37
|
+
setSelectedRegions(regions: Region[]): void;
|
|
38
|
+
getClassificationColors(): Map<string, string>;
|
|
39
|
+
setClassificationColor(label: string, color: string): void;
|
|
40
|
+
/** The current per-user preset set (source of truth for region colours). */
|
|
41
|
+
getPresetSet(): PresetSet;
|
|
42
|
+
/** Emits the preset set on every change (BehaviorSubject-backed). */
|
|
43
|
+
getPresetSet$(): Observable<PresetSet>;
|
|
44
|
+
/** Replace the whole preset set (persists per-user). */
|
|
45
|
+
setPresetSet(set: PresetSet): void;
|
|
46
|
+
/** Add or update one class by name (persists). */
|
|
47
|
+
upsertClass(preset: ClassPreset): void;
|
|
48
|
+
/** Remove a class by name (persists). */
|
|
49
|
+
removeClass(name: string): void;
|
|
50
|
+
/** Restore the default preset set (persists). */
|
|
51
|
+
resetPresets(): void;
|
|
52
|
+
getImageMeta(): Observable<IImageMetadata[]>;
|
|
53
|
+
importRegions(geoJsonStr: string): Region[];
|
|
54
|
+
getGeoJsonString(regions: Region[]): string;
|
|
55
|
+
/** True while a per-slice z-stack region session is active — the editor then
|
|
56
|
+
* saves/edits regions per displayed slice. */
|
|
57
|
+
isStackMode(): boolean;
|
|
58
|
+
/** How the current stack persists: `combined` = one z-indexed geojson
|
|
59
|
+
* (single-file z-stack, QuPath schema); `per-slice-file` = one geojson per
|
|
60
|
+
* slice-file (folder stack). */
|
|
61
|
+
getStackSaveLayout(): 'combined' | 'per-slice-file';
|
|
62
|
+
/** Every slice's annotation regions (profile lines excluded), each tagged
|
|
63
|
+
* with its zero-based {@link Region.z}, for a combined z-indexed save. */
|
|
64
|
+
getSliceAnnotationRegions(): Region[];
|
|
65
|
+
/** Per-slice annotation regions for a folder-stack (`per-slice-file`) save:
|
|
66
|
+
* zero-based slice index → that slice's annotation regions. Includes
|
|
67
|
+
* now-empty slices loaded non-empty, so their file is overwritten empty. */
|
|
68
|
+
getStackSaveAnnotationSlices(): Map<number, Region[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Full-resolution image size (image-pixel dimensions) used to size an exported
|
|
71
|
+
* region mask. Backend-neutral: prefers the active renderer's reported size
|
|
72
|
+
* and falls back to the image metadata. Returns null when no size is known.
|
|
73
|
+
*
|
|
74
|
+
* The mask itself is rasterized off the main thread (see the Region Editor's
|
|
75
|
+
* mask worker) from the region geometry and this size.
|
|
76
|
+
*/
|
|
77
|
+
getMaskImageSize(): {
|
|
78
|
+
width: number;
|
|
79
|
+
height: number;
|
|
80
|
+
} | null;
|
|
81
|
+
}
|
|
82
|
+
/** DI token the Region Editor injects instead of the concrete service. */
|
|
83
|
+
export declare const REGION_EDITOR_API: InjectionToken<IRegionEditorApi>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Region *rendering* abstraction — distinct from `IRegionStore` (which owns the
|
|
3
|
+
* region data/state, shared across backends). An `IRegionOverlay` draws the
|
|
4
|
+
* store's regions on a specific backend's canvas and handles draw/select
|
|
5
|
+
* interaction:
|
|
6
|
+
*
|
|
7
|
+
* - `PlotlyRegionOverlay` — Plotly renders regions natively as plot shapes and
|
|
8
|
+
* edits them via its own drag modes, so its adapter is thin (maps the mode
|
|
9
|
+
* onto Plotly drag modes; redraw is a no-op).
|
|
10
|
+
* - `OsdRegionOverlay` — OpenSeadragon shows pre-rendered tiles, so regions are
|
|
11
|
+
* drawn on an SVG layer kept aligned to the viewport, with custom draw/select.
|
|
12
|
+
*
|
|
13
|
+
* Both read the same `IRegionStore`, so regions stay in sync regardless of which
|
|
14
|
+
* backend is rendering the image.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Region interaction modes.
|
|
18
|
+
*
|
|
19
|
+
* - `none` — display only; backend navigation (OSD pan/zoom) is live.
|
|
20
|
+
* - `select` — click to select; on OSD also drag a vertex / resize a
|
|
21
|
+
* rectangle / move the region body.
|
|
22
|
+
* - `drawrect` — press-drag-release a rectangle.
|
|
23
|
+
* - `drawclosedpath`— freehand closed polygon (press-drag-release).
|
|
24
|
+
* - `drawopenpath` — freehand open polyline (press-drag-release).
|
|
25
|
+
*
|
|
26
|
+
* Vertex-editing tools (OSD only; Plotly maps them to no-op):
|
|
27
|
+
* - `drawpolygon` — click to place each vertex; click the first vertex (or
|
|
28
|
+
* double-click) to close.
|
|
29
|
+
* - `addpoint` — click an edge of the selected polygon to insert a vertex.
|
|
30
|
+
* - `deletepoint` — click a vertex of the selected polygon to remove it.
|
|
31
|
+
* - `move` — drag the selected region body to translate it.
|
|
32
|
+
*/
|
|
33
|
+
export type RegionToolMode = 'none' | 'select' | 'drawrect' | 'drawclosedpath' | 'drawopenpath' | 'drawpolygon' | 'addpoint' | 'deletepoint' | 'move';
|
|
34
|
+
export interface IRegionOverlay {
|
|
35
|
+
/** Set the active draw/select interaction (or 'none' to just display). */
|
|
36
|
+
setMode(mode: RegionToolMode): void;
|
|
37
|
+
/** Re-render the regions (e.g. after the store changes or the view moves). */
|
|
38
|
+
redraw(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Convert the selected region(s) to/from a bezier curve (toBezier /
|
|
41
|
+
* toPolygon). A one-shot action, not a mode. No-op on backends
|
|
42
|
+
* that don't render beziers (Plotly).
|
|
43
|
+
*/
|
|
44
|
+
setSelectedBezier(bezier: boolean): void;
|
|
45
|
+
/** Detach handlers/DOM and stop listening to the store. */
|
|
46
|
+
destroy(): void;
|
|
47
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Rectangle, Polygon, MultiPolygon } from '../models/region';
|
|
2
|
+
import { Region } from '../models/region';
|
|
3
|
+
/**
|
|
4
|
+
* Region-native editing surface — typed geometry operations on the neutral
|
|
5
|
+
* {@link Region} model. The OpenSeadragon overlay (and any future editing UI)
|
|
6
|
+
* mutates regions through these calls instead of reaching into a backend's
|
|
7
|
+
* own shape representation (e.g. Plotly's `x0/y0/x1/y1` / `M…L…Z` dicts).
|
|
8
|
+
*
|
|
9
|
+
* Implemented by the shared `RegionStore`, which owns region *state*; backends
|
|
10
|
+
* own *rendering* and react to the store's update event. This replaces the
|
|
11
|
+
* Plotly-shaped `IRegionEditStore` (getShapes/applyShapesChange) the OSD
|
|
12
|
+
* overlay used to depend on.
|
|
13
|
+
*
|
|
14
|
+
* Coordinates are always **image pixels**. Vertex operations apply to polygon
|
|
15
|
+
* regions only; calling them on a rectangle (or with an out-of-range id/index)
|
|
16
|
+
* is a no-op.
|
|
17
|
+
*/
|
|
18
|
+
export interface IRegionEditApi {
|
|
19
|
+
/** Add a region to the current image, mint its id, select it, and emit.
|
|
20
|
+
* Returns the assigned id. */
|
|
21
|
+
addRegion(region: Region): number;
|
|
22
|
+
/** Remove the region with this id (and drop it from the selection). */
|
|
23
|
+
removeRegion(id: number): void;
|
|
24
|
+
/** Replace a region's geometry wholesale (e.g. after a rectangle resize). */
|
|
25
|
+
updateBounds(id: number, bounds: Rectangle | Polygon | MultiPolygon): void;
|
|
26
|
+
/** Translate the whole region by (dx, dy) image pixels. */
|
|
27
|
+
moveRegion(id: number, dx: number, dy: number): void;
|
|
28
|
+
/** Move a single polygon vertex to (x, y). No-op for rectangles. */
|
|
29
|
+
moveVertex(id: number, index: number, x: number, y: number): void;
|
|
30
|
+
/** Move a single vertex on interior ring `holeIndex` (a hole) to (x, y).
|
|
31
|
+
* No-op for rectangles, or an out-of-range hole/vertex index (jit-ui#85). */
|
|
32
|
+
moveHoleVertex(id: number, holeIndex: number, index: number, x: number, y: number): void;
|
|
33
|
+
/** Insert a vertex on interior ring `holeIndex` after `segIndex` (jit-ui#85). */
|
|
34
|
+
addHoleVertex(id: number, holeIndex: number, segIndex: number, x: number, y: number): void;
|
|
35
|
+
/** Delete the vertex at `index` on interior ring `holeIndex`; dropping the
|
|
36
|
+
* ring below 3 vertices removes the whole hole (jit-ui#85). */
|
|
37
|
+
deleteHoleVertex(id: number, holeIndex: number, index: number): void;
|
|
38
|
+
/** Insert a vertex at (x, y) immediately after `segIndex` (the start vertex
|
|
39
|
+
* of the edge the point lies on). No-op for rectangles. */
|
|
40
|
+
addVertex(id: number, segIndex: number, x: number, y: number): void;
|
|
41
|
+
/** Delete the vertex at `index`. No-op for rectangles, or when removing it
|
|
42
|
+
* would drop the polygon below its minimum (3 closed / 2 open). */
|
|
43
|
+
deleteVertex(id: number, index: number): void;
|
|
44
|
+
/**
|
|
45
|
+
* Toggle the bezier-curve flag on a region (toBezier = `true`,
|
|
46
|
+
* toPolygon = `false`). The vertices stay put — only the smooth-curve
|
|
47
|
+
* rendering/export is added or removed. A rectangle is first converted to a
|
|
48
|
+
* 4-anchor closed polygon when smoothing; turning bezier off on a rectangle
|
|
49
|
+
* is a no-op.
|
|
50
|
+
*/
|
|
51
|
+
setBezier(id: number, bezier: boolean): void;
|
|
52
|
+
/**
|
|
53
|
+
* Move one of a bezier vertex's two cubic control handles to absolute point
|
|
54
|
+
* (x, y). `side` is the in- or out-handle. No-op unless the region is a bezier
|
|
55
|
+
* polygon. The handle is stored relative to its anchor, so it follows the
|
|
56
|
+
* anchor when the vertex is moved.
|
|
57
|
+
*/
|
|
58
|
+
moveBezierHandle(id: number, index: number, side: 'in' | 'out', x: number, y: number): void;
|
|
59
|
+
/**
|
|
60
|
+
* Move a bezier control handle on an interior ring (donut hole) — like
|
|
61
|
+
* {@link moveBezierHandle} but for `holes[holeIndex]`. No-op unless the region is a bezier
|
|
62
|
+
* polygon with hole handles (jit-ui#102).
|
|
63
|
+
*/
|
|
64
|
+
moveHoleBezierHandle(id: number, holeIndex: number, index: number, side: 'in' | 'out', x: number, y: number): void;
|
|
65
|
+
/**
|
|
66
|
+
* Coalesce the emits from a burst of edits (e.g. a live vertex drag) into a
|
|
67
|
+
* single update on `endBatch`. Calls nest; the update fires when the
|
|
68
|
+
* outermost batch closes. The overlay still redraws itself per frame — this
|
|
69
|
+
* only throttles the store's `regionUpdate$` so downstream consumers (the
|
|
70
|
+
* Region Editor table) update once per gesture, not once per pointer move.
|
|
71
|
+
*/
|
|
72
|
+
beginBatch(): void;
|
|
73
|
+
endBatch(): void;
|
|
74
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contracts for the client-side, promptable Segment Anything (SAM) tooling
|
|
3
|
+
* (jit-ui#90). A SAM model is a promptable encoder/decoder ONNX pair: the heavy
|
|
4
|
+
* encoder runs once per image (its embedding is cached), and the light decoder
|
|
5
|
+
* runs per prompt (box/points) to produce a mask.
|
|
6
|
+
*
|
|
7
|
+
* The inference backend is abstracted behind {@link ISamSession} so the tool
|
|
8
|
+
* (SamToolService) is testable with a fake and so different runtimes (an
|
|
9
|
+
* onnxruntime-web session today, a worker-backed one later) can be swapped in.
|
|
10
|
+
*/
|
|
11
|
+
/** A promptable SAM model: a quantized encoder + decoder ONNX pair. */
|
|
12
|
+
export interface SamModelDef {
|
|
13
|
+
/** Stable id used by the registry (e.g. 'microsam-vit-b-lm'). */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Human label for a model picker. */
|
|
16
|
+
label: string;
|
|
17
|
+
/** Encoder ONNX URL (image → image embedding). Empty until hosted. */
|
|
18
|
+
encoderUrl: string;
|
|
19
|
+
/** Decoder ONNX URL (embedding + prompts → mask). Empty until hosted. */
|
|
20
|
+
decoderUrl: string;
|
|
21
|
+
/** Decoder I/O family — SAM v1 vs v2/v3 differ in mask output size + names. */
|
|
22
|
+
variant: 'sam1' | 'sam2' | 'sam3';
|
|
23
|
+
/** Encoder input side length (1024 for SAM v1). */
|
|
24
|
+
inputSize: number;
|
|
25
|
+
/** True for microscopy-finetuned checkpoints (micro-sam, pathoSAM). */
|
|
26
|
+
microscopy?: boolean;
|
|
27
|
+
/** Override the onnxruntime-web execution providers for the ENCODER session
|
|
28
|
+
* (decoder is always WASM). Defaults to WebGPU-with-WASM-fallback. Set to
|
|
29
|
+
* `['wasm']` for architectures whose fp16 attention overflows on the WebGPU
|
|
30
|
+
* EP and returns an empty mask (e.g. micro-sam ViT-T's TinyViT encoder),
|
|
31
|
+
* which run correctly — and fast, when small — on WASM. */
|
|
32
|
+
encoderProviders?: string[];
|
|
33
|
+
/** Run inference in-process on the main thread instead of the SAM Web Worker.
|
|
34
|
+
* Only valid for small WASM-only models (e.g. micro-sam ViT-T) where the
|
|
35
|
+
* worker's spawn + second-ORT-runtime + message overhead outweighs its
|
|
36
|
+
* off-thread benefit. WebGPU models ignore this (they must stay in the
|
|
37
|
+
* worker to avoid freezing the tab). */
|
|
38
|
+
inProcess?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Cached encoder output for one image (reused across every prompt on it). */
|
|
41
|
+
export interface SamEmbedding {
|
|
42
|
+
/** Flattened embedding tensor, shape `dims`. */
|
|
43
|
+
data: Float32Array;
|
|
44
|
+
/** Embedding tensor dims, e.g. [1, 256, 64, 64]. */
|
|
45
|
+
dims: number[];
|
|
46
|
+
/** `inputSize / max(imageWidth, imageHeight)` — scales prompt coords. */
|
|
47
|
+
scale: number;
|
|
48
|
+
/** Image (matrix) size the embedding was computed for. */
|
|
49
|
+
imageWidth: number;
|
|
50
|
+
imageHeight: number;
|
|
51
|
+
/** Opaque handle to the embedding cached inside the inference Web Worker, when
|
|
52
|
+
* the session runs off-thread. `decode` passes it back so the worker reuses
|
|
53
|
+
* the cached tensor instead of round-tripping the (multi-MB) embedding data;
|
|
54
|
+
* `data` is then an empty placeholder. Absent for in-process/fake sessions. */
|
|
55
|
+
token?: number;
|
|
56
|
+
}
|
|
57
|
+
/** A prompt for one object, in image (matrix) pixel coordinates. */
|
|
58
|
+
export interface SamPrompt {
|
|
59
|
+
/** Box prompt `[x0,y0,x1,y1]` (issue #90's primary affordance). */
|
|
60
|
+
box?: {
|
|
61
|
+
x0: number;
|
|
62
|
+
y0: number;
|
|
63
|
+
x1: number;
|
|
64
|
+
y1: number;
|
|
65
|
+
};
|
|
66
|
+
/** Point prompts; `label` 1 = positive (include), 0 = negative (exclude). */
|
|
67
|
+
points?: {
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
label: 0 | 1;
|
|
71
|
+
}[];
|
|
72
|
+
}
|
|
73
|
+
/** A decoded mask, binary (0/1), at image (matrix) resolution. */
|
|
74
|
+
export interface SamMaskResult {
|
|
75
|
+
mask: Uint8Array;
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
/** Model-predicted IoU quality score for the chosen mask. */
|
|
79
|
+
iou: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Promptable-SAM inference backend. Lifecycle: `loadModel` once, `embed` once
|
|
83
|
+
* per image, `decode` per prompt.
|
|
84
|
+
*/
|
|
85
|
+
export interface ISamSession {
|
|
86
|
+
/** Load the model; `onProgress` reports encoder-download fraction (0..1). */
|
|
87
|
+
loadModel(model: SamModelDef, onProgress?: (fraction: number) => void): Promise<void>;
|
|
88
|
+
isLoaded(): boolean;
|
|
89
|
+
/** Run the encoder on an RGBA image; returns a cacheable embedding. */
|
|
90
|
+
embed(image: {
|
|
91
|
+
data: Uint8ClampedArray;
|
|
92
|
+
width: number;
|
|
93
|
+
height: number;
|
|
94
|
+
}): Promise<SamEmbedding>;
|
|
95
|
+
/** Run the decoder for one prompt against a cached embedding. */
|
|
96
|
+
decode(embedding: SamEmbedding, prompt: SamPrompt): Promise<SamMaskResult>;
|
|
97
|
+
dispose(): void;
|
|
98
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which groups of controls the visualization toolbar shows. All default to `true`
|
|
3
|
+
* (the full toolbar); a consumer embedding `<visualizer>` can hide groups
|
|
4
|
+
* it doesn't want via the `toolbarTools` input — e.g. the processing pipeline shows
|
|
5
|
+
* only the zoom and region tools.
|
|
6
|
+
*
|
|
7
|
+
* Groups not listed here (stack navigation, 3D-scene controls, isosurface band) are
|
|
8
|
+
* already shown only when the image/plot type calls for them, so a single 8-bit
|
|
9
|
+
* image never surfaces them regardless of these flags.
|
|
10
|
+
*/
|
|
11
|
+
export interface ToolbarToolVisibility {
|
|
12
|
+
/** Plot-type selector, intensity-profile line, Channels & Histogram, download,
|
|
13
|
+
* and fit-to-view (autoscale) — everything that isn't a zoom or region tool. */
|
|
14
|
+
specialTools?: boolean;
|
|
15
|
+
/** Zoom drag, zoom box, pan, zoom in, zoom out. */
|
|
16
|
+
zoomTools?: boolean;
|
|
17
|
+
/** Region drawing/editing: select, rectangle, polyline, freeform, polygon vertex
|
|
18
|
+
* editing, wand, vertex eraser, delete, Bézier/polygon conversion. */
|
|
19
|
+
regionTools?: boolean;
|
|
20
|
+
/** The Help button and its dialog. */
|
|
21
|
+
help?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** Full toolbar — the default when no `toolbarTools` is supplied. */
|
|
24
|
+
export declare const ALL_TOOLBAR_TOOLS: Required<ToolbarToolVisibility>;
|