@jax-data-science/sci-image-visualizer 0.2.12 → 0.2.13

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/index.d.ts CHANGED
@@ -24,6 +24,7 @@ export * from './lib/contracts/cell-segmenter.contract';
24
24
  export { CellposeSegmenterService } from './lib/toolbar/segmentation/cellpose-segmenter.service';
25
25
  export * from './lib/contracts/instance-segmenter.contract';
26
26
  export { YoloSegmenterService } from './lib/toolbar/segmentation/yolo-segmenter.service';
27
+ export { YoloDetectToolService } from './lib/toolbar/segmentation/yolo-detect-tool.service';
27
28
  export { ProcessingImage } from './lib/processing/processing-image';
28
29
  export { cropImage, CropImageOptions } from './lib/processing/image-crop';
29
30
  export { ImageConverterService } from './lib/processing/image-converter.service';
@@ -52,6 +52,17 @@ export interface InstanceSegmentation {
52
52
  export interface InstanceSegmentOptions {
53
53
  /** Which registered model to run. Defaults to the registry's default. */
54
54
  modelId?: string;
55
+ /**
56
+ * Scale to run at, as a divisor of full resolution — the same meaning the
57
+ * server gives it.
58
+ *
59
+ * This is what puts objects at the size the checkpoint was trained on, and it
60
+ * matters more than any threshold: run a detector at the wrong object scale
61
+ * and it finds nothing. A caller that can re-crop the source (a tile-backed
62
+ * viewer) should honour it rather than accepting whatever the display happens
63
+ * to show.
64
+ */
65
+ downsamplingFactor?: number;
55
66
  /** Minimum detection confidence, per tile. */
56
67
  confidence?: number;
57
68
  /** NMS IoU within a single tile. */
@@ -0,0 +1,49 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { type TileAccessPort } from '../../contracts/ports/tile-access.port';
3
+ import type { IVisualizer } from '../../contracts/visualizer.contract';
4
+ import type { IInstanceSegmenter, InstanceSegmentOptions } from '../../contracts/instance-segmenter.contract';
5
+ import * as i0 from "@angular/core";
6
+ /**
7
+ * YOLO object detection over the current view.
8
+ *
9
+ * The complement to {@link CellSegmentToolService}: cellpose auto-segments cells
10
+ * inside a box you draw, whereas a detector is meant to find objects across a
11
+ * field. So this takes no prompt — it runs on whatever is on screen and turns
12
+ * every detection into a region.
13
+ *
14
+ * Detections come back in the displayed image's pixels; they are mapped onto
15
+ * the full-resolution image through the viewer's own source rect, so the regions
16
+ * land where the objects actually are rather than at view-local coordinates.
17
+ *
18
+ * Exposes the same `status$` / `busy$` / `progress$` surface as the cellpose
19
+ * tool so the host's shared segmentation toast drives it unchanged.
20
+ */
21
+ export declare class YoloDetectToolService {
22
+ /** Server-side crop, so detection can run at the model's scale rather than
23
+ * the viewer's. Optional: without it the tool falls back to the displayed
24
+ * pixels, which is correct but scale-dependent. */
25
+ private tileAccess;
26
+ readonly status$: BehaviorSubject<string>;
27
+ readonly busy$: BehaviorSubject<boolean>;
28
+ readonly progress$: BehaviorSubject<number>;
29
+ constructor(
30
+ /** Server-side crop, so detection can run at the model's scale rather than
31
+ * the viewer's. Optional: without it the tool falls back to the displayed
32
+ * pixels, which is correct but scale-dependent. */
33
+ tileAccess?: TileAccessPort | null);
34
+ /**
35
+ * Detect in the current view and append the results as regions.
36
+ *
37
+ * @returns the number of regions added.
38
+ */
39
+ detectInView(viz: IVisualizer, segmenter: IInstanceSegmenter, opts?: InstanceSegmentOptions): Promise<number>;
40
+ /**
41
+ * Re-crop `rect` at `1/target` of full resolution. Returns null on any
42
+ * failure, so the caller falls back to the displayed pixels — a coarser crop
43
+ * beats a failed run.
44
+ */
45
+ private fetchCropAtScale;
46
+ private makeRegion;
47
+ static ɵfac: i0.ɵɵFactoryDeclaration<YoloDetectToolService, [{ optional: true; }]>;
48
+ static ɵprov: i0.ɵɵInjectableDeclaration<YoloDetectToolService>;
49
+ }
@@ -66,6 +66,12 @@ export declare class ToolbarComponent implements OnChanges {
66
66
  label: string;
67
67
  }[];
68
68
  samModelId: string;
69
+ /** YOLO checkpoints offered by the host's registry, and the active one. */
70
+ yoloModels: {
71
+ id: string;
72
+ label: string;
73
+ }[];
74
+ yoloModelId: string;
69
75
  selectPlotType: EventEmitter<PlotType>;
70
76
  /** Intensity (LINE) mode: add another colored line ROI + inset trace. */
71
77
  addProfileLine: EventEmitter<void>;
@@ -105,6 +111,12 @@ export declare class ToolbarComponent implements OnChanges {
105
111
  segmentRegions: EventEmitter<void>;
106
112
  /** Run cellpose-SAM (auto) inside each drawn rectangle's crop (jit-ui#90). */
107
113
  segmentCellpose: EventEmitter<void>;
114
+ /** Run YOLO detection over the current view. */
115
+ detectYolo: EventEmitter<void>;
116
+ /** Pick the YOLO checkpoint. */
117
+ yoloModelChange: EventEmitter<string>;
118
+ /** Open the YOLO parameter dialog. */
119
+ openYoloParams: EventEmitter<void>;
108
120
  /** SAM model picker (jit-ui#90 P1). */
109
121
  samModelChange: EventEmitter<string>;
110
122
  wandSensitivityChange: EventEmitter<number | undefined>;
@@ -133,6 +145,8 @@ export declare class ToolbarComponent implements OnChanges {
133
145
  * every change-detection tick, which makes the bound `p-menu` overlay rebuild
134
146
  * its DOM mid-interaction and swallow the click on a menu item. */
135
147
  samMenuItems: MenuItem[];
148
+ /** Same stable-array reasoning as {@link samMenuItems}. */
149
+ yoloMenuItems: MenuItem[];
136
150
  /** Rebuild the SAM model menu when the model list or active selection
137
151
  * changes (keeps the array reference stable across other CD ticks). */
138
152
  ngOnChanges(changes: SimpleChanges): void;
@@ -163,5 +177,5 @@ export declare class ToolbarComponent implements OnChanges {
163
177
  get isIntensityCapable(): boolean;
164
178
  showHelp(): void;
165
179
  static ɵfac: i0.ɵɵFactoryDeclaration<ToolbarComponent, never>;
166
- static ɵcmp: i0.ɵɵComponentDeclaration<ToolbarComponent, "plotting-toolbar", never, { "imageInfo": { "alias": "imageInfo"; "required": false; }; "plotTypeOptions": { "alias": "plotTypeOptions"; "required": false; }; "selectedPlotType": { "alias": "selectedPlotType"; "required": false; }; "isoRange": { "alias": "isoRange"; "required": false; }; "maxIndex": { "alias": "maxIndex"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "isHeatmap": { "alias": "isHeatmap"; "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; }; }, { "selectPlotType": "selectPlotType"; "addProfileLine": "addProfileLine"; "toggleImageSmoothing": "toggleImageSmoothing"; "isoRangeChange": "isoRangeChange"; "openChannelHistogram": "openChannelHistogram"; "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"; "samModelChange": "samModelChange"; "wandSensitivityChange": "wandSensitivityChange"; "brushSizeChange": "brushSizeChange"; "vertexEraserRadiusChange": "vertexEraserRadiusChange"; }, never, ["*"], false, never>;
180
+ static ɵcmp: i0.ɵɵComponentDeclaration<ToolbarComponent, "plotting-toolbar", never, { "imageInfo": { "alias": "imageInfo"; "required": false; }; "plotTypeOptions": { "alias": "plotTypeOptions"; "required": false; }; "selectedPlotType": { "alias": "selectedPlotType"; "required": false; }; "isoRange": { "alias": "isoRange"; "required": false; }; "maxIndex": { "alias": "maxIndex"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "isHeatmap": { "alias": "isHeatmap"; "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; }; "yoloModels": { "alias": "yoloModels"; "required": false; }; "yoloModelId": { "alias": "yoloModelId"; "required": false; }; }, { "selectPlotType": "selectPlotType"; "addProfileLine": "addProfileLine"; "toggleImageSmoothing": "toggleImageSmoothing"; "isoRangeChange": "isoRangeChange"; "openChannelHistogram": "openChannelHistogram"; "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"; "detectYolo": "detectYolo"; "yoloModelChange": "yoloModelChange"; "openYoloParams": "openYoloParams"; "samModelChange": "samModelChange"; "wandSensitivityChange": "wandSensitivityChange"; "brushSizeChange": "brushSizeChange"; "vertexEraserRadiusChange": "vertexEraserRadiusChange"; }, never, ["*"], false, never>;
167
181
  }
@@ -12,6 +12,8 @@ import { IVisualizer } from './contracts/visualizer.contract';
12
12
  import { SamToolService } from './toolbar/segmentation/sam-tool.service';
13
13
  import { SamPointToolService } from './toolbar/segmentation/sam-point-tool.service';
14
14
  import { CellSegmentToolService } from './toolbar/segmentation/cell-segment-tool.service';
15
+ import { YoloDetectToolService } from './toolbar/segmentation/yolo-detect-tool.service';
16
+ import type { IInstanceSegmenter, InstanceSegmentOptions } from './contracts/instance-segmenter.contract';
15
17
  import { ToolbarToolVisibility } from './contracts/toolbar-config';
16
18
  import { VizConfig } from './contracts/viz-config';
17
19
  import * as i0 from "@angular/core";
@@ -24,6 +26,8 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
24
26
  private session;
25
27
  private samTool;
26
28
  private cellSegmentTool;
29
+ private yoloDetectTool;
30
+ private instanceSegmenter;
27
31
  private samPointTool;
28
32
  private regionOps;
29
33
  private vizConfig?;
@@ -123,6 +127,16 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
123
127
  label: string;
124
128
  }[];
125
129
  samModelId: string;
130
+ /** YOLO checkpoints with a configured URL, and the active one. */
131
+ yoloModels: {
132
+ id: string;
133
+ label: string;
134
+ }[];
135
+ yoloModelId: string;
136
+ /** Parameter dialog state. Seeded from the active model's own defaults, which
137
+ * encode the scale and crowding each checkpoint was trained for. */
138
+ showYoloParams: boolean;
139
+ yoloParams: InstanceSegmentOptions;
126
140
  /** SAM download/segment toast state (bound by the `sam` p-toast template). */
127
141
  samStatus: string;
128
142
  samProgress: number;
@@ -233,7 +247,7 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
233
247
  private wheelListener?;
234
248
  /** Debounced z-slice scrubbing (see SliceScrubber — refactoring plan Step 7). */
235
249
  private readonly scrubber;
236
- constructor(state: ImageStatePort, plotService: IVisualizer, messageService: MessageService, ngZone: NgZone, cdr: ChangeDetectorRef, session: VisualizerStore, samTool: SamToolService, cellSegmentTool: CellSegmentToolService, samPointTool: SamPointToolService, regionOps: RegionOpsService, vizConfig?: VizConfig | undefined);
250
+ constructor(state: ImageStatePort, plotService: IVisualizer, messageService: MessageService, ngZone: NgZone, cdr: ChangeDetectorRef, session: VisualizerStore, samTool: SamToolService, cellSegmentTool: CellSegmentToolService, yoloDetectTool: YoloDetectToolService, instanceSegmenter: IInstanceSegmenter, samPointTool: SamPointToolService, regionOps: RegionOpsService, vizConfig?: VizConfig | undefined);
237
251
  /**
238
252
  * Plot types offered in the selector for the current image:
239
253
  * - Outside **test mode**, only the curated default set (descriptors with a
@@ -381,6 +395,17 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
381
395
  * (jit-ui#90). Each box is cropped (browser slide-crop) then run through the
382
396
  * cellpose-js model; the same sticky `sam` toast + progress bar is reused. */
383
397
  segmentCellpose(): Promise<void>;
398
+ /** Per-model defaults from the registry — what the checkpoint was trained for. */
399
+ private defaultYoloParams;
400
+ /** Switching checkpoint re-seeds the parameters, since the defaults belong to
401
+ * the model rather than to the tool. */
402
+ onYoloModelChange(id: string): void;
403
+ openYoloParams(): void;
404
+ resetYoloParams(): void;
405
+ /** Detect objects across the current view. No prompt: a detector finds objects
406
+ * in a field rather than being pointed at one. Reuses the shared segmentation
407
+ * toast so progress and status read the same as the SAM/cellpose tools. */
408
+ detectYolo(): Promise<void>;
384
409
  /** Shared driver for the box-prompt segment tools: wires the tool's status +
385
410
  * download progress into the sticky `sam` toast, runs `op`, and reports the
386
411
  * region count. Keeps the toast open until the run settles (bar hits 100%). */
@@ -424,6 +449,6 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
424
449
  onSelectPlotType(type: PlotType): void;
425
450
  /** Deactivate whatever tool is armed and clear every tool mode. */
426
451
  private deactivateActiveTool;
427
- static ɵfac: i0.ɵɵFactoryDeclaration<VisualizerComponent, [null, null, null, null, null, null, null, null, null, null, { optional: true; }]>;
452
+ static ɵfac: i0.ɵɵFactoryDeclaration<VisualizerComponent, [null, null, null, null, null, null, null, null, null, null, null, null, { optional: true; }]>;
428
453
  static ɵcmp: i0.ɵɵComponentDeclaration<VisualizerComponent, "visualizer", never, { "toolbarTools": { "alias": "toolbarTools"; "required": false; }; "testMode": { "alias": "testMode"; "required": false; }; }, { "isStackEvent": "isStackEvent"; "isGrayscaleEvent": "isGrayscaleEvent"; }, never, ["*"], false, never>;
429
454
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jax-data-science/sci-image-visualizer",
3
- "version": "0.2.12",
3
+ "version": "0.2.13",
4
4
  "description": "Browser-based scientific image visualization for Angular — gigapixel whole-slide (OpenSeadragon), 2D/3D (Plotly) and WebGPU (napari-js) rendering, with region/annotation editing and in-browser SAM segmentation.",
5
5
  "keywords": [
6
6
  "angular",