feat(data overlay): add foreground background control plus orientation change in the UI and add RTDOSE support (#5007)

This commit is contained in:
Alireza authored and GitHub committed 2025-05-05 16:35:05 -04:00
1 parent c1fced0573
commit cd4e6408bc
105 files changed
+3117 -788

No files matched your search

@@ -321,7 +321,7 @@ class MeasurementService extends PubSubService {
this.mappings[source.uid] = [mapping];
}
log.info(`New measurement mapping added to source '${this._getSourceToString(source)}'.`);
// log.info(`New measurement mapping added to source '${this._getSourceToString(source)}'.`);
}
/**
@@ -239,7 +239,10 @@ export default class ToolbarService extends PubSubService {
const { disabled, disabledText, className, isActive } = evaluationResults.get(button.id);
return { ...props, disabled, disabledText, className, isActive };
} else {
const evaluated = props.evaluate?.({ ...refreshProps, button });
const evaluated =
typeof props.evaluate === 'function'
? props.evaluate({ ...refreshProps, button })
: undefined;
const updatedProps = {
...props,
...evaluated,
+3
View File
@@ -13,6 +13,9 @@ export type DisplaySet = {
Modality?: string;
imageIds?: string[];
images?: unknown[];
label?: string;
/** Flag indicating if this is an overlay display set (e.g., SEG, RTSTRUCT) */
isOverlayDisplaySet?: boolean;
// Details about how to display:
/** A URL that can be used to display the thumbnail. Typically a data url */
@@ -19,11 +19,14 @@ const combineFrameInstance = (frame, instance) => {
ImageType,
} = instance;
if (NumberOfFrames < 2) {
return instance;
}
instance.ImageType = dicomSplit(ImageType);
const frameNumber = Number.parseInt(frame || 1);
if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) {
const frameNumber = Number.parseInt(frame || 1);
if (PerFrameFunctionalGroupsSequence && SharedFunctionalGroupsSequence) {
// this is to fix NM multiframe datasets with position and orientation
// information inside DetectorInformationSequence
if (!instance.ImageOrientationPatient && instance.DetectorInformationSequence) {
@@ -96,9 +99,52 @@ const combineFrameInstance = (frame, instance) => {
configurable: true,
});
return newInstance;
} else {
return instance;
}
// For RTDOSE datasets
if (instance.GridFrameOffsetVector) {
if (!instance._parentInstance) {
Object.defineProperty(instance, '_parentInstance', {
value: { ...instance },
});
}
const sharedInstance = createCombinedValue(
instance._parentInstance,
SharedFunctionalGroupsSequence?.[0],
'_shared'
);
const newInstance = createCombinedValue(
sharedInstance,
PerFrameFunctionalGroupsSequence?.[frameNumber - 1],
frameNumber
);
const origin = newInstance.ImagePositionPatient?.map(Number);
const orientation = newInstance.ImageOrientationPatient?.map(Number);
const offset = Number(instance.GridFrameOffsetVector[frameNumber - 1]);
if (origin && orientation && !Number.isNaN(offset)) {
const row = vec3.fromValues(orientation[0], orientation[1], orientation[2]);
const col = vec3.fromValues(orientation[3], orientation[4], orientation[5]);
const normal = vec3.cross(vec3.create(), row, col);
const position = vec3.scaleAndAdd(vec3.create(), vec3.fromValues(...origin), normal, offset);
newInstance.ImagePositionPatient = [position[0], position[1], position[2]];
}
Object.defineProperty(newInstance, 'frameNumber', {
value: frameNumber,
writable: true,
enumerable: true,
configurable: true,
});
return newInstance;
}
return instance;
};
/**
@@ -1,4 +1,14 @@
const LOW_PRIORITY_MODALITIES = Object.freeze(['SEG', 'KO', 'PR', 'SR', 'RTSTRUCT', 'RTDOSE', 'RTPLAN', 'RTRECORD', 'REG']);
const LOW_PRIORITY_MODALITIES = Object.freeze([
'SEG',
'KO',
'PR',
'SR',
'RTSTRUCT',
'RTDOSE',
'RTPLAN',
'RTRECORD',
'REG',
]);
export default function isLowPriorityModality(Modality) {
return LOW_PRIORITY_MODALITIES.includes(Modality);