@jax-data-science/sci-image-visualizer 0.17.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.
Files changed (121) hide show
  1. package/esm2022/lib/contracts/display-types.mjs +3 -2
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +1 -1
  4. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +1 -1
  7. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  8. package/esm2022/lib/geometry/cell-meshes.mjs +37 -0
  9. package/esm2022/lib/geometry/place.mjs +47 -0
  10. package/esm2022/lib/implementations/napari-js/napari-camera-depth.mjs +93 -0
  11. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +1 -1
  12. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +2 -2
  13. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  14. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +81 -15
  15. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-cells.mjs +746 -0
  16. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +325 -18
  17. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-transcripts.mjs +182 -24
  18. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +95 -5
  19. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +15 -1
  20. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +30 -2
  21. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +40 -1
  22. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +111 -28
  23. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +14 -2
  24. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +180 -48
  25. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +28 -8
  26. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +2 -2
  27. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +10 -1
  28. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +30 -3
  29. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +15 -3
  30. package/esm2022/lib/region-editor/region-editor.component.mjs +24 -4
  31. package/esm2022/lib/region-source/region-source-ops.mjs +7 -1
  32. package/esm2022/lib/region-source/region-tiles.mjs +1 -1
  33. package/esm2022/lib/region-source/worker-region-source.mjs +24 -1
  34. package/esm2022/lib/routing-visualizer.service.mjs +404 -7
  35. package/esm2022/lib/spatial/observations-in-selection.mjs +83 -0
  36. package/esm2022/lib/spatial/plane-cells.mjs +119 -0
  37. package/esm2022/lib/spatial/spatial-controls.facade.mjs +298 -5
  38. package/esm2022/lib/spatial/spatial-encoding.mjs +35 -3
  39. package/esm2022/lib/spatial/spatial-hover.mjs +34 -1
  40. package/esm2022/lib/spatial/spatial-planes.mjs +49 -0
  41. package/esm2022/lib/spatial/spatial-selection.mjs +2 -2
  42. package/esm2022/lib/spatial/spatial-tile-merge.mjs +38 -1
  43. package/esm2022/lib/spatial/transcripts-in-selection.mjs +208 -0
  44. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +42 -65
  45. package/esm2022/lib/spatial-controls/spatial-color-by/spatial-color-by.component.mjs +187 -0
  46. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +47 -12
  47. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +3 -3
  48. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +38 -10
  49. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +3 -3
  50. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +3 -3
  51. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +79 -57
  52. package/esm2022/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.mjs +101 -0
  53. package/esm2022/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.mjs +94 -0
  54. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +9 -3
  55. package/esm2022/lib/store/region-source-scope.mjs +10 -1
  56. package/esm2022/lib/store/region-store.service.mjs +33 -2
  57. package/esm2022/lib/toolbar/toolbar.component.mjs +10 -3
  58. package/esm2022/lib/visualizer/spatial-region-set.mjs +95 -0
  59. package/esm2022/lib/visualizer.component.mjs +40 -4
  60. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DHrHO2ay.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CBiLcnE6.mjs} +4521 -759
  61. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CBiLcnE6.mjs.map +1 -0
  62. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CKEUwNta.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-BXHjv4PE.mjs} +2 -2
  63. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CKEUwNta.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-BXHjv4PE.mjs.map} +1 -1
  64. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +1 -1
  65. package/fesm2022/region-source.worker.js +84 -2
  66. package/lib/contracts/display-types.d.ts +90 -4
  67. package/lib/contracts/image.contract.d.ts +6 -0
  68. package/lib/contracts/ports/spatial-data.port.d.ts +7 -0
  69. package/lib/contracts/region-editor-api.contract.d.ts +9 -0
  70. package/lib/contracts/region-store.contract.d.ts +6 -0
  71. package/lib/contracts/spatial-dataset.contract.d.ts +7 -1
  72. package/lib/contracts/visualizer.contract.d.ts +43 -1
  73. package/lib/geometry/cell-meshes.d.ts +27 -0
  74. package/lib/geometry/place.d.ts +45 -0
  75. package/lib/implementations/napari-js/napari-camera-depth.d.ts +23 -0
  76. package/lib/implementations/napari-js/napari-loading-state.d.ts +1 -1
  77. package/lib/implementations/napari-js/napari-scene.d.ts +12 -0
  78. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +19 -3
  79. package/lib/implementations/napari-js/napari-spatial-3d-cells.d.ts +141 -0
  80. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +87 -0
  81. package/lib/implementations/napari-js/napari-spatial-3d-transcripts.d.ts +49 -8
  82. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +22 -0
  83. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +12 -0
  84. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +15 -0
  85. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +27 -1
  86. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +38 -19
  87. package/lib/implementations/napari-js/napari-volume-scene.d.ts +2 -0
  88. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +53 -0
  89. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +11 -2
  90. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +7 -0
  91. package/lib/region-editor/class-tree/class-tree.component.d.ts +16 -1
  92. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +10 -1
  93. package/lib/region-editor/region-editor.component.d.ts +4 -0
  94. package/lib/region-source/region-source-ops.d.ts +12 -0
  95. package/lib/region-source/region-tiles.d.ts +8 -0
  96. package/lib/region-source/worker-region-source.d.ts +18 -0
  97. package/lib/routing-visualizer.service.d.ts +140 -1
  98. package/lib/spatial/observations-in-selection.d.ts +43 -0
  99. package/lib/spatial/plane-cells.d.ts +37 -0
  100. package/lib/spatial/spatial-controls.facade.d.ts +59 -0
  101. package/lib/spatial/spatial-encoding.d.ts +14 -1
  102. package/lib/spatial/spatial-hover.d.ts +23 -0
  103. package/lib/spatial/spatial-planes.d.ts +22 -0
  104. package/lib/spatial/spatial-selection.d.ts +2 -1
  105. package/lib/spatial/spatial-tile-merge.d.ts +9 -0
  106. package/lib/spatial/transcripts-in-selection.d.ts +95 -0
  107. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +19 -28
  108. package/lib/spatial-controls/spatial-color-by/spatial-color-by.component.d.ts +64 -0
  109. package/lib/spatial-controls/spatial-controls.component.d.ts +17 -2
  110. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +16 -6
  111. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +26 -23
  112. package/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.d.ts +48 -0
  113. package/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.d.ts +43 -0
  114. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +3 -1
  115. package/lib/store/region-source-scope.d.ts +4 -0
  116. package/lib/store/region-store.service.d.ts +21 -0
  117. package/lib/toolbar/toolbar.component.d.ts +6 -1
  118. package/lib/visualizer/spatial-region-set.d.ts +55 -0
  119. package/lib/visualizer.component.d.ts +14 -0
  120. package/package.json +1 -1
  121. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DHrHO2ay.mjs.map +0 -1
