-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Expand file tree
/
Copy pathutils.ts
More file actions
174 lines (152 loc) · 5.1 KB
/
utils.ts
File metadata and controls
174 lines (152 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import { utilities as csUtils } from '@cornerstonejs/core';
export const DEFAULT_COLORMAP = 'hsv';
export const DEFAULT_OPACITY = 0.5;
export const DEFAULT_OPACITY_PERCENT = DEFAULT_OPACITY * 100;
export const DERIVED_OVERLAY_MODALITIES = ['SEG', 'RTSTRUCT'];
/**
* Get modality-specific color and opacity settings from the customization service
*/
export function getModalityOverlayColormap(customizationService, modality) {
const modalityOverlayDefaultColorMaps = customizationService?.getCustomization(
'cornerstone.modalityOverlayDefaultColorMaps'
) || { defaultSettings: {} };
return (
modalityOverlayDefaultColorMaps.defaultSettings[modality] || {
colormap: DEFAULT_COLORMAP,
opacity: DEFAULT_OPACITY,
}
);
}
/**
* Identifies display sets that can be used as overlays for a specific viewport.
*
* "Enhanced" display sets are those that:
* 1. Are not already in the viewport
* 2. Are evaluated for their ability to be overlaid onto the background display set
* 3. Have an "isOverlayable" flag indicating if they're compatible with the viewport
*
* A display set is considered overlayable when:
* - The background display set is reconstructable
* - The display set is not unsupported
* - The Frame of Reference matches the background display set
* - For non-derived modalities: background can be a volume and display set is either multiframe or valid volume
*
* @returns {Object} Object containing:
* - viewportDisplaySets: Display sets already in the viewport
* - enhancedDisplaySets: Other display sets with overlayability assessment
*/
export function getEnhancedDisplaySets({ viewportId, services }) {
const { displaySetService, viewportGridService } = services;
const displaySetsUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
if (!displaySetsUIDs?.length) {
return {
viewportDisplaySets: [],
enhancedDisplaySets: [],
};
}
const allDisplaySets = displaySetService.getActiveDisplaySets();
const otherDisplaySets = allDisplaySets.filter(
displaySet => !displaySetsUIDs.includes(displaySet.displaySetInstanceUID)
);
const viewportDisplaySets = displaySetsUIDs.map(displaySetUID =>
displaySetService.getDisplaySetByUID(displaySetUID)
);
const backgroundDisplaySet = viewportDisplaySets[0];
if (!backgroundDisplaySet) {
return {
viewportDisplaySets,
enhancedDisplaySets: otherDisplaySets.map(displaySet => ({
...displaySet,
isOverlayable: false,
})),
};
}
const backgroundCanBeVolume = csUtils.isValidVolume(backgroundDisplaySet.imageIds || []);
const enhancedDisplaySets = otherDisplaySets.map(displaySet => {
if (!backgroundDisplaySet.isReconstructable) {
return {
...displaySet,
isOverlayable: false,
};
}
if (displaySet.unsupported) {
return {
...displaySet,
isOverlayable: false,
};
}
// Check if Frame of Reference matches
if (
displaySet.FrameOfReferenceUID &&
displaySet.FrameOfReferenceUID !== backgroundDisplaySet.FrameOfReferenceUID
) {
return {
...displaySet,
isOverlayable: false,
};
}
// Special handling for derived modalities
if (!DERIVED_OVERLAY_MODALITIES.includes(displaySet.Modality)) {
if (!backgroundCanBeVolume) {
return {
...displaySet,
isOverlayable: false,
};
}
const imageIds = displaySet.imageIds || displaySet.images?.map(image => image.imageId);
const isMultiframe = displaySet.isMultiFrame;
if (!isMultiframe && imageIds?.length > 0 && !csUtils.isValidVolume(imageIds)) {
return {
...displaySet,
isOverlayable: false,
};
}
}
return {
...displaySet,
isOverlayable: true,
};
});
return {
viewportDisplaySets,
enhancedDisplaySets,
};
}
/**
* Sort function: puts disabled items (isOverlayable: false) at the end
*/
export const sortByOverlayable = (a, b) => {
if (a.isOverlayable === b.isOverlayable) {
return 0;
}
return a.isOverlayable ? -1 : 1;
};
/**
* Create display set options based on modality and opacity settings
*/
export function createColormapOverlayDisplaySetOptions(displaySet, opacity, customizationService) {
if (displaySet.Modality === 'SEG') {
return {};
}
const modalitySettings = getModalityOverlayColormap(customizationService, displaySet.Modality);
return {
colormap: {
name: modalitySettings.colormap || DEFAULT_COLORMAP,
opacity: opacity / 100, // Convert from percentage to 0-1 range
},
};
}
/**
* Get segmentations that can be added as overlays to the viewport
*
* Note: This function is deprecated as we now use display sets for segmentations
*/
export function getAvailableSegmentations(segmentationService) {
const segmentations = segmentationService.getSegmentations() || [];
return segmentations.map(segmentation => ({
segmentationId: segmentation.segmentationId,
label: segmentation.label || 'Segmentation',
segments: segmentation.segments,
frameOfReferenceUID: segmentation.frameOfReferenceUID,
}));
}