@jax-data-science/sci-image-visualizer 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/esm2022/lib/contracts/display-types.mjs +3 -2
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +1 -1
  4. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  6. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +1 -1
  7. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  8. package/esm2022/lib/geometry/cell-meshes.mjs +37 -0
  9. package/esm2022/lib/geometry/place.mjs +47 -0
  10. package/esm2022/lib/implementations/napari-js/napari-camera-depth.mjs +93 -0
  11. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +1 -1
  12. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +2 -2
  13. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  14. package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +81 -15
  15. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-cells.mjs +746 -0
  16. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +325 -18
  17. package/esm2022/lib/implementations/napari-js/napari-spatial-3d-transcripts.mjs +182 -24
  18. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +95 -5
  19. package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +15 -1
  20. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +30 -2
  21. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +40 -1
  22. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +111 -28
  23. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +14 -2
  24. package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +180 -48
  25. package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +28 -8
  26. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +2 -2
  27. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +10 -1
  28. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +30 -3
  29. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +15 -3
  30. package/esm2022/lib/region-editor/region-editor.component.mjs +24 -4
  31. package/esm2022/lib/region-source/region-source-ops.mjs +7 -1
  32. package/esm2022/lib/region-source/region-tiles.mjs +1 -1
  33. package/esm2022/lib/region-source/worker-region-source.mjs +24 -1
  34. package/esm2022/lib/routing-visualizer.service.mjs +404 -7
  35. package/esm2022/lib/spatial/observations-in-selection.mjs +83 -0
  36. package/esm2022/lib/spatial/plane-cells.mjs +119 -0
  37. package/esm2022/lib/spatial/spatial-controls.facade.mjs +298 -5
  38. package/esm2022/lib/spatial/spatial-encoding.mjs +35 -3
  39. package/esm2022/lib/spatial/spatial-hover.mjs +34 -1
  40. package/esm2022/lib/spatial/spatial-planes.mjs +49 -0
  41. package/esm2022/lib/spatial/spatial-selection.mjs +2 -2
  42. package/esm2022/lib/spatial/spatial-tile-merge.mjs +38 -1
  43. package/esm2022/lib/spatial/transcripts-in-selection.mjs +208 -0
  44. package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +42 -65
  45. package/esm2022/lib/spatial-controls/spatial-color-by/spatial-color-by.component.mjs +187 -0
  46. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +47 -12
  47. package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +3 -3
  48. package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +38 -10
  49. package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +3 -3
  50. package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +3 -3
  51. package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +79 -57
  52. package/esm2022/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.mjs +101 -0
  53. package/esm2022/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.mjs +94 -0
  54. package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +9 -3
  55. package/esm2022/lib/store/region-source-scope.mjs +10 -1
  56. package/esm2022/lib/store/region-store.service.mjs +33 -2
  57. package/esm2022/lib/toolbar/toolbar.component.mjs +10 -3
  58. package/esm2022/lib/visualizer/spatial-region-set.mjs +95 -0
  59. package/esm2022/lib/visualizer.component.mjs +40 -4
  60. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DHrHO2ay.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CBiLcnE6.mjs} +4521 -759
  61. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-CBiLcnE6.mjs.map +1 -0
  62. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CKEUwNta.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-BXHjv4PE.mjs} +2 -2
  63. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CKEUwNta.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-BXHjv4PE.mjs.map} +1 -1
  64. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +1 -1
  65. package/fesm2022/region-source.worker.js +84 -2
  66. package/lib/contracts/display-types.d.ts +90 -4
  67. package/lib/contracts/image.contract.d.ts +6 -0
  68. package/lib/contracts/ports/spatial-data.port.d.ts +7 -0
  69. package/lib/contracts/region-editor-api.contract.d.ts +9 -0
  70. package/lib/contracts/region-store.contract.d.ts +6 -0
  71. package/lib/contracts/spatial-dataset.contract.d.ts +7 -1
  72. package/lib/contracts/visualizer.contract.d.ts +43 -1
  73. package/lib/geometry/cell-meshes.d.ts +27 -0
  74. package/lib/geometry/place.d.ts +45 -0
  75. package/lib/implementations/napari-js/napari-camera-depth.d.ts +23 -0
  76. package/lib/implementations/napari-js/napari-loading-state.d.ts +1 -1
  77. package/lib/implementations/napari-js/napari-scene.d.ts +12 -0
  78. package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +19 -3
  79. package/lib/implementations/napari-js/napari-spatial-3d-cells.d.ts +141 -0
  80. package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +87 -0
  81. package/lib/implementations/napari-js/napari-spatial-3d-transcripts.d.ts +49 -8
  82. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +22 -0
  83. package/lib/implementations/napari-js/napari-spatial-scene.d.ts +12 -0
  84. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +15 -0
  85. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +27 -1
  86. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +38 -19
  87. package/lib/implementations/napari-js/napari-volume-scene.d.ts +2 -0
  88. package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +53 -0
  89. package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +11 -2
  90. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +7 -0
  91. package/lib/region-editor/class-tree/class-tree.component.d.ts +16 -1
  92. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +10 -1
  93. package/lib/region-editor/region-editor.component.d.ts +4 -0
  94. package/lib/region-source/region-source-ops.d.ts +12 -0
  95. package/lib/region-source/region-tiles.d.ts +8 -0
  96. package/lib/region-source/worker-region-source.d.ts +18 -0
  97. package/lib/routing-visualizer.service.d.ts +140 -1
  98. package/lib/spatial/observations-in-selection.d.ts +43 -0
  99. package/lib/spatial/plane-cells.d.ts +37 -0
  100. package/lib/spatial/spatial-controls.facade.d.ts +59 -0
  101. package/lib/spatial/spatial-encoding.d.ts +14 -1
  102. package/lib/spatial/spatial-hover.d.ts +23 -0
  103. package/lib/spatial/spatial-planes.d.ts +22 -0
  104. package/lib/spatial/spatial-selection.d.ts +2 -1
  105. package/lib/spatial/spatial-tile-merge.d.ts +9 -0
  106. package/lib/spatial/transcripts-in-selection.d.ts +95 -0
  107. package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +19 -28
  108. package/lib/spatial-controls/spatial-color-by/spatial-color-by.component.d.ts +64 -0
  109. package/lib/spatial-controls/spatial-controls.component.d.ts +17 -2
  110. package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +16 -6
  111. package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +26 -23
  112. package/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.d.ts +48 -0
  113. package/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.d.ts +43 -0
  114. package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +3 -1
  115. package/lib/store/region-source-scope.d.ts +4 -0
  116. package/lib/store/region-store.service.d.ts +21 -0
  117. package/lib/toolbar/toolbar.component.d.ts +6 -1
  118. package/lib/visualizer/spatial-region-set.d.ts +55 -0
  119. package/lib/visualizer.component.d.ts +14 -0
  120. package/package.json +1 -1
  121. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DHrHO2ay.mjs.map +0 -1