@@ -36,10 +36,27 @@ export declare class Spatial2dScene extends SpatialSceneBase implements NapariSc
36
36
  * SPATIAL-19): a new field key supersedes — and aborts — it; a rebuild that leaves the key
37
37
  * alone lets it finish. */
38
38
  private readonly geneMapLoads;
39
+ /**
40
+ * The planes of the dataset's region set (its `sliceZ`), set while they slice an image of one
41
+ * plane, and which of them the slider shows: the observations and transcripts drawn are that
42
+ * plane's, as a stack's slice shows its own.
43
+ */
44
+ private planes;
45
+ private plane;
46
+ /** Mounted: its markers are in the scene and follow the plane (set before then, it is kept). */
47
+ private mounted;
39
48
  /** `noImage`: an image-less dataset opened before any image — the observations alone. */
40
49
  constructor(ctx: SceneContext, session: SpatialSession, noImage?: boolean);
41
50
  mount(): Promise<void>;
42
51
  setZ(z: number): void;
52
+ setRegionPlanes(z: readonly number[] | null): void;
53
+ setRegionPlane(k: number): void;
54
+ /** The planes and the one shown, while planes slice the image. */
55
+ private planeView;
56
+ /** The z band of the plane shown, or null (every depth). */
57
+ private zBand;
58
+ /** Another plane (or none): its observations and transcripts are drawn. */
59
+ private planeChanged;
43
60
  histogram(channel: number, bins: number): IHistogram | null;
44
61
  setImageSmoothing(enabled: boolean): void;
45
62
  setNavigatorVisible(visible: boolean): void;
@@ -61,9 +78,8 @@ export declare class Spatial2dScene extends SpatialSceneBase implements NapariSc
61
78
  */
62
79
  protected pickObservation(clientX: number, clientY: number, slackPx: number): number;
63
80
  /**
64
- * Whether the markers are drawn: whenever the user wants them, at every zoom. Cell outlines come
65
- * and go with the zoom (their level of detail follows it) and are drawn over the markers; the
66
- * observations themselves never disappear with them.
81
+ * Whether the markers are drawn: while the user wants them, at every zoom, and not while the
82
+ * cells are — the observations are shown as their markers or as their cells, one or the other.
67
83
  */
68
84
  private pointsVisible;
