@jax-data-science/sci-image-visualizer 0.3.3 → 0.4.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 +208 -4
- package/esm2022/index.mjs +20 -1
- package/esm2022/lib/contracts/display-types.mjs +20 -2
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/plot-type.mjs +36 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +3 -0
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +45 -0
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-axes-labels.mjs +10 -19
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +71 -7
- package/esm2022/lib/implementations/napari-js/napari-scale-bar.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +96 -0
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +1934 -55
- package/esm2022/lib/implementations/napari-js/napari-zoom.mjs +18 -0
- package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +5 -3
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +3 -4
- package/esm2022/lib/implementations/osd/osd-zoom.mjs +20 -0
- package/esm2022/lib/implementations/plotly/omics-trace-builders.mjs +555 -0
- package/esm2022/lib/implementations/plotly/plotly.service.mjs +13 -7
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +304 -0
- package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +179 -0
- package/esm2022/lib/routing-visualizer.service.mjs +223 -12
- package/esm2022/lib/spatial/embedding-compute.mjs +142 -0
- package/esm2022/lib/spatial/gene-search.mjs +77 -0
- package/esm2022/lib/spatial/spatial-density.mjs +224 -0
- package/esm2022/lib/spatial/spatial-encoding.mjs +232 -0
- package/esm2022/lib/spatial/spatial-expression.mjs +257 -0
- package/esm2022/lib/spatial/spatial-framing.mjs +60 -0
- package/esm2022/lib/spatial/spatial-heatmap.mjs +185 -0
- package/esm2022/lib/spatial/spatial-hover.mjs +79 -0
- package/esm2022/lib/spatial/spatial-sections.mjs +96 -0
- package/esm2022/lib/spatial/spatial-selection.mjs +264 -0
- package/esm2022/lib/spatial/spatial-volume-image.mjs +163 -0
- package/esm2022/lib/spatial/tsne-worker.mjs +10 -0
- package/esm2022/lib/spatial/world-grid.mjs +77 -0
- package/esm2022/lib/spatial-controls/spatial-charts/spatial-charts.component.mjs +1278 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +621 -0
- package/esm2022/lib/store/spatial-selection.service.mjs +47 -0
- package/esm2022/lib/store/visualizer-store.service.mjs +23 -1
- package/esm2022/lib/toolbar/toolbar.component.mjs +30 -7
- package/esm2022/lib/visualization.module.mjs +23 -5
- package/esm2022/lib/visualizer.component.mjs +283 -22
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs} +6 -4
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-ci1q0xnJ.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-BwP-A11m.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer-tsne-worker-B_nXDGf0.mjs +12 -0
- package/fesm2022/jax-data-science-sci-image-visualizer-tsne-worker-B_nXDGf0.mjs.map +1 -0
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +15769 -8316
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
- package/fesm2022/tsne.worker.js +19091 -0
- package/index.d.ts +15 -0
- package/lib/contracts/display-types.d.ts +131 -0
- package/lib/contracts/image.contract.d.ts +7 -0
- package/lib/contracts/plot-type.d.ts +42 -2
- package/lib/contracts/ports/spatial-data.port.d.ts +90 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +281 -0
- package/lib/contracts/visualizer.contract.d.ts +99 -1
- package/lib/implementations/napari-js/napari-axes-labels.d.ts +9 -7
- package/lib/implementations/napari-js/napari-region-overlay.d.ts +38 -4
- package/lib/implementations/napari-js/napari-scale-bar.d.ts +7 -3
- package/lib/implementations/napari-js/napari-spatial-tooltip.d.ts +32 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +497 -16
- package/lib/implementations/napari-js/napari-zoom.d.ts +15 -0
- package/lib/implementations/osd/osd-zoom.d.ts +19 -0
- package/lib/implementations/plotly/omics-trace-builders.d.ts +193 -0
- package/lib/implementations/plotly/plotly.service.d.ts +9 -0
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +123 -0
- package/lib/implementations/spatial-data-http/spatial-wire.d.ts +115 -0
- package/lib/routing-visualizer.service.d.ts +45 -6
- package/lib/spatial/embedding-compute.d.ts +73 -0
- package/lib/spatial/gene-search.d.ts +48 -0
- package/lib/spatial/spatial-density.d.ts +73 -0
- package/lib/spatial/spatial-encoding.d.ts +155 -0
- package/lib/spatial/spatial-expression.d.ts +144 -0
- package/lib/spatial/spatial-framing.d.ts +37 -0
- package/lib/spatial/spatial-heatmap.d.ts +111 -0
- package/lib/spatial/spatial-hover.d.ts +49 -0
- package/lib/spatial/spatial-sections.d.ts +59 -0
- package/lib/spatial/spatial-selection.d.ts +113 -0
- package/lib/spatial/spatial-volume-image.d.ts +67 -0
- package/lib/spatial/tsne-worker.d.ts +7 -0
- package/lib/spatial/world-grid.d.ts +58 -0
- package/lib/spatial-controls/spatial-charts/spatial-charts.component.d.ts +439 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +257 -0
- package/lib/store/spatial-selection.service.d.ts +27 -0
- package/lib/store/visualizer-store.service.d.ts +13 -0
- package/lib/toolbar/toolbar.component.d.ts +19 -3
- package/lib/visualization.module.d.ts +28 -24
- package/lib/visualizer.component.d.ts +73 -2
- package/package.json +6 -2
- package/src/lib/assets/spatial-omics-3d.svg +31 -0
- package/src/lib/assets/spatial-omics.svg +27 -0
|
@@ -7,7 +7,9 @@ import { PlotType, PlotTypeDescriptor } from './plot-type';
|
|
|
7
7
|
import { ViewerCapabilities } from './capabilities.contract';
|
|
8
8
|
import { IRegionOverlay } from './region-overlay.contract';
|
|
9
9
|
import { IHistogram } from './channel-histogram-api.contract';
|
|
10
|
-
import { ColormapNode, IWandOptions, IBrushOptions } from './display-types';
|
|
10
|
+
import { ColormapNode, IWandOptions, IBrushOptions, SpatialViewState, SpatialColorBy } from './display-types';
|
|
11
|
+
import { SpatialDataset, SpatialEmbedding } from './spatial-dataset.contract';
|
|
12
|
+
import { SpatialSelectionMask } from '../spatial/spatial-selection';
|
|
11
13
|
/**
|
|
12
14
|
* Backend-neutral visualization contract. Plotly is one implementation;
|
|
13
15
|
* OpenSeadragon is another (for the image plot type). The abstraction renders
|
|
@@ -270,6 +272,98 @@ export interface IIntensityControls {
|
|
|
270
272
|
* backend, or null if no image extent is known yet. */
|
|
271
273
|
addProfileLine(): Region | null;
|
|
272
274
|
}
|
|
275
|
+
/** A categorical column resolved for charting: labels, codes and map colours. */
|
|
276
|
+
export interface SpatialCategoricalView {
|
|
277
|
+
name: string;
|
|
278
|
+
categories: string[];
|
|
279
|
+
/** `#rrggbb` per category, index-aligned with {@link categories}. */
|
|
280
|
+
colors: string[];
|
|
281
|
+
/** Per-observation category index, or `NO_CATEGORY`. */
|
|
282
|
+
codes: Uint16Array;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Controls for the SPATIAL_OMICS plot type: what the observation markers are
|
|
286
|
+
* coloured by, and how they are drawn. Capability-gated like
|
|
287
|
+
* {@link IIsosurfaceControls} — `getSpatialControls()` returns null unless a
|
|
288
|
+
* host has bound `SPATIAL_DATA_PORT`.
|
|
289
|
+
*
|
|
290
|
+
* The view state is backend-neutral (it lives in the shared store, like the
|
|
291
|
+
* colormap), so these controls work whichever backend is on screen.
|
|
292
|
+
*/
|
|
293
|
+
export interface ISpatialControls {
|
|
294
|
+
/** The dataset being visualized, or null. Drives the column/gene pickers and
|
|
295
|
+
* the legend. */
|
|
296
|
+
getDataset$(): Observable<SpatialDataset | null>;
|
|
297
|
+
/** Current display state (colour source, point scale, opacity, scaling). */
|
|
298
|
+
getViewState$(): Observable<SpatialViewState>;
|
|
299
|
+
/** Synchronous read, for seeding a control's initial value. */
|
|
300
|
+
viewState(): SpatialViewState;
|
|
301
|
+
/** Patch the display state; the markers rebuild without remounting the scene. */
|
|
302
|
+
setViewState(partial: Partial<SpatialViewState>): void;
|
|
303
|
+
/** Colour by an annotation column. Rejects for an unknown column. */
|
|
304
|
+
colorByColumn(name: string): void;
|
|
305
|
+
/** Colour by a gene; its vector is fetched on demand. */
|
|
306
|
+
colorByFeature(name: string): void;
|
|
307
|
+
/** Clear the colour source — every observation renders in one neutral colour. */
|
|
308
|
+
clearColorBy(): void;
|
|
309
|
+
/** Typeahead over feature names, for datasets too wide to inline the list. */
|
|
310
|
+
searchFeatures(query: string, limit?: number): Promise<string[]>;
|
|
311
|
+
/** Per-category display colours for a categorical column, index-aligned with
|
|
312
|
+
* its `categories` — the legend's swatches, resolved the same way the
|
|
313
|
+
* renderer resolves them so the two cannot disagree. */
|
|
314
|
+
categoryColors(name: string): Promise<string[]>;
|
|
315
|
+
/**
|
|
316
|
+
* The values behind a colour source, index-aligned with the observations.
|
|
317
|
+
* Rejects for a categorical column — there is nothing continuous to chart.
|
|
318
|
+
*/
|
|
319
|
+
continuousValues(source: SpatialColorBy): Promise<Float32Array>;
|
|
320
|
+
/**
|
|
321
|
+
* A categorical column's categories, per-observation codes and display
|
|
322
|
+
* colours — everything a grouped violin/box needs, with the colours resolved
|
|
323
|
+
* the same way the map resolves them.
|
|
324
|
+
*/
|
|
325
|
+
categoricalView(column: string): Promise<SpatialCategoricalView>;
|
|
326
|
+
/**
|
|
327
|
+
* One embedding's coordinates — a UMAP, t-SNE or PCA plane over the same observations.
|
|
328
|
+
*
|
|
329
|
+
* Optional, and absent when the data source serves none: `SpatialDataPort.getEmbedding`
|
|
330
|
+
* is itself optional, so a panel must be able to ask whether this exists rather than
|
|
331
|
+
* calling it and catching.
|
|
332
|
+
*/
|
|
333
|
+
getEmbedding?(name: string): Promise<SpatialEmbedding>;
|
|
334
|
+
/** Names of the categorical columns available to group by. */
|
|
335
|
+
categoricalColumns(): string[];
|
|
336
|
+
/**
|
|
337
|
+
* The z positions of the sections the dataset was imaged at, ascending — or
|
|
338
|
+
* null when its z is continuous rather than sectioned (so there are no sections
|
|
339
|
+
* to offer) or when there is no dataset.
|
|
340
|
+
*
|
|
341
|
+
* Lets a panel offer "one section at a time" for the 3D cloud only where that
|
|
342
|
+
* means something, and label the chosen one. Scanned once per dataset.
|
|
343
|
+
*/
|
|
344
|
+
sampledSections(): Float32Array | null;
|
|
345
|
+
/** The current selection. Empty means "nothing selected", in which case the
|
|
346
|
+
* whole tissue renders normally rather than everything being muted. */
|
|
347
|
+
getSelection$(): Observable<SpatialSelectionMask>;
|
|
348
|
+
/**
|
|
349
|
+
* Select every observation inside the currently-drawn regions (their union).
|
|
350
|
+
* Reuses the existing ROI tools — rectangle, polygon, freehand, wand, brush —
|
|
351
|
+
* so there is no separate marquee to learn. Returns how many were selected.
|
|
352
|
+
*/
|
|
353
|
+
selectFromRegions(): number;
|
|
354
|
+
/** Select every observation in one category of a categorical column — the
|
|
355
|
+
* legend click. Rejects for an unknown or continuous column. */
|
|
356
|
+
selectCategory(column: string, categoryIndex: number): Promise<number>;
|
|
357
|
+
/**
|
|
358
|
+
* Select an explicit set of observations, replacing any current selection.
|
|
359
|
+
*
|
|
360
|
+
* For a linked plot: lassoing points in an embedding is a selection OF observations,
|
|
361
|
+
* and every other view — the map, the distributions — reads the same mask, so brushing
|
|
362
|
+
* one lights up the rest. Returns how many were selected.
|
|
363
|
+
*/
|
|
364
|
+
selectIndices(indices: Iterable<number>): number;
|
|
365
|
+
clearSelection(): void;
|
|
366
|
+
}
|
|
273
367
|
/** Display options (colormap/LUT, reverse scale, image metadata). */
|
|
274
368
|
export interface IDisplayOptions {
|
|
275
369
|
getColormap(): Observable<ColormapNode | null>;
|
|
@@ -321,6 +415,10 @@ export interface IVisualizer extends IDataRenderer, IRegionStore, IToolControlle
|
|
|
321
415
|
* the capability-gated replacement for the deprecated top-level
|
|
322
416
|
* `setSurfaceDragMode`/`resetSurfaceCamera`. */
|
|
323
417
|
getSurface3dControls(): ISurface3dControls | null;
|
|
418
|
+
/** Spatial-omics controls when a `SPATIAL_DATA_PORT` is bound, else null.
|
|
419
|
+
* Optional: only the routing service implements it, since the state is shared
|
|
420
|
+
* rather than owned by any one backend. */
|
|
421
|
+
getSpatialControls?(): ISpatialControls | null;
|
|
324
422
|
/** Binned intensity histogram for a channel from the currently-displayed
|
|
325
423
|
* pixels, or null when none are available. Feeds the Channels & Histogram
|
|
326
424
|
* pane. */
|
|
@@ -20,14 +20,16 @@ export interface AxesLabelCamera3D {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
23
|
+
* Re-exported from napari-js, which owns the projection now.
|
|
24
|
+
*
|
|
25
|
+
* This used to be a local copy: the same column-major multiply, perspective divide and y-flip
|
|
26
|
+
* that {@link NapariVisualizerService.getSpatialScreenProjection} ALSO carried, written twice
|
|
27
|
+
* with two different behind-the-eye conventions. The renderer owns the camera and the clip
|
|
28
|
+
* convention, so it owns the projection; kept as a named export here only so the overlays that
|
|
29
|
+
* import it from this module do not all have to change.
|
|
25
30
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
y: number;
|
|
29
|
-
visible: boolean;
|
|
30
|
-
};
|
|
31
|
+
import { projectPoint } from 'napari-js';
|
|
32
|
+
export { projectPoint };
|
|
31
33
|
export declare class NapariAxesLabels {
|
|
32
34
|
private readonly host;
|
|
33
35
|
private readonly camera3d;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { IRegionOverlay, RegionToolMode } from '../../contracts/region-overlay.contract';
|
|
2
2
|
import { RegionStore } from '../../store/region-store.service';
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* The slice of the napari Viewer the overlay needs (coord transforms + control gating).
|
|
5
|
+
*
|
|
6
|
+
* Exported because the 3D spatial mode supplies a SCREEN-SPACE implementation of it: there the
|
|
7
|
+
* drawn shape is a lasso in canvas pixels, not a rectangle in image space, so "world" is the
|
|
8
|
+
* canvas itself and both transforms collapse to identity. That lets the 3D view reuse this whole
|
|
9
|
+
* overlay — every tool, the handles, the store round-trip — with no 3D-specific drawing code.
|
|
10
|
+
*/
|
|
11
|
+
export interface OverlayViewer {
|
|
5
12
|
canvasToWorld(clientX: number, clientY: number): [number, number];
|
|
6
13
|
worldToCanvas(worldX: number, worldY: number): [number, number];
|
|
7
14
|
setControlsEnabled(enabled: boolean): void;
|
|
@@ -45,11 +52,39 @@ export declare class NapariRegionOverlay implements IRegionOverlay {
|
|
|
45
52
|
* rectangle corner. `anchor` is the fixed opposite corner for a rectangle resize. */
|
|
46
53
|
private edit;
|
|
47
54
|
constructor(host: HTMLElement, viewer: OverlayViewer, store: RegionStore);
|
|
55
|
+
/**
|
|
56
|
+
* Whether a region tool currently owns the pointer.
|
|
57
|
+
*
|
|
58
|
+
* Exposed so the spatial views can tell a bare click on the cloud (select the
|
|
59
|
+
* class under the cursor) from a click that belongs to a drawing gesture —
|
|
60
|
+
* placing a polygon vertex is also a click that does not move, and it must not
|
|
61
|
+
* change the selection behind the shape being drawn.
|
|
62
|
+
*/
|
|
63
|
+
get toolActive(): boolean;
|
|
48
64
|
setMode(mode: RegionToolMode): void;
|
|
49
65
|
setSelectedBezier(bezier: boolean): void;
|
|
66
|
+
/**
|
|
67
|
+
* How finely a drawn vertex may be placed, in world units.
|
|
68
|
+
*
|
|
69
|
+
* One by default, because for an image the world IS pixels and a region should align to
|
|
70
|
+
* them. A dataset whose coordinates are not pixels sets it finer — seqFISH's whole
|
|
71
|
+
* sample spans about 5 x 7 units, where whole-unit vertices leave roughly six by eight
|
|
72
|
+
* placeable positions and no ROI can be drawn at all.
|
|
73
|
+
*/
|
|
74
|
+
private worldQuantum;
|
|
75
|
+
setWorldQuantum(quantum: number): void;
|
|
50
76
|
destroy(): void;
|
|
51
|
-
/** Pointer client coords →
|
|
77
|
+
/** Pointer client coords → world coords, snapped to {@link worldQuantum}. */
|
|
52
78
|
private toImage;
|
|
79
|
+
/**
|
|
80
|
+
* World units spanned by one screen pixel, measured through the viewer's own transform.
|
|
81
|
+
*
|
|
82
|
+
* Read from the transform rather than from the camera, so it holds for both the 2D and
|
|
83
|
+
* the 3D screen-space adapters without either having to expose a zoom. Falls back to 1
|
|
84
|
+
* if the transform gives nothing usable, which keeps the established pixel behaviour
|
|
85
|
+
* rather than collapsing the threshold to zero and recording a point per event.
|
|
86
|
+
*/
|
|
87
|
+
private worldPerCanvasPixel;
|
|
53
88
|
/** Image coords → SVG-local px (the svg overlays the canvas at the same client rect). */
|
|
54
89
|
private toLocal;
|
|
55
90
|
private readonly onPointerDown;
|
|
@@ -112,4 +147,3 @@ export declare class NapariRegionOverlay implements IRegionOverlay {
|
|
|
112
147
|
private drawDraft;
|
|
113
148
|
private styleDraft;
|
|
114
149
|
}
|
|
115
|
-
export {};
|
|
@@ -8,8 +8,13 @@
|
|
|
8
8
|
/** Format a length given in micrometres, picking the unit that suits its magnitude (jit-service
|
|
9
9
|
* normalises whatever unit Bio-Formats reports to µm). */
|
|
10
10
|
export declare function formatUm(um: number): string;
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The slice of the napari Camera the scale bar reads (zoom = CSS px per world/image pixel).
|
|
13
|
+
*
|
|
14
|
+
* Exported so the 3D spatial view can satisfy it with a shim: an orbit camera has no `zoom`, but
|
|
15
|
+
* px-per-world-unit AT THE PIVOT DEPTH is well defined, and that is what a 3D scale bar means.
|
|
16
|
+
*/
|
|
17
|
+
export interface ScaleBarCamera {
|
|
13
18
|
readonly zoom: number;
|
|
14
19
|
readonly changed: {
|
|
15
20
|
connect(listener: () => void): () => void;
|
|
@@ -28,4 +33,3 @@ export declare class NapariScaleBar {
|
|
|
28
33
|
private update;
|
|
29
34
|
destroy(): void;
|
|
30
35
|
}
|
|
31
|
-
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor tooltip naming the observation under the pointer, for the spatial-omics
|
|
3
|
+
* views — the same overlay-in-the-host pattern as {@link NapariScaleBar}.
|
|
4
|
+
*
|
|
5
|
+
* A 34-entry legend cannot be read back from a dot: several classes get similar
|
|
6
|
+
* colours, and matching one to a swatch by eye is the job a tooltip removes. It
|
|
7
|
+
* shows what the cloud is CURRENTLY coloured by, so it always agrees with the
|
|
8
|
+
* legend beside it.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately not PrimeNG's `pTooltip`: that binds to an element, and these
|
|
11
|
+
* points are pixels in a WebGPU canvas with no DOM of their own.
|
|
12
|
+
*/
|
|
13
|
+
export declare class NapariSpatialTooltip {
|
|
14
|
+
private readonly host;
|
|
15
|
+
private readonly el;
|
|
16
|
+
private readonly primary;
|
|
17
|
+
private readonly secondary;
|
|
18
|
+
/** Gap between the cursor and the box, so the box never sits under the arrow. */
|
|
19
|
+
private static readonly OFFSET;
|
|
20
|
+
constructor(host: HTMLElement);
|
|
21
|
+
/**
|
|
22
|
+
* Show `lines` at a point given in HOST-relative pixels.
|
|
23
|
+
*
|
|
24
|
+
* Flips to the other side of the cursor near an edge rather than being clipped
|
|
25
|
+
* by the host — a tooltip half outside the plot is worse than one on the left.
|
|
26
|
+
*/
|
|
27
|
+
show(lines: readonly string[], hostX: number, hostY: number): void;
|
|
28
|
+
hide(): void;
|
|
29
|
+
/** True while the box is on screen — for tests, and to skip redundant hides. */
|
|
30
|
+
get visible(): boolean;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
}
|