feat: Multiframe metadata provider (#2938)
* fix(volume):Support volume viewing * fix(multiframe):Display multiframe US, and multiframe PR fixes * fix(metadataProvider):Don't call combine if frame not defined
This commit is contained in:
1 parent
3900e62641
commit
ff24b57a4b
5 files changed
+62
-136
No files matched your search
@@ -5,6 +5,7 @@ import getPixelSpacingInformation from '../utils/metadataProvider/getPixelSpacin
|
||||
import DicomMetadataStore from '../services/DicomMetadataStore';
|
||||
import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData';
|
||||
import toNumber from '../utils/toNumber';
|
||||
import combineFrameInstance from '../utils/combineFrameInstance';
|
||||
|
||||
class MetadataProvider {
|
||||
constructor() {
|
||||
@@ -57,13 +58,21 @@ class MetadataProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = uids;
|
||||
const {
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID,
|
||||
frameNumber,
|
||||
} = uids;
|
||||
|
||||
return DicomMetadataStore.getInstance(
|
||||
const instance = DicomMetadataStore.getInstance(
|
||||
StudyInstanceUID,
|
||||
SeriesInstanceUID,
|
||||
SOPInstanceUID
|
||||
);
|
||||
return (
|
||||
(frameNumber && combineFrameInstance(frameNumber, instance)) || instance
|
||||
);
|
||||
}
|
||||
|
||||
get(query, imageId, options = { fallback: false }) {
|
||||
@@ -408,7 +417,10 @@ class MetadataProvider {
|
||||
// SOPInstanceUID,
|
||||
// })
|
||||
// somewhere else
|
||||
if (imageId.startsWith('wadors:')) {
|
||||
if (
|
||||
imageId.startsWith('wadors:') ||
|
||||
imageId.startsWith('streaming-wadors:')
|
||||
) {
|
||||
const strippedImageId = imageId.split('/studies/')[1];
|
||||
const splitImageId = strippedImageId.split('/');
|
||||
|
||||
@@ -416,6 +428,7 @@ class MetadataProvider {
|
||||
StudyInstanceUID: splitImageId[0], // Note: splitImageId[1] === 'series'
|
||||
SeriesInstanceUID: splitImageId[2], // Note: splitImageId[3] === 'instances'
|
||||
SOPInstanceUID: splitImageId[4],
|
||||
frameNumber: splitImageId[6],
|
||||
};
|
||||
} else if (imageId.includes('?requestType=WADO')) {
|
||||
const qs = queryString.parse(imageId);
|
||||
@@ -424,6 +437,7 @@ class MetadataProvider {
|
||||
StudyInstanceUID: qs.studyUID,
|
||||
SeriesInstanceUID: qs.seriesUID,
|
||||
SOPInstanceUID: qs.objectUID,
|
||||
frameNumber: qs.frameNumber,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -438,7 +452,13 @@ class MetadataProvider {
|
||||
imageURI = imageIdToURI(imageId);
|
||||
}
|
||||
|
||||
return this.imageURIToUIDs.get(imageURI);
|
||||
const uids = this.imageURIToUIDs.get(imageURI);
|
||||
const frameNumber = imageId.split(/\/frames\//)[1];
|
||||
|
||||
if (uids && frameNumber !== undefined) {
|
||||
return { ...uids, frameNumber };
|
||||
}
|
||||
return uids;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Combine the Per instance frame data, the shared frame data
|
||||
* and the root data objects.
|
||||
* The data is combined by taking nested sequence objects within
|
||||
* the functional group sequences. Data that is directly contained
|
||||
* within the functional group sequences, such as private creators
|
||||
* will be ignored.
|
||||
* This can be safely called with an undefined frame in order to handle
|
||||
* single frame data. (eg frame is undefined is the same as frame===1).
|
||||
*/
|
||||
const combineFrameInstance = (frame, instance) => {
|
||||
const {
|
||||
PerFrameFunctionalGroupsSequence,
|
||||
SharedFunctionalGroupsSequence,
|
||||
} = instance;
|
||||
if (!PerFrameFunctionalGroupsSequence) return instance;
|
||||
const shared = Object.values(SharedFunctionalGroupsSequence[0])
|
||||
.map(it => it[0])
|
||||
.filter(it => it !== undefined && typeof it === 'object');
|
||||
const perFrame = Object.values(
|
||||
PerFrameFunctionalGroupsSequence[(frame || 1) - 1]
|
||||
)
|
||||
.map(it => it[0])
|
||||
.filter(it => it !== undefined && typeof it === 'object');
|
||||
return Object.assign(
|
||||
{},
|
||||
instance,
|
||||
...Object.values(shared),
|
||||
...Object.values(perFrame)
|
||||
);
|
||||
};
|
||||
|
||||
export default combineFrameInstance;
|
||||
@@ -12,6 +12,7 @@ const imagesTypes = [
|
||||
sopClassDictionary.EnhancedCTImageStorage,
|
||||
sopClassDictionary.LegacyConvertedEnhancedCTImageStorage,
|
||||
sopClassDictionary.UltrasoundMultiframeImageStorage,
|
||||
sopClassDictionary.EnhancedUSVolumeStorage,
|
||||
sopClassDictionary.MRImageStorage,
|
||||
sopClassDictionary.EnhancedMRImageStorage,
|
||||
sopClassDictionary.EnhancedMRColorImageStorage,
|
||||
|
||||
@@ -128,3 +128,5 @@ export const sopClassDictionary = {
|
||||
ImplantAssemblyTemplateStorage: '1.2.840.10008.5.1.4.44.1',
|
||||
ImplantTemplateGroupStorage: '1.2.840.10008.5.1.4.45.1',
|
||||
};
|
||||
|
||||
export default sopClassDictionary;
|
||||
Reference in new issue
Block a user