69
85
  /**
@@ -0,0 +1,141 @@
1
+ import type { Layer, Viewer } from 'napari-js';
2
+ import type { Cells3dStatus } from '../../contracts/display-types';
3
+ import type { SpatialDataPort } from '../../contracts/ports/spatial-data.port';
4
+ import type { SpatialDataset } from '../../contracts/spatial-dataset.contract';
5
+ import { PlanePlacement } from './napari-volume-region-meshes';
6
+ /**
7
+ * A 3D segmentation's cells in the spatial 3D view, each reconstructed by itself (see
8
+ * `geometry/cell-meshes`), where the region classes are otherwise one merged surface per class.
9
+ *
10
+ * Built to stay out of the way of the UI thread and the GPU:
11
+ * - the space is cut into chunks (a grid over the region set's bounds); each chunk is one surface
12
+ * layer of its cells, meshed in the cells' own worker, a few hundred cells per call, so the
13
+ * work is cancelled between calls when the view moves on (and the region tiles the 2D view
14
+ * reads never wait behind it);
15
+ * - level of detail by chunk: a coarse mesh everywhere first, then the chunks on screen are meshed
16
+ * finer as the camera comes close, within a triangle budget for the whole scene; the region
17
+ * set's tiles are read at the level of detail that mesh needs;
18
+ * - at most {@link CELLS_3D_MAX_CELLS} cells and {@link CELLS_3D_TRIANGLE_BUDGET} triangles, the
19
+ * chunks nearest the centre of the view first (one chunk over either by itself is meshed in
20
+ * part), planned again as each chunk's real size is learnt; the status says when cells are left
21
+ * out, so the view never claims to show them all;
22
+ * - colour and visibility change no geometry: colours are per vertex (each vertex's cell), and a
23
+ * hidden cell's triangles are left out of what is drawn.
24
+ * Builds report on the canvas's loading badge.
25
+ */
26
+ /** The most cells drawn at once. */
27
+ export declare const CELLS_3D_MAX_CELLS = 20000;
28
+ /** The most triangles every chunk together may have. */
29
+ export declare const CELLS_3D_TRIANGLE_BUDGET = 3000000;
30
+ export interface Cells3dHost {
31
+ readonly viewer: Viewer;
32
+ readonly port: SpatialDataPort | null;
33
+ /** Show the cells loading on the canvas until the returned function is called. */
34
+ beginTask(label: 'Cells'): () => void;
35
+ status(status: Cells3dStatus | null): void;
36
+ }
37
+ export type { Cells3dStatus };
38
+ export declare class Spatial3dCells {
39
+ private readonly host;
40
+ private dataset;
41
+ private source;
42
+ private classes;
43
+ private hidden;
44
+ private colors;
45
+ private visible;
46
+ /** The selection (null: none): the cells it leaves out fade, keeping their colours. */
47
+ private selected;
48
+ private opacity;
49
+ private placement;
50
+ private zScale;
51
+ private chunks;
52
+ private readonly byLayer;
53
+ private generation;
54
+ private timer;
55
+ private running;
56
+ private disposed;
57
+ /** Each surface's geometry as last set: a recolour that leaves it so uploads none again. */
58
+ private readonly installed;
59
+ private cameraOff;
60
+ constructor(host: Cells3dHost);
61
+ /** The dataset whose region set the cells are read from. */
62
+ setDataset(dataset: SpatialDataset | null): void;
63
+ /** The classes drawn as cells (none: the cells are not drawn). */
64
+ setClasses(classes: ReadonlySet<string> | null): void;
65
+ /** Classes hidden (the Region Editor's eyes): their cells are left out of what is drawn. */
66
+ setHiddenClasses(classes: readonly string[]): void;
67
+ /**
68
+ * Each observation's colour (RGBA 0..1) and whether it is shown (null: all), and the surfaces'
69
+ * opacity: the panel's Cell Color, groups and selection. Changes no geometry.
70
+ */
71
+ setStyle(colors: Float32Array | null, visible: Uint8Array | null, opacity: number, selected?: Uint8Array | null): void;
72
+ /** Where the planes are among the observations (null: nowhere, nothing drawn), and the Z stretch. */
73
+ setPlacement(placement: PlanePlacement | null, zScale: number): void;
74
+ /** The observation of the cell drawn under canvas point (`x`, `y`) (CSS px), or -1. */
75
+ pick(x: number, y: number): number;
76
+ /** Whether `layer` is one of the cells' surfaces. */
77
+ owns(layer: Layer): boolean;
78
+ dispose(): void;
79
+ private schedule;
80
+ /** Drop every chunk (their layers) and any build in flight. */
81
+ private reset;
82
+ private closeSource;
83
+ /** Decide each chunk's detail (and whether it is drawn at all), then build what changed. */
84
+ private plan;
85
+ /** {@link assignTiers} from the view as it is now, taking down what it leaves out. */
86
+ private replanTiers;
87
+ /** Voxel edge of each tier, image px: fractions of a typical cell's diameter. */
88
+ private steps;
89
+ /**
90
+ * The chunks, nearest the centre of the view first, with how many screen pixels an image pixel
91
+ * of each takes (0 off screen).
92
+ */
93
+ private priority;
94
+ /**
95
+ * Each chunk's tier: in order, within the cell cap, as fine as the screen asks within the
96
+ * triangle budget. The chunks last in order give up their detail first, then are left out; the
97
+ * first is never left out, but one over the cap or the budget by itself meshes only the cells
98
+ * that fit (its {@link Chunk.limit}).
99
+ */
100
+ private assignTiers;
101
+ /** A chunk's triangles at `tier`: as built, else scaled from a tier built (by the step's square). */
102
+ private trianglesAt;
103
+ /** Build every chunk whose tier changed, nearest first, one at a time, until none is left. */
104
+ private run;
105
+ private build;
106
+ /**
107
+ * Draw every chunk again (a recolour, a hidden class, a selection): a few at a time, yielding the
108
+ * main thread between them so that a click selecting a cell never holds a frame; a newer redraw
109
+ * takes over from this one.
110
+ */
111
+ private redraw;
112
+ private redrawGeneration;
113
+ /** Place a chunk's vertices in the world, in the cells' worker, then draw it (unless superseded). */
114
+ private placeChunk;
115
+ /** Draw a chunk's visible cells, in their colours: its layer updated in place, or added. */
116
+ private draw;
117
+ /**
118
+ * One of a chunk's surfaces with these triangles and colours: updated in place, added, or hidden
119
+ * when it has none. Returns the layer (null: none was ever needed).
120
+ */
121
+ private drawSurface;
122
+ /** The triangles of the cells shown: their class not hidden, the observation shown. */
123
+ private visibleFaces;
124
+ /**
125
+ * Each vertex its cell's colour (white without colours). With a selection, a cell it leaves out
126
+ * keeps its colour and fades, as a picked region fades the others: its alpha brought down to the
127
+ * dimmed regions' opacity. `solid`: the selected cells' own surface, every vertex opaque.
128
+ */
129
+ private vertexColors;
130
+ private dropLayer;
131
+ private report;
132
+ /** Tell the host how the cells stand, only when that changed (the camera re-plans often). */
133
+ private lastStatus;
134
+ private emit;
135
+ private toWorldPoint;
136
+ }
137
+ /**
138
+ * Triangles `faces` split by whether their cell (`vertexCell` of their first vertex) is selected:
139
+ * the selected cells' triangles, then the others'.
140
+ */
141
+ export declare function splitFaces(faces: Uint32Array, vertexCell: Uint32Array, selected: Uint8Array): [Uint32Array, Uint32Array];
@@ -12,6 +12,11 @@ import { SpatialSceneBase, SpatialSession } from './napari-spatial-scene';
12
12
  import type { NapariScene, SceneContext } from './napari-scene';
