2020-05-10 16:33:04 +02:00
|
|
|
import { isImage } from '@ohif/core/src/utils/isImage';
|
2022-09-20 20:47:18 +02:00
|
|
|
import sopClassDictionary from '@ohif/core/src/utils/sopClassDictionary';
|
2020-05-10 16:33:04 +02:00
|
|
|
import ImageSet from '@ohif/core/src/classes/ImageSet';
|
|
|
|
|
import isDisplaySetReconstructable from '@ohif/core/src/utils/isDisplaySetReconstructable';
|
2022-04-06 19:28:42 +02:00
|
|
|
import { id } from './id';
|
2023-08-12 00:16:25 +02:00
|
|
|
import getDisplaySetMessages from './getDisplaySetMessages';
|
2023-08-16 17:37:28 +02:00
|
|
|
import getDisplaySetsFromUnsupportedSeries from './getDisplaySetsFromUnsupportedSeries';
|
2020-05-11 18:56:46 +02:00
|
|
|
|
|
|
|
|
const sopClassHandlerName = 'stack';
|
2020-05-10 16:33:04 +02:00
|
|
|
|
|
|
|
|
const isMultiFrame = instance => {
|
|
|
|
|
return instance.NumberOfFrames > 1;
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-11 18:56:46 +02:00
|
|
|
const makeDisplaySet = instances => {
|
2020-05-10 16:33:04 +02:00
|
|
|
const instance = instances[0];
|
|
|
|
|
const imageSet = new ImageSet(instances);
|
|
|
|
|
|
2023-09-01 22:19:39 +02:00
|
|
|
const { value: isReconstructable, averageSpacingBetweenFrames } =
|
|
|
|
|
isDisplaySetReconstructable(instances);
|
2020-05-10 16:33:04 +02:00
|
|
|
// set appropriate attributes to image set...
|
2023-08-12 00:16:25 +02:00
|
|
|
const messages = getDisplaySetMessages(instances, isReconstructable);
|
|
|
|
|
|
2020-05-10 16:33:04 +02:00
|
|
|
imageSet.setAttributes({
|
2020-05-15 19:07:21 +02:00
|
|
|
displaySetInstanceUID: imageSet.uid, // create a local alias for the imageSet UID
|
2020-05-11 18:56:46 +02:00
|
|
|
SeriesDate: instance.SeriesDate,
|
|
|
|
|
SeriesTime: instance.SeriesTime,
|
2020-05-14 16:28:45 +02:00
|
|
|
SeriesInstanceUID: instance.SeriesInstanceUID,
|
|
|
|
|
StudyInstanceUID: instance.StudyInstanceUID,
|
2021-08-20 18:14:19 +02:00
|
|
|
SeriesNumber: instance.SeriesNumber || 0,
|
2020-05-11 18:56:46 +02:00
|
|
|
FrameRate: instance.FrameTime,
|
2022-11-16 20:19:52 +01:00
|
|
|
SOPClassUID: instance.SOPClassUID,
|
2021-08-20 18:14:19 +02:00
|
|
|
SeriesDescription: instance.SeriesDescription || '',
|
2020-05-15 10:05:40 +02:00
|
|
|
Modality: instance.Modality,
|
2020-05-10 16:33:04 +02:00
|
|
|
isMultiFrame: isMultiFrame(instance),
|
feat(RT): add dicom RT support via volume viewports (#3310)
* feat: initial RT support
* make the segmentation service work with representation data
* feat: make segmentation service work with representations
* fix rtss vis
* fix: rt hydration
* fix the rendering of rt names
* fix imports
* refactor: Modify status and click handling for hydration of RTStructures
Modify status and click handling for hydration of RTStructures by renaming `onPillClick` to `onStatusClick` in `OHIFCornerstoneRTViewport.tsx` and `_getStatusComponent.tsx` files. Also, update initial segmentation configurations in `PanelSegmentation.tsx` and simplify configuration changes and values for segmentation service in `SegmentationService.ts`. Finally, remove console debug in `CornerstoneViewportService.ts`.
* wip for highlighting contours
* refactor rt displayset code
* review code update
* update cornerstone dependencies
* refactor: Update license year, version number, and minor code cleanup
This commit updates the license year in several files, updates the version number in package.json, and contains minor code cleanup in two files.
* add bulkdataURI retrieve for RT
* fix package version
* apply review comments
* apply review comments
* apply review comments
* feat(panels): refactor and streamline segmentation configuration and inputs
Rewrote state hooks and streamlined the configuration input for `PanelSegmentation` to be more verbose and reusable. Included several new input types, including the `InputRange` component which now shows a fixed floating value based on the step provided. The `SegmentationConfig` component now works with dynamic values controlled by `initialConfig`. These changes should improve function usability and make the code more maintainable going forward.
* fix various bugs
* fix contour delete by upgrade cs3d version
* feat(viewport, inputNumber, segmentationConfig, orthanc): Implement minimum and maximum values for input number components, and useBulkDataURI for Orthanc configuration. Compare measurement view planes with absolute viewport view planes in Cornerstone viewport.
* update yarn lock
2023-04-26 18:21:08 +02:00
|
|
|
countIcon: isReconstructable ? 'icon-mpr' : undefined,
|
2020-05-14 13:04:39 +02:00
|
|
|
numImageFrames: instances.length,
|
2020-05-11 18:56:46 +02:00
|
|
|
SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`,
|
feat(RT): add dicom RT support via volume viewports (#3310)
* feat: initial RT support
* make the segmentation service work with representation data
* feat: make segmentation service work with representations
* fix rtss vis
* fix: rt hydration
* fix the rendering of rt names
* fix imports
* refactor: Modify status and click handling for hydration of RTStructures
Modify status and click handling for hydration of RTStructures by renaming `onPillClick` to `onStatusClick` in `OHIFCornerstoneRTViewport.tsx` and `_getStatusComponent.tsx` files. Also, update initial segmentation configurations in `PanelSegmentation.tsx` and simplify configuration changes and values for segmentation service in `SegmentationService.ts`. Finally, remove console debug in `CornerstoneViewportService.ts`.
* wip for highlighting contours
* refactor rt displayset code
* review code update
* update cornerstone dependencies
* refactor: Update license year, version number, and minor code cleanup
This commit updates the license year in several files, updates the version number in package.json, and contains minor code cleanup in two files.
* add bulkdataURI retrieve for RT
* fix package version
* apply review comments
* apply review comments
* apply review comments
* feat(panels): refactor and streamline segmentation configuration and inputs
Rewrote state hooks and streamlined the configuration input for `PanelSegmentation` to be more verbose and reusable. Included several new input types, including the `InputRange` component which now shows a fixed floating value based on the step provided. The `SegmentationConfig` component now works with dynamic values controlled by `initialConfig`. These changes should improve function usability and make the code more maintainable going forward.
* fix various bugs
* fix contour delete by upgrade cs3d version
* feat(viewport, inputNumber, segmentationConfig, orthanc): Implement minimum and maximum values for input number components, and useBulkDataURI for Orthanc configuration. Compare measurement view planes with absolute viewport view planes in Cornerstone viewport.
* update yarn lock
2023-04-26 18:21:08 +02:00
|
|
|
isReconstructable,
|
2023-08-12 00:16:25 +02:00
|
|
|
messages,
|
feat(RT): add dicom RT support via volume viewports (#3310)
* feat: initial RT support
* make the segmentation service work with representation data
* feat: make segmentation service work with representations
* fix rtss vis
* fix: rt hydration
* fix the rendering of rt names
* fix imports
* refactor: Modify status and click handling for hydration of RTStructures
Modify status and click handling for hydration of RTStructures by renaming `onPillClick` to `onStatusClick` in `OHIFCornerstoneRTViewport.tsx` and `_getStatusComponent.tsx` files. Also, update initial segmentation configurations in `PanelSegmentation.tsx` and simplify configuration changes and values for segmentation service in `SegmentationService.ts`. Finally, remove console debug in `CornerstoneViewportService.ts`.
* wip for highlighting contours
* refactor rt displayset code
* review code update
* update cornerstone dependencies
* refactor: Update license year, version number, and minor code cleanup
This commit updates the license year in several files, updates the version number in package.json, and contains minor code cleanup in two files.
* add bulkdataURI retrieve for RT
* fix package version
* apply review comments
* apply review comments
* apply review comments
* feat(panels): refactor and streamline segmentation configuration and inputs
Rewrote state hooks and streamlined the configuration input for `PanelSegmentation` to be more verbose and reusable. Included several new input types, including the `InputRange` component which now shows a fixed floating value based on the step provided. The `SegmentationConfig` component now works with dynamic values controlled by `initialConfig`. These changes should improve function usability and make the code more maintainable going forward.
* fix various bugs
* fix contour delete by upgrade cs3d version
* feat(viewport, inputNumber, segmentationConfig, orthanc): Implement minimum and maximum values for input number components, and useBulkDataURI for Orthanc configuration. Compare measurement view planes with absolute viewport view planes in Cornerstone viewport.
* update yarn lock
2023-04-26 18:21:08 +02:00
|
|
|
averageSpacingBetweenFrames: averageSpacingBetweenFrames || null,
|
2020-05-10 16:33:04 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Sort the images in this series if needed
|
|
|
|
|
const shallSort = true; //!OHIF.utils.ObjectPath.get(Meteor, 'settings.public.ui.sortSeriesByIncomingOrder');
|
|
|
|
|
if (shallSort) {
|
|
|
|
|
imageSet.sortBy((a, b) => {
|
|
|
|
|
// Sort by InstanceNumber (0020,0013)
|
2023-09-01 22:19:39 +02:00
|
|
|
return (parseInt(a.InstanceNumber) || 0) - (parseInt(b.InstanceNumber) || 0);
|
2020-05-10 16:33:04 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Include the first image instance number (after sorted)
|
|
|
|
|
/*imageSet.setAttribute(
|
|
|
|
|
'instanceNumber',
|
|
|
|
|
imageSet.getImage(0).InstanceNumber
|
|
|
|
|
);*/
|
|
|
|
|
|
|
|
|
|
/*const isReconstructable = isDisplaySetReconstructable(series, instances);
|
|
|
|
|
|
|
|
|
|
imageSet.isReconstructable = isReconstructable.value;
|
|
|
|
|
|
|
|
|
|
if (isReconstructable.missingFrames) {
|
|
|
|
|
// TODO -> This is currently unused, but may be used for reconstructing
|
|
|
|
|
// Volumes with gaps later on.
|
|
|
|
|
imageSet.missingFrames = isReconstructable.missingFrames;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
return imageSet;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const isSingleImageModality = modality => {
|
|
|
|
|
return modality === 'CR' || modality === 'MG' || modality === 'DX';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function getSopClassUids(instances) {
|
|
|
|
|
const uniqueSopClassUidsInSeries = new Set();
|
|
|
|
|
instances.forEach(instance => {
|
|
|
|
|
uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
|
|
|
|
|
});
|
|
|
|
|
const sopClassUids = Array.from(uniqueSopClassUidsInSeries);
|
|
|
|
|
|
|
|
|
|
return sopClassUids;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Basic SOPClassHandler:
|
|
|
|
|
* - For all Image types that are stackable, create
|
|
|
|
|
* a displaySet with a stack of images
|
|
|
|
|
*
|
|
|
|
|
* @param {Array} sopClassHandlerModules List of SOP Class Modules
|
|
|
|
|
* @param {SeriesMetadata} series The series metadata object from which the display sets will be created
|
|
|
|
|
* @returns {Array} The list of display sets created for the given series object
|
|
|
|
|
*/
|
2020-05-11 18:56:46 +02:00
|
|
|
function getDisplaySetsFromSeries(instances) {
|
2020-05-10 16:33:04 +02:00
|
|
|
// If the series has no instances, stop here
|
|
|
|
|
if (!instances || !instances.length) {
|
|
|
|
|
throw new Error('No instances were provided');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displaySets = [];
|
|
|
|
|
const sopClassUids = getSopClassUids(instances);
|
|
|
|
|
|
|
|
|
|
// Search through the instances (InstanceMetadata object) of this series
|
|
|
|
|
// Split Multi-frame instances and Single-image modalities
|
|
|
|
|
// into their own specific display sets. Place the rest of each
|
|
|
|
|
// series into another display set.
|
|
|
|
|
const stackableInstances = [];
|
|
|
|
|
instances.forEach(instance => {
|
|
|
|
|
// All imaging modalities must have a valid value for sopClassUid (x00080016) or rows (x00280010)
|
|
|
|
|
if (!isImage(instance.SOPClassUID) && !instance.Rows) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let displaySet;
|
|
|
|
|
|
|
|
|
|
if (isMultiFrame(instance)) {
|
|
|
|
|
displaySet = makeDisplaySet([instance]);
|
|
|
|
|
|
|
|
|
|
displaySet.setAttributes({
|
|
|
|
|
sopClassUids,
|
|
|
|
|
isClip: true,
|
|
|
|
|
numImageFrames: instance.NumberOfFrames,
|
|
|
|
|
instanceNumber: instance.InstanceNumber,
|
|
|
|
|
acquisitionDatetime: instance.AcquisitionDateTime,
|
|
|
|
|
});
|
|
|
|
|
displaySets.push(displaySet);
|
2022-09-21 15:54:29 +02:00
|
|
|
} else if (isSingleImageModality(instance.Modality)) {
|
2020-05-10 16:33:04 +02:00
|
|
|
displaySet = makeDisplaySet([instance]);
|
|
|
|
|
displaySet.setAttributes({
|
|
|
|
|
sopClassUids,
|
|
|
|
|
instanceNumber: instance.InstanceNumber,
|
|
|
|
|
acquisitionDatetime: instance.AcquisitionDateTime,
|
|
|
|
|
});
|
|
|
|
|
displaySets.push(displaySet);
|
|
|
|
|
} else {
|
|
|
|
|
stackableInstances.push(instance);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (stackableInstances.length) {
|
|
|
|
|
const displaySet = makeDisplaySet(stackableInstances);
|
|
|
|
|
displaySet.setAttribute('studyInstanceUid', instances[0].StudyInstanceUID);
|
|
|
|
|
displaySet.setAttributes({
|
|
|
|
|
sopClassUids,
|
|
|
|
|
});
|
|
|
|
|
displaySets.push(displaySet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return displaySets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sopClassUids = [
|
|
|
|
|
sopClassDictionary.ComputedRadiographyImageStorage,
|
|
|
|
|
sopClassDictionary.DigitalXRayImageStorageForPresentation,
|
|
|
|
|
sopClassDictionary.DigitalXRayImageStorageForProcessing,
|
|
|
|
|
sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation,
|
|
|
|
|
sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing,
|
|
|
|
|
sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation,
|
|
|
|
|
sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing,
|
|
|
|
|
sopClassDictionary.CTImageStorage,
|
|
|
|
|
sopClassDictionary.EnhancedCTImageStorage,
|
|
|
|
|
sopClassDictionary.LegacyConvertedEnhancedCTImageStorage,
|
|
|
|
|
sopClassDictionary.UltrasoundMultiframeImageStorage,
|
|
|
|
|
sopClassDictionary.MRImageStorage,
|
|
|
|
|
sopClassDictionary.EnhancedMRImageStorage,
|
|
|
|
|
sopClassDictionary.EnhancedMRColorImageStorage,
|
|
|
|
|
sopClassDictionary.LegacyConvertedEnhancedMRImageStorage,
|
|
|
|
|
sopClassDictionary.UltrasoundImageStorage,
|
2022-03-11 17:18:56 +01:00
|
|
|
sopClassDictionary.UltrasoundImageStorageRET,
|
2020-05-10 16:33:04 +02:00
|
|
|
sopClassDictionary.SecondaryCaptureImageStorage,
|
|
|
|
|
sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage,
|
|
|
|
|
sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage,
|
|
|
|
|
sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage,
|
|
|
|
|
sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage,
|
|
|
|
|
sopClassDictionary.XRayAngiographicImageStorage,
|
|
|
|
|
sopClassDictionary.EnhancedXAImageStorage,
|
|
|
|
|
sopClassDictionary.XRayRadiofluoroscopicImageStorage,
|
|
|
|
|
sopClassDictionary.EnhancedXRFImageStorage,
|
|
|
|
|
sopClassDictionary.XRay3DAngiographicImageStorage,
|
|
|
|
|
sopClassDictionary.XRay3DCraniofacialImageStorage,
|
|
|
|
|
sopClassDictionary.BreastTomosynthesisImageStorage,
|
|
|
|
|
sopClassDictionary.BreastProjectionXRayImageStorageForPresentation,
|
|
|
|
|
sopClassDictionary.BreastProjectionXRayImageStorageForProcessing,
|
|
|
|
|
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation,
|
|
|
|
|
sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing,
|
|
|
|
|
sopClassDictionary.NuclearMedicineImageStorage,
|
|
|
|
|
sopClassDictionary.VLEndoscopicImageStorage,
|
|
|
|
|
sopClassDictionary.VideoEndoscopicImageStorage,
|
|
|
|
|
sopClassDictionary.VLMicroscopicImageStorage,
|
|
|
|
|
sopClassDictionary.VideoMicroscopicImageStorage,
|
|
|
|
|
sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage,
|
|
|
|
|
sopClassDictionary.VLPhotographicImageStorage,
|
|
|
|
|
sopClassDictionary.VideoPhotographicImageStorage,
|
|
|
|
|
sopClassDictionary.OphthalmicPhotography8BitImageStorage,
|
|
|
|
|
sopClassDictionary.OphthalmicPhotography16BitImageStorage,
|
|
|
|
|
sopClassDictionary.OphthalmicTomographyImageStorage,
|
|
|
|
|
sopClassDictionary.VLWholeSlideMicroscopyImageStorage,
|
|
|
|
|
sopClassDictionary.PositronEmissionTomographyImageStorage,
|
|
|
|
|
sopClassDictionary.EnhancedPETImageStorage,
|
|
|
|
|
sopClassDictionary.LegacyConvertedEnhancedPETImageStorage,
|
|
|
|
|
sopClassDictionary.RTImageStorage,
|
2022-09-20 20:47:18 +02:00
|
|
|
sopClassDictionary.EnhancedUSVolumeStorage,
|
2020-05-10 16:33:04 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function getSopClassHandlerModule() {
|
|
|
|
|
return [
|
|
|
|
|
{
|
2020-05-11 18:56:46 +02:00
|
|
|
name: sopClassHandlerName,
|
2020-05-10 16:33:04 +02:00
|
|
|
sopClassUids,
|
2020-05-11 18:56:46 +02:00
|
|
|
getDisplaySetsFromSeries,
|
2020-05-10 16:33:04 +02:00
|
|
|
},
|
2023-08-16 17:37:28 +02:00
|
|
|
{
|
|
|
|
|
name: 'not-supported-display-sets-handler',
|
|
|
|
|
sopClassUids: [],
|
|
|
|
|
getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries,
|
|
|
|
|
},
|
2020-05-10 16:33:04 +02:00
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default getSopClassHandlerModule;
|