fix: Having sop instance in a per-frame or shared attribute breaks load (#4560)
Co-authored-by: sedghi <ar.sedghi@gmail.com>
This commit is contained in:
1 parent
27c040fdda
commit
cded082617
15 files changed
+136
-71
No files matched your search
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
@@ -0,0 +1,5 @@
|
||||
export function dicomSplit(value) {
|
||||
return (
|
||||
(Array.isArray(value) && value) || (typeof value === 'string' && value.split('\\')) || value
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user