13
13
  /** The least Z stretch: a tenth of the true depth. */
14
14
  export declare const SPATIAL_Z_SCALE_MIN = 0.1;
15
+ /**
16
+ * In-plane voxels across the image when a region set's planes are reconstructed over the dataset's
17
+ * own image (see voxelStep): a step of about 5 px on a 5,700 px wide MERFISH section (0.6 µm).
18
+ */
19
+ export declare const REGION_PLANES_VOXELS = 1024;
15
20
  /**
16
21
  * The most a box's Z may be stretched: until it is twice as deep as it is wide, so even a section
17
22
  * microns thick and millimetres wide can be stood up into a block — but never less than the
@@ -62,6 +67,12 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
62
67
  /** The anatomical volume the cloud sits inside, when the dataset has one. */
63
68
  private volume;
64
69
  private volumeKey;
70
+ /**
71
+ * The reference volume on its way (its key and the load), shared by every rebuild that asks for
72
+ * it meanwhile: each one adding its own left one layer behind, which the view's toggle (bound to
73
+ * {@link volume}) then never hid.
74
+ */
75
+ private volumeLoading;
65
76
  /** Per-cluster density volumes drawn alongside the cloud, and what they were
66
77
  * built from — rasterising is seconds of work, so it must not repeat for a
67
78
  * change that cannot affect the field. */
@@ -107,6 +118,11 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
107
118
  private readonly transcripts3d;
108
119
  /** Whether the reference volume lets every region surface through (see setRegionsThroughVolume). */
109
120
  private regionsThrough;
