fix(cornerstone-dicom-rt): adding caching usage to cornerstone-dicom-rt SOP Class Handler (#5387)
This commit is contained in:
parent
7de1c78fc4
commit
d6ea179ac4
@ -4,7 +4,11 @@ import i18n from '@ohif/i18n';
|
|||||||
import { SOPClassHandlerId } from './id';
|
import { SOPClassHandlerId } from './id';
|
||||||
import loadRTStruct from './loadRTStruct';
|
import loadRTStruct from './loadRTStruct';
|
||||||
|
|
||||||
const sopClassUids = ['1.2.840.10008.5.1.4.1.1.481.3'];
|
const { sopClassDictionary } = utils;
|
||||||
|
|
||||||
|
const sopClassUids = [sopClassDictionary.RTStructureSetStorage];
|
||||||
|
|
||||||
|
const cachedRTStructsSEG = new Set<string>();
|
||||||
|
|
||||||
const loadPromises = {};
|
const loadPromises = {};
|
||||||
|
|
||||||
@ -113,39 +117,45 @@ function _load(
|
|||||||
) {
|
) {
|
||||||
const { SOPInstanceUID } = rtDisplaySet;
|
const { SOPInstanceUID } = rtDisplaySet;
|
||||||
const { segmentationService } = servicesManager.services;
|
const { segmentationService } = servicesManager.services;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(rtDisplaySet.loading || rtDisplaySet.isLoaded) &&
|
(rtDisplaySet.loading || rtDisplaySet.isLoaded) &&
|
||||||
loadPromises[SOPInstanceUID] &&
|
loadPromises[SOPInstanceUID] &&
|
||||||
_segmentationExistsInCache(rtDisplaySet, segmentationService)
|
cachedRTStructsSEG.has(rtDisplaySet.displaySetInstanceUID)
|
||||||
) {
|
) {
|
||||||
return loadPromises[SOPInstanceUID];
|
return loadPromises[SOPInstanceUID];
|
||||||
}
|
}
|
||||||
|
|
||||||
rtDisplaySet.loading = true;
|
rtDisplaySet.loading = true;
|
||||||
|
|
||||||
|
const { unsubscribe } = segmentationService.subscribe(
|
||||||
|
segmentationService.EVENTS.SEGMENTATION_LOADING_COMPLETE,
|
||||||
|
(evt: { rtDisplaySet: { displaySetInstanceUID: string } }) => {
|
||||||
|
if (evt.rtDisplaySet?.displaySetInstanceUID === rtDisplaySet.displaySetInstanceUID) {
|
||||||
|
cachedRTStructsSEG.add(rtDisplaySet.displaySetInstanceUID);
|
||||||
|
unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// We don't want to fire multiple loads, so we'll wait for the first to finish
|
// We don't want to fire multiple loads, so we'll wait for the first to finish
|
||||||
// and also return the same promise to any other callers.
|
// and also return the same promise to any other callers.
|
||||||
loadPromises[SOPInstanceUID] = new Promise(async (resolve, reject) => {
|
loadPromises[SOPInstanceUID] = new Promise<void>(async (resolve, reject) => {
|
||||||
if (!rtDisplaySet.structureSet) {
|
try {
|
||||||
const structureSet = await loadRTStruct(extensionManager, rtDisplaySet, headers);
|
if (!rtDisplaySet.structureSet) {
|
||||||
|
const structureSet = await loadRTStruct(extensionManager, rtDisplaySet, headers);
|
||||||
|
rtDisplaySet.structureSet = structureSet;
|
||||||
|
}
|
||||||
|
|
||||||
rtDisplaySet.structureSet = structureSet;
|
if (createSegmentation) {
|
||||||
}
|
await segmentationService.createSegmentationForRTDisplaySet(rtDisplaySet);
|
||||||
|
}
|
||||||
|
|
||||||
if (createSegmentation) {
|
|
||||||
segmentationService
|
|
||||||
.createSegmentationForRTDisplaySet(rtDisplaySet)
|
|
||||||
.then(() => {
|
|
||||||
rtDisplaySet.loading = false;
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
rtDisplaySet.loading = false;
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
rtDisplaySet.loading = false;
|
|
||||||
resolve();
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
} finally {
|
||||||
|
rtDisplaySet.loading = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -187,11 +197,6 @@ function _deriveReferencedSeriesSequenceFromFrameOfReferenceSequence(
|
|||||||
return ReferencedSeriesSequence;
|
return ReferencedSeriesSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _segmentationExistsInCache() {
|
|
||||||
// Todo: fix this
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSopClassHandlerModule(params: OhifTypes.Extensions.ExtensionParams) {
|
function getSopClassHandlerModule(params: OhifTypes.Extensions.ExtensionParams) {
|
||||||
const { servicesManager, extensionManager } = params;
|
const { servicesManager, extensionManager } = params;
|
||||||
|
|
||||||
|
|||||||
@ -137,16 +137,12 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSupported = false;
|
|
||||||
|
|
||||||
const ContourSequenceArray = _toArray(ContourSequence);
|
const ContourSequenceArray = _toArray(ContourSequence);
|
||||||
|
|
||||||
const contourPoints = [];
|
const contourPoints = [];
|
||||||
for (let c = 0; c < ContourSequenceArray.length; c++) {
|
for (const ContourSequenceItem of ContourSequenceArray) {
|
||||||
const { ContourData, NumberOfContourPoints, ContourGeometricType, ContourImageSequence } =
|
const { ContourData, NumberOfContourPoints, ContourGeometricType, ContourImageSequence } =
|
||||||
ContourSequenceArray[c];
|
ContourSequenceItem;
|
||||||
|
|
||||||
let isSupported = false;
|
|
||||||
|
|
||||||
const points = [];
|
const points = [];
|
||||||
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
|
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
|
||||||
@ -157,22 +153,18 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ContourGeometricType) {
|
const supportedContourTypesMap = new Map([
|
||||||
case 'CLOSED_PLANAR':
|
['CLOSED_PLANAR', false],
|
||||||
case 'OPEN_PLANAR':
|
['OPEN_NONPLANAR', false],
|
||||||
case 'POINT':
|
['OPEN_PLANAR', false],
|
||||||
isSupported = true;
|
['POINT', true],
|
||||||
|
]);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
contourPoints.push({
|
contourPoints.push({
|
||||||
numberOfPoints: NumberOfContourPoints,
|
numberOfPoints: NumberOfContourPoints,
|
||||||
points,
|
points,
|
||||||
type: ContourGeometricType,
|
type: ContourGeometricType,
|
||||||
isSupported,
|
isSupported: supportedContourTypesMap.get(ContourGeometricType) ?? false,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ContourImageSequence?.ReferencedSOPInstanceUID) {
|
if (ContourImageSequence?.ReferencedSOPInstanceUID) {
|
||||||
@ -187,8 +179,7 @@ export default async function loadRTStruct(extensionManager, rtStructDisplaySet,
|
|||||||
StructureSetROISequence,
|
StructureSetROISequence,
|
||||||
RTROIObservationsSequence,
|
RTROIObservationsSequence,
|
||||||
ROIContour,
|
ROIContour,
|
||||||
contourPoints,
|
contourPoints
|
||||||
isSupported
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return structureSet;
|
return structureSet;
|
||||||
@ -199,8 +190,7 @@ function _setROIContourMetadata(
|
|||||||
StructureSetROISequence,
|
StructureSetROISequence,
|
||||||
RTROIObservationsSequence,
|
RTROIObservationsSequence,
|
||||||
ROIContour,
|
ROIContour,
|
||||||
contourPoints,
|
contourPoints
|
||||||
isSupported
|
|
||||||
) {
|
) {
|
||||||
const StructureSetROI = StructureSetROISequence.find(
|
const StructureSetROI = StructureSetROISequence.find(
|
||||||
structureSetROI => structureSetROI.ROINumber === ROIContour.ReferencedROINumber
|
structureSetROI => structureSetROI.ROINumber === ROIContour.ReferencedROINumber
|
||||||
@ -211,9 +201,9 @@ function _setROIContourMetadata(
|
|||||||
ROIName: StructureSetROI.ROIName,
|
ROIName: StructureSetROI.ROIName,
|
||||||
ROIGenerationAlgorithm: StructureSetROI.ROIGenerationAlgorithm,
|
ROIGenerationAlgorithm: StructureSetROI.ROIGenerationAlgorithm,
|
||||||
ROIDescription: StructureSetROI.ROIDescription,
|
ROIDescription: StructureSetROI.ROIDescription,
|
||||||
isSupported,
|
|
||||||
contourPoints,
|
contourPoints,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
colorArray: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
_setROIContourDataColor(ROIContour, ROIContourData);
|
_setROIContourDataColor(ROIContour, ROIContourData);
|
||||||
|
|||||||
@ -574,10 +574,19 @@ class SegmentationService extends PubSubService {
|
|||||||
// find the first image id that contains a referenced SOP instance UID
|
// find the first image id that contains a referenced SOP instance UID
|
||||||
const firstSegmentedSliceImageId =
|
const firstSegmentedSliceImageId =
|
||||||
referencedImageIds?.find(imageId =>
|
referencedImageIds?.find(imageId =>
|
||||||
referencedImageIdsWithGeometry.some(referencedId => imageId.includes(referencedId))
|
referencedImageIdsWithGeometry.some(referencedId =>
|
||||||
|
imageId.includes(referencedId as string)
|
||||||
|
)
|
||||||
) || null;
|
) || null;
|
||||||
|
|
||||||
rtDisplaySet.firstSegmentedSliceImageId = firstSegmentedSliceImageId;
|
rtDisplaySet.firstSegmentedSliceImageId = firstSegmentedSliceImageId;
|
||||||
|
|
||||||
|
if (!structureSet.ROIContours?.length) {
|
||||||
|
throw new Error(
|
||||||
|
'The structureSet does not contain any ROIContours. Please ensure the structureSet is loaded first.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Map ROI contours to RT Struct Data
|
// Map ROI contours to RT Struct Data
|
||||||
const allRTStructData = mapROIContoursToRTStructData(structureSet, rtDisplaySetUID);
|
const allRTStructData = mapROIContoursToRTStructData(structureSet, rtDisplaySetUID);
|
||||||
|
|
||||||
@ -600,12 +609,6 @@ class SegmentationService extends PubSubService {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!structureSet.ROIContours?.length) {
|
|
||||||
throw new Error(
|
|
||||||
'The structureSet does not contain any ROIContours. Please ensure the structureSet is loaded first.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const segments: { [segmentIndex: string]: cstTypes.Segment } = {};
|
const segments: { [segmentIndex: string]: cstTypes.Segment } = {};
|
||||||
let segmentsCachedStats = {};
|
let segmentsCachedStats = {};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user