@cornerstonejs/core 5.0.16 → 5.1.1

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 (79) hide show
  1. package/dist/esm/RenderingEngine/BaseVolumeViewport.d.ts +4 -0
  2. package/dist/esm/RenderingEngine/BaseVolumeViewport.js +24 -0
  3. package/dist/esm/RenderingEngine/ContextPoolRenderingEngine.d.ts +1 -0
  4. package/dist/esm/RenderingEngine/ContextPoolRenderingEngine.js +16 -6
  5. package/dist/esm/RenderingEngine/ECGViewport.d.ts +4 -0
  6. package/dist/esm/RenderingEngine/ECGViewport.js +8 -0
  7. package/dist/esm/RenderingEngine/GenericViewport/ECG/DefaultECGDataProvider.js +1 -1
  8. package/dist/esm/RenderingEngine/GenericViewport/GenericViewport.d.ts +24 -15
  9. package/dist/esm/RenderingEngine/GenericViewport/GenericViewport.js +26 -0
  10. package/dist/esm/RenderingEngine/GenericViewport/Planar/CpuImageSliceRenderPath.js +12 -3
  11. package/dist/esm/RenderingEngine/GenericViewport/Planar/CpuVolumeSliceRenderPath.js +3 -1
  12. package/dist/esm/RenderingEngine/GenericViewport/Planar/DefaultPlanarDataProvider.js +7 -4
  13. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarLegacyCompatibilityController.js +3 -3
  14. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarRenderPathDecisionService.d.ts +1 -0
  15. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarRenderPathDecisionService.js +26 -9
  16. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewport.d.ts +15 -2
  17. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewport.js +182 -18
  18. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewportLegacyAdapter.js +2 -2
  19. package/dist/esm/RenderingEngine/GenericViewport/Planar/PlanarViewportTypes.d.ts +4 -2
  20. package/dist/esm/RenderingEngine/GenericViewport/Planar/VtkImageMapperRenderPath.js +42 -9
  21. package/dist/esm/RenderingEngine/GenericViewport/Planar/VtkVolumeSliceRenderPath.js +3 -1
  22. package/dist/esm/RenderingEngine/GenericViewport/Planar/planarImageEvents.d.ts +1 -0
  23. package/dist/esm/RenderingEngine/GenericViewport/Planar/planarImageEvents.js +11 -2
  24. package/dist/esm/RenderingEngine/GenericViewport/Planar/planarVolumePresentation.js +30 -3
  25. package/dist/esm/RenderingEngine/GenericViewport/Video/DefaultVideoDataProvider.js +1 -1
  26. package/dist/esm/RenderingEngine/GenericViewport/Video/VideoViewport.d.ts +1 -0
  27. package/dist/esm/RenderingEngine/GenericViewport/Video/VideoViewport.js +4 -1
  28. package/dist/esm/RenderingEngine/GenericViewport/ViewportArchitectureTypes.d.ts +12 -8
  29. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/DefaultVolume3DDataProvider.js +3 -3
  30. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/VolumeViewport3DLegacyAdapter.js +4 -4
  31. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/viewport3D.d.ts +5 -1
  32. package/dist/esm/RenderingEngine/GenericViewport/Volume3D/viewport3D.js +18 -4
  33. package/dist/esm/RenderingEngine/GenericViewport/WSI/DefaultWSIDataProvider.js +2 -2
  34. package/dist/esm/RenderingEngine/GenericViewport/WSI/WSIViewportLegacyAdapter.js +2 -2
  35. package/dist/esm/RenderingEngine/GenericViewport/genericViewportDisplaySetAccess.d.ts +35 -0
  36. package/dist/esm/RenderingEngine/GenericViewport/{genericViewportDataSetAccess.js → genericViewportDisplaySetAccess.js} +19 -19
  37. package/dist/esm/RenderingEngine/GenericViewport/genericViewportReferenceCompatibility.js +26 -4
  38. package/dist/esm/RenderingEngine/GenericViewport/index.d.ts +1 -1
  39. package/dist/esm/RenderingEngine/StackViewport.d.ts +4 -0
  40. package/dist/esm/RenderingEngine/StackViewport.js +14 -0
  41. package/dist/esm/RenderingEngine/VideoViewport.d.ts +10 -0
  42. package/dist/esm/RenderingEngine/VideoViewport.js +13 -0
  43. package/dist/esm/RenderingEngine/Viewport.d.ts +17 -0
  44. package/dist/esm/RenderingEngine/Viewport.js +18 -0
  45. package/dist/esm/RenderingEngine/WSIViewport.d.ts +4 -0
  46. package/dist/esm/RenderingEngine/WSIViewport.js +15 -1
  47. package/dist/esm/RenderingEngine/helpers/planarImageRendering.d.ts +5 -1
  48. package/dist/esm/RenderingEngine/helpers/planarImageRendering.js +19 -5
  49. package/dist/esm/RenderingEngine/helpers/stats/RenderModesPanel.d.ts +4 -0
  50. package/dist/esm/RenderingEngine/helpers/stats/RenderModesPanel.js +48 -1
  51. package/dist/esm/RenderingEngine/helpers/stats/StatsOverlay.js +66 -9
  52. package/dist/esm/init.js +1 -1
  53. package/dist/esm/types/IGenericViewport.d.ts +24 -0
  54. package/dist/esm/types/IGenericViewport.js +0 -0
  55. package/dist/esm/types/ScalingDescriptor.d.ts +5 -0
  56. package/dist/esm/types/ScalingDescriptor.js +0 -0
  57. package/dist/esm/types/index.d.ts +4 -1
  58. package/dist/esm/utilities/VoxelManager.d.ts +2 -0
  59. package/dist/esm/utilities/VoxelManager.js +12 -1
  60. package/dist/esm/utilities/genericViewportDisplaySetMetadataProvider.d.ts +8 -0
  61. package/dist/esm/utilities/genericViewportDisplaySetMetadataProvider.js +23 -0
  62. package/dist/esm/utilities/getScalingDescriptor.d.ts +10 -0
  63. package/dist/esm/utilities/getScalingDescriptor.js +41 -0
  64. package/dist/esm/utilities/getTargetVolumeAndSpacingInNormalDir.js +4 -5
  65. package/dist/esm/utilities/getViewportModality.js +5 -14
  66. package/dist/esm/utilities/index.d.ts +5 -3
  67. package/dist/esm/utilities/index.js +6 -3
  68. package/dist/esm/utilities/isPTPrescaledWithSUV.d.ts +1 -1
  69. package/dist/esm/utilities/isPTPrescaledWithSUV.js +1 -1
  70. package/dist/esm/utilities/resolveGenericViewportVolumeId.d.ts +2 -0
  71. package/dist/esm/utilities/resolveGenericViewportVolumeId.js +12 -0
  72. package/dist/esm/utilities/viewportCapabilities.d.ts +10 -1
  73. package/dist/esm/utilities/viewportCapabilities.js +22 -0
  74. package/dist/esm/version.d.ts +1 -1
  75. package/dist/esm/version.js +1 -1
  76. package/package.json +6 -6
  77. package/dist/esm/RenderingEngine/GenericViewport/genericViewportDataSetAccess.d.ts +0 -35
  78. package/dist/esm/utilities/genericViewportDataSetMetadataProvider.d.ts +0 -8
  79. package/dist/esm/utilities/genericViewportDataSetMetadataProvider.js +0 -23