121
+ /**
122
+ * Each slice's z, in the observations' units, of the region set the surfaces are built from when
123
+ * it says where its slices are (a 3D segmentation's planes, see setRegionPlanes); else null.
124
+ */
125
+ private regionPlanes;
110
126
  /** The store's invert setting, which the density volumes follow (no other subscription of
111
127
  * this scene carries it). */
112
128
  private invertSub;
@@ -115,10 +131,37 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
115
131
  * image, see showVolumeAsImage) when the dataset has a volume, which the regions are on
116
132
  */
117
133
  constructor(ctx: SceneContext, session: SpatialSession, info?: IImageInfo | undefined);
134
+ /** The region set's classes drawn as individual cells (none: the class surfaces only). */
135
+ private readonly cells3d;
136
+ private readonly cellLookup;
137
+ private readonly cellWindows;
138
+ private cellClasses;
139
+ /** What the cells were last coloured for, so a rebuild that changed none of it recolours nothing. */
140
+ private cellStyleKey;
141
+ private cellStyleRequest;
142
+ /**
143
+ * Draw these classes of the dataset's region set as individual cells, each its own surface in
144
+ * the panel's Cell Color (see Spatial3dCells); none: no cells.
145
+ */
146
+ setRegionCells(classes: readonly string[] | null): void;
147
+ /**
148
+ * The cells' colours (the panel's Cell Color, its selection muting), which are shown (its groups
149
+ * switched off and gene filter hide theirs; the Cells switch all), and their opacity.
150
+ */
151
+ private styleCells;
152
+ private lastCellSelection;
153
+ private cellSelectionCount;
154
+ private cellSelectionRev;
118
155
  /** Show these region reconstructions with the cloud (replacing the ones shown). */
119
156
  setRegionMeshes(meshes: readonly RegionMesh3D[]): void;
120
157
  setRegionHighlight(keys: readonly string[]): void;
121
158
  setRegionHidden(keys: readonly string[]): void;
159
+ /**
160
+ * Where the region set's slices are, in the observations' units (null: they are the plotted
161
+ * stack's slices): its surfaces then sit at their planes among the observations (see
162
+ * placeRegionMeshes), on an image of one plane too.
163
+ */
164
+ setRegionPlanes(z: readonly number[] | null): void;
122
165
  /** As the Volume view: the reference volume hides the surfaces behind what it shows, or none. */
123
166
  setRegionsThroughVolume(through: boolean): void;
124
167
  /**
@@ -128,6 +171,11 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
128
171
  * is offset to sit in it). Only when the plotted image IS that volume's stack: regions drawn on
129
172
  * another image (a tissue image) have no place in it, and are not shown - nor are surfaces
130
173
  * placed in a volume this one replaced.
174
+ *
175
+ * Unless the region set says where its slices are ({@link setRegionPlanes}: a 3D segmentation's
176
+ * planes) and the plotted image is the dataset's own (`imageRef`): image pixels are then taken
177
+ * back to the observations' units through `imageRef`, slice k to its plane's z, and both moved
178
+ * by the offset the cloud is, so each cell's surface sits around its observation.
131
179
  */
132
180
  private placeRegionMeshes;
133
181
  /**
@@ -136,9 +184,26 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
136
184
  * share its cached surface). Null while there is no volume stack to place them in.
137
185
  */
138
186
  voxelStep(): number | null;
187
+ /**
188
+ * Where the region set's slices go (see placeRegionMeshes): only with their planes known, on the
189
+ * dataset's own image (one with an `imageRef`, not the reference volume's stack), once the box
190
+ * the cloud is offset into is there.
191
+ */
192
+ private planePlacement;
139
193
  /** Whether the plotted image is the reference volume's stack: its size and slice count. */
140
194
  private isVolumeStack;
141
195
  mount(): Promise<void>;
196
+ /**
197
+ * Picking the region surfaces (a cell type's, by type), as the Volume view does: with the selection
198
+ * tool armed, a click on one picks its class (null beside them), and the Region Editor highlights
199
+ * it, the others fading. Hovering is the spatial tooltip's (the type and its cells).
200
+ */
201
+ private listenToRegionMeshes;
202
+ private meshPointer;
203
+ /** Gives the camera back napari-js's own depth range (see keepSceneInDepth). */
204
+ private restoreDepth;
205
+ private toolSub;
206
+ private selecting;
142
207
  /** The observations' own z is on screen: there is no plane to step. */
143
208
  setZ(): void;
144
209
  /** A cloud has no intensity distribution for the histogram pane. */
@@ -174,6 +239,19 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
174
239
  * observation whose section is hidden.
175
240
  */
176
241
  screenProjection(obs: SpatialObservations): Float32Array | null;
