@jax-data-science/sci-image-visualizer 0.16.0 → 0.18.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/esm2022/lib/contracts/display-types.mjs +4 -2
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +1 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +1 -1
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/geometry/cell-meshes.mjs +37 -0
- package/esm2022/lib/geometry/place.mjs +47 -0
- package/esm2022/lib/implementations/napari-js/napari-camera-depth.mjs +93 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +2 -2
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +86 -18
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-cells.mjs +746 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +343 -18
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-transcripts.mjs +427 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-encoding.mjs +11 -4
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +95 -5
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +15 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +35 -8
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +40 -1
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +136 -28
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +19 -3
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +188 -52
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +35 -11
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +2 -2
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +10 -1
- package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +30 -3
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +15 -3
- package/esm2022/lib/region-editor/region-editor.component.mjs +24 -4
- package/esm2022/lib/region-source/region-source-ops.mjs +7 -1
- package/esm2022/lib/region-source/region-tiles.mjs +1 -1
- package/esm2022/lib/region-source/worker-region-source.mjs +24 -1
- package/esm2022/lib/routing-visualizer.service.mjs +404 -7
- package/esm2022/lib/spatial/observations-in-selection.mjs +83 -0
- package/esm2022/lib/spatial/plane-cells.mjs +119 -0
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +304 -8
- package/esm2022/lib/spatial/spatial-encoding.mjs +52 -3
- package/esm2022/lib/spatial/spatial-hover.mjs +34 -1
- package/esm2022/lib/spatial/spatial-planes.mjs +49 -0
- package/esm2022/lib/spatial/spatial-selection.mjs +2 -2
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +38 -1
- package/esm2022/lib/spatial/transcripts-in-selection.mjs +208 -0
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +42 -65
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +6 -2
- package/esm2022/lib/spatial-controls/spatial-color-by/spatial-color-by.component.mjs +187 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +51 -12
- package/esm2022/lib/spatial-controls/spatial-gene-style/spatial-gene-style.component.mjs +7 -3
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +21 -6
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +94 -13
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +79 -57
- package/esm2022/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.mjs +101 -0
- package/esm2022/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.mjs +94 -0
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +9 -3
- package/esm2022/lib/store/region-source-scope.mjs +10 -1
- package/esm2022/lib/store/region-store.service.mjs +33 -2
- package/esm2022/lib/toolbar/toolbar.component.mjs +10 -3
- package/esm2022/lib/visualizer/spatial-region-set.mjs +95 -0
- package/esm2022/lib/visualizer.component.mjs +40 -4
- package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CYsPzX3J.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CBiLcnE6.mjs} +4838 -656
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CBiLcnE6.mjs.map +1 -0
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-DaZVXq1s.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-BXHjv4PE.mjs} +2 -2
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-DaZVXq1s.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-BXHjv4PE.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +1 -1
- package/fesm2022/region-source.worker.js +84 -2
- package/lib/contracts/display-types.d.ts +99 -6
- package/lib/contracts/image.contract.d.ts +6 -0
- package/lib/contracts/ports/spatial-data.port.d.ts +7 -0
- package/lib/contracts/region-editor-api.contract.d.ts +9 -0
- package/lib/contracts/region-store.contract.d.ts +6 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +7 -1
- package/lib/contracts/visualizer.contract.d.ts +43 -1
- package/lib/geometry/cell-meshes.d.ts +27 -0
- package/lib/geometry/place.d.ts +45 -0
- package/lib/implementations/napari-js/napari-camera-depth.d.ts +23 -0
- package/lib/implementations/napari-js/napari-loading-state.d.ts +1 -1
- package/lib/implementations/napari-js/napari-scene.d.ts +12 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +19 -3
- package/lib/implementations/napari-js/napari-spatial-3d-cells.d.ts +141 -0
- package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +89 -0
- package/lib/implementations/napari-js/napari-spatial-3d-transcripts.d.ts +103 -0
- package/lib/implementations/napari-js/napari-spatial-encoding.d.ts +9 -2
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +22 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +12 -0
- package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +20 -6
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +27 -1
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +48 -16
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +2 -0
- package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +54 -1
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +11 -2
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +7 -0
- package/lib/region-editor/class-tree/class-tree.component.d.ts +16 -1
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +10 -1
- package/lib/region-editor/region-editor.component.d.ts +4 -0
- package/lib/region-source/region-source-ops.d.ts +12 -0
- package/lib/region-source/region-tiles.d.ts +8 -0
- package/lib/region-source/worker-region-source.d.ts +18 -0
- package/lib/routing-visualizer.service.d.ts +140 -1
- package/lib/spatial/observations-in-selection.d.ts +43 -0
- package/lib/spatial/plane-cells.d.ts +37 -0
- package/lib/spatial/spatial-controls.facade.d.ts +59 -0
- package/lib/spatial/spatial-encoding.d.ts +24 -1
- package/lib/spatial/spatial-hover.d.ts +23 -0
- package/lib/spatial/spatial-planes.d.ts +22 -0
- package/lib/spatial/spatial-selection.d.ts +2 -1
- package/lib/spatial/spatial-tile-merge.d.ts +9 -0
- package/lib/spatial/transcripts-in-selection.d.ts +95 -0
- package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +19 -28
- package/lib/spatial-controls/spatial-color-by/spatial-color-by.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +19 -2
- package/lib/spatial-controls/spatial-gene-style/spatial-gene-style.component.d.ts +3 -1
- package/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.d.ts +7 -0
- package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +28 -7
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +26 -23
- package/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.d.ts +48 -0
- package/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.d.ts +43 -0
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +3 -1
- package/lib/store/region-source-scope.d.ts +4 -0
- package/lib/store/region-store.service.d.ts +21 -0
- package/lib/toolbar/toolbar.component.d.ts +6 -1
- package/lib/visualizer/spatial-region-set.d.ts +55 -0
- package/lib/visualizer.component.d.ts +14 -0
- package/package.json +2 -2
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CYsPzX3J.mjs.map +0 -1
|
@@ -2,7 +2,7 @@ import { Observable, BehaviorSubject } from 'rxjs';
|
|
|
2
2
|
import { Image } from 'image-js';
|
|
3
3
|
import { IImageInfo } from '../../contracts/image.contract';
|
|
4
4
|
import { IHistogram } from '../../contracts/channel-histogram-api.contract';
|
|
5
|
-
import { CanvasToolId } from '../../contracts/display-types';
|
|
5
|
+
import { CanvasToolId, Cells3dStatus } from '../../contracts/display-types';
|
|
6
6
|
import { IRegionOverlay } from '../../contracts/region-overlay.contract';
|
|
7
7
|
import { SpatialObservations } from '../../contracts/spatial-dataset.contract';
|
|
8
8
|
import { SpatialDataPort } from '../../contracts/ports/spatial-data.port';
|
|
@@ -82,6 +82,8 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
|
|
|
82
82
|
} | null>;
|
|
83
83
|
/** The observation gene filter could not be applied (an expression read failed). */
|
|
84
84
|
readonly geneFilterFailed$: BehaviorSubject<boolean>;
|
|
85
|
+
/** The 3D view's individual cells as they stand (see Spatial3dCells), for the panel. */
|
|
86
|
+
readonly cells3dStatus$: BehaviorSubject<Cells3dStatus | null>;
|
|
85
87
|
/** "x reloading…" at the bottom of the canvas: the tile layers' loads and the observations'. */
|
|
86
88
|
private readonly badge;
|
|
87
89
|
/** The store's display state (colormap, reverse, invert) and the colormaps derived from it. */
|
|
@@ -99,6 +101,12 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
|
|
|
99
101
|
private regionMeshes;
|
|
100
102
|
/** The image (file name) {@link regionMeshes} were built from. */
|
|
101
103
|
private regionMeshesImage;
|
|
104
|
+
/** Where {@link regionMeshes}' slices are, when their region set says (see setRegionMeshes). */
|
|
105
|
+
private regionPlanes;
|
|
106
|
+
/** The plane of {@link regionPlanes} the 2D spatial view shows (see setRegionPlane). */
|
|
107
|
+
private regionPlane;
|
|
108
|
+
/** The classes the spatial 3D view draws as individual cells (see setRegionCells). */
|
|
109
|
+
private regionCells;
|
|
102
110
|
/** The keys of the reconstructions highlighted. */
|
|
103
111
|
private regionHighlight;
|
|
104
112
|
/** The keys of the reconstructions hidden. */
|
|
@@ -162,6 +170,24 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
|
|
|
162
170
|
beginTask(message: string): () => void;
|
|
163
171
|
/** Show these region reconstructions of `image` in the volume view (kept for its next volume plot). */
|
|
164
172
|
setRegionMeshes(meshes: readonly RegionMesh3D[], image: string | undefined): void;
|
|
173
|
+
/**
|
|
174
|
+
* Where the region reconstructions' slices are, in the observations' units, when their region set
|
|
175
|
+
* says (a 3D segmentation's planes, placed among the observations in spatial 3D); null: they are
|
|
176
|
+
* the plotted stack's. Kept for the next plot of the same image, as the meshes are; the spatial 3D
|
|
177
|
+
* view's voxel step follows it (see regionVoxelStep).
|
|
178
|
+
*/
|
|
179
|
+
/**
|
|
180
|
+
* Draw these classes of the dataset's region set as individual cells in the spatial 3D view, each
|
|
181
|
+
* its own surface in the panel's Cell Color, rather than as their merged class surfaces (none:
|
|
182
|
+
* no cells). Kept for the next scene.
|
|
183
|
+
*/
|
|
184
|
+
setRegionCells(classes: readonly string[] | null): void;
|
|
185
|
+
setRegionPlanes(planes: readonly number[] | null): void;
|
|
186
|
+
/**
|
|
187
|
+
* Which of the region set's planes (see {@link setRegionPlanes}) the 2D spatial view shows over
|
|
188
|
+
* an image of one plane, whose own slice stays 0: the slider picks the plane, not the image's.
|
|
189
|
+
*/
|
|
190
|
+
setRegionPlane(k: number): void;
|
|
165
191
|
/** Highlight the reconstructions of these keys (none: all as usual). */
|
|
166
192
|
setRegionHighlight(keys: readonly string[]): void;
|
|
167
193
|
/** Hide the reconstructions of these keys (kept for the next volume plot). */
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { Viewer } from 'napari-js';
|
|
2
|
+
import { PlanePlacement, VolumeFrame, sliceZ, toWorld } from '../../geometry/place';
|
|
3
|
+
export type { PlanePlacement, VolumeFrame };
|
|
4
|
+
export { sliceZ, toWorld };
|
|
2
5
|
/** A region's 3D reconstruction to show in the volume: a mesh in image px (x, y) and slices (z). */
|
|
3
6
|
export interface RegionMesh3D {
|
|
4
7
|
/** Identity (a class name): a mesh with the same key and arrays is kept, not rebuilt. */
|
|
@@ -10,43 +13,69 @@ export interface RegionMesh3D {
|
|
|
10
13
|
vertices: Float32Array;
|
|
11
14
|
faces: Uint32Array;
|
|
12
15
|
}
|
|
13
|
-
/**
|
|
14
|
-
export
|
|
15
|
-
/** Image width, height (px) and slice count. */
|
|
16
|
-
size: [number, number, number];
|
|
17
|
-
/** The world box (centred on the origin), Z as currently stretched. */
|
|
18
|
-
world: [number, number, number];
|
|
19
|
-
}
|
|
16
|
+
/** Places a mesh's vertices (image px, slices) in a 3D view's world, off the main thread. */
|
|
17
|
+
export type RegionPlacer = (vertices: Float32Array, frame: VolumeFrame) => Promise<Float32Array>;
|
|
20
18
|
/** Opacity of a region's surface in the volume. */
|
|
21
19
|
export declare const REGION_MESH_OPACITY = 0.55;
|
|
22
20
|
/** While some surfaces are highlighted: theirs (near opaque, so their shape reads) … */
|
|
23
21
|
export declare const REGION_MESH_HIGHLIGHT_OPACITY = 0.9;
|
|
24
22
|
/** … and the others' (ghosted: still there for context, not in the way). */
|
|
25
23
|
export declare const REGION_MESH_DIMMED_OPACITY = 0.12;
|
|
24
|
+
/**
|
|
25
|
+
* A selection's surfaces while the others are ghosted: opaque, so they are drawn first and write
|
|
26
|
+
* depth, and the ghosted surfaces in front of them are blended over them rather than hiding them
|
|
27
|
+
* (a translucent surface draws only its own nearest faces, and is drawn after the opaque ones).
|
|
28
|
+
*/
|
|
29
|
+
export declare const REGION_MESH_SELECTED_OPACITY = 1;
|
|
26
30
|
/**
|
|
27
31
|
* The region reconstructions shown in a volume view: one translucent surface per region, in its
|
|
28
32
|
* colour, placed in the volume's world box (pixel x, y and slice z mapped onto it the way the
|
|
29
|
-
* volume maps its voxels)
|
|
30
|
-
*
|
|
33
|
+
* volume maps its voxels). The box's Z stretch is the surfaces' `scale3d` (a uniform), so a stretch
|
|
34
|
+
* alone changes no geometry; a new box re-places them. A surface is updated in place (`setData`,
|
|
35
|
+
* `color`, `scale3d`) rather than added again, and picked by napari-js (`pickSurface`), which
|
|
36
|
+
* picks it where it is drawn.
|
|
31
37
|
*
|
|
32
38
|
* Highlighting is focus + context: the highlighted surfaces turn near opaque and the others fade
|
|
33
39
|
* to a ghost, so the selection stands out while staying in place among its neighbours.
|
|
34
40
|
*/
|
|
35
41
|
export declare class VolumeRegionMeshes {
|
|
36
42
|
private readonly viewer;
|
|
43
|
+
private readonly placer?;
|
|
37
44
|
private readonly layers;
|
|
38
45
|
private highlighted;
|
|
39
46
|
private hidden;
|
|
47
|
+
/** Surfaces faded: none of what is selected is in them. */
|
|
48
|
+
private muted;
|
|
40
49
|
/** The meshes to show (kept while the volume has no frame yet). */
|
|
41
50
|
private wanted;
|
|
42
51
|
private frame;
|
|
43
|
-
|
|
52
|
+
/** The placements in flight, by key: the mesh and box each is for. */
|
|
53
|
+
private readonly placing;
|
|
54
|
+
private token;
|
|
55
|
+
/**
|
|
56
|
+
* `placer`, when given, places a mesh's vertices in the world off the main thread (a worker, see
|
|
57
|
+
* `placeInWorker`): a class's surface has hundreds of thousands of vertices, and placing every
|
|
58
|
+
* one in a loop here held the UI for seconds. Each surface then comes up as its placement lands,
|
|
59
|
+
* the one it replaces kept until then. Without one, they are placed at once (the tests).
|
|
60
|
+
*/
|
|
61
|
+
constructor(viewer: Viewer, placer?: RegionPlacer | undefined);
|
|
44
62
|
/** Show exactly `meshes` (adding, keeping or removing surfaces). */
|
|
45
63
|
set(meshes: readonly RegionMesh3D[]): void;
|
|
46
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* Follow the volume's frame. A new box (it opened, another volume) re-places every surface; a Z
|
|
66
|
+
* stretch of the same box only sets their `scale3d`, so nothing is re-uploaded while dragging.
|
|
67
|
+
*/
|
|
47
68
|
setFrame(frame: VolumeFrame): void;
|
|
69
|
+
/** The surfaces' GPU scale: the frame's Z stretch. */
|
|
70
|
+
private scale3d;
|
|
48
71
|
/** Highlight the surfaces of these keys (none: every surface as usual). */
|
|
49
72
|
setHighlight(keys: Iterable<string>): void;
|
|
73
|
+
/**
|
|
74
|
+
* Fade the surfaces of these keys, as a picked region fades the others (none: each as usual):
|
|
75
|
+
* with a selection, the regions none of it is in fade and those it is in come forward, each
|
|
76
|
+
* keeping its colour.
|
|
77
|
+
*/
|
|
78
|
+
setMuted(keys: Iterable<string>): void;
|
|
50
79
|
/** Hide the surfaces of these keys (they are kept, so showing them again is instant). */
|
|
51
80
|
setHidden(keys: Iterable<string>): void;
|
|
52
81
|
/** The front-most surface under screen point (`x`, `y`) (canvas CSS px), or null. */
|
|
@@ -60,12 +89,15 @@ export declare class VolumeRegionMeshes {
|
|
|
60
89
|
*/
|
|
61
90
|
clearFrame(): void;
|
|
62
91
|
private sync;
|
|
92
|
+
/**
|
|
93
|
+
* Place `mesh` in the current box, adding its surface or updating it: at once, or through the
|
|
94
|
+
* placer, its result kept only if the mesh and the box are still the ones wanted. A placement
|
|
95
|
+
* already in flight for the same mesh and box is not asked again.
|
|
96
|
+
*/
|
|
97
|
+
private place;
|
|
98
|
+
/** `mesh`'s surface with its vertices placed at `world`: updated in place, or added. */
|
|
99
|
+
private apply;
|
|
63
100
|
private add;
|
|
64
101
|
private opacityOf;
|
|
65
102
|
private remove;
|
|
66
103
|
}
|
|
67
|
-
/**
|
|
68
|
-
* Image px / slice coordinates → the volume's centred world box: pixel x of a `w`-wide image
|
|
69
|
-
* spans the box's width, slice k sits at the middle of its share of the box's depth.
|
|
70
|
-
*/
|
|
71
|
-
export declare function toWorld(vertices: Float32Array, frame: VolumeFrame): Float32Array;
|
|
@@ -99,6 +99,8 @@ export declare class VolumeScene implements NapariScene {
|
|
|
99
99
|
histogram(channel: number, bins: number): IHistogram | null;
|
|
100
100
|
isoControls(): IIsosurfaceControls | null;
|
|
101
101
|
surface3dControls(): ISurface3dControls | null;
|
|
102
|
+
/** Gives the camera back napari-js's own depth range (see keepSceneInDepth). */
|
|
103
|
+
private restoreDepth;
|
|
102
104
|
dispose(): void;
|
|
103
105
|
/**
|
|
104
106
|
* Restretch the volume's Z height live (driven by the in-view {@link NapariVolumeZHandle}). Only
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
+
import type { Colormap, RGBA } from 'napari-js';
|
|
1
2
|
import type { Rgb } from '../../../contracts/colormap-lut';
|
|
2
3
|
import type { SpatialDataPort } from '../../../contracts/ports/spatial-data.port';
|
|
3
4
|
import type { SpatialViewState } from '../../../contracts/display-types';
|
|
4
5
|
import { SpatialDataset } from '../../../contracts/spatial-dataset.contract';
|
|
5
6
|
import { SpatialSelectionMask } from '../../../spatial/spatial-selection';
|
|
6
7
|
import { DataRect } from '../../../spatial/lod';
|
|
8
|
+
import { ContrastWindowCache } from '../napari-spatial-encoding';
|
|
7
9
|
import type { CategoricalLookup } from './categorical-lookup';
|
|
8
10
|
import type { OrderedLayerGroups, TileGroup } from './layer-groups';
|
|
9
11
|
import type { PlanContext } from './plan-context';
|
|
12
|
+
/** The cells' colours as a shapes layer takes them: per-shape RGBA, values over a colormap, or
|
|
13
|
+
* one colour. */
|
|
14
|
+
export interface CellColors {
|
|
15
|
+
values?: Float32Array;
|
|
16
|
+
colormap?: Colormap;
|
|
17
|
+
contrastLimits?: [number, number];
|
|
18
|
+
color?: RGBA;
|
|
19
|
+
faceColor?: Float32Array;
|
|
20
|
+
}
|
|
10
21
|
/** What the cell layers need from the service. */
|
|
11
22
|
export interface CellLayersHost {
|
|
12
23
|
/** The continuous LUT the view is using (so cells coloured by a gene match the markers). */
|
|
@@ -39,9 +50,25 @@ export declare class CellLayers {
|
|
|
39
50
|
/** Continuous colourings' windows, per (vector, clip, log): `contrastWindow` sorts every
|
|
40
51
|
* value, and a selection or opacity change recolours with the vector unchanged (SPATIAL-12). */
|
|
41
52
|
private readonly contrastWindows;
|
|
53
|
+
/**
|
|
54
|
+
* The plane of a 3D segmentation the view shows (see {@link setPlane}), or null: every set draws
|
|
55
|
+
* its own tiles.
|
|
56
|
+
*/
|
|
57
|
+
private plane;
|
|
58
|
+
/** The region set opened for a boundary set's per-plane outlines: its id and the source. */
|
|
59
|
+
private planeSource;
|
|
42
60
|
constructor(port: SpatialDataPort, groups: OrderedLayerGroups<TileGroup>, lookup: CategoricalLookup, host: CellLayersHost);
|
|
43
|
-
/** True while outlines are on screen
|
|
61
|
+
/** True while outlines are on screen. */
|
|
44
62
|
get outlinesShown(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Show plane `plane` (an index into the region set's planes) of a 3D segmentation, or none: a
|
|
65
|
+
* boundary set that names its region set (`regionSource`, a cell outlined on every plane it spans)
|
|
66
|
+
* then draws that plane's outlines, rather than one outline per cell, so the cells follow the
|
|
67
|
+
* slice. Its cells keep the view's colouring, groups and selection.
|
|
68
|
+
*/
|
|
69
|
+
setPlane(plane: number | null): void;
|
|
70
|
+
/** Close the region set opened for the per-plane outlines. */
|
|
71
|
+
dispose(): void;
|
|
45
72
|
/** The viewer went away (its layers with it): the outlines are no longer shown. */
|
|
46
73
|
detached(): void;
|
|
47
74
|
/** Draw the cells covering `rect` at the level `pxPerUnit` calls for, or drop them. */
|
|
@@ -64,7 +91,33 @@ export declare class CellLayers {
|
|
|
64
91
|
* view went stale or the dataset has no set to draw.
|
|
65
92
|
*/
|
|
66
93
|
private cellGeometry;
|
|
94
|
+
/**
|
|
95
|
+
* The cells of boundary set `set` on the plane shown, from its region set (`regionSource`): the
|
|
96
|
+
* plane's tiles meeting `rect`, at the detail the zoom calls for, each outline owned by its cell
|
|
97
|
+
* (by its id among the observations'), minus the hidden groups. Undefined when it cannot be drawn
|
|
98
|
+
* so (no observation ids to tell its cells by, no port to open the set, or a plane it has not), so
|
|
99
|
+
* the set's own tiles are drawn; null when the view went stale.
|
|
100
|
+
*/
|
|
101
|
+
private planeGeometry;
|
|
102
|
+
/** The region set `id`, opened once (another id closes the one before). */
|
|
103
|
+
private openPlaneSource;
|
|
67
104
|
/** Remove the cell layers and forget what they showed. */
|
|
68
105
|
drop(): void;
|
|
69
106
|
private setPolygonsShown;
|
|
70
107
|
}
|
|
108
|
+
/** What {@link cellColorsFor} reads with: the port, the categorical columns, the windows cache, the LUT. */
|
|
109
|
+
export interface CellColorDeps {
|
|
110
|
+
port: SpatialDataPort;
|
|
111
|
+
lookup: CategoricalLookup;
|
|
112
|
+
contrastWindows: ContrastWindowCache;
|
|
113
|
+
continuousLut(view: SpatialViewState): Rgb[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The cells' colours by their owners (`owners[i]` the observation of shape i), by the view's
|
|
117
|
+
* cell-colour mode (Xenium Explorer's "Cell Color"): one RGBA per shape for a grouping, values +
|
|
118
|
+
* colormap for a measurement, one colour for "single". A selection mutes what it leaves out. The 2D
|
|
119
|
+
* cell outlines and the 3D cells both colour by it.
|
|
120
|
+
*/
|
|
121
|
+
export declare function cellColorsFor(deps: CellColorDeps, dataset: SpatialDataset, view: SpatialViewState, selection: SpatialSelectionMask, owners: Uint32Array): Promise<CellColors>;
|
|
122
|
+
/** {@link cellColorsFor}'s colours as one RGBA (0..1) per shape, `n` shapes. */
|
|
123
|
+
export declare function cellColorsRgba(colors: CellColors, n: number): Float32Array;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PointSymbol } from 'napari-js';
|
|
2
2
|
import type { SpatialViewState } from '../../../contracts/display-types';
|
|
3
3
|
import { SpatialDataset } from '../../../contracts/spatial-dataset.contract';
|
|
4
|
+
import type { SpatialSelectionMask } from '../../../spatial/spatial-selection';
|
|
4
5
|
import { DataRect } from '../../../spatial/lod';
|
|
5
6
|
import { TranscriptGlyph } from '../../../spatial/glyphs';
|
|
6
7
|
import type { CategoricalLookup } from './categorical-lookup';
|
|
@@ -40,8 +41,12 @@ export declare class TranscriptLayers {
|
|
|
40
41
|
geneCountsIn(rect: DataRect): Record<string, number> | null;
|
|
41
42
|
/** The viewer went away: no counts until the next plan. */
|
|
42
43
|
detached(): void;
|
|
43
|
-
/**
|
|
44
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Draw the view's transcript markers (or drop them); an unchanged plan key is a no-op. With a
|
|
46
|
+
* `zBand`, the view shows one plane of a 3D assay: only the transcripts at that depth are drawn
|
|
47
|
+
* (summed density grids and aggregates, which mix depths, stay whole).
|
|
48
|
+
*/
|
|
49
|
+
plan(dataset: SpatialDataset, view: SpatialViewState, rect: DataRect, pxPerUnit: number, ctx: PlanContext, zBand?: readonly [number, number] | null, selection?: SpatialSelectionMask | null): Promise<void>;
|
|
45
50
|
/**
|
|
46
51
|
* Gene icons: each entry drawn as its gene's napari-js point symbol, in the same one points
|
|
47
52
|
* layer as the circles. With every gene drawn there is one icon for all of them — 18,000
|
|
@@ -53,6 +58,10 @@ export declare class TranscriptLayers {
|
|
|
53
58
|
* for, drawn as the layer's disc or as each entry's `symbols` code.
|
|
54
59
|
*/
|
|
55
60
|
private drawTranscripts;
|
|
61
|
+
/** The selection the last plan faded by, and its revision, bumped each time it changes. */
|
|
62
|
+
private lastSelection;
|
|
63
|
+
private selectionRevision;
|
|
64
|
+
private selectionRev;
|
|
56
65
|
/** Per-entry colours, as packed RGBA. */
|
|
57
66
|
private transcriptColors;
|
|
58
67
|
}
|
|
@@ -3,6 +3,7 @@ import { Observable } from 'rxjs';
|
|
|
3
3
|
import { SpatialDataPort, TranscriptTileQuery } from '../../contracts/ports/spatial-data.port';
|
|
4
4
|
import { SpatialColumn, SpatialDataset, SpatialDensityRaster, SpatialEmbedding, SpatialPolygonTile, SpatialPolygons, CategoricalColumnMeta, SpatialMarkerGenes, SpatialTranscriptCounts, SpatialTranscriptSummary, SpatialTranscriptTile } from '../../contracts/spatial-dataset.contract';
|
|
5
5
|
import { SpatialDatasetSummary, SpatialManifest } from './spatial-wire';
|
|
6
|
+
import type { RegionSource } from '../../region-source/region-source';
|
|
6
7
|
import * as i0 from "@angular/core";
|
|
7
8
|
/**
|
|
8
9
|
* A dataset selection that a newer selection (or a `clear`) overtook.
|
|
@@ -137,6 +138,12 @@ export declare class SpatialDataHttpService implements SpatialDataPort {
|
|
|
137
138
|
/** Oldest first, past the entry cap or the byte budget, keeping the newest. */
|
|
138
139
|
private evictTiles;
|
|
139
140
|
private dropTile;
|
|
141
|
+
/**
|
|
142
|
+
* The region set a boundary set names (`polygonTiles.sets[i].regionSource`), served beside the
|
|
143
|
+
* datasets as an HTTP region source (`{base}/regions/{id}/…`, see `openHttpRegionSource`), its
|
|
144
|
+
* requests through the host's `HttpClient` as every other request here.
|
|
145
|
+
*/
|
|
146
|
+
openRegionSet(id: string): Promise<RegionSource>;
|
|
140
147
|
/**
|
|
141
148
|
* The reference volume's voxels, single-flighted like the polygons.
|
|
142
149
|
*
|
|
@@ -33,6 +33,15 @@ export declare class ClassTreeComponent implements OnChanges {
|
|
|
33
33
|
volume: boolean;
|
|
34
34
|
/** The classes shown in 3D. */
|
|
35
35
|
shown3d: ReadonlySet<string>;
|
|
36
|
+
/** Classes that can be drawn as individual cells here (a 3D segmentation's, in spatial 3D). */
|
|
37
|
+
cellable: ReadonlySet<string>;
|
|
38
|
+
/** Those drawn as individual cells now. */
|
|
39
|
+
individual: ReadonlySet<string>;
|
|
40
|
+
/** Draw a class (its subclasses with it) as individual cells, or merged again. */
|
|
41
|
+
toggleCells: EventEmitter<{
|
|
42
|
+
classes: string[];
|
|
43
|
+
individual: boolean;
|
|
44
|
+
}>;
|
|
36
45
|
/** The classes hidden from view. */
|
|
37
46
|
hidden: ReadonlySet<string>;
|
|
38
47
|
pick: EventEmitter<ClassTreePick>;
|
|
@@ -63,6 +72,12 @@ export declare class ClassTreeComponent implements OnChanges {
|
|
|
63
72
|
protected total(name: string): number;
|
|
64
73
|
protected toggle(row: ClassTreeRow, event: Event): void;
|
|
65
74
|
protected choose(name: string, event: Event): void;
|
|
75
|
+
/** A class (with its subclasses) as individual cells, or merged again: all of them as it is. */
|
|
76
|
+
protected flipCells(name: string, event: Event): void;
|
|
77
|
+
/** Whether every cellable class of `name`'s subtree is drawn as cells. */
|
|
78
|
+
protected allIndividual(name: string): boolean;
|
|
79
|
+
/** Whether `name` or a subclass can be drawn as cells. */
|
|
80
|
+
protected anyCellable(name: string): boolean;
|
|
66
81
|
/** The eye: a class hidden (wholly) is shown again with its subclasses; otherwise they are hidden. */
|
|
67
82
|
protected flipHidden(name: string, event: Event): void;
|
|
68
83
|
protected flip3d(name: string, event: Event): void;
|
|
@@ -72,7 +87,7 @@ export declare class ClassTreeComponent implements OnChanges {
|
|
|
72
87
|
protected readonly trackRow: (_: number, r: ClassTreeRow) => string;
|
|
73
88
|
private refresh;
|
|
74
89
|
static ɵfac: i0.ɵɵFactoryDeclaration<ClassTreeComponent, never>;
|
|
75
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ClassTreeComponent, "region-class-tree", never, { "nodes": { "alias": "nodes"; "required": false; }; "counts": { "alias": "counts"; "required": false; }; "colorOf": { "alias": "colorOf"; "required": false; }; "picked": { "alias": "picked"; "required": false; }; "marked": { "alias": "marked"; "required": false; }; "volume": { "alias": "volume"; "required": false; }; "shown3d": { "alias": "shown3d"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; }, { "pick": "pick"; "recolor": "recolor"; "toggle3d": "toggle3d"; "toggleHidden": "toggleHidden"; }, never, never, true, never>;
|
|
90
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ClassTreeComponent, "region-class-tree", never, { "nodes": { "alias": "nodes"; "required": false; }; "counts": { "alias": "counts"; "required": false; }; "colorOf": { "alias": "colorOf"; "required": false; }; "picked": { "alias": "picked"; "required": false; }; "marked": { "alias": "marked"; "required": false; }; "volume": { "alias": "volume"; "required": false; }; "shown3d": { "alias": "shown3d"; "required": false; }; "cellable": { "alias": "cellable"; "required": false; }; "individual": { "alias": "individual"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; }, { "toggleCells": "toggleCells"; "pick": "pick"; "recolor": "recolor"; "toggle3d": "toggle3d"; "toggleHidden": "toggleHidden"; }, never, never, true, never>;
|
|
76
91
|
}
|
|
77
92
|
/** Scroll the row matching `selector` inside `host` into view, if it is out of it. */
|
|
78
93
|
export declare function scrollToPicked(host: HTMLElement, selector: string): void;
|
|
@@ -41,6 +41,15 @@ export declare class ClassesPanelComponent implements OnChanges {
|
|
|
41
41
|
volume: boolean;
|
|
42
42
|
/** The classes shown in 3D. */
|
|
43
43
|
shown3d: ReadonlySet<string>;
|
|
44
|
+
/** Classes that can be drawn as individual cells here (a 3D segmentation's, in spatial 3D). */
|
|
45
|
+
cellable: ReadonlySet<string>;
|
|
46
|
+
/** Those drawn as individual cells now. */
|
|
47
|
+
individual: ReadonlySet<string>;
|
|
48
|
+
/** Draw a class (its subclasses with it) as individual cells, or merged again. */
|
|
49
|
+
toggleCells: EventEmitter<{
|
|
50
|
+
classes: string[];
|
|
51
|
+
individual: boolean;
|
|
52
|
+
}>;
|
|
44
53
|
/** The classes hidden from view. */
|
|
45
54
|
hidden: ReadonlySet<string>;
|
|
46
55
|
/** A class's eye (its name): hide it, or show it again. */
|
|
@@ -81,6 +90,6 @@ export declare class ClassesPanelComponent implements OnChanges {
|
|
|
81
90
|
protected rowTooltip(name: string): string;
|
|
82
91
|
protected removeTooltip(name: string): string;
|
|
83
92
|
static ɵfac: i0.ɵɵFactoryDeclaration<ClassesPanelComponent, never>;
|
|
84
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ClassesPanelComponent, "region-classes-panel", never, { "classes": { "alias": "classes"; "required": false; }; "counts": { "alias": "counts"; "required": false; }; "matchMode": { "alias": "matchMode"; "required": false; }; "activeClass": { "alias": "activeClass"; "required": false; }; "picked": { "alias": "picked"; "required": false; }; "marked": { "alias": "marked"; "required": false; }; "selectedCount": { "alias": "selectedCount"; "required": false; }; "defaultClassName": { "alias": "defaultClassName"; "required": false; }; "volume": { "alias": "volume"; "required": false; }; "shown3d": { "alias": "shown3d"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; "treeView": { "alias": "treeView"; "required": false; }; }, { "toggleHidden": "toggleHidden"; "toggle3d": "toggle3d"; "treeViewChange": "treeViewChange"; "pick": "pick"; "recolor": "recolor"; "remove": "remove"; "manage": "manage"; }, never, ["*"], true, never>;
|
|
93
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ClassesPanelComponent, "region-classes-panel", never, { "classes": { "alias": "classes"; "required": false; }; "counts": { "alias": "counts"; "required": false; }; "matchMode": { "alias": "matchMode"; "required": false; }; "activeClass": { "alias": "activeClass"; "required": false; }; "picked": { "alias": "picked"; "required": false; }; "marked": { "alias": "marked"; "required": false; }; "selectedCount": { "alias": "selectedCount"; "required": false; }; "defaultClassName": { "alias": "defaultClassName"; "required": false; }; "volume": { "alias": "volume"; "required": false; }; "shown3d": { "alias": "shown3d"; "required": false; }; "cellable": { "alias": "cellable"; "required": false; }; "individual": { "alias": "individual"; "required": false; }; "hidden": { "alias": "hidden"; "required": false; }; "treeView": { "alias": "treeView"; "required": false; }; }, { "toggleCells": "toggleCells"; "toggleHidden": "toggleHidden"; "toggle3d": "toggle3d"; "treeViewChange": "treeViewChange"; "pick": "pick"; "recolor": "recolor"; "remove": "remove"; "manage": "manage"; }, never, ["*"], true, never>;
|
|
85
94
|
}
|
|
86
95
|
export {};
|
|
@@ -196,6 +196,10 @@ export declare class RegionEditorComponent implements OnInit, OnDestroy {
|
|
|
196
196
|
*/
|
|
197
197
|
protected toggleClass3d(name: string, classes?: string[]): void;
|
|
198
198
|
/** Hide (or show again) these classes' regions, wherever they are drawn. */
|
|
199
|
+
/** Classes that can be drawn as individual cells in spatial 3D, and those that are. */
|
|
200
|
+
protected cellableClasses: ReadonlySet<string>;
|
|
201
|
+
protected individualClasses: ReadonlySet<string>;
|
|
202
|
+
protected setClassesIndividual3d(classes: readonly string[], individual: boolean): void;
|
|
199
203
|
protected setClassesHidden(classes: readonly string[], hidden: boolean): void;
|
|
200
204
|
/** The surfaces shown in 3D, in their classes' colours now. */
|
|
201
205
|
private groups3d;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Protocol: `{ id, op, ...args }` → `{ id, ok: true, result }` | `{ id, ok: false, error }`.
|
|
7
7
|
*/
|
|
8
8
|
import { ReconstructOptions, SliceOutlines } from '../geometry/reconstruct';
|
|
9
|
+
import { CellOutlines, CellsMesh } from '../geometry/cell-meshes';
|
|
10
|
+
import { VolumeFrame } from '../geometry/place';
|
|
9
11
|
import type { Mesh } from 'napari-js/geometry';
|
|
10
12
|
import { ClassOutlines, RegionIndexPage, RegionIndexQuery, RegionSourceInfo, RegionTile } from './region-tiles';
|
|
11
13
|
import type { SourceFeature } from './region-source';
|
|
@@ -44,6 +46,14 @@ export type RegionSourceRequest = {
|
|
|
44
46
|
op: 'mesh';
|
|
45
47
|
slices: readonly SliceOutlines[];
|
|
46
48
|
options?: ReconstructOptions;
|
|
49
|
+
} | {
|
|
50
|
+
op: 'cells';
|
|
51
|
+
cells: readonly CellOutlines[];
|
|
52
|
+
options?: ReconstructOptions;
|
|
53
|
+
} | {
|
|
54
|
+
op: 'place';
|
|
55
|
+
vertices: Float32Array;
|
|
56
|
+
frame: VolumeFrame;
|
|
47
57
|
} | {
|
|
48
58
|
op: 'export';
|
|
49
59
|
handle: number;
|
|
@@ -64,6 +74,8 @@ export interface RegionSourceResults {
|
|
|
64
74
|
classes: Record<string, number>;
|
|
65
75
|
outlines: ClassOutlines[];
|
|
66
76
|
mesh: Mesh;
|
|
77
|
+
cells: CellsMesh;
|
|
78
|
+
place: Float32Array;
|
|
67
79
|
export: string;
|
|
68
80
|
close: null;
|
|
69
81
|
}
|
|
@@ -53,6 +53,14 @@ export interface RegionSourceInfo {
|
|
|
53
53
|
hierarchy?: RegionClassNode[];
|
|
54
54
|
/** How the set wants to be drawn, when it says. */
|
|
55
55
|
style?: RegionSourceStyle;
|
|
56
|
+
/**
|
|
57
|
+
* Where each plane is, when the set says: `sliceZ[i]` the z of plane `planes[i]`, in the units of
|
|
58
|
+
* the coordinates its outlines are in (a 3D segmentation's planes, in its observations' units).
|
|
59
|
+
* Planes stay ordinals for addressing; these place them (see the spatial 3D view).
|
|
60
|
+
*/
|
|
61
|
+
sliceZ?: number[];
|
|
62
|
+
/** Microns per unit of the set's coordinates, when it says. */
|
|
63
|
+
micronsPerUnit?: number;
|
|
56
64
|
}
|
|
57
65
|
/** One feature as a tile carries it: identity, class and outline at the tile's level. */
|
|
58
66
|
export interface TileFeature {
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
import { RegionSource } from './region-source';
|
|
10
10
|
import { RegionSourceRequest, RegionSourceResults } from './region-source-ops';
|
|
11
11
|
import type { ReconstructOptions, SliceOutlines } from '../geometry/reconstruct';
|
|
12
|
+
import type { CellOutlines, CellsMesh } from '../geometry/cell-meshes';
|
|
13
|
+
import type { VolumeFrame } from '../geometry/place';
|
|
12
14
|
import type { Mesh } from 'napari-js/geometry';
|
|
13
15
|
/** Makes the worker; may be async, as the default one is (it imports the factory on demand). */
|
|
14
16
|
export type RegionSourceWorkerFactory = () => Worker | Promise<Worker>;
|
|
@@ -58,6 +60,22 @@ export declare function sharedRegionSourceClient(): RegionSourceWorkerClient;
|
|
|
58
60
|
* a collection without `features`.
|
|
59
61
|
*/
|
|
60
62
|
export declare function openGeoJsonRegionSource(text: string, client?: RegionSourceWorkerClient): Promise<RegionSource>;
|
|
63
|
+
/**
|
|
64
|
+
* The worker client cells are meshed on: a worker of its own, so a few thousand cells meshing does
|
|
65
|
+
* not hold up the region tiles the 2D views read from the shared one.
|
|
66
|
+
*/
|
|
67
|
+
export declare function cellsWorkerClient(): RegionSourceWorkerClient;
|
|
68
|
+
/**
|
|
69
|
+
* A 3D segmentation's cells, each meshed by itself (see `geometry/cell-meshes`), in the cells'
|
|
70
|
+
* worker (on the main thread where there is none). Batch them: one call meshes its cells in one go.
|
|
71
|
+
*/
|
|
72
|
+
export declare function reconstructCellsInWorker(cells: readonly CellOutlines[], options?: ReconstructOptions, client?: RegionSourceWorkerClient): Promise<CellsMesh>;
|
|
73
|
+
/**
|
|
74
|
+
* A mesh's vertices placed in a 3D view's world (see `geometry/place`), in the cells' worker: a
|
|
75
|
+
* class's surface has hundreds of thousands, and placing every surface on the main thread held it
|
|
76
|
+
* for seconds.
|
|
77
|
+
*/
|
|
78
|
+
export declare function placeInWorker(vertices: Float32Array, frame: VolumeFrame, client?: RegionSourceWorkerClient): Promise<Float32Array>;
|
|
61
79
|
/**
|
|
62
80
|
* The 3D reconstruction of a region from its outlines on a stack (see `geometry/reconstruct`),
|
|
63
81
|
* meshed in the region-source worker (on the main thread where there is none).
|