@jax-data-science/sci-image-visualizer 0.9.0 → 0.10.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/index.mjs +7 -1
- package/esm2022/lib/contracts/image.contract.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/section-view.contract.mjs +2 -0
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/contracts/viz-config.mjs +1 -1
- package/esm2022/lib/geometry/loft.mjs +128 -0
- package/esm2022/lib/geometry/polylabel.mjs +156 -0
- package/esm2022/lib/geometry/reconstruct.mjs +315 -0
- package/esm2022/lib/geometry/reslice-image.mjs +57 -0
- package/esm2022/lib/geometry/section.mjs +215 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
- package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
- package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
- package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
- package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
- package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
- package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
- package/esm2022/lib/models/class-preset.mjs +1 -1
- package/esm2022/lib/models/polygon-factory.mjs +17 -1
- package/esm2022/lib/models/region-geojson.mjs +44 -6
- package/esm2022/lib/models/region.mjs +1 -1
- package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
- package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
- package/esm2022/lib/region-editor/region-editor.component.mjs +527 -42
- package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
- package/esm2022/lib/region-editor/region-persistence.service.mjs +36 -10
- package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
- package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
- package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
- package/esm2022/lib/region-overlay/region-style.mjs +97 -0
- package/esm2022/lib/region-source/http-region-source.mjs +104 -0
- package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
- package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
- package/esm2022/lib/region-source/region-source.mjs +67 -0
- package/esm2022/lib/region-source/region-tiles.mjs +708 -0
- package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
- package/esm2022/lib/routing-visualizer.service.mjs +418 -22
- package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
- package/esm2022/lib/store/class-color.util.mjs +10 -5
- package/esm2022/lib/store/class-signatures.mjs +63 -0
- package/esm2022/lib/store/region-scope-cache.mjs +5 -1
- package/esm2022/lib/store/region-source-scope.mjs +171 -0
- package/esm2022/lib/store/region-store.service.mjs +724 -12
- package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
- package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
- package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
- package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
- package/esm2022/lib/visualizer/region-load.mjs +67 -4
- package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
- package/esm2022/lib/visualizer.component.mjs +128 -6
- package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs} +7239 -1153
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs} +4 -4
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
- package/fesm2022/region-source.worker.js +1067 -0
- package/index.d.ts +6 -0
- package/lib/contracts/image.contract.d.ts +4 -0
- package/lib/contracts/region-editor-api.contract.d.ts +84 -0
- package/lib/contracts/region-store.contract.d.ts +22 -0
- package/lib/contracts/section-view.contract.d.ts +44 -0
- package/lib/contracts/visualizer.contract.d.ts +10 -0
- package/lib/contracts/viz-config.d.ts +8 -0
- package/lib/geometry/loft.d.ts +22 -0
- package/lib/geometry/polylabel.d.ts +23 -0
- package/lib/geometry/reconstruct.d.ts +54 -0
- package/lib/geometry/reslice-image.d.ts +33 -0
- package/lib/geometry/section.d.ts +52 -0
- package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
- package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
- package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
- package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
- package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
- package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
- package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
- package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
- package/lib/models/class-preset.d.ts +7 -0
- package/lib/models/polygon-factory.d.ts +5 -0
- package/lib/models/region-geojson.d.ts +40 -0
- package/lib/models/region.d.ts +19 -0
- package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
- package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
- package/lib/region-editor/region-editor.component.d.ts +133 -17
- package/lib/region-editor/region-metrics.d.ts +8 -0
- package/lib/region-editor/region-persistence.service.d.ts +12 -4
- package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
- package/lib/region-overlay/region-geometry.d.ts +4 -3
- package/lib/region-overlay/region-source-layer.d.ts +96 -0
- package/lib/region-overlay/region-style.d.ts +52 -0
- package/lib/region-source/http-region-source.d.ts +45 -0
- package/lib/region-source/region-source-ops.d.ts +89 -0
- package/lib/region-source/region-source-worker.d.ts +7 -0
- package/lib/region-source/region-source.d.ts +82 -0
- package/lib/region-source/region-tiles.d.ts +289 -0
- package/lib/region-source/worker-region-source.d.ts +65 -0
- package/lib/routing-visualizer.service.d.ts +138 -1
- package/lib/section-pane/section-pane.component.d.ts +47 -0
- package/lib/store/class-color.util.d.ts +6 -3
- package/lib/store/class-signatures.d.ts +11 -0
- package/lib/store/region-scope-cache.d.ts +2 -0
- package/lib/store/region-source-scope.d.ts +68 -0
- package/lib/store/region-store.service.d.ts +206 -2
- package/lib/store/visualizer-store.service.d.ts +10 -0
- package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
- package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
- package/lib/toolbar/toolbar.component.d.ts +9 -2
- package/lib/visualizer/region-load.d.ts +23 -4
- package/lib/visualizer/volume-sections.d.ts +64 -0
- package/lib/visualizer.component.d.ts +31 -0
- package/package.json +2 -2
- package/src/lib/assets/slice.svg +23 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
|
@@ -23,6 +23,9 @@ import { CellSegmentToolService } from '../../toolbar/segmentation/cell-segment-
|
|
|
23
23
|
import { BaseStoreVisualizer } from '../base-store-visualizer';
|
|
24
24
|
import { SimpleSliceAccessService } from '../simple-slice-access.service';
|
|
25
25
|
import { TranscriptEstimate } from './napari-spatial-tiles';
|
|
26
|
+
import { VolumeVoxelsOnScreen } from './napari-scene';
|
|
27
|
+
import type { PlaneAxis, SlicePlanes } from './napari-volume-slice-planes';
|
|
28
|
+
import type { RegionMesh3D } from './napari-volume-region-meshes';
|
|
26
29
|
import * as i0 from "@angular/core";
|
|
27
30
|
/** Opaque handle from {@link NapariVisualizerService.load}, passed back to plot(). */
|
|
28
31
|
interface NapariLoaded {
|
|
@@ -90,6 +93,20 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
|
|
|
90
93
|
private lifetime;
|
|
91
94
|
/** What {@link plot} mounted, while it is mounted. */
|
|
92
95
|
private scene;
|
|
96
|
+
/** Region reconstructions to show in a volume view, kept across re-plots of their image. */
|
|
97
|
+
private regionMeshes;
|
|
98
|
+
/** The image (file name) {@link regionMeshes} were built from. */
|
|
99
|
+
private regionMeshesImage;
|
|
100
|
+
/** The keys of the reconstructions highlighted. */
|
|
101
|
+
private regionHighlight;
|
|
102
|
+
/** The keys of the reconstructions hidden. */
|
|
103
|
+
private regionHidden;
|
|
104
|
+
/** The planes of the sections beside a volume view, or none. */
|
|
105
|
+
private slicePlanes;
|
|
106
|
+
/** A section's plane dragged in the volume (see {@link getSlicePlaneMove$}). */
|
|
107
|
+
private readonly slicePlaneMove$;
|
|
108
|
+
/** Clicks on the reconstructions (see {@link getRegionMeshPick$}). */
|
|
109
|
+
private readonly regionMeshPick$;
|
|
93
110
|
/** Spatial state that outlives a scene (latest data, windows, estimated gene-map fields). */
|
|
94
111
|
private readonly spatial;
|
|
95
112
|
/** Viewer settings that outlive a scene. */
|
|
@@ -136,12 +153,43 @@ export declare class NapariVisualizerService extends BaseStoreVisualizer impleme
|
|
|
136
153
|
private fitCameraSoon;
|
|
137
154
|
/** @deprecated Plotly-specific; host re-drives plot() from its image stream. */
|
|
138
155
|
reloadAndPlot(): void;
|
|
156
|
+
/** Show `message` on the canvas's loading badge until the returned function is called. */
|
|
157
|
+
beginTask(message: string): () => void;
|
|
158
|
+
/** Show these region reconstructions of `image` in the volume view (kept for its next volume plot). */
|
|
159
|
+
setRegionMeshes(meshes: readonly RegionMesh3D[], image: string | undefined): void;
|
|
160
|
+
/** Highlight the reconstructions of these keys (none: all as usual). */
|
|
161
|
+
setRegionHighlight(keys: readonly string[]): void;
|
|
162
|
+
/** Hide the reconstructions of these keys (kept for the next volume plot). */
|
|
163
|
+
setRegionHidden(keys: readonly string[]): void;
|
|
164
|
+
/** Draw the reconstructions through the volume rather than hidden behind it (kept across plots). */
|
|
165
|
+
setRegionsThroughVolume(through: boolean): void;
|
|
166
|
+
private regionsThroughVolume;
|
|
167
|
+
/** Show the planes of the sections beside a volume view (null: hide one); kept across plots. */
|
|
168
|
+
setSlicePlanes(planes: SlicePlanes): void;
|
|
169
|
+
/** A section's plane dragged in the volume view, to `value` along its axis (image px, or a slice). */
|
|
170
|
+
getSlicePlaneMove$(): Observable<{
|
|
171
|
+
axis: PlaneAxis;
|
|
172
|
+
value: number;
|
|
173
|
+
}>;
|
|
174
|
+
/** The volume on screen, as assembled (see VolumeScene.volumeVoxels); null outside a volume view. */
|
|
175
|
+
volumeVoxels(): VolumeVoxelsOnScreen | null;
|
|
176
|
+
/** A reconstruction clicked with the selection tool (its key), or the volume beside them (null). */
|
|
177
|
+
getRegionMeshPick$(): Observable<{
|
|
178
|
+
key: string | null;
|
|
179
|
+
additive: boolean;
|
|
180
|
+
}>;
|
|
181
|
+
/** Image px per voxel of the volume on screen, in-plane; null outside a volume view. */
|
|
182
|
+
regionVoxelStep(): number | null;
|
|
139
183
|
/**
|
|
140
184
|
* End the mounted scene: abort its lifetime (its descriptor poll, tile counts, frame loading and
|
|
141
185
|
* awaits) and dispose it — its layers, keys, subscriptions and listeners go with it, so the next
|
|
142
186
|
* plot can never inherit an "already built" key (NAPARI-SVC-1) — then tear the viewer down.
|
|
143
187
|
*/
|
|
144
188
|
reset(): void;
|
|
189
|
+
/**
|
|
190
|
+
* The plot area changed size (the slice editor split it, a divider moved): fit the canvas, whose
|
|
191
|
+
* height was fixed at plot time, to it again.
|
|
192
|
+
*/
|
|
145
193
|
relayout(_trueImageSize?: number[]): void;
|
|
146
194
|
/** @deprecated Plotly-specific axis reset. */
|
|
147
195
|
resetAxes(): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Viewer } from 'napari-js';
|
|
2
|
+
/** A region's 3D reconstruction to show in the volume: a mesh in image px (x, y) and slices (z). */
|
|
3
|
+
export interface RegionMesh3D {
|
|
4
|
+
/** Identity (a class name): a mesh with the same key and arrays is kept, not rebuilt. */
|
|
5
|
+
key: string;
|
|
6
|
+
/** `#rrggbb`. */
|
|
7
|
+
color: string;
|
|
8
|
+
/** What hovering it shows ("HPF · Hippocampal formation"); default: the key. */
|
|
9
|
+
label?: string;
|
|
10
|
+
vertices: Float32Array;
|
|
11
|
+
faces: Uint32Array;
|
|
12
|
+
}
|
|
13
|
+
/** Where the stack sits in the volume's world: its full size, and the centred world box it fills. */
|
|
14
|
+
export interface VolumeFrame {
|
|
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
|
+
}
|
|
20
|
+
/** Opacity of a region's surface in the volume. */
|
|
21
|
+
export declare const REGION_MESH_OPACITY = 0.55;
|
|
22
|
+
/** While some surfaces are highlighted: theirs (near opaque, so their shape reads) … */
|
|
23
|
+
export declare const REGION_MESH_HIGHLIGHT_OPACITY = 0.9;
|
|
24
|
+
/** … and the others' (ghosted: still there for context, not in the way). */
|
|
25
|
+
export declare const REGION_MESH_DIMMED_OPACITY = 0.12;
|
|
26
|
+
/**
|
|
27
|
+
* The region reconstructions shown in a volume view: one translucent surface per region, in its
|
|
28
|
+
* 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) and re-placed when the volume's Z is stretched. A surface is updated in
|
|
30
|
+
* place (`setData`, `color`) rather than added again, and picked by napari-js (`pickSurface`).
|
|
31
|
+
*
|
|
32
|
+
* Highlighting is focus + context: the highlighted surfaces turn near opaque and the others fade
|
|
33
|
+
* to a ghost, so the selection stands out while staying in place among its neighbours.
|
|
34
|
+
*/
|
|
35
|
+
export declare class VolumeRegionMeshes {
|
|
36
|
+
private readonly viewer;
|
|
37
|
+
private readonly layers;
|
|
38
|
+
private highlighted;
|
|
39
|
+
private hidden;
|
|
40
|
+
/** The meshes to show (kept while the volume has no frame yet). */
|
|
41
|
+
private wanted;
|
|
42
|
+
private frame;
|
|
43
|
+
constructor(viewer: Viewer);
|
|
44
|
+
/** Show exactly `meshes` (adding, keeping or removing surfaces). */
|
|
45
|
+
set(meshes: readonly RegionMesh3D[]): void;
|
|
46
|
+
/** Follow the volume's frame (it opened, or its Z was stretched): re-place every surface. */
|
|
47
|
+
setFrame(frame: VolumeFrame): void;
|
|
48
|
+
/** Highlight the surfaces of these keys (none: every surface as usual). */
|
|
49
|
+
setHighlight(keys: Iterable<string>): void;
|
|
50
|
+
/** Hide the surfaces of these keys (they are kept, so showing them again is instant). */
|
|
51
|
+
setHidden(keys: Iterable<string>): void;
|
|
52
|
+
/** The front-most surface under screen point (`x`, `y`) (canvas CSS px), or null. */
|
|
53
|
+
pickAt(x: number, y: number): RegionMesh3D | null;
|
|
54
|
+
/** The meshes shown. */
|
|
55
|
+
get shown(): RegionMesh3D[];
|
|
56
|
+
clear(): void;
|
|
57
|
+
private sync;
|
|
58
|
+
private add;
|
|
59
|
+
private opacityOf;
|
|
60
|
+
private remove;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Image px / slice coordinates → the volume's centred world box: pixel x of a `w`-wide image
|
|
64
|
+
* spans the box's width, slice k sits at the middle of its share of the box's depth.
|
|
65
|
+
*/
|
|
66
|
+
export declare function toWorld(vertices: Float32Array, frame: VolumeFrame): Float32Array;
|
|
@@ -4,7 +4,9 @@ import { IImageInfo } from '../../contracts/image.contract';
|
|
|
4
4
|
import { IHistogram } from '../../contracts/channel-histogram-api.contract';
|
|
5
5
|
import { IIsosurfaceControls, ISurface3dControls } from '../../contracts/visualizer.contract';
|
|
6
6
|
import { Axes3dGizmo, Box3 } from './napari-axes-gizmo';
|
|
7
|
-
import type { NapariScene, SceneContext } from './napari-scene';
|
|
7
|
+
import type { NapariScene, SceneContext, VolumeVoxelsOnScreen } from './napari-scene';
|
|
8
|
+
import { RegionMesh3D } from './napari-volume-region-meshes';
|
|
9
|
+
import { SlicePlanes } from './napari-volume-slice-planes';
|
|
8
10
|
/**
|
|
9
11
|
* NAPARI_VOLUME / NAPARI_ISOSURFACE (review Appendix B, cluster F): the stack assembled into a
|
|
10
12
|
* decimated volume — one additive, tinted `VolumeLayer` per channel for a multichannel image, a
|
|
@@ -29,7 +31,49 @@ export declare class VolumeScene implements NapariScene {
|
|
|
29
31
|
gizmo: Axes3dGizmo | null;
|
|
30
32
|
private zHandle;
|
|
31
33
|
private displaySub;
|
|
34
|
+
/** Regions' 3D reconstructions shown in the volume (see {@link setRegionMeshes}). */
|
|
35
|
+
private readonly regionMeshes;
|
|
36
|
+
/** The planes of the sections shown beside the volume, marked and draggable in it. */
|
|
37
|
+
private readonly slicePlanes;
|
|
38
|
+
/** The image's full size (px, px, slices), which reconstructions are in. */
|
|
39
|
+
private fullSize;
|
|
40
|
+
/** Clicks and hover on the reconstructions (with the selection tool). */
|
|
41
|
+
private meshPointer;
|
|
42
|
+
private toolSub;
|
|
43
|
+
private selecting;
|
|
32
44
|
constructor(ctx: SceneContext, info: IImageInfo | undefined, rendering: 'iso' | 'mip');
|
|
45
|
+
/** Show these region reconstructions in the volume (replacing the ones shown). */
|
|
46
|
+
setRegionMeshes(meshes: readonly RegionMesh3D[]): void;
|
|
47
|
+
setRegionHighlight(keys: readonly string[]): void;
|
|
48
|
+
setRegionHidden(keys: readonly string[]): void;
|
|
49
|
+
/** Whether the volume lets every region through (see {@link setRegionsThroughVolume}). */
|
|
50
|
+
private regionsThrough;
|
|
51
|
+
/**
|
|
52
|
+
* The volume hides the region reconstructions behind what it shows (its brightest sample along
|
|
53
|
+
* each ray, napari-js's `'translucent'` depth) — the perspective of a region behind the
|
|
54
|
+
* cerebellum — or, `through`, hides none (`'translucent_no_depth'`): surfaces traced inside its
|
|
55
|
+
* bright structures, an OCT's layer boundaries in its bright bands, which that depth speckles
|
|
56
|
+
* or hides. A multichannel volume's channels add up and hide nothing either way.
|
|
57
|
+
*/
|
|
58
|
+
setRegionsThroughVolume(through: boolean): void;
|
|
59
|
+
private applyVolumeDepth;
|
|
60
|
+
/** Show the planes of the sections beside the volume where they are (null: hide one). */
|
|
61
|
+
setSlicePlanes(planes: SlicePlanes): void;
|
|
62
|
+
/**
|
|
63
|
+
* The assembled volume's voxels per channel (key 0: the grayscale one), its frame, and whether
|
|
64
|
+
* it is a multichannel composite — what the sections beside it are cut from. Null before it is
|
|
65
|
+
* assembled.
|
|
66
|
+
*/
|
|
67
|
+
volumeVoxels(): VolumeVoxelsOnScreen | null;
|
|
68
|
+
/**
|
|
69
|
+
* Picking the reconstructions: with the selection tool armed, a click on one selects its class
|
|
70
|
+
* (null beside them); resting over one names it, whatever the tool.
|
|
71
|
+
*/
|
|
72
|
+
private listenToRegionMeshes;
|
|
73
|
+
/** Image px per voxel of the assembled volume (in-plane), or null before it is assembled. */
|
|
74
|
+
voxelStep(): number | null;
|
|
75
|
+
/** Place the region reconstructions in the volume's world box as it is now. */
|
|
76
|
+
private frameRegionMeshes;
|
|
33
77
|
/**
|
|
34
78
|
* Assemble and render the volume, then add the axes gizmo + labels and the Z handle and follow
|
|
35
79
|
* the display state.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Viewer } from 'napari-js';
|
|
2
|
+
import type { VolumeFrame } from './napari-volume-region-meshes';
|
|
3
|
+
/** A plane across the volume: x = const, y = const (image px) or z = const (a slice). */
|
|
4
|
+
export type PlaneAxis = 'x' | 'y' | 'z';
|
|
5
|
+
/** Where each plane is (image px for x and y, the slice for z); null: not shown. */
|
|
6
|
+
export type SlicePlanes = Record<PlaneAxis, number | null>;
|
|
7
|
+
/** Each plane's colour: its axis's, as the axes gizmo draws them. */
|
|
8
|
+
export declare const SLICE_PLANE_COLORS: Readonly<Record<PlaneAxis, string>>;
|
|
9
|
+
/** A plane's opacity: enough to read where it is, not to hide the volume behind it … */
|
|
10
|
+
export declare const SLICE_PLANE_OPACITY = 0.22;
|
|
11
|
+
/** … and while it is dragged. */
|
|
12
|
+
export declare const SLICE_PLANE_DRAG_OPACITY = 0.4;
|
|
13
|
+
export interface SlicePlanesOptions {
|
|
14
|
+
/** A plane dragged to `value` along its axis (image px, or a fractional slice). */
|
|
15
|
+
onMove(axis: PlaneAxis, value: number): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The planes of the sections shown beside a volume view: napari-js's {@link SlicePlanesWidget}
|
|
19
|
+
* (translucent quads in their axis's colour, each with a grip that drags it along its axis) over
|
|
20
|
+
* the stack's frame. It works in the frame's image px and slices: the widget's box is the image,
|
|
21
|
+
* one voxel per px, so a px position is the widget's shifted by half a pixel (pixel i spans
|
|
22
|
+
* [i, i + 1) here, is centred on i there); a slice is the same in both.
|
|
23
|
+
*/
|
|
24
|
+
export declare class VolumeSlicePlanes {
|
|
25
|
+
private readonly viewer;
|
|
26
|
+
private readonly host;
|
|
27
|
+
private readonly opts;
|
|
28
|
+
private widget;
|
|
29
|
+
private frame;
|
|
30
|
+
private planes;
|
|
31
|
+
/** Set while the planes are moved from here, so the widget's echo is not reported as a drag. */
|
|
32
|
+
private applying;
|
|
33
|
+
constructor(viewer: Viewer, host: HTMLElement, opts: SlicePlanesOptions);
|
|
34
|
+
/** Follow the volume's frame (it opened, or its Z was stretched). */
|
|
35
|
+
setFrame(frame: VolumeFrame): void;
|
|
36
|
+
/** Show the planes where they are now (null: hide one). */
|
|
37
|
+
set(planes: SlicePlanes): void;
|
|
38
|
+
clear(): void;
|
|
39
|
+
destroy(): void;
|
|
40
|
+
/** The widget over the current frame, made when there is one and a plane to show. */
|
|
41
|
+
private rebuild;
|
|
42
|
+
private apply;
|
|
43
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Region } from '../../models/region';
|
|
2
2
|
import { ScreenLayer } from '../../region-overlay/svg-region-renderer';
|
|
3
|
+
import { RegionStyle } from '../../region-overlay/region-style';
|
|
3
4
|
/**
|
|
4
5
|
* The OpenSeadragon region overlay's look: region stroke/fill, labels, the
|
|
5
6
|
* selected region's handles, the marquee and the in-progress drawing. Pure SVG
|
|
@@ -12,14 +13,14 @@ type Pt = {
|
|
|
12
13
|
};
|
|
13
14
|
/** `color` with `alpha`; a colour that doesn't parse (a named one) is used as-is. */
|
|
14
15
|
export declare function rgba(color: string, alpha: number): string;
|
|
15
|
-
/** Stroke/fill for a region shape (drawn in image coordinates by the renderer)
|
|
16
|
-
export declare function styleRegionShape(el: SVGElement, region: Region, selected: boolean, shapeColor: string): void;
|
|
16
|
+
/** Stroke/fill for a region shape (drawn in image coordinates by the renderer), in `style`. */
|
|
17
|
+
export declare function styleRegionShape(el: SVGElement, region: Region, selected: boolean, shapeColor: string, style?: RegionStyle): void;
|
|
17
18
|
/**
|
|
18
19
|
* The class label (legend) just above the region's top-left — mirrors Plotly's
|
|
19
20
|
* per-shape label, drawn in the region's colour. region.label is restored from
|
|
20
21
|
* the shape's legend in getRegion().
|
|
21
22
|
*/
|
|
22
|
-
export declare function drawRegionLabel(layer: ScreenLayer, region: Region, shapeColor: string): void;
|
|
23
|
+
export declare function drawRegionLabel(layer: ScreenLayer, region: Region, shapeColor: string, style?: RegionStyle): void;
|
|
23
24
|
/** A small vertex handle (filled when emphasised, hollow otherwise) at an image point. */
|
|
24
25
|
export declare function vertexMarker(layer: ScreenLayer, x: number, y: number, emphasised: boolean, color: string): void;
|
|
25
26
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IRegionStore } from '../../contracts/visualizer.contract';
|
|
2
|
-
import { IRegionEditApi } from '../../contracts/region-store.contract';
|
|
2
|
+
import { IRegionEditApi, IRegionSourceApi } from '../../contracts/region-store.contract';
|
|
3
3
|
import { IRegionOverlay, RegionToolMode } from '../../contracts/region-overlay.contract';
|
|
4
4
|
import { OsdViewerLike } from './osd-viewer-like';
|
|
5
5
|
/**
|
|
@@ -8,9 +8,10 @@ import { OsdViewerLike } from './osd-viewer-like';
|
|
|
8
8
|
* {@link IRegionEditApi} (add/move/resize/vertex edits). The shared RegionStore
|
|
9
9
|
* satisfies both. The overlay edits through these typed operations on the
|
|
10
10
|
* neutral Region model — it never touches a backend's own shape representation
|
|
11
|
-
* (e.g. Plotly's `x0/y0/x1/y1` / `M…L…Z` dicts).
|
|
11
|
+
* (e.g. Plotly's `x0/y0/x1/y1` / `M…L…Z` dicts). With {@link IRegionSourceApi}
|
|
12
|
+
* (optional) it also draws and picks the image's region source.
|
|
12
13
|
*/
|
|
13
|
-
export type RegionEditStore = IRegionStore & IRegionEditApi
|
|
14
|
+
export type RegionEditStore = IRegionStore & IRegionEditApi & Partial<IRegionSourceApi>;
|
|
14
15
|
/**
|
|
15
16
|
* OpenSeadragon implementation of {@link IRegionOverlay}.
|
|
16
17
|
*
|
|
@@ -62,6 +63,8 @@ export declare class OsdRegionOverlay implements IRegionOverlay {
|
|
|
62
63
|
* projection, and so the DOM, untouched. */
|
|
63
64
|
private readonly cameraHandler;
|
|
64
65
|
private readonly renderer;
|
|
66
|
+
/** The image's region source, drawn under the regions at the zoom's level of detail. */
|
|
67
|
+
private readonly sourceLayer;
|
|
65
68
|
/** OSD's MouseTracker drops a cancelled pointer (touch interrupted, pointer
|
|
66
69
|
* capture lost to the browser) without calling releaseHandler, so the
|
|
67
70
|
* gesture is ended here instead. */
|
|
@@ -152,8 +155,12 @@ export declare class OsdRegionOverlay implements IRegionOverlay {
|
|
|
152
155
|
*/
|
|
153
156
|
private applyEdit;
|
|
154
157
|
private selectAt;
|
|
158
|
+
/** Take the region-source features the band meets into the regions, adding them to the selection. */
|
|
159
|
+
private selectSourceIn;
|
|
155
160
|
/** Index of the topmost region under an image point, or -1. */
|
|
156
161
|
private regionIndexAt;
|
|
162
|
+
/** Whether a region's class is hidden (not drawn, not picked). */
|
|
163
|
+
private hidden;
|
|
157
164
|
/** Whether the element-pixel `position` lands on `region` (see `regionContains`). */
|
|
158
165
|
private containsPoint;
|
|
159
166
|
/** Abandon whatever pointer gesture is in progress (drawing, edit drag,
|
|
@@ -38,6 +38,9 @@ export interface TileDescriptor {
|
|
|
38
38
|
/** Physical pixel size in µm (0 when the format doesn't report it). */
|
|
39
39
|
mppX?: number;
|
|
40
40
|
mppY?: number;
|
|
41
|
+
/** Spacing between z slices in µm (0 or absent when the format doesn't report it): what
|
|
42
|
+
* lets a z-stack be drawn as a volume to scale. */
|
|
43
|
+
mppZ?: number;
|
|
41
44
|
}
|
|
42
45
|
/** Tile coordinates for one `/tile` request. `channel == null` (or omitted)
|
|
43
46
|
* requests the server-composited tile; an index (including 0) requests that
|
|
@@ -38,6 +38,13 @@ export interface PresetSet {
|
|
|
38
38
|
autoPromote: boolean;
|
|
39
39
|
/** Label matching against `Region.label` (default `'exact'`). */
|
|
40
40
|
matchMode: MatchMode;
|
|
41
|
+
/**
|
|
42
|
+
* Class colours that imported GeoJSON carried for classes with no preset, keyed by the
|
|
43
|
+
* match mode's key (see `presetKey`). They come before the fallback palette, so an imported
|
|
44
|
+
* file keeps its own colours. Session-only: never persisted, and absent from a set a caller
|
|
45
|
+
* saves or exports.
|
|
46
|
+
*/
|
|
47
|
+
importedColors?: Readonly<Record<string, string>>;
|
|
41
48
|
}
|
|
42
49
|
/**
|
|
43
50
|
* Fallback palette for classes not present in the preset set — reasonably distinct hues.
|
|
@@ -38,3 +38,8 @@ export declare function replaceBounds(existing: Region, bounds: Region['bounds']
|
|
|
38
38
|
* are rounded to whole pixels.
|
|
39
39
|
*/
|
|
40
40
|
export declare function regionPolygons(region: Region): Polygon[];
|
|
41
|
+
/**
|
|
42
|
+
* The open polylines a region traces (a polyline, or a multi-polygon's open parts), as interleaved
|
|
43
|
+
* `x, y` image px; a bézier polyline as its flattened curve. Closed shapes yield nothing.
|
|
44
|
+
*/
|
|
45
|
+
export declare function regionPolylines(region: Region): Float64Array[];
|
|
@@ -5,13 +5,53 @@ import { Region } from './region';
|
|
|
5
5
|
* coordinates.
|
|
6
6
|
*/
|
|
7
7
|
export declare function regionsFromGeoJson(geoJsonStr: string): Region[];
|
|
8
|
+
/** A feature's `classification`: QuPath's `{name, color}`, or a bare name. */
|
|
9
|
+
type Classification = string | {
|
|
10
|
+
name?: string;
|
|
11
|
+
color?: number[];
|
|
12
|
+
};
|
|
13
|
+
/** The parts of a GeoJSON feature the reader looks at, JIT's bezier extras
|
|
14
|
+
* included. Parsed from a file, so nothing here is guaranteed. */
|
|
15
|
+
export interface GeoJsonFeature {
|
|
16
|
+
id?: string | number;
|
|
17
|
+
geometry: {
|
|
18
|
+
type?: string;
|
|
19
|
+
coordinates?: unknown;
|
|
20
|
+
plane?: {
|
|
21
|
+
z?: number;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
properties?: {
|
|
25
|
+
id?: string | number;
|
|
26
|
+
classification?: Classification;
|
|
27
|
+
isBezier?: boolean;
|
|
28
|
+
bezierAnchors?: number[][];
|
|
29
|
+
bezierHandlesIn?: number[][];
|
|
30
|
+
bezierHandlesOut?: number[][];
|
|
31
|
+
holes?: number[][][];
|
|
32
|
+
holeHandlesIn?: number[][][];
|
|
33
|
+
holeHandlesOut?: number[][][];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* One GeoJSON feature as the region `shape<idx>`. Throws on a feature without coordinates.
|
|
38
|
+
* The feature's id becomes {@link Region.sourceId} (or `sourceId`, when given: a region source's
|
|
39
|
+
* id for the feature) and its other properties {@link Region.properties}.
|
|
40
|
+
*/
|
|
41
|
+
export declare function regionFromGeoJsonFeature(feature: GeoJsonFeature, idx: number, sourceId?: string): Region;
|
|
8
42
|
/**
|
|
9
43
|
* Serialise regions as a GeoJSON FeatureCollection string (QuPath-compatible),
|
|
10
44
|
* leaving out intensity-profile lines.
|
|
11
45
|
*/
|
|
12
46
|
export declare function regionsToGeoJson(rois: readonly Region[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* A region as a GeoJSON feature; null for a region without bounds. Its {@link Region.sourceId}
|
|
49
|
+
* is the feature's `id` and its {@link Region.properties} come along beside the classification.
|
|
50
|
+
*/
|
|
51
|
+
export declare function featureFromRegion(roi: Region): object | null;
|
|
13
52
|
/**
|
|
14
53
|
* Download a GeoJSON string as `<baseName without extension>.geojson`
|
|
15
54
|
* (`rois.geojson` without a base name).
|
|
16
55
|
*/
|
|
17
56
|
export declare function downloadGeoJson(jsonString: string, baseName?: string): void;
|
|
57
|
+
export {};
|
package/lib/models/region.d.ts
CHANGED
|
@@ -35,6 +35,25 @@ export declare class Region {
|
|
|
35
35
|
* through the store, so the marker has to travel with the data.
|
|
36
36
|
*/
|
|
37
37
|
source?: string;
|
|
38
|
+
/**
|
|
39
|
+
* The id of the GeoJSON feature this region was read from (the feature's `id`, else
|
|
40
|
+
* `properties.id`; for a tiled region source, else its position in the file). Written back
|
|
41
|
+
* as the feature's `id` on export, so a region keeps its identity through a save. A region
|
|
42
|
+
* taken out of a region source for editing carries it, and the source stops drawing that
|
|
43
|
+
* feature while it does.
|
|
44
|
+
*/
|
|
45
|
+
sourceId?: string;
|
|
46
|
+
/**
|
|
47
|
+
* A region source feature's area (image px²) while it stands in for the feature in the Region
|
|
48
|
+
* Editor's table: such a row has no geometry until the feature is taken.
|
|
49
|
+
*/
|
|
50
|
+
sourceArea?: number;
|
|
51
|
+
/**
|
|
52
|
+
* The feature's other GeoJSON properties (everything but the ones SIV reads and writes:
|
|
53
|
+
* `classification`, `id` and the bézier fields), carried through untouched so a save keeps
|
|
54
|
+
* them, e.g. an atlas structure's acronym and id.
|
|
55
|
+
*/
|
|
56
|
+
properties?: Readonly<Record<string, unknown>>;
|
|
38
57
|
color?: string;
|
|
39
58
|
label?: string;
|
|
40
59
|
/** True when the user set this region's colour explicitly (Region Editor Color
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ElementRef, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
+
import type { RegionClassNode } from '../../region-source/region-tiles';
|
|
3
|
+
import { ClassTree, ClassTreeRow } from './class-tree';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/** A pick in the tree: the class, and it with every class under it. */
|
|
6
|
+
export interface ClassTreePick {
|
|
7
|
+
name: string;
|
|
8
|
+
classes: string[];
|
|
9
|
+
additive: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Whether a class is shown: it and its subclasses all, none ('hidden'), or only some ('partial'). */
|
|
12
|
+
export type ClassVisibility = 'shown' | 'hidden' | 'partial';
|
|
13
|
+
/**
|
|
14
|
+
* The Region Editor's classes as a hierarchy (a brain atlas's ontology), as the Allen atlas viewer
|
|
15
|
+
* shows it: collapsible, each class with its colour, name and long name, and the regions it and
|
|
16
|
+
* its subclasses have on this slice; a class with none is greyed. Picking a class selects all its
|
|
17
|
+
* regions and its subclasses' (the editor does the selecting). Search by name or long name. A
|
|
18
|
+
* class's swatch recolours it, as the class list's does; its eye hides it and its subclasses.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ClassTreeComponent implements OnChanges {
|
|
21
|
+
private readonly el;
|
|
22
|
+
/** The hierarchy. */
|
|
23
|
+
nodes: readonly RegionClassNode[];
|
|
24
|
+
/** Regions per class on this slice (the regions and the region source's). */
|
|
25
|
+
counts: ReadonlyMap<string, number>;
|
|
26
|
+
/** A class's colour (a new function when the colours change, so the rows repaint). */
|
|
27
|
+
colorOf: (name: string) => string;
|
|
28
|
+
/** The class picked last (highlighted, its path expanded, scrolled into view). */
|
|
29
|
+
picked: string | null;
|
|
30
|
+
/** Classes with a selected region (marked). */
|
|
31
|
+
marked: ReadonlySet<string>;
|
|
32
|
+
/** Whether a volume view is on screen: each class can then be shown in 3D. */
|
|
33
|
+
volume: boolean;
|
|
34
|
+
/** The classes shown in 3D. */
|
|
35
|
+
shown3d: ReadonlySet<string>;
|
|
36
|
+
/** The classes hidden from view. */
|
|
37
|
+
hidden: ReadonlySet<string>;
|
|
38
|
+
pick: EventEmitter<ClassTreePick>;
|
|
39
|
+
/** A class's swatch picked a new colour. */
|
|
40
|
+
recolor: EventEmitter<{
|
|
41
|
+
name: string;
|
|
42
|
+
color: string;
|
|
43
|
+
}>;
|
|
44
|
+
/** A class's 3D toggle: it with every class under it. */
|
|
45
|
+
toggle3d: EventEmitter<{
|
|
46
|
+
name: string;
|
|
47
|
+
classes: string[];
|
|
48
|
+
}>;
|
|
49
|
+
/** A class's eye: hide (or show) it with every class under it. */
|
|
50
|
+
toggleHidden: EventEmitter<{
|
|
51
|
+
classes: string[];
|
|
52
|
+
hidden: boolean;
|
|
53
|
+
}>;
|
|
54
|
+
protected tree: ClassTree;
|
|
55
|
+
protected rows: ClassTreeRow[];
|
|
56
|
+
/** Each row's visibility (a row absent: shown). */
|
|
57
|
+
protected visibility: Map<string, ClassVisibility>;
|
|
58
|
+
protected query: string;
|
|
59
|
+
private expanded;
|
|
60
|
+
constructor(el: ElementRef<HTMLElement>);
|
|
61
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
62
|
+
protected node(name: string): RegionClassNode | undefined;
|
|
63
|
+
protected total(name: string): number;
|
|
64
|
+
protected toggle(row: ClassTreeRow, event: Event): void;
|
|
65
|
+
protected choose(name: string, event: Event): void;
|
|
66
|
+
/** The eye: a class hidden (wholly) is shown again with its subclasses; otherwise they are hidden. */
|
|
67
|
+
protected flipHidden(name: string, event: Event): void;
|
|
68
|
+
protected flip3d(name: string, event: Event): void;
|
|
69
|
+
protected onQuery(value: string): void;
|
|
70
|
+
/** Enter in the search box picks the first match. */
|
|
71
|
+
protected pickFirstMatch(event: Event): void;
|
|
72
|
+
protected readonly trackRow: (_: number, r: ClassTreeRow) => string;
|
|
73
|
+
private refresh;
|
|
74
|
+
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>;
|
|
76
|
+
}
|
|
77
|
+
/** Scroll the row matching `selector` inside `host` into view, if it is out of it. */
|
|
78
|
+
export declare function scrollToPicked(host: HTMLElement, selector: string): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RegionClassNode } from '../../region-source/region-tiles';
|
|
2
|
+
/** A class hierarchy as a tree: children in order, subtree counts, depths. Pure. */
|
|
3
|
+
export interface ClassTree {
|
|
4
|
+
roots: string[];
|
|
5
|
+
node: Map<string, RegionClassNode>;
|
|
6
|
+
children: Map<string, string[]>;
|
|
7
|
+
parent: Map<string, string | null>;
|
|
8
|
+
/** Regions of the class and every class under it. */
|
|
9
|
+
total: Map<string, number>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Build the tree of `nodes`, counting `counts` (regions per class) up through it. A node whose
|
|
13
|
+
* parent is not in the hierarchy is a root; siblings sort by `order`, then as listed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildClassTree(nodes: readonly RegionClassNode[], counts: ReadonlyMap<string, number>): ClassTree;
|
|
16
|
+
/** `name` and every class under it. */
|
|
17
|
+
export declare function subtree(tree: ClassTree, name: string): string[];
|
|
18
|
+
/** The classes from the root down to `name`'s parent. */
|
|
19
|
+
export declare function ancestors(tree: ClassTree, name: string): string[];
|
|
20
|
+
/** One visible row of the tree. */
|
|
21
|
+
export interface ClassTreeRow {
|
|
22
|
+
name: string;
|
|
23
|
+
depth: number;
|
|
24
|
+
hasChildren: boolean;
|
|
25
|
+
expanded: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The rows to draw: depth-first through the expanded nodes. With a `query`, only the nodes whose
|
|
29
|
+
* name or title contains it and their ancestors, all expanded.
|
|
30
|
+
*/
|
|
31
|
+
export declare function visibleRows(tree: ClassTree, expanded: ReadonlySet<string>, query?: string): ClassTreeRow[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter, OnChanges } from '@angular/core';
|
|
1
|
+
import { ElementRef, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
2
|
import { ClassPreset, MatchMode } from '../../models/class-preset';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
/** One class row as the template draws it, derived once per input change. */
|
|
@@ -14,10 +14,13 @@ interface ClassRow {
|
|
|
14
14
|
* The Region Editor's docked "Classes" panel (jit-ui#70): every annotation
|
|
15
15
|
* class with its colour swatch and region count. A row click picks the active
|
|
16
16
|
* class (and re-classifies a selection), the swatch recolours the class, the
|
|
17
|
-
* trash removes it, Manage opens the full editor
|
|
18
|
-
*
|
|
17
|
+
* trash removes it, Manage opens the full editor; the search box filters the
|
|
18
|
+
* rows by name; the eye hides a class's regions. For a class hierarchy the editor projects a class tree in,
|
|
19
|
+
* shown in place of the list while {@link treeView} is on. Presentational: the
|
|
20
|
+
* editor applies every action.
|
|
19
21
|
*/
|
|
20
22
|
export declare class ClassesPanelComponent implements OnChanges {
|
|
23
|
+
private readonly el;
|
|
21
24
|
/** The classes in display order. */
|
|
22
25
|
classes: ClassPreset[];
|
|
23
26
|
/** Region count per class, keyed by {@link presetKey} under `matchMode`. */
|
|
@@ -26,10 +29,28 @@ export declare class ClassesPanelComponent implements OnChanges {
|
|
|
26
29
|
matchMode: MatchMode;
|
|
27
30
|
/** The active class (highlighted), or null. */
|
|
28
31
|
activeClass: string | null;
|
|
32
|
+
/** The class picked last (in the class tree, or a surface in 3D): highlighted, scrolled into view. */
|
|
33
|
+
picked: string | null;
|
|
34
|
+
/** Classes with a selected region (marked). */
|
|
35
|
+
marked: ReadonlySet<string>;
|
|
29
36
|
/** Number of selected regions (changes what a row click does). */
|
|
30
37
|
selectedCount: number;
|
|
31
38
|
/** The class regions revert to; it can't be removed while in use. */
|
|
32
39
|
defaultClassName: string;
|
|
40
|
+
/** Whether a volume view is on screen: each class can then be shown in 3D. */
|
|
41
|
+
volume: boolean;
|
|
42
|
+
/** The classes shown in 3D. */
|
|
43
|
+
shown3d: ReadonlySet<string>;
|
|
44
|
+
/** The classes hidden from view. */
|
|
45
|
+
hidden: ReadonlySet<string>;
|
|
46
|
+
/** A class's eye (its name): hide it, or show it again. */
|
|
47
|
+
toggleHidden: EventEmitter<string>;
|
|
48
|
+
/** A class's 3D toggle (its name). */
|
|
49
|
+
toggle3d: EventEmitter<string>;
|
|
50
|
+
/** Whether the projected class tree is shown instead of the list; null: there is no tree. */
|
|
51
|
+
treeView: boolean | null;
|
|
52
|
+
/** The list / tree switch. */
|
|
53
|
+
treeViewChange: EventEmitter<boolean>;
|
|
33
54
|
/** A row was clicked: make the class active / apply it to the selection. */
|
|
34
55
|
pick: EventEmitter<string>;
|
|
35
56
|
/** A class's swatch picked a new colour. */
|
|
@@ -43,14 +64,23 @@ export declare class ClassesPanelComponent implements OnChanges {
|
|
|
43
64
|
manage: EventEmitter<void>;
|
|
44
65
|
/** trackBy for the class rows so re-sorting doesn't re-create the pickers. */
|
|
45
66
|
protected readonly trackByName: (_: number, c: ClassRow) => string;
|
|
46
|
-
/**
|
|
67
|
+
/** Every class's row, rebuilt when an input changes rather than per check. */
|
|
47
68
|
protected rows: ClassRow[];
|
|
48
|
-
|
|
69
|
+
/** The rows matching {@link query}. */
|
|
70
|
+
protected shownRows: ClassRow[];
|
|
71
|
+
/** The search box's text. */
|
|
72
|
+
protected query: string;
|
|
73
|
+
constructor(el: ElementRef<HTMLElement>);
|
|
74
|
+
ngOnChanges(changes?: SimpleChanges): void;
|
|
75
|
+
protected onQuery(value: string): void;
|
|
76
|
+
/** Enter in the search box picks the first match. */
|
|
77
|
+
protected pickFirstMatch(): void;
|
|
78
|
+
private filter;
|
|
49
79
|
private count;
|
|
50
80
|
private canRemove;
|
|
51
81
|
protected rowTooltip(name: string): string;
|
|
52
82
|
protected removeTooltip(name: string): string;
|
|
53
83
|
static ɵfac: i0.ɵɵFactoryDeclaration<ClassesPanelComponent, never>;
|
|
54
|
-
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; }; "selectedCount": { "alias": "selectedCount"; "required": false; }; "defaultClassName": { "alias": "defaultClassName"; "required": false; }; }, { "pick": "pick"; "recolor": "recolor"; "remove": "remove"; "manage": "manage"; }, 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>;
|
|
55
85
|
}
|
|
56
86
|
export {};
|