@@ -8,16 +8,6 @@ import { PanelOption } from '../../spatial/spatial-panel-model';
8
8
  import type { GenePickerModel } from '../spatial-gene-picker';
9
9
  import type { SpatialLegendEntry } from '../spatial-key/spatial-key.model';
10
10
  import * as i0 from "@angular/core";
11
- /**
12
- * The Observations section — one marker per observation (cell centroid, Visium spot) — and
13
- * what else draws them: what colours them (a column or a gene, mutually exclusive, with
14
- * the {@link SpatialKeyComponent key}), point size and opacity, the gene map, the 3D scene
15
- * (volume, cloud, sections, density volumes) and the continuous-only knobs.
16
- *
17
- * Renders the section and the sections after it as siblings in the dialog body
18
- * (`display: contents`). Writes only through the port: `setViewState`, and the colour
19
- * source's own `colorByColumn` / `colorByFeature` / `clearColorBy`.
20
- */
21
11
  export declare class SpatialObservationsPanelComponent implements OnChanges {
22
12
  /** The spatial controls this panel reads and writes through; null without a `SPATIAL_DATA_PORT`. */
23
13
  controls: ISpatialControls | null;
@@ -43,6 +33,11 @@ export declare class SpatialObservationsPanelComponent implements OnChanges {
43
33
  open: boolean;
44
34
  /** Asks to open or close it; two-way with `open`. */
45
35
  readonly openChange: EventEmitter<boolean>;
36
+ /**
37
+ * Whether the dataset's cells can be drawn here (a cell segmentation, and in 3D a 3D one): the
38
+ * observations are shown as Markers or as Cell segmentations.
39
+ */
40
+ cellsAvailable: boolean;
46
41
  /** A legend row was clicked (see the key). */
47
42
  readonly categoryClicked: EventEmitter<number>;
48
43
  protected readonly clipOptions: PanelOption<[number, number]>[];
@@ -50,10 +45,10 @@ export declare class SpatialObservationsPanelComponent implements OnChanges {
50
45
  protected readonly matchOptions: PanelOption<SpatialViewState['observationGenesMatch']>[];
51
46
  /** Virtual-scrolled only past this many options (see the cells panel's gene dropdown). */
52
47
  protected readonly geneVirtualScrollFrom = 200;
53
- /** Colour-by column choices — "None" plus every column the dataset declares. */
54
- protected columnOptions: PanelOption<string | null>[];
55
- protected selectedColumn: string | null;
56
- protected selectedGene: string | null;
48
+ /** What the observations are shown as, with a cell segmentation. */
49
+ protected readonly showAsOptions: PanelOption<'markers' | 'cells'>[];
50
+ /** The choice of Markers or Cell segmentations, kept while the observations are hidden. */
51
+ private chosenShownAs;
57
52
  /**
58
53
  * The dataset's imaged section positions, or null when its z is continuous rather than
59
54
  * sectioned. Read once per dataset — the scan walks the z of every observation, so it
@@ -61,10 +56,22 @@ export declare class SpatialObservationsPanelComponent implements OnChanges {
61
56
  */
62
57
  protected sections: Float32Array | null;
63
58
  ngOnChanges(changes: SimpleChanges): void;
64
- /** Column dropdown. Choosing a column supersedes any gene selection. */
65
- protected onColumn(name: string | null): void;
66
- /** A gene was picked; it supersedes any column selection. */
67
- protected onGene(name: string | null): void;
59
+ /** Whether the cells are drawn (the explicit choice, or automatically for data that has them). */
60
+ private get cellsOn();
61
+ /** Whether the observations are shown at all, as markers or as cells. */
62
+ protected get observationsShown(): boolean;
63
+ /** What the observations are shown as (the toggle): the cells while they are drawn, else the
64
+ * markers, or, hidden, what was last chosen. */
65
+ protected get shownAs(): 'markers' | 'cells';
66
+ /** Show or hide the observations, as what they were shown as. */
67
+ protected onShowObservations(on: boolean): void;
68
+ protected onShownAs(as: 'markers' | 'cells' | null): void;
69
+ /**
70
+ * Draw the observations as the markers, or as the cells: one or the other, never both (the
71
+ * renderers draw no markers while the cells are drawn). The markers stay switched on under the
72
+ * cells, so a view without them (spatial 3D of a 2D segmentation) still shows the markers.
73
+ */
74
+ private showAs;
68
75
  /** Genes picked for the observation filter; none draws every observation. */
69
76
  protected onObservationGenes(genes: string[] | null): void;
70
77
  protected onObservationGenesMatch(match: SpatialViewState['observationGenesMatch'] | null): void;
@@ -94,8 +101,6 @@ export declare class SpatialObservationsPanelComponent implements OnChanges {
94
101
  protected resetGeneStyle(gene: string): void;
95
102
  /** What the filter hides, in words. */
96
103
  protected get geneFilterHint(): string;
97
- /** Cell outlines on offer, which changes what the circles mean. */
98
- protected get hasCells(): boolean;
99
104
  /** True while a selection is active — everything else renders muted. */
100
105
  get hasSelection(): boolean;
101
106
  /** Whether log/clip apply — they are continuous-only knobs. */
@@ -122,8 +127,6 @@ export declare class SpatialObservationsPanelComponent implements OnChanges {
122
127
  protected get geneMapVolumeNote(): string;
123
128
  /** True while a gene is the colour source — the only thing a gene map can map. */
124
129
  protected get canMapGene(): boolean;
125
- protected onShowVolume(on: boolean): void;
126
- protected onVolumeOpacity(value: number | undefined): void;
127
130
  protected onShowPoints(on: boolean): void;
128
131
  /** The "one section at a time" switch: null restores the whole stack. */
129
132
  protected onOneSection(on: boolean): void;
@@ -145,5 +148,5 @@ export declare class SpatialObservationsPanelComponent implements OnChanges {
145
148
  private static readonly DENSITY_MAX_CLUSTERS;
146
149
  protected onClip(value: [number, number]): void;
147
150
  static ɵfac: i0.ɵɵFactoryDeclaration<SpatialObservationsPanelComponent, never>;
148
- static ɵcmp: i0.ɵɵComponentDeclaration<SpatialObservationsPanelComponent, "spatial-observations-panel", never, { "controls": { "alias": "controls"; "required": false; }; "dataset": { "alias": "dataset"; "required": false; }; "view": { "alias": "view"; "required": false; }; "genes": { "alias": "genes"; "required": false; }; "legend": { "alias": "legend"; "required": false; }; "colorBarCss": { "alias": "colorBarCss"; "required": false; }; "selection": { "alias": "selection"; "required": false; }; "selectedCategory": { "alias": "selectedCategory"; "required": false; }; "colormapOptions": { "alias": "colormapOptions"; "required": false; }; "is3d": { "alias": "is3d"; "required": false; }; "open": { "alias": "open"; "required": false; }; }, { "openChange": "openChange"; "categoryClicked": "categoryClicked"; }, never, never, true, never>;
151
+ static ɵcmp: i0.ɵɵComponentDeclaration<SpatialObservationsPanelComponent, "spatial-observations-panel", never, { "controls": { "alias": "controls"; "required": false; }; "dataset": { "alias": "dataset"; "required": false; }; "view": { "alias": "view"; "required": false; }; "genes": { "alias": "genes"; "required": false; }; "legend": { "alias": "legend"; "required": false; }; "colorBarCss": { "alias": "colorBarCss"; "required": false; }; "selection": { "alias": "selection"; "required": false; }; "selectedCategory": { "alias": "selectedCategory"; "required": false; }; "colormapOptions": { "alias": "colormapOptions"; "required": false; }; "is3d": { "alias": "is3d"; "required": false; }; "open": { "alias": "open"; "required": false; }; "cellsAvailable": { "alias": "cellsAvailable"; "required": false; }; }, { "openChange": "openChange"; "categoryClicked": "categoryClicked"; }, never, ["spatial-cells-panel"], true, never>;
149
152
  }
@@ -0,0 +1,48 @@
1
+ import { ChangeDetectorRef, NgZone, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
+ import type { ISpatialControls } from '../../contracts/visualizer.contract';
3
+ import type { ObservationsInSelection } from '../../contracts/display-types';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * "Observations in selection", in the Observations section: the observations of what is selected —
7
+ * a cell, a cell type picked on the canvas, the selected regions — by the grouping they are coloured
8
+ * by (else the cell types), with a few measurements' means, or one cell's id, groupings and values.
9
+ * Every observation in spatial 3D; in 2D those on the plane shown. See
10
+ * `ISpatialControls.getObservationsInSelection$`.
11
+ *
12
+ * Collapsible; followed only while expanded (and while the Observations section, which holds it, is
13
+ * open).
14
+ */
15
+ export declare class SpatialSelectionObservationsComponent implements OnChanges, OnDestroy {
16
+ private readonly zone;
17
+ private readonly cdr;
18
+ /** The spatial controls the list is read through; null without a `SPATIAL_DATA_PORT`. */
19
+ controls: ISpatialControls | null;
20
+ /** In spatial 3D: the list is of the whole volume. */
21
+ is3d: boolean;
22
+ /** Expanded: the list is followed and shown. */
23
+ protected expanded: boolean;
24
+ /** The selection's observations (null until the first answer). */
25
+ protected list: ObservationsInSelection | null;
26
+ private sub;
27
+ constructor(zone: NgZone, cdr: ChangeDetectorRef);
28
+ ngOnChanges(changes: SimpleChanges): void;
29
+ ngOnDestroy(): void;
30
+ /** Whether there is a list to offer. */
31
+ protected get available(): boolean;
32
+ /** The largest group, for the bars. */
33
+ protected get max(): number;
34
+ protected toggle(): void;
35
+ private watch;
36
+ /** A measurement as shown: a number to 3 significant figures (with its unit), text as it is. */
37
+ protected format(m: {
38
+ value: string | number;
39
+ unit?: string;
40
+ }): string;
41
+ /** The groups as tab-separated text (group, observations), for a spreadsheet. */
42
+ protected copy(): void;
43
+ protected trackGroup(_i: number, g: {
44
+ name: string;
45
+ }): string;
46
+ static ɵfac: i0.ɵɵFactoryDeclaration<SpatialSelectionObservationsComponent, never>;
47
+ static ɵcmp: i0.ɵɵComponentDeclaration<SpatialSelectionObservationsComponent, "spatial-selection-observations", never, { "controls": { "alias": "controls"; "required": false; }; "is3d": { "alias": "is3d"; "required": false; }; }, {}, never, never, true, never>;
48
+ }
@@ -0,0 +1,43 @@
1
+ import { ChangeDetectorRef, NgZone, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
2
+ import type { ISpatialControls } from '../../contracts/visualizer.contract';
3
+ import type { TranscriptsInSelection } from '../../contracts/display-types';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * "Transcripts in selection", in the Transcripts section: the transcripts of what is selected, by
7
+ * gene, most frequent first — through the volume in spatial 3D (a cell, or a cell type picked on the
8
+ * canvas), on the plane shown in 2D (the selected cells or regions). See
9
+ * `ISpatialControls.getTranscriptsInSelection$`.
10
+ *
11
+ * Collapsible; counted only while expanded (and while the Transcripts section, which holds it, is
12
+ * open): the counts read the finest transcript tiles of the selection.
13
+ */
14
+ export declare class SpatialSelectionTranscriptsComponent implements OnChanges, OnDestroy {
15
+ private readonly zone;
16
+ private readonly cdr;
17
+ /** The spatial controls the list is read through; null without a `SPATIAL_DATA_PORT`. */
18
+ controls: ISpatialControls | null;
19
+ /** In spatial 3D: the list is of the whole volume. */
20
+ is3d: boolean;
21
+ /** Expanded: the list is counted and shown. */
22
+ protected expanded: boolean;
23
+ /** The selection's transcripts by gene (null until the first answer). */
24
+ protected list: TranscriptsInSelection | null;
25
+ private sub;
26
+ constructor(zone: NgZone, cdr: ChangeDetectorRef);
27
+ ngOnChanges(changes: SimpleChanges): void;
28
+ ngOnDestroy(): void;
29
+ /** Whether there is a list to offer: the controls count transcripts. */
30
+ protected get available(): boolean;
31
+ /** The largest gene count, for the bars. */
32
+ protected get max(): number;
33
+ protected toggle(): void;
34
+ /** Subscribe while expanded, else not (a collapsed list reads nothing). */
35
+ private watch;
36
+ /** The list as tab-separated text (gene, count), for a spreadsheet. */
37
+ protected copy(): void;
38
+ protected trackGene(_i: number, g: {
39
+ name: string;
40
+ }): string;
41
+ static ɵfac: i0.ɵɵFactoryDeclaration<SpatialSelectionTranscriptsComponent, never>;
42
+ static ɵcmp: i0.ɵɵComponentDeclaration<SpatialSelectionTranscriptsComponent, "spatial-selection-transcripts", never, { "controls": { "alias": "controls"; "required": false; }; "is3d": { "alias": "is3d"; "required": false; }; }, {}, never, never, true, never>;
43
+ }
@@ -29,6 +29,8 @@ export declare class SpatialTranscriptsPanelComponent implements OnChanges {
29
29
  controls: ISpatialControls | null;
30
30
  /** The dataset on offer, or null. */
31
31
  dataset: SpatialDataset | null;
32
+ /** In spatial 3D (the transcripts in selection are then the whole volume's). */
33
+ is3d: boolean;
32
34
  /** The current spatial view state: what is drawn, and how. */
33
35
  view: SpatialViewState;
34
36
  /** The gene list the transcript genes are picked from, shared with the other gene dropdowns. */
@@ -150,5 +152,5 @@ export declare class SpatialTranscriptsPanelComponent implements OnChanges {
150
152
  /** '⋮' menu. */
151
153
  private buildGeneMenu;
152
154
  static ɵfac: i0.ɵɵFactoryDeclaration<SpatialTranscriptsPanelComponent, never>;
153
- static ɵcmp: i0.ɵɵComponentDeclaration<SpatialTranscriptsPanelComponent, "spatial-transcripts-panel", never, { "controls": { "alias": "controls"; "required": false; }; "dataset": { "alias": "dataset"; "required": false; }; "view": { "alias": "view"; "required": false; }; "genes": { "alias": "genes"; "required": false; }; "estimate": { "alias": "estimate"; "required": false; }; "densityStats": { "alias": "densityStats"; "required": false; }; "geneCounts": { "alias": "geneCounts"; "required": false; }; "colormapOptions": { "alias": "colormapOptions"; "required": false; }; "open": { "alias": "open"; "required": false; }; }, { "openChange": "openChange"; }, never, never, true, never>;
155
+ static ɵcmp: i0.ɵɵComponentDeclaration<SpatialTranscriptsPanelComponent, "spatial-transcripts-panel", never, { "controls": { "alias": "controls"; "required": false; }; "dataset": { "alias": "dataset"; "required": false; }; "is3d": { "alias": "is3d"; "required": false; }; "view": { "alias": "view"; "required": false; }; "genes": { "alias": "genes"; "required": false; }; "estimate": { "alias": "estimate"; "required": false; }; "densityStats": { "alias": "densityStats"; "required": false; }; "geneCounts": { "alias": "geneCounts"; "required": false; }; "colormapOptions": { "alias": "colormapOptions"; "required": false; }; "open": { "alias": "open"; "required": false; }; }, { "openChange": "openChange"; }, never, never, true, never>;
154
156
  }
@@ -51,6 +51,10 @@ export declare class RegionSourceScope {
51
51
  slicesWithSource(image: string | undefined): number[];
52
52
  /** Whether `image` has one source over all its slices. */
53
53
  hasPlanesSource(image: string | undefined): boolean;
54
+ /** The opener of `image`'s source over all its slices (as attached), or null without one. */
55
+ planesOpener(image: string | undefined): RegionSourceOpener | null;
56
+ /** Whether `image` has any source: one over all its slices, or one of a slice's own. */
57
+ hasAny(image: string | undefined): boolean;
54
58
  /**
55
59
  * The source behind `slice` of `image`, opening it if needed. Resolves null when there is
56
60
  * none, and rejects when it cannot be opened.
@@ -92,6 +92,8 @@ export declare class RegionStore implements IRegionStore, IRegionEditApi, IRegio
92
92
  */
93
93
  private readonly sources;
94
94
  private readonly sourceView$;
95
+ /** Whether the overlays draw the source (see setRegionSourceDrawn). */
96
+ private readonly sourceDrawn$;
95
97
  /** The region look the user chose (overrides the source's hint), field by field. */
96
98
  private userStyle;
97
99
  /** The current source's style hint. */
@@ -355,10 +357,29 @@ export declare class RegionStore implements IRegionStore, IRegionEditApi, IRegio
355
357
  dropSliceRegionSource(): Promise<void>;
356
358
  /** Whether the slice shown has a region source. */
357
359
  hasRegionSource(): boolean;
360
+ /** Whether the current image has any region source, over all its slices or a slice's own. */
361
+ hasAnyRegionSource(): boolean;
362
+ /**
363
+ * The opener of the current image's source over all its slices, as attached (see
364
+ * {@link attachRegionSource}), or null without one: tells whose source it still is.
365
+ */
366
+ getPlanesSourceOpener(): RegionSourceOpener | null;
358
367
  /** The slice's region source as a source layer draws it; null without one (or until it opens). */
359
368
  getRegionSourceView(): RegionSourceView | null;
360
369
  /** {@link getRegionSourceView} and every change of it (slice, taken ids, class colours). */
361
370
  getRegionSourceView$(): Observable<RegionSourceView | null>;
371
+ /**
372
+ * The source view the overlays draw: {@link getRegionSourceView$}, or null while the source is
373
+ * drawn by another layer instead (see {@link setRegionSourceDrawn}). The Region Editor's list
374
+ * and the source's other uses keep reading the source itself.
375
+ */
376
+ getDrawnRegionSourceView$(): Observable<RegionSourceView | null>;
377
+ /**
378
+ * Whether the overlays draw the region source (default), or leave it to another layer that draws
379
+ * the same outlines (the 2D spatial view's cells, from a 3D segmentation's region set), so they
380
+ * are not drawn twice. Only the drawing: the source stays attached, listed and editable.
381
+ */
382
+ setRegionSourceDrawn(drawn: boolean): void;
362
383
  /**
363
384
  * Take source features into the working set for editing: their exact geometry becomes
364
385
  * ordinary regions (minted, coloured and slice-tagged as any region entering the store) and
@@ -41,6 +41,11 @@ export declare class ToolbarComponent {
41
41
  isoRange: number[];
42
42
  /** The last slice index of a stack. */
43
43
  maxIndex: number;
44
+ /**
45
+ * The image is one plane, but a spatial dataset's region set slices it into planes: the live
46
+ * views offer the slider over them ({@link maxIndex} is the last plane), as over a stack.
47
+ */
48
+ planeSlices: boolean;
44
49
  /** The current slice (0-based). */
45
50
  zIndex: number;
46
51
  /** True for any 2D (non Surface-3D) plot type. */
@@ -231,5 +236,5 @@ export declare class ToolbarComponent {
231
236
  protected get isIntensityCapable(): boolean;
232
237
  protected showHelp(): void;
233
238
  static ɵfac: i0.ɵɵFactoryDeclaration<ToolbarComponent, never>;
234
- static ɵcmp: i0.ɵɵComponentDeclaration<ToolbarComponent, "plotting-toolbar", never, { "imageInfo": { "alias": "imageInfo"; "required": false; }; "hasSpatialDataset": { "alias": "hasSpatialDataset"; "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; }; "isVolumeView": { "alias": "isVolumeView"; "required": false; }; "sliceEditor": { "alias": "sliceEditor"; "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"; "toggleSliceEditor": "toggleSliceEditor"; "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, ["*"], true, never>;
239
+ static ɵcmp: i0.ɵɵComponentDeclaration<ToolbarComponent, "plotting-toolbar", never, { "imageInfo": { "alias": "imageInfo"; "required": false; }; "hasSpatialDataset": { "alias": "hasSpatialDataset"; "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; }; "planeSlices": { "alias": "planeSlices"; "required": false; }; "zIndex": { "alias": "zIndex"; "required": false; }; "isHeatmap": { "alias": "isHeatmap"; "required": false; }; "is3dRegions": { "alias": "is3dRegions"; "required": false; }; "isVolumeView": { "alias": "isVolumeView"; "required": false; }; "sliceEditor": { "alias": "sliceEditor"; "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"; "toggleSliceEditor": "toggleSliceEditor"; "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, ["*"], true, never>;
235
240
  }
@@ -0,0 +1,55 @@
1
+ import { Observable } from 'rxjs';
2
+ import { IImageInfo } from '../contracts/image.contract';
3
+ import { SpatialDataPort } from '../contracts/ports/spatial-data.port';
4
+ import { SpatialDataset } from '../contracts/spatial-dataset.contract';
5
+ import type { RegionSourceOpener } from '../store/region-source-scope';
6
+ /** What {@link SpatialRegionSetLink} attaches a dataset's region set through (the router). */
7
+ export interface DatasetRegionSetTarget {
8
+ attachDatasetRegionSet?(open: RegionSourceOpener, key: string): Promise<boolean>;
9
+ releaseDatasetRegionSet?(keep: string | null): void;
10
+ }
11
+ /**
12
+ * The region set a spatial dataset's boundaries name (a 3D segmentation's cells, see
13
+ * `SpatialPolygonTilesMeta.sets`): the default set's when it names one, else the first that does.
14
+ */
15
+ export declare function datasetRegionSet(dataset: SpatialDataset | null | undefined): string | null;
16
+ /**
17
+ * Whether `info` is the dataset's own image, the one its `imageRef` names. Exactly, when the host
18
+ * gives the image's id ({@link IImageInfo.imageId}); otherwise by the file name the id ends in (the
19
+ * host opens the image by that id, a path), which images of other datasets can share: then the link
20
+ * only takes an image that landed after the dataset was selected (see {@link SpatialRegionSetLink}).
21
+ * Not the reference volume's stack, which a dataset without an `imageRef` is drawn over: the region
22
+ * set's coordinates are not its pixels.
23
+ */
24
+ export declare function isDatasetImage(info: IImageInfo | null | undefined, dataset: SpatialDataset | null | undefined): boolean;
25
+ /**
26
+ * Attaches a spatial dataset's region set to its image in the region editor, once both are there:
27
+ * the dataset (the port's) and its image, landed. Each time either changes it asks again; the
28
+ * target attaches once per image and set.
29
+ *
30
+ * An image that landed while another dataset was selected is not taken for this one by its file name,
31
+ * only by its id ({@link IImageInfo.imageId}): a host selects the dataset and then opens its image,
32
+ * and until that lands the image on screen is the previous dataset's, though its file name may be the
33
+ * same (every converted bundle's is `plate.ome.tif`). One that landed with no dataset selected may be.
34
+ */
35
+ export declare class SpatialRegionSetLink {
36
+ private readonly port;
37
+ private readonly target;
38
+ private dataset;
39
+ private image;
40
+ /** The dataset selected when the image landed (its id), or null: none was. */
41
+ private imageDataset;
42
+ /** The region set last asked to be attached, until the dataset stops naming it. */
43
+ private asked;
44
+ constructor(port: SpatialDataPort | undefined, target: DatasetRegionSetTarget);
45
+ /** Follow the port's dataset until `until$` emits. */
46
+ bind(until$: Observable<unknown>): void;
47
+ /** An image landed (its render settled): the dataset's own, perhaps. */
48
+ imageLanded(info: IImageInfo): void;
49
+ /**
50
+ * Whether the landed image may be the dataset's: by its id when the host gives one, else only when
51
+ * it landed under this dataset or under none (see the class's note).
52
+ */
53
+ private imageOf;
54
+ private sync;
55
+ }
@@ -122,6 +122,11 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
122
122
  private readonly consumedSliceHints;
123
123
  protected zIndex: number;
124
124
  protected maxIndex: number;
125
+ /**
126
+ * Planes of the spatial dataset's region set slicing the image, an image of one plane (see
127
+ * `IVisualizer.getDatasetPlanes$`): the slider then runs over them. 0 without.
128
+ */
129
+ protected datasetPlanes: number;
125
130
  contextMenu: ContextMenu;
126
131
  protected contextMenuItems: MenuItem[];
127
132
  /** The armed tool mode and the toolbar's tool settings. */
@@ -285,6 +290,8 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
285
290
  protected isoRange: number[];
286
291
  /** The spatial-omics dataset on offer and the gates it puts on the selector. */
287
292
  protected readonly spatial: SpatialDatasetBinder;
293
+ /** Attaches a spatial dataset's region set (a 3D segmentation's cells) to its image's regions. */
294
+ private readonly regionSetLink;
288
295
  /** Whether a spatial-omics dataset is published on `SPATIAL_DATA_PORT` — gates the
289
296
  * spatial plot types; the toolbar offers the plot modes for an image-less one too. */
290
297
  protected get hasSpatialDataset(): boolean;
@@ -298,6 +305,13 @@ export declare class VisualizerComponent implements OnInit, OnChanges, AfterView
298
305
  /** Follow the spatial-omics dataset: a dataset appearing, switching or being cleared
299
306
  * re-gates the selector exactly as the image stream and the test-mode toggle do. */
300
307
  private watchSpatialDataset;
308
+ /**
309
+ * The slider over the dataset's planes, on an image of one plane: its bounds are the planes'
310
+ * (none left: back to the image's one), the slice kept within them.
311
+ */
312
+ private layOutPlanes;
313
+ /** The last slice index the dataset's planes give an image of one plane (0 without). */
314
+ private planeMaxIndex;
301
315
  /** Recompute the selector's entries for the current image, dataset and test mode
302
316
  * (see {@link computePlotTypeMenu}). */
303
317
  private computePlotTypeOptions;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jax-data-science/sci-image-visualizer",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "engines": {
5
5
  "node": ">=20.9.0"
6
6
  },