242
+ /** The region surface (a class) under a client position, or null. */
243
+ pickRegion(clientX: number, clientY: number): {
244
+ key: string;
245
+ label?: string;
246
+ } | null;
247
+ /**
248
+ * With a selection, grey out the class surfaces none of it is in (a class is a category of the
249
+ * cell-type column: a 3D segmentation's cell type), as the observations it leaves out are muted.
250
+ */
251
+ private muteRegions;
252
+ private muteRequest;
253
+ /** The observation of the individual cell drawn under a client position, or -1. */
254
+ pickCell(clientX: number, clientY: number): number;
177
255
  dispose(): void;
178
256
  /**
179
257
  * The observation under a client position: the FRONT-most marker within `slackPx` of the
@@ -208,6 +286,13 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
208
286
  * source swapped in place otherwise; then the selection and the visibility.
209
287
  */
210
288
  private drawCloud;
289
+ /**
290
+ * The markers shown as the view asks, but not while the cells (a 3D segmentation's) stand in for
291
+ * them: the observations are shown as their markers or as their cells. Only once the set is placed
292
+ * here (its planes known): a set that could not be opened, has no planes or was not attached draws
293
+ * no cells, and the markers stay.
294
+ */
295
+ private showPointsAsAsked;
211
296
  /** Interleaved x,y,z of the `shown` observations (null: all of them), offset by {@link origin}. */
212
297
  private cloudPositions;
213
298
  /**
@@ -287,6 +372,8 @@ export declare class Spatial3dScene extends SpatialSceneBase implements NapariSc
287
372
  * the camera frames the points instead.
288
373
  */
289
374
  private ensureVolume;
375
+ /** Fetch the reference volume and add it, unless another one was asked for meanwhile. */
376
+ private loadVolume;
290
377
  /**
291
378
  * The box everything sits in, centred on the world origin, and the offset that sits the
292
379
  * observations in it; with the axes gizmo and the Z handle on it.
@@ -2,6 +2,7 @@ import type { Points3DLayer, Viewer } from 'napari-js';
2
2
  import { type SpatialDataPort } from '../../contracts/ports/spatial-data.port';
3
3
  import type { SpatialViewState } from '../../contracts/display-types';
4
4
  import { type SpatialDataset } from '../../contracts/spatial-dataset.contract';
5
+ import type { SpatialSelectionMask } from '../../spatial/spatial-selection';
5
6
  /** Most transcripts drawn in the 3D view: past it, every k-th one is drawn (and the console says so). */
6
7
  export declare const TRANSCRIPTS_3D_MAX = 2000000;
7
8
  /** Most level-0 tiles read for the 3D view: a dataset needing more is too large to draw whole. */
