diff --git a/extensions/default/src/DicomLocalDataSource/index.js b/extensions/default/src/DicomLocalDataSource/index.js index d049b404a..462fb8751 100644 --- a/extensions/default/src/DicomLocalDataSource/index.js +++ b/extensions/default/src/DicomLocalDataSource/index.js @@ -142,7 +142,9 @@ function createDicomLocalApi(dicomLocalConfig) { study.series.forEach(aSeries => { const { SeriesInstanceUID } = aSeries; - aSeries.instances.forEach(instance => { + const isMultiframe = aSeries.instances[0].NumberOfFrames > 1; + + aSeries.instances.forEach((instance, index) => { const { url: imageId, StudyInstanceUID, @@ -151,22 +153,14 @@ function createDicomLocalApi(dicomLocalConfig) { } = instance; instance.imageId = imageId; - const numberOfFrames = instance.NumberOfFrames || 1; - // Process all frames consistently, whether single or multiframe - for (let i = 0; i < numberOfFrames; i++) { - const frameNumber = i + 1; - const frameImageId = implementation.getImageIdsForInstance({ - instance, - frame: frameNumber, - }); - // Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI. - metadataProvider.addImageIdToUIDs(frameImageId, { - StudyInstanceUID, - SeriesInstanceUID, - SOPInstanceUID, - frameNumber: numberOfFrames > 1 ? frameNumber : undefined, - }); - } + + // Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI. + metadataProvider.addImageIdToUIDs(imageId, { + StudyInstanceUID, + SeriesInstanceUID, + SOPInstanceUID, + frameIndex: isMultiframe ? index : 1, + }); }); DicomMetadataStore._broadcastEvent(EVENTS.INSTANCES_ADDED, { diff --git a/extensions/default/src/DicomWebDataSource/index.ts b/extensions/default/src/DicomWebDataSource/index.ts index 6bf6c4e12..7d9cde6d3 100644 --- a/extensions/default/src/DicomWebDataSource/index.ts +++ b/extensions/default/src/DicomWebDataSource/index.ts @@ -478,7 +478,6 @@ function createDicomWebApi(dicomWebConfig: DicomWebConfig, servicesManager) { instance.wadoUri = dicomWebConfig.wadoUri; const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance; - const numberOfFrames = instance.NumberOfFrames || 1; // Process all frames consistently, whether single or multiframe for (let i = 0; i < numberOfFrames; i++) { diff --git a/platform/app/public/config/local_orthanc.js b/platform/app/public/config/local_orthanc.js index 0a6fbafce..b17dc3fbe 100644 --- a/platform/app/public/config/local_orthanc.js +++ b/platform/app/public/config/local_orthanc.js @@ -8,7 +8,7 @@ window.config = { showLoadingIndicator: true, showWarningMessageForCrossOrigin: true, showCPUFallbackMessage: true, - strictZSpacingForVolumeViewport: false, + strictZSpacingForVolumeViewport: true, // filterQueryParam: false, defaultDataSourceName: 'orthanc', dataSources: [ diff --git a/platform/core/src/classes/MetadataProvider.ts b/platform/core/src/classes/MetadataProvider.ts index 87a2d9396..3fccff5e6 100644 --- a/platform/core/src/classes/MetadataProvider.ts +++ b/platform/core/src/classes/MetadataProvider.ts @@ -9,7 +9,6 @@ import combineFrameInstance from '../utils/combineFrameInstance'; class MetadataProvider { private readonly imageURIToUIDs: Map = new Map(); - private readonly imageUIDsByImageId: Map = new Map(); // Can be used to store custom metadata for a specific type. // For instance, the scaling metadata for PET can be stored here // as type "scalingModule" @@ -25,7 +24,6 @@ class MetadataProvider { // An example would be dicom hosted at some random site. const imageURI = imageIdToURI(imageId); this.imageURIToUIDs.set(imageURI, uids); - this.imageUIDsByImageId.set(imageId, uids); } addCustomMetadata(imageId, type, metadata) { @@ -462,11 +460,6 @@ class MetadataProvider { } getUIDsFromImageID(imageId) { - const cachedUIDs = this.imageUIDsByImageId.get(imageId); - if (cachedUIDs) { - return cachedUIDs; - } - if (imageId.startsWith('wadors:')) { const strippedImageId = imageId.split('/studies/')[1]; const splitImageId = strippedImageId.split('/'); diff --git a/platform/core/src/utils/combineFrameInstance.ts b/platform/core/src/utils/combineFrameInstance.ts index ee3aeaa99..4202c5b0f 100644 --- a/platform/core/src/utils/combineFrameInstance.ts +++ b/platform/core/src/utils/combineFrameInstance.ts @@ -67,18 +67,27 @@ const combineFrameInstance = (frame, instance) => { ImagePositionPatientToUse = [position[0], position[1], position[2]]; } } - const sharedInstance = createCombinedValue(instance, SharedFunctionalGroupsSequence?.[0]); + + // Cache the _parentInstance at the top level as a full copy to prevent + // setting values hard. + if (!instance._parentInstance) { + Object.defineProperty(instance, '_parentInstance', { + value: { ...instance }, + }); + } + const sharedInstance = createCombinedValue( + instance._parentInstance, + SharedFunctionalGroupsSequence?.[0], + '_shared' + ); const newInstance = createCombinedValue( sharedInstance, - PerFrameFunctionalGroupsSequence?.[frameNumber] + PerFrameFunctionalGroupsSequence?.[frameNumber - 1], + frameNumber ); - Object.defineProperty(newInstance, 'ImagePositionPatient', { - value: ImagePositionPatientToUse ?? newInstance.ImagePositionPatient ?? [0, 0, frameNumber], - writable: true, - enumerable: true, - configurable: true, - }); + newInstance.ImagePositionPatient = ImagePositionPatientToUse ?? + newInstance.ImagePositionPatient ?? [0, 0, frameNumber]; Object.defineProperty(newInstance, 'frameNumber', { value: frameNumber, @@ -92,14 +101,25 @@ const combineFrameInstance = (frame, instance) => { } }; -function createCombinedValue(parent, functionalGroups) { +/** + * Creates a combined instance stored in the parent object which + * inherits from the parent instance the attributes in the functional groups. + * The storage key in the parent is in key + */ +function createCombinedValue(parent, functionalGroups, key) { + if (parent[key]) { + return parent[key]; + } + // Exclude any proxying values const newInstance = Object.create(parent); + Object.defineProperty(parent, key, { + value: newInstance, + writable: false, + enumerable: false, + }); if (!functionalGroups) { return newInstance; } - if (functionalGroups._sharedValue) { - return functionalGroups._sharedValue; - } const shared = functionalGroups ? Object.values(functionalGroups) .filter(Boolean) @@ -117,11 +137,6 @@ function createCombinedValue(parent, functionalGroups) { newInstance[key] = value; }); }); - Object.defineProperty(functionalGroups, '_sharedValue', { - value: newInstance, - writable: false, - enumerable: false, - }); return newInstance; }