feat(4D): Add 4D dynamic volume rendering and new pre-clinical 4d pt/ct mode (#3664)

Co-authored-by: Alireza <ar.sedghi@gmail.com>
Co-authored-by: Neil <neil.a.macphee@gmail.com>
This commit is contained in:
authored and GitHub committed 2024-04-09 23:57:34 -04:00
1 parent dc0b183dd4
commit d57e8bc157
200 files changed
+9589 -2178

No files matched your search

@@ -5,23 +5,79 @@ import isDisplaySetReconstructable from '@ohif/core/src/utils/isDisplaySetRecons
import { id } from './id';
import getDisplaySetMessages from './getDisplaySetMessages';
import getDisplaySetsFromUnsupportedSeries from './getDisplaySetsFromUnsupportedSeries';
import { chartHandler } from './SOPClassHandlers/chartSOPClassHandler';
const DEFAULT_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';
const DYNAMIC_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingDynamicImageVolume';
const sopClassHandlerName = 'stack';
let appContext = {};
const getDynamicVolumeInfo = instances => {
const { extensionManager } = appContext;
if (!extensionManager) {
throw new Error('extensionManager is not available');
}
const imageIds = instances.map(({ imageId }) => imageId);
const volumeLoaderUtility = extensionManager.getModuleEntry(
'@ohif/extension-cornerstone.utilityModule.volumeLoader'
);
const { getDynamicVolumeInfo: csGetDynamicVolumeInfo } = volumeLoaderUtility.exports;
return csGetDynamicVolumeInfo(imageIds);
};
const isMultiFrame = instance => {
return instance.NumberOfFrames > 1;
};
function getDisplaySetInfo(instances) {
const dynamicVolumeInfo = getDynamicVolumeInfo(instances);
const { isDynamicVolume, timePoints } = dynamicVolumeInfo;
let displaySetInfo;
if (isDynamicVolume) {
const timePoint = timePoints[0];
const instancesMap = new Map();
// O(n) to convert it into a map and O(1) to find each instance
instances.forEach(instance => instancesMap.set(instance.imageId, instance));
const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));
displaySetInfo = isDisplaySetReconstructable(firstTimePointInstances);
} else {
displaySetInfo = isDisplaySetReconstructable(instances);
}
return {
isDynamicVolume,
...displaySetInfo,
dynamicVolumeInfo,
};
}
const makeDisplaySet = instances => {
const instance = instances[0];
const imageSet = new ImageSet(instances);
const { value: isReconstructable, averageSpacingBetweenFrames } =
isDisplaySetReconstructable(instances);
const {
isDynamicVolume,
value: isReconstructable,
averageSpacingBetweenFrames,
dynamicVolumeInfo,
} = getDisplaySetInfo(instances);
const volumeLoaderSchema = isDynamicVolume
? DYNAMIC_VOLUME_LOADER_SCHEME
: DEFAULT_VOLUME_LOADER_SCHEME;
// set appropriate attributes to image set...
const messages = getDisplaySetMessages(instances, isReconstructable);
const messages = getDisplaySetMessages(instances, isReconstructable, isDynamicVolume);
imageSet.setAttributes({
volumeLoaderSchema,
displaySetInstanceUID: imageSet.uid, // create a local alias for the imageSet UID
SeriesDate: instance.SeriesDate,
SeriesTime: instance.SeriesTime,
@@ -39,6 +95,8 @@ const makeDisplaySet = instances => {
isReconstructable,
messages,
averageSpacingBetweenFrames: averageSpacingBetweenFrames || null,
isDynamicVolume,
dynamicVolumeInfo,
});
// Sort the images in this series if needed
@@ -88,7 +146,6 @@ function getSopClassUids(instances) {
* - 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
*/
@@ -203,7 +260,9 @@ const sopClassUids = [
sopClassDictionary.EnhancedUSVolumeStorage,
];
function getSopClassHandlerModule() {
function getSopClassHandlerModule(appContextParam) {
appContext = appContextParam;
return [
{
name: sopClassHandlerName,
@@ -215,6 +274,11 @@ function getSopClassHandlerModule() {
sopClassUids: [],
getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries,
},
{
name: chartHandler.name,
sopClassUids: chartHandler.sopClassUids,
getDisplaySetsFromSeries: chartHandler.getDisplaySetsFromSeries,
},
];
}