@jax-data-science/sci-image-visualizer 0.5.0 → 0.6.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/README.md +49 -0
- package/esm2022/lib/contracts/display-types.mjs +1 -1
- package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
- package/esm2022/lib/contracts/toolbar-tool.contract.mjs +46 -4
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +2 -3
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +2 -2
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +2 -3
- package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +44 -3
- package/esm2022/lib/toolbar/toolbar.component.mjs +15 -3
- package/esm2022/lib/visualizer.component.mjs +221 -7
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +325 -18
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
- package/lib/contracts/display-types.d.ts +10 -0
- package/lib/contracts/plot-type-contribution.contract.d.ts +27 -0
- package/lib/contracts/toolbar-tool.contract.d.ts +84 -5
- package/lib/toolbar/brush/brush-tool.service.d.ts +21 -0
- package/lib/toolbar/toolbar.component.d.ts +11 -3
- package/lib/visualizer.component.d.ts +54 -2
- package/package.json +1 -1
|
@@ -38,6 +38,16 @@ export interface IWandOptions {
|
|
|
38
38
|
export interface IBrushOptions {
|
|
39
39
|
/** Brush diameter in matrix (image) pixels. */
|
|
40
40
|
size?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Paint as one class: new regions take this label, and a stroke only extends
|
|
43
|
+
* or merges regions with the same label. Unset = the plain brush (label
|
|
44
|
+
* `'Region'`, extends any region). `setBrushMode(true, …)` sets the class in
|
|
45
|
+
* full; `setBrushOptions` changes it only when `label` or `color` is passed,
|
|
46
|
+
* so a size-only update keeps it.
|
|
47
|
+
*/
|
|
48
|
+
label?: string;
|
|
49
|
+
/** Colour for the painted regions instead of the shape colour. Kept against preset re-apply. */
|
|
50
|
+
color?: string;
|
|
41
51
|
}
|
|
42
52
|
/** What drives point colour in the spatial-omics mode: an annotation column
|
|
43
53
|
* from the dataset, or one feature (gene) vector fetched on demand. */
|
|
@@ -103,6 +103,31 @@ export interface PlotModeViewport {
|
|
|
103
103
|
* A new subscriber first receives the current rect when the viewport is ready. */
|
|
104
104
|
settled$: Observable<PlotModeRect>;
|
|
105
105
|
}
|
|
106
|
+
/** The class a {@link PlotModeTools.armBrush} stroke paints. */
|
|
107
|
+
export interface PlotModeBrushClass {
|
|
108
|
+
/** Label for the painted regions; the stroke only extends or merges regions with it. */
|
|
109
|
+
label?: string;
|
|
110
|
+
/** Colour for the painted regions (instead of the toolbar's shape colour). */
|
|
111
|
+
color?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The visualizer's own toolbar tools, armed on a mode's behalf. Going through
|
|
115
|
+
* this rather than {@link IVisualizer} keeps the toolbar in step: the armed
|
|
116
|
+
* tool's button is highlighted and its controls (e.g. the brush size) show.
|
|
117
|
+
*/
|
|
118
|
+
export interface PlotModeTools {
|
|
119
|
+
/**
|
|
120
|
+
* Arm the toolbar brush, painting `brushClass`. Calling it again while the
|
|
121
|
+
* brush is armed switches class; the next stroke starts a region of it.
|
|
122
|
+
* The user picking any tool from the toolbar (including the brush) replaces
|
|
123
|
+
* this with the plain tool.
|
|
124
|
+
*/
|
|
125
|
+
armBrush(brushClass?: PlotModeBrushClass): void;
|
|
126
|
+
/** Disarm whatever tool is armed, as if the user toggled it off. */
|
|
127
|
+
disarm(): void;
|
|
128
|
+
/** The armed toolbar tool id ('brush', 'pan', … or null). Replays the current value. */
|
|
129
|
+
activeTool$: Observable<string | null>;
|
|
130
|
+
}
|
|
106
131
|
/** Everything a contributed mode gets to work with while it is active. */
|
|
107
132
|
export interface PlotModeContext {
|
|
108
133
|
/** Full public visualizer API: regions, region overlay (tool modes), undo, etc. */
|
|
@@ -110,6 +135,8 @@ export interface PlotModeContext {
|
|
|
110
135
|
viewport: PlotModeViewport;
|
|
111
136
|
/** Current image info from IMAGE_STATE_PORT (null until an image is loaded). */
|
|
112
137
|
imageInfo$: Observable<IImageInfo | null>;
|
|
138
|
+
/** Toolbar tools (since 0.6.0). Optional so a context built for 0.5.0 still type-checks. */
|
|
139
|
+
tools?: PlotModeTools;
|
|
113
140
|
}
|
|
114
141
|
/** A live activation of a contributed mode. */
|
|
115
142
|
export interface PlotModeSession {
|
|
@@ -35,6 +35,17 @@
|
|
|
35
35
|
* than an escape hatch that returns a component — the moment one tool draws
|
|
36
36
|
* itself, the toolbar stops being able to lay tools out consistently.
|
|
37
37
|
*
|
|
38
|
+
* DIALOG TOOLS
|
|
39
|
+
* Some tools are not "set parameters, run once" but an interactive session: the
|
|
40
|
+
* user paints, the tool retrains and redraws, over and over (DIANNE). A schema
|
|
41
|
+
* cannot describe that, so {@link ToolbarDialogToolContribution} is the one
|
|
42
|
+
* variant that renders its own body. The toolbar still owns the button, its
|
|
43
|
+
* placement and the dialog chrome; the tool only fills the dialog, with plain
|
|
44
|
+
* DOM (`mount`), so it needs neither Angular nor this library's PrimeNG version.
|
|
45
|
+
* Its button sits with the host's own actions at the start of the toolbar, and
|
|
46
|
+
* shows only in the Image view, the view its context ({@link ToolDialogContext})
|
|
47
|
+
* draws over.
|
|
48
|
+
*
|
|
38
49
|
* WHY AN EMPTY MODEL LIST HIDES THE TOOL
|
|
39
50
|
* {@link ToolbarToolContribution.models} returning `[]` removes the tool from
|
|
40
51
|
* the toolbar entirely. This preserves the behaviour the built-in tools already
|
|
@@ -45,6 +56,7 @@
|
|
|
45
56
|
import { InjectionToken } from '@angular/core';
|
|
46
57
|
import type { Observable } from 'rxjs';
|
|
47
58
|
import type { IVisualizer } from './visualizer.contract';
|
|
59
|
+
import type { PlotModeContext, PlotModeSession, PlotModeTools } from './plot-type-contribution.contract';
|
|
48
60
|
/** A number field. Rendered as a stepper, matching the built-in dialogs. */
|
|
49
61
|
export interface NumberParamSpec {
|
|
50
62
|
id: string;
|
|
@@ -177,14 +189,81 @@ export interface ToolbarToolContribution {
|
|
|
177
189
|
run(viz: IVisualizer, params: Record<string, unknown>): Promise<number>;
|
|
178
190
|
}
|
|
179
191
|
/**
|
|
180
|
-
*
|
|
192
|
+
* What a dialog tool gets while its dialog is open: the same surface a
|
|
193
|
+
* contributed plot mode gets (the public visualizer, the Image view's viewport
|
|
194
|
+
* and the current image), with the toolbar tools always present.
|
|
195
|
+
*/
|
|
196
|
+
export type ToolDialogContext = PlotModeContext & {
|
|
197
|
+
tools: PlotModeTools;
|
|
198
|
+
};
|
|
199
|
+
/** A live dialog-tool session. `deactivate()` runs exactly once, after the body's teardown. */
|
|
200
|
+
export type ToolDialogSession = PlotModeSession;
|
|
201
|
+
/**
|
|
202
|
+
* A toolbar tool that opens a dialog instead of running once (see DIALOG TOOLS
|
|
203
|
+
* above). Clicking its button opens the dialog and starts a session; clicking it
|
|
204
|
+
* again, or closing the dialog, ends it.
|
|
205
|
+
*
|
|
206
|
+
* The session is bound to the Image view on screen. When that view is re-rendered
|
|
207
|
+
* (another image, another slice) the session ends and, with the dialog still
|
|
208
|
+
* open, a fresh one starts once the new view is ready. Leaving the Image view
|
|
209
|
+
* closes the dialog. As with plot modes, nothing the tool throws or rejects
|
|
210
|
+
* escapes: a failed start closes the dialog with a warning.
|
|
211
|
+
*/
|
|
212
|
+
export interface ToolbarDialogToolContribution {
|
|
213
|
+
kind: 'dialog';
|
|
214
|
+
/** Stable identity. Must not clash with another toolbar tool. */
|
|
215
|
+
id: string;
|
|
216
|
+
/** Short name; the dialog title unless `dialog.title` is set. */
|
|
217
|
+
label: string;
|
|
218
|
+
icon: ToolIcon;
|
|
219
|
+
/** Tooltip on the button. */
|
|
220
|
+
tooltip: string;
|
|
221
|
+
/** Order among the dialog tools. Lower sorts first; ties keep registration order. */
|
|
222
|
+
order?: number;
|
|
223
|
+
dialog?: {
|
|
224
|
+
title?: string;
|
|
225
|
+
/** CSS width of the dialog. Default `'22rem'`. */
|
|
226
|
+
width?: string;
|
|
227
|
+
};
|
|
228
|
+
/** Entry for the help dialog's tool list, rendered as HTML (trusted content). */
|
|
229
|
+
help?: {
|
|
230
|
+
body: string;
|
|
231
|
+
};
|
|
232
|
+
/** Start a session, once the Image view's viewport is ready. */
|
|
233
|
+
activate(ctx: ToolDialogContext): ToolDialogSession | Promise<ToolDialogSession>;
|
|
234
|
+
/**
|
|
235
|
+
* Render the dialog body into `host`; return its teardown (called before
|
|
236
|
+
* `deactivate()`). Called after `activate` resolves, once the dialog has rendered and
|
|
237
|
+
* `host` is in the document, so the body can measure itself.
|
|
238
|
+
*/
|
|
239
|
+
mount(host: HTMLElement, ctx: ToolDialogContext, session: ToolDialogSession): () => void;
|
|
240
|
+
}
|
|
241
|
+
/** Anything provided on {@link TOOLBAR_TOOLS}. A run tool has no `kind`. */
|
|
242
|
+
export type ToolbarContribution = ToolbarToolContribution | ToolbarDialogToolContribution;
|
|
243
|
+
/** Whether a contribution is a {@link ToolbarDialogToolContribution}. */
|
|
244
|
+
export declare function isDialogToolContribution(c: unknown): c is ToolbarDialogToolContribution;
|
|
245
|
+
/**
|
|
246
|
+
* Multi-provider token for contributed tools: run tools
|
|
247
|
+
* ({@link ToolbarToolContribution}) and, since 0.6.0, dialog tools
|
|
248
|
+
* ({@link ToolbarDialogToolContribution}).
|
|
181
249
|
*
|
|
182
250
|
* Deliberately has no `factory`: unregistered means no tools, which is what
|
|
183
251
|
* makes this library shippable without the closed model packages. Inject it
|
|
184
252
|
* `{ optional: true }` and treat null as empty.
|
|
185
253
|
*/
|
|
186
|
-
export declare const TOOLBAR_TOOLS: InjectionToken<readonly
|
|
254
|
+
export declare const TOOLBAR_TOOLS: InjectionToken<readonly ToolbarContribution[]>;
|
|
187
255
|
/** Sort contributed tools into display order. */
|
|
188
|
-
export declare function sortToolContributions
|
|
189
|
-
|
|
190
|
-
|
|
256
|
+
export declare function sortToolContributions<T extends {
|
|
257
|
+
order?: number;
|
|
258
|
+
}>(tools: readonly T[]): T[];
|
|
259
|
+
/** The run tools a toolbar should actually show: those with at least one model.
|
|
260
|
+
* Dialog tools are left out (see {@link dialogToolContributions}). */
|
|
261
|
+
export declare function visibleToolContributions(tools: readonly ToolbarContribution[] | null | undefined): ToolbarToolContribution[];
|
|
262
|
+
/**
|
|
263
|
+
* The dialog tools, in display order. A malformed one (no string `id`, no
|
|
264
|
+
* `activate` or `mount` function) or a repeated `id` is dropped with a warning
|
|
265
|
+
* rather than breaking the toolbar.
|
|
266
|
+
*/
|
|
267
|
+
export declare function dialogToolContributions(tools: readonly ToolbarContribution[] | null | undefined, log?: {
|
|
268
|
+
warn(...args: unknown[]): void;
|
|
269
|
+
}): ToolbarDialogToolContribution[];
|
|
@@ -4,6 +4,15 @@ import * as i0 from "@angular/core";
|
|
|
4
4
|
/** Brush parameters. `size` is the brush *diameter* in matrix (image) pixels. */
|
|
5
5
|
export interface BrushOptions {
|
|
6
6
|
size?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Paint as one class. With `label` set, new regions take this label, and the
|
|
9
|
+
* stroke only adopts or merges regions that already have it, so painting one
|
|
10
|
+
* class never grows another class's region. `color` colours the painted
|
|
11
|
+
* regions instead of the toolbar's shape colour. Leave both unset for the
|
|
12
|
+
* plain toolbar brush.
|
|
13
|
+
*/
|
|
14
|
+
label?: string;
|
|
15
|
+
color?: string;
|
|
7
16
|
}
|
|
8
17
|
/**
|
|
9
18
|
* The brush host is identical to the wand's — both need the cached-image
|
|
@@ -60,6 +69,8 @@ export declare class BrushToolService {
|
|
|
60
69
|
private lastMatrix;
|
|
61
70
|
private dragging;
|
|
62
71
|
private size;
|
|
72
|
+
/** The class being painted ({@link BrushOptions.label} / `color`); null = plain brush. */
|
|
73
|
+
private paintClass;
|
|
63
74
|
private readonly boundMouseDown;
|
|
64
75
|
private readonly boundMouseMove;
|
|
65
76
|
private readonly boundMouseUp;
|
|
@@ -68,6 +79,13 @@ export declare class BrushToolService {
|
|
|
68
79
|
bindHost(host: BrushToolHost): void;
|
|
69
80
|
/** Toggle the brush on/off. */
|
|
70
81
|
setMode(active: boolean, options?: BrushOptions): void;
|
|
82
|
+
/**
|
|
83
|
+
* Update size and/or class while armed. The class changes only when `label`
|
|
84
|
+
* or `color` is passed (as a key, even `undefined`), so a size-only update
|
|
85
|
+
* keeps it. Switching class drops the active region, so the next stroke
|
|
86
|
+
* starts a region of the new class.
|
|
87
|
+
*/
|
|
88
|
+
setOptions(options?: BrushOptions): void;
|
|
71
89
|
/** Live-update the brush size (matrix-pixel diameter). */
|
|
72
90
|
setSize(size: number): void;
|
|
73
91
|
/** Drop the active brush region so the next stroke starts a new one. */
|
|
@@ -102,6 +120,9 @@ export declare class BrushToolService {
|
|
|
102
120
|
* erase stroke deletes every pixel.
|
|
103
121
|
*/
|
|
104
122
|
private dropActiveShape;
|
|
123
|
+
/** Whether the stroke may adopt or merge `region`: always for the plain brush,
|
|
124
|
+
* otherwise only a region of the class being painted. */
|
|
125
|
+
private paintsInto;
|
|
105
126
|
/** A region's closed-polygon vertices (image/data coords), or null when it
|
|
106
127
|
* isn't a fillable closed polygon (rectangles, open polylines). */
|
|
107
128
|
private regionVerts;
|
|
@@ -3,7 +3,7 @@ import { MenuItem } from 'primeng/api';
|
|
|
3
3
|
import { IImageInfo } from '../contracts/image.contract';
|
|
4
4
|
import { PlotType, PlotTypeId } from '../contracts/plot-type';
|
|
5
5
|
import { ToolbarToolVisibility } from '../contracts/toolbar-config';
|
|
6
|
-
import { ToolbarToolContribution } from '../contracts/toolbar-tool.contract';
|
|
6
|
+
import { ToolbarDialogToolContribution, ToolbarToolContribution } from '../contracts/toolbar-tool.contract';
|
|
7
7
|
import { PlotTypeOption } from '../contracts/plot-type-contribution.contract';
|
|
8
8
|
import * as i0 from "@angular/core";
|
|
9
9
|
/**
|
|
@@ -90,6 +90,10 @@ export declare class ToolbarComponent implements OnChanges {
|
|
|
90
90
|
* per-tool parameter state; this component only draws them.
|
|
91
91
|
*/
|
|
92
92
|
contributedTools: ToolbarToolContribution[];
|
|
93
|
+
/** Dialog tools (TOOLBAR_TOOLS, kind: 'dialog'), sorted; shown in the Image view. */
|
|
94
|
+
dialogTools: ToolbarDialogToolContribution[];
|
|
95
|
+
/** Id of the dialog tool whose dialog is open, or null. */
|
|
96
|
+
openDialogToolId: string | null;
|
|
93
97
|
/** Active checkpoint per contributed tool, keyed by tool id. */
|
|
94
98
|
toolModelIds: Record<string, string>;
|
|
95
99
|
selectPlotType: EventEmitter<string>;
|
|
@@ -135,6 +139,8 @@ export declare class ToolbarComponent implements OnChanges {
|
|
|
135
139
|
segmentCellpose: EventEmitter<void>;
|
|
136
140
|
/** Run a contributed tool over the current view, by tool id. */
|
|
137
141
|
runTool: EventEmitter<string>;
|
|
142
|
+
/** A dialog tool's button was clicked: open its dialog, or close it if open. */
|
|
143
|
+
toggleDialogTool: EventEmitter<string>;
|
|
138
144
|
/** Pick a contributed tool's checkpoint. */
|
|
139
145
|
toolModelChange: EventEmitter<{
|
|
140
146
|
toolId: string;
|
|
@@ -205,7 +211,9 @@ export declare class ToolbarComponent implements OnChanges {
|
|
|
205
211
|
get contributedToolNames(): string;
|
|
206
212
|
/** Keeps each contributed tool's `p-menu` overlay alive across CD ticks —
|
|
207
213
|
* re-creating it mid-interaction swallows the click on a menu item. */
|
|
208
|
-
trackToolById(_index: number, tool:
|
|
214
|
+
trackToolById(_index: number, tool: {
|
|
215
|
+
id: string;
|
|
216
|
+
}): string;
|
|
209
217
|
/** The built-in type whose tools and controls apply to the current selection. */
|
|
210
218
|
get effectivePlotType(): PlotType;
|
|
211
219
|
/** The Image plot type renders as a natively pan/zoom-able raster, so the
|
|
@@ -242,5 +250,5 @@ export declare class ToolbarComponent implements OnChanges {
|
|
|
242
250
|
get isIntensityCapable(): boolean;
|
|
243
251
|
showHelp(): void;
|
|
244
252
|
static ɵfac: i0.ɵɵFactoryDeclaration<ToolbarComponent, never>;
|
|
245
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<ToolbarComponent, "plotting-toolbar", never, { "imageInfo": { "alias": "imageInfo"; "required": false; }; "plotTypeOptions": { "alias": "plotTypeOptions"; "required": false; }; "selectedPlotType": { "alias": "selectedPlotType"; "required": false; }; "basePlotType": { "alias": "basePlotType"; "required": false; }; "isoRange": { "alias": "isoRange"; "required": false; }; "maxIndex": { "alias": "maxIndex"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "isHeatmap": { "alias": "isHeatmap"; "required": false; }; "is3dRegions": { "alias": "is3dRegions"; "required": false; }; "activeDragMode": { "alias": "activeDragMode"; "required": false; }; "activeSurface3dMode": { "alias": "activeSurface3dMode"; "required": false; }; "axesVisible": { "alias": "axesVisible"; "required": false; }; "wireframeActive": { "alias": "wireframeActive"; "required": false; }; "resolutionScale": { "alias": "resolutionScale"; "required": false; }; "wandSensitivity": { "alias": "wandSensitivity"; "required": false; }; "brushSize": { "alias": "brushSize"; "required": false; }; "vertexEraserRadius": { "alias": "vertexEraserRadius"; "required": false; }; "canUndo": { "alias": "canUndo"; "required": false; }; "canRedo": { "alias": "canRedo"; "required": false; }; "stackOptions": { "alias": "stackOptions"; "required": false; }; "tools": { "alias": "tools"; "required": false; }; "imageSmoothingEnabled": { "alias": "imageSmoothingEnabled"; "required": false; }; "samModels": { "alias": "samModels"; "required": false; }; "samModelId": { "alias": "samModelId"; "required": false; }; "contributedTools": { "alias": "contributedTools"; "required": false; }; "toolModelIds": { "alias": "toolModelIds"; "required": false; }; }, { "selectPlotType": "selectPlotType"; "addProfileLine": "addProfileLine"; "toggleImageSmoothing": "toggleImageSmoothing"; "isoRangeChange": "isoRangeChange"; "openChannelHistogram": "openChannelHistogram"; "openSpatialControls": "openSpatialControls"; "openRegionEditor": "openRegionEditor"; "selectStackOption": "selectStackOption"; "zScrub": "zScrub"; "zSlide": "zSlide"; "zIndexInput": "zIndexInput"; "reloadAndPlot": "reloadAndPlot"; "downloadImage": "downloadImage"; "autoscaleImage": "autoscaleImage"; "toggleDragMode": "toggleDragMode"; "zoomIn": "zoomIn"; "zoomOut": "zoomOut"; "toggleSurface3dMode": "toggleSurface3dMode"; "resetSurfaceCamera": "resetSurfaceCamera"; "toggleAxes": "toggleAxes"; "toggleWireframe": "toggleWireframe"; "selectResolution": "selectResolution"; "deleteRegion": "deleteRegion"; "undoRegion": "undoRegion"; "redoRegion": "redoRegion"; "segmentRegions": "segmentRegions"; "segmentCellpose": "segmentCellpose"; "runTool": "runTool"; "toolModelChange": "toolModelChange"; "openToolParams": "openToolParams"; "samModelChange": "samModelChange"; "wandSensitivityChange": "wandSensitivityChange"; "brushSizeChange": "brushSizeChange"; "vertexEraserRadiusChange": "vertexEraserRadiusChange"; }, never, ["*"], false, never>;
|
|
253
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ToolbarComponent, "plotting-toolbar", never, { "imageInfo": { "alias": "imageInfo"; "required": false; }; "plotTypeOptions": { "alias": "plotTypeOptions"; "required": false; }; "selectedPlotType": { "alias": "selectedPlotType"; "required": false; }; "basePlotType": { "alias": "basePlotType"; "required": false; }; "isoRange": { "alias": "isoRange"; "required": false; }; "maxIndex": { "alias": "maxIndex"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "isHeatmap": { "alias": "isHeatmap"; "required": false; }; "is3dRegions": { "alias": "is3dRegions"; "required": false; }; "activeDragMode": { "alias": "activeDragMode"; "required": false; }; "activeSurface3dMode": { "alias": "activeSurface3dMode"; "required": false; }; "axesVisible": { "alias": "axesVisible"; "required": false; }; "wireframeActive": { "alias": "wireframeActive"; "required": false; }; "resolutionScale": { "alias": "resolutionScale"; "required": false; }; "wandSensitivity": { "alias": "wandSensitivity"; "required": false; }; "brushSize": { "alias": "brushSize"; "required": false; }; "vertexEraserRadius": { "alias": "vertexEraserRadius"; "required": false; }; "canUndo": { "alias": "canUndo"; "required": false; }; "canRedo": { "alias": "canRedo"; "required": false; }; "stackOptions": { "alias": "stackOptions"; "required": false; }; "tools": { "alias": "tools"; "required": false; }; "imageSmoothingEnabled": { "alias": "imageSmoothingEnabled"; "required": false; }; "samModels": { "alias": "samModels"; "required": false; }; "samModelId": { "alias": "samModelId"; "required": false; }; "contributedTools": { "alias": "contributedTools"; "required": false; }; "dialogTools": { "alias": "dialogTools"; "required": false; }; "openDialogToolId": { "alias": "openDialogToolId"; "required": false; }; "toolModelIds": { "alias": "toolModelIds"; "required": false; }; }, { "selectPlotType": "selectPlotType"; "addProfileLine": "addProfileLine"; "toggleImageSmoothing": "toggleImageSmoothing"; "isoRangeChange": "isoRangeChange"; "openChannelHistogram": "openChannelHistogram"; "openSpatialControls": "openSpatialControls"; "openRegionEditor": "openRegionEditor"; "selectStackOption": "selectStackOption"; "zScrub": "zScrub"; "zSlide": "zSlide"; "zIndexInput": "zIndexInput"; "reloadAndPlot": "reloadAndPlot"; "downloadImage": "downloadImage"; "autoscaleImage": "autoscaleImage"; "toggleDragMode": "toggleDragMode"; "zoomIn": "zoomIn"; "zoomOut": "zoomOut"; "toggleSurface3dMode": "toggleSurface3dMode"; "resetSurfaceCamera": "resetSurfaceCamera"; "toggleAxes": "toggleAxes"; "toggleWireframe": "toggleWireframe"; "selectResolution": "selectResolution"; "deleteRegion": "deleteRegion"; "undoRegion": "undoRegion"; "redoRegion": "redoRegion"; "segmentRegions": "segmentRegions"; "segmentCellpose": "segmentCellpose"; "runTool": "runTool"; "toggleDialogTool": "toggleDialogTool"; "toolModelChange": "toolModelChange"; "openToolParams": "openToolParams"; "samModelChange": "samModelChange"; "wandSensitivityChange": "wandSensitivityChange"; "brushSizeChange": "brushSizeChange"; "vertexEraserRadiusChange": "vertexEraserRadiusChange"; }, never, ["*"], false, never>;
|
|
246
254
|
}
|
|
@@ -14,7 +14,7 @@ import { IVisualizer } from './contracts/visualizer.contract';
|
|
|
14
14
|
import { SamToolService } from './toolbar/segmentation/sam-tool.service';
|
|
15
15
|
import { SamPointToolService } from './toolbar/segmentation/sam-point-tool.service';
|
|
16
16
|
import { CellSegmentToolService } from './toolbar/segmentation/cell-segment-tool.service';
|
|
17
|
-
import { NumberParamSpec, SelectParamSpec, ToolParamSpec, ToolbarToolContribution } from './contracts/toolbar-tool.contract';
|
|
17
|
+
import { NumberParamSpec, SelectParamSpec, ToolParamSpec, ToolbarContribution, ToolbarDialogToolContribution, ToolbarToolContribution } from './contracts/toolbar-tool.contract';
|
|
18
18
|
import { ToolbarToolVisibility } from './contracts/toolbar-config';
|
|
19
19
|
import { VizConfig } from './contracts/viz-config';
|
|
20
20
|
import { SpatialDataPort } from './contracts/ports/spatial-data.port';
|
|
@@ -121,6 +121,8 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
|
|
|
121
121
|
wandSensitivity: number;
|
|
122
122
|
/** Brush diameter in image-pixel coordinates (drives the painted disc size). */
|
|
123
123
|
brushSize: number;
|
|
124
|
+
/** Class the brush paints while a plot mode armed it (PlotModeTools.armBrush); null = plain brush. */
|
|
125
|
+
private brushClass;
|
|
124
126
|
/** SAM model picker options + current selection (jit-ui#90 P1). Only models
|
|
125
127
|
* with a hosted ONNX pair (configured via setSamModelUrls at app init) are
|
|
126
128
|
* offered, so the picker can't select a model that can't run. */
|
|
@@ -136,6 +138,22 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
|
|
|
136
138
|
* and help dialog simply omit that group.
|
|
137
139
|
*/
|
|
138
140
|
contributedTools: ToolbarToolContribution[];
|
|
141
|
+
/**
|
|
142
|
+
* Dialog tools registered through {@link TOOLBAR_TOOLS} (`kind: 'dialog'`),
|
|
143
|
+
* sorted. Their buttons sit with the host's own actions and show in the Image
|
|
144
|
+
* view only; each opens a floating dialog the tool fills.
|
|
145
|
+
*/
|
|
146
|
+
dialogTools: ToolbarDialogToolContribution[];
|
|
147
|
+
/** The dialog tool the user has open (its session may be between renders). */
|
|
148
|
+
openDialogToolId: string | null;
|
|
149
|
+
/** The open dialog tool's live dialog, as the template renders it. */
|
|
150
|
+
toolDialog: {
|
|
151
|
+
title: string;
|
|
152
|
+
width: string;
|
|
153
|
+
host: HTMLElement;
|
|
154
|
+
} | null;
|
|
155
|
+
/** Dialog-tool sessions: the same lifecycle and isolation as contributed plot modes. */
|
|
156
|
+
private readonly toolDialogs;
|
|
139
157
|
/** Active checkpoint per contributed tool. */
|
|
140
158
|
toolModelIds: Record<string, string>;
|
|
141
159
|
/**
|
|
@@ -318,7 +336,7 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
|
|
|
318
336
|
private wheelListener?;
|
|
319
337
|
/** Debounced z-slice scrubbing (see SliceScrubber — refactoring plan Step 7). */
|
|
320
338
|
private readonly scrubber;
|
|
321
|
-
constructor(state: ImageStatePort, plotService: IVisualizer, messageService: MessageService, ngZone: NgZone, cdr: ChangeDetectorRef, session: VisualizerStore, samTool: SamToolService, cellSegmentTool: CellSegmentToolService, samPointTool: SamPointToolService, regionOps: RegionOpsService, vizConfig?: VizConfig | undefined, toolContributions?: readonly
|
|
339
|
+
constructor(state: ImageStatePort, plotService: IVisualizer, messageService: MessageService, ngZone: NgZone, cdr: ChangeDetectorRef, session: VisualizerStore, samTool: SamToolService, cellSegmentTool: CellSegmentToolService, samPointTool: SamPointToolService, regionOps: RegionOpsService, vizConfig?: VizConfig | undefined, toolContributions?: readonly ToolbarContribution[], spatialData?: SpatialDataPort | undefined, plotTypeContributions?: readonly PlotTypeContribution[], injector?: Injector | undefined);
|
|
322
340
|
/**
|
|
323
341
|
* Plot types offered in the selector for the current image:
|
|
324
342
|
* - Outside **test mode**, only the curated default set (descriptors with a
|
|
@@ -454,6 +472,8 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
|
|
|
454
472
|
onToggleImageSmoothing(): void;
|
|
455
473
|
resetAxes(): void;
|
|
456
474
|
toggleDragMode(mode: string): void;
|
|
475
|
+
/** Arm `mode` (or nothing) across every tool, keeping the toolbar in step. */
|
|
476
|
+
private applyDragMode;
|
|
457
477
|
/** Region draw/select/edit modes routed through the region overlay. The
|
|
458
478
|
* The vertex tools (drawpolygon/addpoint/deletepoint/move) are
|
|
459
479
|
* handled by the OpenSeadragon overlay; Plotly's overlay maps them to no-op. */
|
|
@@ -606,6 +626,38 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
|
|
|
606
626
|
private fallBackFromPlotMode;
|
|
607
627
|
/** Run change detection; returns what it threw (logged), or null. */
|
|
608
628
|
private detectChangesSafely;
|
|
629
|
+
/** The toolbar button: open the tool's dialog, or close it if it is open. */
|
|
630
|
+
toggleDialogTool(id: string): void;
|
|
631
|
+
/** Close the open dialog tool: its body is torn down, then its session ends. */
|
|
632
|
+
closeDialogTool(): void;
|
|
633
|
+
/** Start (or restart, after a re-render) the open dialog tool's session. */
|
|
634
|
+
private activateOpenDialogTool;
|
|
635
|
+
/** The live dialog body's teardown, and a pending wait for its host to connect. */
|
|
636
|
+
private toolDialogTeardown;
|
|
637
|
+
private toolDialogFrame;
|
|
638
|
+
/**
|
|
639
|
+
* The session is live: render the dialog, then mount the tool's body once the host
|
|
640
|
+
* element is in the document, so `mount()` can measure it and start widgets that need
|
|
641
|
+
* a connected element.
|
|
642
|
+
*/
|
|
643
|
+
private showToolDialog;
|
|
644
|
+
/** How many animation frames to wait for the dialog to attach the body's host. */
|
|
645
|
+
private static readonly TOOL_DIALOG_ATTACH_FRAMES;
|
|
646
|
+
/**
|
|
647
|
+
* Mount `tool`'s body into `host` once it is connected (the dialog may attach it a
|
|
648
|
+
* frame later, when it moves itself to `<body>`). If it never connects within
|
|
649
|
+
* {@link TOOL_DIALOG_ATTACH_FRAMES} it is mounted anyway, with a warning, rather than
|
|
650
|
+
* leaving an empty dialog. A throwing `mount()` fails the session like a failed start.
|
|
651
|
+
*/
|
|
652
|
+
private mountToolDialogBody;
|
|
653
|
+
/** The session is about to end: tear the body down first, then drop the dialog. */
|
|
654
|
+
private hideToolDialog;
|
|
655
|
+
/** A dialog tool could not start: close it and say so. */
|
|
656
|
+
private dialogToolFailed;
|
|
657
|
+
/** Where the open dialog tool's host element is attached once its dialog renders. */
|
|
658
|
+
set toolDialogSlot(ref: ElementRef<HTMLElement> | undefined);
|
|
659
|
+
/** Toolbar tools for contributed modes. Calls can come from outside Angular, hence the zone. */
|
|
660
|
+
private readonly plotModeTools;
|
|
609
661
|
/** Deactivate whatever tool is armed and clear every tool mode. */
|
|
610
662
|
private deactivateActiveTool;
|
|
611
663
|
static ɵfac: i0.ɵɵFactoryDeclaration<VisualizerComponent, [null, null, null, null, null, null, null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
|