diff --git a/bun.lockb b/bun.lockb index c6644930208..0ffd08fccbc 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/extensions/cornerstone-dicom-pmap/package.json b/extensions/cornerstone-dicom-pmap/package.json index 7e22dfb29df..825263f40b0 100644 --- a/extensions/cornerstone-dicom-pmap/package.json +++ b/extensions/cornerstone-dicom-pmap/package.json @@ -46,8 +46,8 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^2.14.7", - "@cornerstonejs/core": "^2.14.7", + "@cornerstonejs/adapters": "^2.15.3", + "@cornerstonejs/core": "^2.15.3", "@kitware/vtk.js": "32.1.1", "react-color": "^2.19.3" } diff --git a/extensions/cornerstone-dicom-seg/package.json b/extensions/cornerstone-dicom-seg/package.json index fcf7d0d62d2..fcace98de44 100644 --- a/extensions/cornerstone-dicom-seg/package.json +++ b/extensions/cornerstone-dicom-seg/package.json @@ -46,8 +46,8 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^2.14.7", - "@cornerstonejs/core": "^2.14.7", + "@cornerstonejs/adapters": "^2.15.3", + "@cornerstonejs/core": "^2.15.3", "@kitware/vtk.js": "32.1.1", "react-color": "^2.19.3" } diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 50b65f8b505..b22f713c8e4 100644 --- a/extensions/cornerstone-dicom-sr/package.json +++ b/extensions/cornerstone-dicom-sr/package.json @@ -46,9 +46,9 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^2.14.7", - "@cornerstonejs/core": "^2.14.7", - "@cornerstonejs/tools": "^2.14.7", + "@cornerstonejs/adapters": "^2.15.3", + "@cornerstonejs/core": "^2.15.3", + "@cornerstonejs/tools": "^2.15.3", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone-dynamic-volume/package.json b/extensions/cornerstone-dynamic-volume/package.json index 1ece9fb9690..57246f3ae0b 100644 --- a/extensions/cornerstone-dynamic-volume/package.json +++ b/extensions/cornerstone-dynamic-volume/package.json @@ -42,8 +42,8 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/core": "^2.14.7", - "@cornerstonejs/tools": "^2.14.7", + "@cornerstonejs/core": "^2.15.3", + "@cornerstonejs/tools": "^2.15.3", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json index 3bde05195a8..a288b45dcde 100644 --- a/extensions/cornerstone/package.json +++ b/extensions/cornerstone/package.json @@ -38,7 +38,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.4", "@cornerstonejs/codec-openjph": "^2.4.5", - "@cornerstonejs/dicom-image-loader": "^2.14.7", + "@cornerstonejs/dicom-image-loader": "^2.15.3", "@icr/polyseg-wasm": "^0.4.0", "@ohif/core": "3.10.0-beta.59", "@ohif/ui": "3.10.0-beta.59", @@ -55,9 +55,9 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^2.14.7", - "@cornerstonejs/core": "^2.14.7", - "@cornerstonejs/tools": "^2.14.7", + "@cornerstonejs/adapters": "^2.15.3", + "@cornerstonejs/core": "^2.15.3", + "@cornerstonejs/tools": "^2.15.3", "@icr/polyseg-wasm": "^0.4.0", "@kitware/vtk.js": "32.1.1", "html2canvas": "^1.4.1", diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index d3740c43f8c..c551958e43b 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -32,8 +32,8 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "^2.14.7", - "@cornerstonejs/tools": "^2.14.7", + "@cornerstonejs/core": "^2.15.3", + "@cornerstonejs/tools": "^2.15.3", "@ohif/core": "3.10.0-beta.59", "@ohif/extension-cornerstone-dicom-sr": "3.10.0-beta.59", "@ohif/extension-default": "3.10.0-beta.59", diff --git a/platform/app/package.json b/platform/app/package.json index d3179e33906..21cea4e4dab 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -54,7 +54,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.4", "@cornerstonejs/codec-openjph": "^2.4.5", - "@cornerstonejs/dicom-image-loader": "^2.14.7", + "@cornerstonejs/dicom-image-loader": "^2.15.3", "@emotion/serialize": "^1.1.3", "@ohif/core": "3.10.0-beta.59", "@ohif/extension-cornerstone": "3.10.0-beta.59", diff --git a/platform/app/public/config/local_orthanc.js b/platform/app/public/config/local_orthanc.js index b17dc3fbe3c..0a6fbafce2b 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: true, + strictZSpacingForVolumeViewport: false, // filterQueryParam: false, defaultDataSourceName: 'orthanc', dataSources: [ diff --git a/platform/core/package.json b/platform/core/package.json index ab043e055e7..0b79f7c3685 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -37,7 +37,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.4", "@cornerstonejs/codec-openjph": "^2.4.5", - "@cornerstonejs/dicom-image-loader": "^2.14.7", + "@cornerstonejs/dicom-image-loader": "^2.15.3", "@ohif/ui": "3.10.0-beta.59", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21" diff --git a/platform/core/src/classes/MetadataProvider.ts b/platform/core/src/classes/MetadataProvider.ts index 2bd41646cdc..87a2d939602 100644 --- a/platform/core/src/classes/MetadataProvider.ts +++ b/platform/core/src/classes/MetadataProvider.ts @@ -545,6 +545,7 @@ const WADO_IMAGE_LOADER = { frameOfReferenceUID: instance.FrameOfReferenceUID, rows: toNumber(instance.Rows), columns: toNumber(instance.Columns), + spacingBetweenSlices: toNumber(instance.SpacingBetweenSlices), imageOrientationPatient: toNumber(ImageOrientationPatient) || [0, 1, 0, 0, 0, -1], rowCosines: toNumber(rowCosines || [0, 1, 0]), isDefaultValueSetForRowCosine: toNumber(rowCosines) ? false : true, diff --git a/platform/core/src/utils/combineFrameInstance.ts b/platform/core/src/utils/combineFrameInstance.ts index b2e61c9074f..ee3aeaa996a 100644 --- a/platform/core/src/utils/combineFrameInstance.ts +++ b/platform/core/src/utils/combineFrameInstance.ts @@ -1,4 +1,5 @@ import { vec3 } from 'gl-matrix'; +import { dicomSplit } from './dicomSplit'; /** * Combine the Per instance frame data, the shared frame data @@ -15,24 +16,13 @@ const combineFrameInstance = (frame, instance) => { PerFrameFunctionalGroupsSequence, SharedFunctionalGroupsSequence, NumberOfFrames, - SpacingBetweenSlices, + ImageType, } = instance; + instance.ImageType = dicomSplit(ImageType); + if (PerFrameFunctionalGroupsSequence || NumberOfFrames > 1) { const frameNumber = Number.parseInt(frame || 1); - const shared = SharedFunctionalGroupsSequence - ? Object.values(SharedFunctionalGroupsSequence[0]) - .filter(Boolean) - .map(it => it[0]) - .filter(it => typeof it === 'object') - : []; - - const perFrame = PerFrameFunctionalGroupsSequence - ? Object.values(PerFrameFunctionalGroupsSequence[frameNumber - 1]) - .filter(Boolean) - .map(it => it[0]) - .filter(it => typeof it === 'object') - : []; // this is to fix NM multiframe datasets with position and orientation // information inside DetectorInformationSequence @@ -44,8 +34,12 @@ const combineFrameInstance = (frame, instance) => { let ImagePositionPatientToUse = instance.ImagePositionPatient; if (!instance.ImagePositionPatient && instance.DetectorInformationSequence) { - const imagePositionPatient = instance.DetectorInformationSequence[0].ImagePositionPatient; - const imageOrientationPatient = instance.ImageOrientationPatient; + let imagePositionPatient = instance.DetectorInformationSequence[0].ImagePositionPatient; + let imageOrientationPatient = instance.ImageOrientationPatient; + + imagePositionPatient = imagePositionPatient.map(it => Number(it)); + imageOrientationPatient = imageOrientationPatient.map(it => Number(it)); + const SpacingBetweenSlices = Number(instance.SpacingBetweenSlices); // Calculate the position for the current frame if (imageOrientationPatient && SpacingBetweenSlices) { @@ -73,26 +67,62 @@ const combineFrameInstance = (frame, instance) => { ImagePositionPatientToUse = [position[0], position[1], position[2]]; } } + const sharedInstance = createCombinedValue(instance, SharedFunctionalGroupsSequence?.[0]); + const newInstance = createCombinedValue( + sharedInstance, + PerFrameFunctionalGroupsSequence?.[frameNumber] + ); - const newInstance = Object.assign(instance, { frameNumber: frameNumber }); - - // merge the shared first then the per frame to override - [...shared, ...perFrame].forEach(item => { - Object.entries(item).forEach(([key, value]) => { - newInstance[key] = value; - }); + Object.defineProperty(newInstance, 'ImagePositionPatient', { + value: ImagePositionPatientToUse ?? newInstance.ImagePositionPatient ?? [0, 0, frameNumber], + writable: true, + enumerable: true, + configurable: true, }); - // Todo: we should cache this combined instance somewhere, maybe add it - // back to the dicomMetaStore so we don't have to do this again. - return { - ...newInstance, - ImagePositionPatient: ImagePositionPatientToUse ?? - newInstance.ImagePositionPatient ?? [0, 0, frameNumber], - }; + Object.defineProperty(newInstance, 'frameNumber', { + value: frameNumber, + writable: true, + enumerable: true, + configurable: true, + }); + return newInstance; } else { return instance; } }; +function createCombinedValue(parent, functionalGroups) { + const newInstance = Object.create(parent); + if (!functionalGroups) { + return newInstance; + } + if (functionalGroups._sharedValue) { + return functionalGroups._sharedValue; + } + const shared = functionalGroups + ? Object.values(functionalGroups) + .filter(Boolean) + .map(it => it[0]) + .filter(it => typeof it === 'object') + : []; + + // merge the shared first then the per frame to override + [...shared].forEach(item => { + if (item.SOPInstanceUID) { + // This sub-item is a previous value information item, so don't merge it + return; + } + Object.entries(item).forEach(([key, value]) => { + newInstance[key] = value; + }); + }); + Object.defineProperty(functionalGroups, '_sharedValue', { + value: newInstance, + writable: false, + enumerable: false, + }); + return newInstance; +} + export default combineFrameInstance; diff --git a/platform/core/src/utils/dicomSplit.ts b/platform/core/src/utils/dicomSplit.ts new file mode 100644 index 00000000000..54b20d38f0d --- /dev/null +++ b/platform/core/src/utils/dicomSplit.ts @@ -0,0 +1,5 @@ +export function dicomSplit(value) { + return ( + (Array.isArray(value) && value) || (typeof value === 'string' && value.split('\\')) || value + ); +} diff --git a/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx b/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx index 40519d38c3b..fe39e2d6cd9 100644 --- a/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx +++ b/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx @@ -11,7 +11,6 @@ function LayoutPreset({ classNames: classNameProps, disabled, }) { - console.debug('🚀 ~ icon:', icon); return (