@@ -32,12 +33,15 @@ export declare function transcripts3dColors(view: SpatialViewState, names: reado
32
33
  */
33
34
  export declare function transcripts3dColorBy(dataset: SpatialDataset, view: SpatialViewState, allGenes: boolean): 'cellType' | 'cluster' | 'gene';
34
35
  /**
35
- * The transcripts of the 3D spatial view: every molecule of the genes the Transcripts panel draws
36
- * (its selected genes, or "All genes"), at its own x, y and z, in the cloud's box and Z stretch.
36
+ * The transcripts of the 3D spatial view: the molecules of the genes the Transcripts panel draws
37
+ * (its selected genes, or "All genes"), at their own x, y and z, in the cloud's box and Z stretch.
37
38
  *
38
- * The 2D view reads transcripts by level of detail for the camera; a 3D orbit has no such window,
39
- * so this reads the whole level 0 once per gene selection (a few hundred thousand molecules for a
40
- * MERFISH section) and only restyles after that. Drawn only for a dataset whose transcripts carry z.
39
+ * By level of detail, as the 2D view reads them: the pyramid level the camera's distance calls for
40
+ * (`transcriptLevelFor`, the markers per screen kept about constant: aggregates far out, every
41
+ * molecule close in on a cell), and only the tiles of the part of the section in view (the canvas's
42
+ * corners cast onto the section's plane). Planned again when the camera rests; tiles are cached, so
43
+ * coming back reads nothing. "Loading transcripts…" shows on the canvas while they load and draw.
44
+ * Drawn only for a dataset whose transcripts carry z.
41
45
  */
42
46
  export declare class Spatial3dTranscripts {
43
47
  private readonly viewer;
@@ -48,15 +52,52 @@ export declare class Spatial3dTranscripts {
48
52
  private styleKey;
49
53
  private loaded;
50
54
  private readonly loads;
51
- constructor(viewer: Viewer, begin: (label: 'Transcripts') => () => void);
55
+ /** Each drawn transcript's cell ({@link NO_OBSERVATION} for none), for fading by the selection. */
56
+ private drawnCells;
57
+ /** The selection the layer's alphas fade by (null: none, every transcript as it is). */
58
+ private fadedBy;
59
+ /** The last sync's inputs: the camera resting plans the detail again from them. */
60
+ private last;
61
+ private cameraTimer;
62
+ private cameraOff;
63
+ /** Tiles read, by genes, quality, level and tile (least recently used dropped first). */
64
+ private readonly tileCache;
65
+ constructor(viewer: Viewer, begin: (message: string) => () => void);
66
+ /** The camera moved: once it rests, read the level and tiles it now calls for. */
67
+ private cameraMoved;
68
+ /** Stop following the camera (the scene went away). */
69
+ dispose(): void;
70
+ /**
71
+ * The level and the tiles the camera calls for: the level whose tiles come out about 512 screen
72
+ * pixels across at the target's depth, the tiles of the section in view (whole, when a corner of
73
+ * the canvas looks past the section's plane).
74
+ */
75
+ private plan;
76
+ /**
77
+ * The part of the section the canvas sees, in observation units: its corners and centre cast onto
78
+ * the plane through the camera's target, widened by a quarter. A corner looking past the plane
79
+ * (towards the horizon) reaches far along its ray instead (the tiles are clipped to the section).
80
+ */
81
+ private footprint;
82
+ /** A tile, read once (and again only once dropped from the cache). */
83
+ private tile;
52
84
  /** The layer drawn, if any (for tests and the scene's Z stretch). */
53
85
  get drawn(): Points3DLayer | null;
54
- /** Draw what `view` asks for, loading the molecules when the genes changed. */
55
- sync(dataset: SpatialDataset, view: SpatialViewState, port: SpatialDataPort | null, frame: Transcripts3dFrame): Promise<void>;
86
+ /**
87
+ * Draw what `view` asks for, loading the molecules when the genes changed. With a `selection`
88
+ * (a cell, or a cell type's cells), the transcripts of the selected cells keep their colour and
89
+ * the others fade, as the cells do.
90
+ */
91
+ sync(dataset: SpatialDataset, view: SpatialViewState, port: SpatialDataPort | null, frame: Transcripts3dFrame, selection?: SpatialSelectionMask | null): Promise<void>;
56
92
  /** Follow the scene's Z stretch (nothing is re-uploaded). */
57
93
  setZScale(s: number): void;
58
94
  /** Take the layer down and forget what it showed. */
59
95
  remove(): void;
60
96
  private clearLayer;
97
+ /**
98
+ * Fade the drawn transcripts outside the selection (their alpha only: the colours stay
99
+ * uploaded), or bring them all back without one. A no-op for the selection already applied.
100
+ */
101
+ private fade;
61
102
  private draw;
62
103
  }
@@ -23,6 +23,16 @@ export interface SpatialHoverHost {
23
23
  * drawn index back to the observation.
24
24
  */
25
25
  pick(clientX: number, clientY: number, slackPx: number): number;
26
+ /**
27
+ * The observation of an individual cell's surface under a client position (spatial 3D's cells),
28
+ * or -1: a click on one selects that cell rather than its class. Optional.
29
+ */
30
+ pickCell?(clientX: number, clientY: number): number;
31
+ /** The region surface (a class: a cell type's, in spatial 3D) under a client position, or null. Optional. */
32
+ pickRegion?(clientX: number, clientY: number): {
33
+ key: string;
34
+ label?: string;
35
+ } | null;
26
36
  /** The 2D transcript markers, which sit on top of everything and are asked first. */
27
37
  tiles(): NapariSpatialTileLayers | null;
28
38
  /** A region tool owns the pointer (placing a polygon vertex is also a still click). */
@@ -47,6 +57,10 @@ export declare class SpatialHover {
47
57
  /** What the markers are coloured by, resolved once per colour source rather than per hover. */
48
58
  private hoverSource;
49
59
  private hoverSourceKey;
60
+ /** In 3D: what a cell's tooltip says of it (its type, id, measurements), resolved once per dataset. */
61
+ private cellInfo;
62
+ private cellInfoKey;
63
+ private readonly cellInfoLoads;
50
64
  /** Latest wins within the scene: the KEY is only committed once a resolution lands, so a
51
65
  * superseded fetch cannot leave the cache claiming to hold a source it never stored. */
52
66
  private readonly resolutions;
@@ -75,6 +89,14 @@ export declare class SpatialHover {
75
89
  * the pointer moved would be indefensible either way.
76
90
  */
77
91
  resolveSource(dataset: SpatialDataset | null, view: SpatialViewState): Promise<void>;
92
+ /**
93
+ * What a 3D cell's tooltip says (see `cellText`): the cell-type column's codes, the ids, and the
94
+ * dataset's first few continuous columns. Resolved once per dataset and type column; a failure
95
+ * leaves the tooltip with what the colouring says.
96
+ */
97
+ private resolveCellInfo;
98
+ /** In 3D: the tooltip of the cell, or of the cell type's surface, under a client position. */
99
+ private cell3dText;
78
100
  /** Hit-test the last pointer position and show or hide the tooltip. */
79
101
  private update;
80
102
  /**
@@ -1,3 +1,4 @@
1
+ import type { Cells3dStatus } from '../../contracts/display-types';
1
2
  import { Observable } from 'rxjs';
2
3
  import { SpatialDataPort } from '../../contracts/ports/spatial-data.port';
3
4
  import { SpatialDataset } from '../../contracts/spatial-dataset.contract';
@@ -28,6 +29,8 @@ export interface SpatialTileSinks {
28
29
  loadingChanged(layers: string[]): void;
29
30
  /** Whether the observation gene filter could be applied; see {@link SpatialSession.reportGeneFilter}. */
30
31
  geneFilterFailed?(failed: boolean): void;
32
+ /** How the 3D view's individual cells stand; see {@link SpatialSession.reportCells3d}. */
33
+ cells3dStatus?(status: Cells3dStatus | null): void;
31
34
  }
32
35
  /** The 2D scene the tile layers currently draw into. */
33
36
  export interface SpatialTileOwner {
@@ -66,6 +69,8 @@ export declare class SpatialSession {
66
69
  private tileLayers;
67
70
  private tileOwner;
68
71
  constructor(port: SpatialDataPort | null, selection: SpatialSelectionStore | null, sinks: SpatialTileSinks);
72
+ /** Tell the panel how the 3D view's individual cells stand (null: none drawn). */
73
+ reportCells3d(status: Cells3dStatus | null): void;
69
74
  /** Tell the panel whether the observation gene filter could be applied this rebuild. */
70
75
  reportGeneFilter(failed: boolean): void;
71
76
  /** The tile layers, if they were ever built. */
@@ -116,6 +121,13 @@ export declare abstract class SpatialSceneBase {
116
121
  protected afterChange(): void;
117
122
  /** The observation drawn under a client position, or -1 (see `SpatialHoverHost.pick`). */
118
123
  protected abstract pickObservation(clientX: number, clientY: number, slackPx: number): number;
124
+ /** The region surface (a class) under a client position, or null (none drawn). */
125
+ pickRegion(_clientX: number, _clientY: number): {
126
+ key: string;
127
+ label?: string;
128
+ } | null;
129
+ /** The observation of an individual cell's surface under a client position, or -1 (none drawn). */
130
+ pickCell(_clientX: number, _clientY: number): number;
119
131
  protected hoverTiles(): NapariSpatialTileLayers | null;
120
132
  /** Stop following the data, drop the hover, and make every rebuild in flight stale. */
121
133
  protected disposeSpatial(): void;
@@ -67,6 +67,10 @@ export declare class NapariSpatialTileLayers {
67
67
  /** Consecutive retries of an incomplete view. */
68
68
  private tileRetries;
69
69
  private token;
70
+ /** The z band of the plane shown, when the view shows one plane of a 3D assay (see setZBand). */
71
+ private zBand;
72
+ /** The plane of a 3D segmentation shown (see setPlane), or null. */
73
+ private plane;
70
74
  /** The overlays' layers, one per group, in their fixed order. */
71
75
  private readonly groups;
72
76
  /** Loads in flight, per layer label, for the loading badge. */
@@ -100,6 +104,17 @@ export declare class NapariSpatialTileLayers {
100
104
  get densityStats(): DensityStats | null;
101
105
  /** Dataset, view or selection changed: re-plan now rather than on camera idle. */
102
106
  refresh(): void;
107
+ /**
108
+ * Show one plane of a 3D assay (its z band, `[lo, hi)` in observation units), or every depth
109
+ * (null): the transcripts drawn are those in the band. Re-plans when it changes.
110
+ */
111
+ setZBand(band: readonly [number, number] | null): void;
112
+ /**
113
+ * Show plane `plane` of a 3D segmentation (an index into its region set's planes), or none: a
114
+ * boundary set naming its region set draws that plane's cells (see `CellLayers.setPlane`).
115
+ * Re-plans when it changes.
116
+ */
117
+ setPlane(plane: number | null): void;
103
118
  /** Called right after the service adds its marker layer: everything goes back on top. */
104
119
  afterObservations(): void;
105
120
  private schedule;
@@ -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). */