@@ -3,7 +3,7 @@ import type { ReferenceCompatibleOptions, ViewReference, ViewReferenceSpecifier
3
3
  import type ViewportType from '../../enums/ViewportType';
4
4
  import type ResolvedViewportView from './ResolvedViewportView';
5
5
  export type ViewportId = string;
6
- export type DataId = string;
6
+ export type DisplaySetId = string;
7
7
  export type KnownViewportRenderContext = 'planar' | 'video' | 'ecg' | 'wsi' | '3d';
8
8
  export type ExtensionViewportRenderContext = string & {};
9
9
  export type ViewportRenderContextType = KnownViewportRenderContext | ExtensionViewportRenderContext;
@@ -36,7 +36,7 @@ export interface BasePresentationProps {
36
36
  opacity?: number;
37
37
  }
38
38
  export type LoadedData<TData extends object = object> = {
39
- id: DataId;
39
+ id: DisplaySetId;
40
40
  type: LogicalDataType;
41
41
  } & TData;
42
42
  export type MountedRendering<TRendering extends {
@@ -75,7 +75,7 @@ export interface RenderPathResolver {
75
75
  resolve<TContext extends BaseViewportRenderContext>(type: ViewportType, data: LoadedData, options: DataAddOptions): RenderPathDefinition<TContext, BaseViewportRenderContext>;
76
76
  }
77
77
  export interface DataProvider<TData extends object = object, TOptions = unknown> {
78
- load(dataId: DataId, options?: TOptions): Promise<LoadedData<TData>>;
78
+ load(dataId: DisplaySetId, options?: TOptions): Promise<LoadedData<TData>>;
79
79
  }
80
80
  export interface ViewportDataBinding<TPresentation = unknown> extends RenderPathAttachment<TPresentation> {
81
81
  data: LoadedData;
@@ -84,20 +84,24 @@ export interface ViewportDataBinding<TPresentation = unknown> extends RenderPath
84
84
  export interface ViewportController<TViewState = unknown, TDataPresentation = unknown> {
85
85
  readonly id: ViewportId;
86
86
  readonly type: ViewportType;
87
- addDisplaySet(displaySetId: DataId, options: DataAddOptions): Promise<void>;
87
+ addDisplaySet(displaySetId: DisplaySetId, options: DataAddOptions): Promise<void>;
88
88
  setDisplaySets(...entries: Array<{
89
- displaySetId: DataId;
89
+ displaySetId: DisplaySetId;
90
90
  options?: unknown;
91
91
  }>): Promise<void>;
92
- removeData(dataId: DataId): void;
92
+ getDisplaySets(): Array<{
93
+ displaySetId: DisplaySetId;
94
+ options?: unknown;
95
+ }>;
96
+ removeData(displaySetId: DisplaySetId): void;
93
97
  setViewState(viewState: Partial<TViewState>): void;
94
98
  getViewState(): TViewState;
95
99
  getResolvedView(): ResolvedViewportView<unknown, ICamera<unknown>> | undefined;
96
100
  updateViewState(updater: Partial<TViewState> | ((viewState: TViewState) => Partial<TViewState> | void)): void;
97
101
  resetViewState(options?: unknown): boolean;
98
102
  setDisplaySetPresentation(props: Partial<TDataPresentation>): void;
99
- setDisplaySetPresentation(displaySetId: DataId, props: Partial<TDataPresentation>): void;
100
- getDisplaySetPresentation(dataId: DataId): TDataPresentation | undefined;
103
+ setDisplaySetPresentation(displaySetId: DisplaySetId, props: Partial<TDataPresentation>): void;
104
+ getDisplaySetPresentation(displaySetId: DisplaySetId): TDataPresentation | undefined;
101
105
  setViewReference(viewReference: ViewReference): void;
102
106
  getViewReference(specifier?: ViewReferenceSpecifier): ViewReference;
103
107
  getViewReferenceId(specifier?: ViewReferenceSpecifier): string;
@@ -2,7 +2,7 @@ import cache from '../../../cache/cache';
2
2
  import { loadAndCacheGeometry } from '../../../loaders/geometryLoader';
3
3
  import { createAndCacheVolume } from '../../../loaders/volumeLoader';
4
4
  import resolveViewportVolumeId from '../../helpers/resolveViewportVolumeId';
5
- import { getGenericViewportImageDataSet, isGenericViewportImageDataSet, } from '../genericViewportDataSetAccess';
5
+ import { getGenericViewportImageDisplaySet, isGenericViewportImageDisplaySet, } from '../genericViewportDisplaySetAccess';
6
6
  export class DefaultVolume3DDataProvider {
7
7
  async load(dataId, options) {
8
8
  if (!options) {
@@ -39,7 +39,7 @@ export class DefaultVolume3DDataProvider {
39
39
  };
40
40
  }
41
41
  getDataSet(dataId) {
42
- const dataSet = getGenericViewportImageDataSet(dataId);
42
+ const dataSet = getGenericViewportImageDisplaySet(dataId);
43
43
  if (!isVolume3DRegisteredDataSet(dataSet)) {
44
44
  return;
45
45
  }
@@ -47,7 +47,7 @@ export class DefaultVolume3DDataProvider {
47
47
  }
48
48
  }
49
49
  function isVolume3DRegisteredDataSet(value) {
50
- if (!isGenericViewportImageDataSet(value)) {
50
+ if (!isGenericViewportImageDisplaySet(value)) {
51
51
  return false;
52
52
  }
53
53
  return ((value.geometryId === undefined || typeof value.geometryId === 'string') &&
@@ -3,7 +3,7 @@ import { VIEWPORT_PRESETS } from '../../../constants';
3
3
  import { Events } from '../../../enums';
4
4
  import applyPreset from '../../../utilities/applyPreset';
5
5
  import triggerEvent from '../../../utilities/triggerEvent';
6
- import genericViewportDataSetMetadataProvider from '../../../utilities/genericViewportDataSetMetadataProvider';
6
+ import genericViewportDisplaySetMetadataProvider from '../../../utilities/genericViewportDisplaySetMetadataProvider';
7
7
  import { viewportProjection } from '../viewportProjection';
8
8
  import VolumeViewport3D from './viewport3D';
9
9
  class VolumeViewport3DLegacyAdapter extends VolumeViewport3D {
@@ -142,7 +142,7 @@ class VolumeViewport3DLegacyAdapter extends VolumeViewport3D {
142
142
  imageIds: cachedVolume.imageIds,
143
143
  volumeId: volumeInput.volumeId,
144
144
  };
145
- genericViewportDataSetMetadataProvider.add(dataId, dataSet);
145
+ genericViewportDisplaySetMetadataProvider.add(dataId, dataSet);
146
146
  this.managedDataIds.add(dataId);
147
147
  this.volumeDataIds.set(volumeInput.volumeId, dataId);
148
148
  dataIds.push(dataId);
@@ -268,7 +268,7 @@ class VolumeViewport3DLegacyAdapter extends VolumeViewport3D {
268
268
  if (!this.managedDataIds.delete(dataId)) {
269
269
  return;
270
270
  }
271
- genericViewportDataSetMetadataProvider.remove(dataId);
271
+ genericViewportDisplaySetMetadataProvider.remove(dataId);
272
272
  this.legacyProperties.delete(dataId);
273
273
  this.defaultLegacyProperties.delete(dataId);
274
274
  for (const [volumeId, mappedDataId] of this.volumeDataIds.entries()) {
@@ -279,7 +279,7 @@ class VolumeViewport3DLegacyAdapter extends VolumeViewport3D {
279
279
  }
280
280
  onDestroy() {
281
281
  for (const dataId of Array.from(this.managedDataIds)) {
282
- genericViewportDataSetMetadataProvider.remove(dataId);
282
+ genericViewportDisplaySetMetadataProvider.remove(dataId);
283
283
  }
284
284
  this.managedDataIds.clear();
285
285
  this.volumeDataIds.clear();
@@ -41,7 +41,11 @@ declare class VolumeViewport3D extends GenericViewport<Volume3DCamera, Volume3DD
41
41
  getImageData(): IImageData | undefined;
42
42
  getActors(): ActorEntry[];
43
43
  getDefaultActor(): ActorEntry | undefined;
44
- resetViewState(): boolean;
44
+ resetViewState(options?: {
45
+ resetPan?: boolean;
46
+ resetZoom?: boolean;
47
+ resetToCenter?: boolean;
48
+ }): boolean;
45
49
  resetViewStateForResize(): boolean;
46
50
  resize(): void;
47
51
  render(): void;
@@ -3,7 +3,7 @@ import { ViewportType } from '../../../enums';
3
3
  import renderingEngineCache from '../../renderingEngineCache';
4
4
  import GenericViewport from '../GenericViewport';
5
5
  import { getDimensionGroupReferenceContext, } from '../genericViewportReferenceCompatibility';
6
- import { getGenericViewportImageDataSet, isGenericViewportImageDataSet, } from '../genericViewportDataSetAccess';
6
+ import { getGenericViewportImageDisplaySet, isGenericViewportImageDisplaySet, } from '../genericViewportDisplaySetAccess';
7
7
  import { DefaultVolume3DDataProvider } from './DefaultVolume3DDataProvider';
8
8
  import { createVolume3DRenderPathResolver } from './Volume3DRenderPathResolver';
9
9
  import Volume3DResolvedView from './Volume3DResolvedView';
@@ -25,6 +25,7 @@ class VolumeViewport3D extends GenericViewport {
25
25
  this.suppressEvents = false;
26
26
  this.renderingEngineId = args.renderingEngineId;
27
27
  this.canvas = args.canvas;
28
+ this.canvas.style.display = '';
28
29
  this.sWidth = args.sWidth;
29
30
  this.sHeight = args.sHeight;
30
31
  this.defaultOptions = args.defaultOptions || {};
@@ -230,11 +231,24 @@ class VolumeViewport3D extends GenericViewport {
230
231
  }
231
232
  return this.getActorEntriesForRendering(this.getVolume3DRendering(binding), data)[0];
232
233
  }
233
- resetViewState() {
234
+ resetViewState(options) {
235
+ const { resetPan = true, resetZoom = true, resetToCenter = true, } = options || {};
234
236
  const previousCamera = this.getCameraForEvent();
235
237
  const renderer = this.getRenderer();
238
+ const camera = renderer.getActiveCamera();
239
+ const previousParallelScale = camera.getParallelScale();
240
+ const previousPosition = camera.getPosition();
241
+ const previousFocalPoint = camera.getFocalPoint();
236
242
  renderer.resetCamera();
237
243
  renderer.resetCameraClippingRange();
244
+ if (!resetZoom) {
245
+ camera.setParallelScale(previousParallelScale);
246
+ }
247
+ if (!resetPan || !resetToCenter) {
248
+ camera.setFocalPoint(...previousFocalPoint);
249
+ camera.setPosition(...previousPosition);
250
+ renderer.resetCameraClippingRange();
251
+ }
238
252
  this.viewState = this.getViewState();
239
253
  this.render();
240
254
  this.triggerCameraModifiedEvent(previousCamera);
@@ -322,7 +336,7 @@ class VolumeViewport3D extends GenericViewport {
322
336
  return 'vtkGeometry3d';
323
337
  }
324
338
  getDataSet(dataId) {
325
- const dataSet = getGenericViewportImageDataSet(dataId);
339
+ const dataSet = getGenericViewportImageDisplaySet(dataId);
326
340
  if (!isVolume3DRegisteredDataSet(dataSet)) {
327
341
  return;
328
342
  }
@@ -388,7 +402,7 @@ function isVolume3DRendering(rendering) {
388
402
  rendering.renderMode === 'vtkGeometry3d');
389
403
  }
390
404
  function isVolume3DRegisteredDataSet(value) {
391
- if (!isGenericViewportImageDataSet(value)) {
405
+ if (!isGenericViewportImageDisplaySet(value)) {
392
406
  return false;
393
407
  }
394
408
  return ((value.geometryId === undefined || typeof value.geometryId === 'string') &&
@@ -1,5 +1,5 @@
1
1
  import { addWSIMiniNavigationOverlayCss, loadWSIData, } from '../../../utilities/WSIUtilities';
2
- import { getGenericViewportWSIDataSet } from '../genericViewportDataSetAccess';
2
+ import { getGenericViewportWSIDisplaySet } from '../genericViewportDisplaySetAccess';
3
3
  export class DefaultWSIDataProvider {
4
4
  async load(dataId) {
5
5
  const dataSet = this.getDataSet(dataId);
@@ -26,7 +26,7 @@ export class DefaultWSIDataProvider {
26
26
  };
27
27
  }
28
28
  getDataSet(dataId) {
29
- const registered = getGenericViewportWSIDataSet(dataId);
29
+ const registered = getGenericViewportWSIDisplaySet(dataId);
30
30
  if (!registered) {
31
31
  return;
32
32
  }
@@ -1,6 +1,6 @@
1
1
  import { MetadataModules } from '../../../enums';
2
2
  import * as metaData from '../../../metaData';
3
- import genericViewportDataSetMetadataProvider from '../../../utilities/genericViewportDataSetMetadataProvider';
3
+ import genericViewportDisplaySetMetadataProvider from '../../../utilities/genericViewportDisplaySetMetadataProvider';
4
4
  import { viewportProjection } from '../viewportProjection';
5
5
  import { canvasToIndexForWSI } from './wsiTransformUtils';
6
6
  import WSIViewport from './WSIViewport';
@@ -63,7 +63,7 @@ class WSIViewportLegacyAdapter extends WSIViewport {
63
63
  if (!webClient) {
64
64
  throw new Error(`To use setDataIds on WSI data, you must provide metaData.webClient for ${dataId}.`);
65
65
  }
66
- genericViewportDataSetMetadataProvider.add(dataId, {
66
+ genericViewportDisplaySetMetadataProvider.add(dataId, {
67
67
  imageIds,
68
68
  kind: 'wsi',
69
69
  options: {
@@ -0,0 +1,35 @@
1
+ import type { IImage } from '../../types';
2
+ import type { WSIClientLike } from '../../utilities/WSIUtilities';
3
+ import type { ViewportDataReference } from './ViewportArchitectureTypes';
4
+ export interface GenericViewportImageDisplaySet {
5
+ imageIds: string[];
6
+ [key: string]: unknown;
7
+ }
8
+ export interface GenericViewportPlanarDisplaySet extends GenericViewportImageDisplaySet {
9
+ kind?: 'planar';
10
+ initialImageIdIndex?: number;
11
+ volumeId?: string;
12
+ image?: IImage;
13
+ reference?: ViewportDataReference;
14
+ }
15
+ export interface GenericViewportSourceAliasDisplaySet {
16
+ kind: 'video' | 'ecg';
17
+ sourceDataId: string;
18
+ }
19
+ export interface GenericViewportWSIDisplaySet {
20
+ kind: 'wsi';
21
+ imageIds: string[];
22
+ options: {
23
+ miniNavigationOverlay?: boolean;
24
+ webClient: WSIClientLike;
25
+ };
26
+ }
27
+ export type GenericViewportRegisteredDisplaySet = string | string[] | GenericViewportPlanarDisplaySet | GenericViewportSourceAliasDisplaySet | GenericViewportWSIDisplaySet;
28
+ export declare function getGenericViewportRegisteredDisplaySet(displaySetId: string): GenericViewportRegisteredDisplaySet | undefined;
29
+ export declare function getGenericViewportImageDisplaySet(displaySetId: string): GenericViewportImageDisplaySet | undefined;
30
+ export declare function getGenericViewportPlanarDisplaySet(displaySetId: string): GenericViewportPlanarDisplaySet | undefined;
31
+ export declare function getGenericViewportWSIDisplaySet(displaySetId: string): GenericViewportWSIDisplaySet | undefined;
32
+ export declare function getGenericViewportSourceDataId(displaySetId: string): string;
33
+ export declare function isGenericViewportImageDisplaySet(value: unknown): value is GenericViewportImageDisplaySet;
34
+ export declare function isGenericViewportWSIDisplaySet(value: unknown): value is GenericViewportWSIDisplaySet;
35
+ export declare function isGenericViewportSourceAliasDisplaySet(value: unknown): value is GenericViewportSourceAliasDisplaySet;
@@ -1,27 +1,27 @@
1
- import genericViewportDataSetMetadataProvider from '../../utilities/genericViewportDataSetMetadataProvider';
2
- export function getGenericViewportRegisteredData(dataId) {
3
- return genericViewportDataSetMetadataProvider.get(genericViewportDataSetMetadataProvider.VIEWPORT_V2_DATA_SET, dataId);
1
+ import genericViewportDisplaySetMetadataProvider from '../../utilities/genericViewportDisplaySetMetadataProvider';
2
+ export function getGenericViewportRegisteredDisplaySet(displaySetId) {
3
+ return genericViewportDisplaySetMetadataProvider.get(genericViewportDisplaySetMetadataProvider.VIEWPORT_V2_DISPLAY_SET, displaySetId);
4
4
  }
5
- export function getGenericViewportImageDataSet(dataId) {
6
- const registered = getGenericViewportRegisteredData(dataId);
5
+ export function getGenericViewportImageDisplaySet(displaySetId) {
6
+ const registered = getGenericViewportRegisteredDisplaySet(displaySetId);
7
7
  if (isStringArray(registered)) {
8
8
  return {
9
9
  imageIds: registered,
10
10
  };
11
11
  }
12
- if (!isGenericViewportImageDataSet(registered)) {
12
+ if (!isGenericViewportImageDisplaySet(registered)) {
13
13
  return;
14
14
  }
15
15
  return registered;
16
16
  }
17
- export function getGenericViewportPlanarDataSet(dataId) {
18
- const registered = getGenericViewportRegisteredData(dataId);
17
+ export function getGenericViewportPlanarDisplaySet(displaySetId) {
18
+ const registered = getGenericViewportRegisteredDisplaySet(displaySetId);
19
19
  if (isStringArray(registered)) {
20
20
  return {
21
21
  imageIds: registered,
22
22
  };
23
23
  }
24
- if (!isGenericViewportImageDataSet(registered)) {
24
+ if (!isGenericViewportImageDisplaySet(registered)) {
25
25
  return;
26
26
  }
27
27
  if ('kind' in registered && registered.kind && registered.kind !== 'planar') {
@@ -29,9 +29,9 @@ export function getGenericViewportPlanarDataSet(dataId) {
29
29
  }
30
30
  return registered;
31
31
  }
32
- export function getGenericViewportWSIDataSet(dataId) {
33
- const registered = getGenericViewportRegisteredData(dataId);
34
- if (isGenericViewportWSIDataSet(registered)) {
32
+ export function getGenericViewportWSIDisplaySet(displaySetId) {
33
+ const registered = getGenericViewportRegisteredDisplaySet(displaySetId);
34
+ if (isGenericViewportWSIDisplaySet(registered)) {
35
35
  return registered;
36
36
  }
37
37
  if (isRecord(registered) &&
@@ -48,30 +48,30 @@ export function getGenericViewportWSIDataSet(dataId) {
48
48
  };
49
49
  }
50
50
  }
51
- export function getGenericViewportSourceDataId(dataId) {
52
- const registered = getGenericViewportRegisteredData(dataId);
51
+ export function getGenericViewportSourceDataId(displaySetId) {
52
+ const registered = getGenericViewportRegisteredDisplaySet(displaySetId);
53
53
  if (typeof registered === 'string') {
54
54
  return registered;
55
55
  }
56
56
  if (isStringArray(registered) && registered[0]) {
57
57
  return registered[0];
58
58
  }
59
- if (isGenericViewportSourceAliasDataSet(registered)) {
59
+ if (isGenericViewportSourceAliasDisplaySet(registered)) {
60
60
  return registered.sourceDataId;
61
61
  }
62
- return dataId;
62
+ return displaySetId;
63
63
  }
64
- export function isGenericViewportImageDataSet(value) {
64
+ export function isGenericViewportImageDisplaySet(value) {
65
65
  return isRecord(value) && isStringArray(value.imageIds);
66
66
  }
67
- export function isGenericViewportWSIDataSet(value) {
67
+ export function isGenericViewportWSIDisplaySet(value) {
68
68
  return (isRecord(value) &&
69
69
  value.kind === 'wsi' &&
70
70
  isStringArray(value.imageIds) &&
71
71
  isRecord(value.options) &&
72
72
  isWSIClientLike(value.options.webClient));
73
73
  }
74
- export function isGenericViewportSourceAliasDataSet(value) {
74
+ export function isGenericViewportSourceAliasDisplaySet(value) {
75
75
  return (isRecord(value) &&
76
76
  (value.kind === 'video' || value.kind === 'ecg') &&
77
77
  typeof value.sourceDataId === 'string');
@@ -189,15 +189,32 @@ function getReferencedImageRangeEndIndex(imageURIEntries, viewRef) {
189
189
  const rangeEndSliceIndex = imageURIEntries.findIndex((imageURIEntry) => imageURIEntryMatches(imageURIEntry, rangeEndImageURI));
190
190
  return rangeEndSliceIndex === -1 ? undefined : rangeEndSliceIndex;
191
191
  }
192
+ const imageIdCompatibleURIsCache = new Map();
193
+ const imageIdsURIEntriesCache = new WeakMap();
194
+ function getImageIdsURIEntries(imageIds) {
195
+ let entries = imageIdsURIEntriesCache.get(imageIds);
196
+ if (!entries) {
197
+ entries = imageIds.map((imageId) => getImageIdCompatibleURIs(imageId));
198
+ imageIdsURIEntriesCache.set(imageIds, entries);
199
+ }
200
+ return entries;
201
+ }
192
202
  function getContextImageURIEntries(context) {
193
- const imageURIEntries = (context.imageIds || []).map((imageId) => getImageIdCompatibleURIs(imageId));
203
+ const baseEntries = context.imageIds?.length
204
+ ? getImageIdsURIEntries(context.imageIds)
205
+ : [];
206
+ const extraImageURIs = context.imageURIs;
207
+ if (!extraImageURIs?.length) {
208
+ return baseEntries;
209
+ }
210
+ const imageURIEntries = baseEntries.slice();
194
211
  const knownImageURIs = new Set();
195
- for (const imageURIEntry of imageURIEntries) {
212
+ for (const imageURIEntry of baseEntries) {
196
213
  for (const imageURI of imageURIEntry) {
197
214
  knownImageURIs.add(imageURI);
198
215
  }
199
216
  }
200
- for (const imageURI of context.imageURIs || []) {
217
+ for (const imageURI of extraImageURIs) {
201
218
  if (!knownImageURIs.has(imageURI)) {
202
219
  imageURIEntries.push([imageURI]);
203
220
  knownImageURIs.add(imageURI);
@@ -206,7 +223,12 @@ function getContextImageURIEntries(context) {
206
223
  return imageURIEntries;
207
224
  }
208
225
  function getImageIdCompatibleURIs(imageId) {
209
- return uniqueStrings([imageIdToURI(imageId), getLegacyImageIdURI(imageId)]);
226
+ let uris = imageIdCompatibleURIsCache.get(imageId);
227
+ if (!uris) {
228
+ uris = uniqueStrings([imageIdToURI(imageId), getLegacyImageIdURI(imageId)]);
229
+ imageIdCompatibleURIsCache.set(imageId, uris);
230
+ }
231
+ return uris;
210
232
  }
211
233
  function getLegacyImageIdURI(imageId) {
212
234
  const colonIndex = imageId.indexOf(':');
@@ -4,7 +4,7 @@ export { ViewportProjectionService, viewportProjection, } from './viewportProjec
4
4
  export type { BuiltInViewportProjectionByKind, BuiltInViewportProjectionByType, BuiltInViewportProjectionKind, BuiltInViewportProjectionType, ProjectionPresentationForKind, ProjectionPresentationForViewport, ProjectionPresentationForViewportType, ProjectionSnapshotForKind, ProjectionSnapshotForViewport, ProjectionSnapshotForViewportType, ProjectionViewStateForKind, ProjectionViewStateForViewport, ProjectionViewStateForViewportType, } from './viewportProjection';
5
5
  export type { ProjectionPosition, ProjectionPresentation, ProjectionRequest, ProjectionScale, ProjectionSnapshot, ProjectionSpaces, ProjectionTransforms, ProjectionWriteOptions, ViewportProjectionAdapter, } from './ViewportProjectionTypes';
6
6
  export type { CameraFrame, CameraScale, CameraScaleMode, ViewAnchor, ViewportCameraBase, } from './ViewportCameraTypes';
7
- export type { BaseViewportRenderContext, BasePresentationProps, DataAddOptions, DataId, DataProvider, ICanvasWorldViewport, IFrameOfReferenceViewport, IPanViewport, IZoomViewport, LoadedData, MountedRendering, RenderPathDefinition, RenderPathAttachment, RenderPathResolver, RenderPath, ViewportDataBinding, ViewportDataReference, ViewportController, ViewportId, ViewportRenderContextType, } from './ViewportArchitectureTypes';
7
+ export type { BaseViewportRenderContext, BasePresentationProps, DataAddOptions, DisplaySetId, DataProvider, ICanvasWorldViewport, IFrameOfReferenceViewport, IPanViewport, IZoomViewport, LoadedData, MountedRendering, RenderPathDefinition, RenderPathAttachment, RenderPathResolver, RenderPath, ViewportDataBinding, ViewportDataReference, ViewportController, ViewportId, ViewportRenderContextType, } from './ViewportArchitectureTypes';
8
8
  export { viewportHasCanvasWorldTransform, viewportHasFrameOfReferenceUID, viewportHasPan, viewportHasZoom, } from './ViewportArchitectureTypes';
9
9
  export { default as ECGViewport } from './ECG';
10
10
  export { createDefaultECGRenderPaths, createECGRenderPathResolver, DefaultECGDataProvider, ecgProjection, } from './ECG';
@@ -142,6 +142,10 @@ declare class StackViewport extends Viewport {
142
142
  }): vtkImageDataType;
143
143
  private _createVTKImageData;
144
144
  setStack(imageIds: string[], currentImageIdIndex?: number): Promise<string>;
145
+ setDisplaySets(...entries: Array<{
146
+ displaySetId: string;
147
+ options?: unknown;
148
+ }>): Promise<void>;
145
149
  private _throwIfDestroyed;
146
150
  private _checkVTKImageDataMatchesCornerstoneImage;
147
151
  private _updateVTKImageDataFromCornerstoneImage;
@@ -8,6 +8,7 @@ import eventTarget from '../eventTarget';
8
8
  import * as metaData from '../metaData';
9
9
  import { getImageDataMetadata as getImageDataMetadataUtil } from '../utilities/getImageDataMetadata';
10
10
  import { coreLog } from '../utilities/logger';
11
+ import { getGenericViewportImageDisplaySet } from './GenericViewport/genericViewportDisplaySetAccess';
11
12
  import { actorIsA, isImageActor } from '../utilities/actorCheck';
12
13
  import * as colormapUtils from '../utilities/colormap';
13
14
  import { getTransferFunctionNodes, setTransferFunctionNodes, } from '../utilities/transferFunctionUtils';
@@ -1304,6 +1305,7 @@ class StackViewport extends Viewport {
1304
1305
  }
1305
1306
  async setStack(imageIds, currentImageIdIndex = 0) {
1306
1307
  this._throwIfDestroyed();
1308
+ this.clearDisplaySets();
1307
1309
  this.imageIds = imageIds;
1308
1310
  if (currentImageIdIndex > imageIds.length) {
1309
1311
  throw new Error('Current image index is greater than the number of images in the stack');
@@ -1341,6 +1343,18 @@ class StackViewport extends Viewport {
1341
1343
  triggerEvent(this.element, Events.VIEWPORT_NEW_IMAGE_SET, eventDetail);
1342
1344
  return imageId;
1343
1345
  }
1346
+ async setDisplaySets(...entries) {
1347
+ await this.mountDisplaySets(entries, async (entry) => {
1348
+ const dataSet = getGenericViewportImageDisplaySet(entry.displaySetId);
1349
+ if (!dataSet?.imageIds?.length) {
1350
+ throw new Error(`[StackViewport] No registered imageIds for display set ${entry.displaySetId}`);
1351
+ }
1352
+ const initialImageIdIndex = typeof dataSet.initialImageIdIndex === 'number'
1353
+ ? dataSet.initialImageIdIndex
1354
+ : 0;
1355
+ await this.setStack(dataSet.imageIds, initialImageIdIndex);
1356
+ });
1357
+ }
1344
1358
  _throwIfDestroyed() {
1345
1359
  if (this.isDisabled) {
1346
1360
  throw new Error('The stack viewport has been destroyed and is no longer usable. Renderings will not be performed. If you ' +
@@ -1,5 +1,6 @@
1
1
  import type { mat4 } from 'gl-matrix';
2
2
  import { VideoEnums as VideoViewportEnum } from '../enums';
3
+ import type { DisplaySetId } from './GenericViewport/ViewportArchitectureTypes';
3
4
  import type { VideoViewportProperties, Point3, Point2, ICamera, VideoViewportInput, VOIRange, IImage, ViewReferenceSpecifier, ViewReference, ReferenceCompatibleOptions, ImageSetOptions, IStackInput, CPUIImageData, IImageData } from '../types';
4
5
  import { Transform } from './helpers/cpuFallback/rendering/transform';
5
6
  import Viewport from './Viewport';
@@ -44,6 +45,15 @@ declare class VideoViewport extends Viewport {
44
45
  dataId: string;
45
46
  options?: Record<string, unknown>;
46
47
  }>): Promise<unknown>;
48
+ setDisplaySets(...entries: Array<{
49
+ displaySetId: DisplaySetId;
50
+ options?: {
51
+ frameNumber?: number;
52
+ viewReference?: {
53
+ sliceIndex?: number;
54
+ };
55
+ };
56
+ }>): Promise<void>;
47
57
  setVideo(imageId: string, frameNumber?: number): Promise<unknown>;
48
58
  private setVideoURL;
49
59
  getImageIds(): string[];
@@ -1,4 +1,5 @@
1
1
  import { Events as EVENTS, VideoEnums as VideoViewportEnum } from '../enums';
2
+ import { getGenericViewportSourceDataId } from './GenericViewport/genericViewportDisplaySetAccess';
2
3
  import { Transform } from './helpers/cpuFallback/rendering/transform';
3
4
  import triggerEvent from '../utilities/triggerEvent';
4
5
  import Viewport from './Viewport';
@@ -204,7 +205,19 @@ class VideoViewport extends Viewport {
204
205
  }
205
206
  return this.setVideo(entries[0].dataId);
206
207
  }
208
+ async setDisplaySets(...entries) {
209
+ await this.mountDisplaySets(entries, async (entry) => {
210
+ const sourceDataId = getGenericViewportSourceDataId(entry.displaySetId);
211
+ const { frameNumber, viewReference } = entry.options ?? {};
212
+ const initialFrame = frameNumber ??
213
+ (typeof viewReference?.sliceIndex === 'number'
214
+ ? viewReference.sliceIndex + 1
215
+ : undefined);
216
+ await this.setVideo(sourceDataId, initialFrame);
217
+ });
218
+ }
207
219
  setVideo(imageId, frameNumber) {
220
+ this.clearDisplaySets();
208
221
  this.imageId = Array.isArray(imageId) ? imageId[0] : imageId;
209
222
  const stream = loadVideoStreamMetadata(imageId);
210
223
  this.modality = stream.modality;
@@ -28,6 +28,10 @@ declare class Viewport {
28
28
  sWidth: number;
29
29
  sHeight: number;
30
30
  _actors: Map<string, ActorEntry>;
31
+ protected _displaySets: Array<{
32
+ displaySetId: string;
33
+ options?: unknown;
34
+ }>;
31
35
  readonly defaultOptions: ViewportInputOptions;
32
36
  options: ViewportInputOptions;
33
37
  _suppressCameraModifiedEvents: boolean;
@@ -150,6 +154,19 @@ declare class Viewport {
150
154
  dataId: string;
151
155
  options?: DataSetOptions;
152
156
  }>): void;
157
+ setDisplaySets(...entries: Array<{
158
+ displaySetId: string;
159
+ options?: unknown;
160
+ }>): void | Promise<void>;
161
+ protected mountDisplaySets<TEntry extends {
162
+ displaySetId: string;
163
+ options?: unknown;
164
+ }>(entries: TEntry[], load: (sourceEntry: TEntry) => void | Promise<void>): Promise<void>;
165
+ getDisplaySets(): Array<{
166
+ displaySetId: string;
167
+ options?: unknown;
168
+ }>;
169
+ protected clearDisplaySets(): void;
153
170
  }
154
171
  export declare function getVolumeCenterIJK(dimensions: number[], direction: ArrayLike<number>, viewPlaneNormal: ArrayLike<number>): number[];
155
172
  export default Viewport;
@@ -26,6 +26,7 @@ class Viewport {
26
26
  this.flipHorizontal = false;
27
27
  this.flipVertical = false;
28
28
  this.viewportStatus = ViewportStatus.NO_DATA;
29
+ this._displaySets = [];
29
30
  this._suppressCameraModifiedEvents = false;
30
31
  this.hasPixelSpacing = true;
31
32
  this.getProperties = () => ({});
@@ -1189,6 +1190,23 @@ class Viewport {
1189
1190
  setDataList(_entries) {
1190
1191
  throw new Error('Unsupported operation setDataList');
1191
1192
  }
1193
+ setDisplaySets(...entries) {
1194
+ this._displaySets = entries;
1195
+ }
1196
+ async mountDisplaySets(entries, load) {
1197
+ const [entry] = entries;
1198
+ if (!entry?.displaySetId) {
1199
+ throw new Error(`${this.constructor.name}: setDisplaySets requires a displaySetId`);
1200
+ }
1201
+ await load(entry);
1202
+ this._displaySets = [entry];
1203
+ }
1204
+ getDisplaySets() {
1205
+ return this._displaySets;
1206
+ }
1207
+ clearDisplaySets() {
1208
+ this._displaySets = [];
1209
+ }
1192
1210
  }
1193
1211
  Viewport.CameraViewPresentation = {
1194
1212
  rotation: true,
@@ -61,6 +61,10 @@ declare class WSIViewport extends Viewport {
61
61
  webClient: WSIClientLike;
62
62
  }): Promise<void>;
63
63
  setWSI(imageIds: string[], client: WSIClientLike): Promise<void>;
64
+ setDisplaySets(...entries: Array<{
65
+ displaySetId: string;
66
+ options?: unknown;
67
+ }>): Promise<void>;
64
68
  postrender: () => void;
65
69
  scroll(delta: number): void;
66
70
  getRotation: () => number;
@@ -9,6 +9,7 @@ import { EPSILON } from '../constants';
9
9
  import triggerEvent from '../utilities/triggerEvent';
10
10
  import eventTarget from '../eventTarget';
11
11
  import imageIdToURI from '../utilities/imageIdToURI';
12
+ import { getGenericViewportWSIDisplaySet } from './GenericViewport/genericViewportDisplaySetAccess';
12
13
  import { addWSIMiniNavigationOverlayCss, getDicomMicroscopyViewer, loadWSIData, } from '../utilities/WSIUtilities';
13
14
  let WSIUtilFunctions = null;
14
15
  const EVENT_POSTRENDER = 'postrender';
@@ -341,7 +342,7 @@ class WSIViewport extends Viewport {
341
342
  return;
342
343
  }
343
344
  const { dataId } = entries[0];
344
- const dataSet = metaData.get('genericViewportDataSet', dataId);
345
+ const dataSet = metaData.get('genericViewportDisplaySet', dataId);
345
346
  if (dataSet?.imageIds) {
346
347
  return this.setDataIds(dataSet.imageIds, {
347
348
  webClient: dataSet.options?.webClient,
@@ -361,6 +362,7 @@ class WSIViewport extends Viewport {
361
362
  return this.setWSI(imageIds, webClient);
362
363
  }
363
364
  async setWSI(imageIds, client) {
365
+ this.clearDisplaySets();
364
366
  this.microscopyElement.style.background = 'black';
365
367
  this.microscopyElement.innerText = 'Loading';
366
368
  this.imageIds = imageIds;
@@ -397,6 +399,18 @@ class WSIViewport extends Viewport {
397
399
  background: 'none',
398
400
  });
399
401
  }
402
+ async setDisplaySets(...entries) {
403
+ await this.mountDisplaySets(entries, async (entry) => {
404
+ const dataSet = getGenericViewportWSIDisplaySet(entry.displaySetId);
405
+ if (!dataSet?.imageIds?.length || !dataSet.options?.webClient) {
406
+ throw new Error(`[WSIViewport] No registered WSI dataset (imageIds + webClient) for display set ${entry.displaySetId}`);
407
+ }
408
+ if (dataSet.options.miniNavigationOverlay !== false) {
409
+ addWSIMiniNavigationOverlayCss();
410
+ }
411
+ await WSIViewport.prototype.setWSI.call(this, dataSet.imageIds, dataSet.options.webClient);
412
+ });
413
+ }
400
414
  scroll(delta) {
401
415
  const camera = this.getCamera();
402
416
  this.setCamera({