fix(MetadataProvider): Correctly assign imageId for multiframe images and remove unused frame information retrieval method (#5965)
This commit is contained in:
1 parent
2c54616136
commit
1eee3e6119
7 files changed
+369
-43
No files matched your search
@@ -0,0 +1,82 @@
|
||||
import metadataProvider from './MetadataProvider';
|
||||
|
||||
beforeEach(() => {
|
||||
(
|
||||
metadataProvider as unknown as {
|
||||
imageURIToUIDs: Map<string, unknown>;
|
||||
}
|
||||
).imageURIToUIDs.clear();
|
||||
});
|
||||
|
||||
describe('MetadataProvider', () => {
|
||||
it('uses the WADO frame query parameter as the frame number', () => {
|
||||
expect(
|
||||
metadataProvider.getUIDsFromImageID(
|
||||
'dicomweb:http://localhost/wado?requestType=WADO&studyUID=study-wado&seriesUID=series-wado&objectUID=sop-wado&contentType=application/dicom&transferSyntax=*&frame=5'
|
||||
)
|
||||
).toEqual({
|
||||
StudyInstanceUID: 'study-wado',
|
||||
SeriesInstanceUID: 'series-wado',
|
||||
SOPInstanceUID: 'sop-wado',
|
||||
frameNumber: '5',
|
||||
});
|
||||
});
|
||||
|
||||
it('uses the frame query parameter for local multiframe imageIds registered by base URL', () => {
|
||||
const baseImageId = 'blob:http://localhost/local-multiframe';
|
||||
const uids = {
|
||||
StudyInstanceUID: 'study-local',
|
||||
SeriesInstanceUID: 'series-local',
|
||||
SOPInstanceUID: 'sop-local',
|
||||
};
|
||||
|
||||
metadataProvider.addImageIdToUIDs(baseImageId, uids);
|
||||
|
||||
expect(metadataProvider.getUIDsFromImageID(`${baseImageId}&frame=3`)).toEqual({
|
||||
...uids,
|
||||
frameNumber: '3',
|
||||
});
|
||||
});
|
||||
|
||||
it('prefers the frame query parameter over stored frame metadata', () => {
|
||||
const baseImageId = 'blob:http://localhost/local-multiframe-with-frame-number';
|
||||
const uids = {
|
||||
StudyInstanceUID: 'study-local-with-frame-number',
|
||||
SeriesInstanceUID: 'series-local-with-frame-number',
|
||||
SOPInstanceUID: 'sop-local-with-frame-number',
|
||||
frameNumber: '1',
|
||||
};
|
||||
|
||||
metadataProvider.addImageIdToUIDs(baseImageId, uids);
|
||||
|
||||
expect(metadataProvider.getUIDsFromImageID(`${baseImageId}&frame=4`)).toEqual({
|
||||
...uids,
|
||||
frameNumber: '4',
|
||||
});
|
||||
});
|
||||
|
||||
it('prefers an exact frame imageId mapping before falling back to the base URL', () => {
|
||||
const baseImageId = 'blob:http://localhost/local-multiframe-exact-frame';
|
||||
metadataProvider.addImageIdToUIDs(baseImageId, {
|
||||
StudyInstanceUID: 'study-base',
|
||||
SeriesInstanceUID: 'series-base',
|
||||
SOPInstanceUID: 'sop-base',
|
||||
frameNumber: '1',
|
||||
});
|
||||
|
||||
const frameImageId = `${baseImageId}&frame=3`;
|
||||
metadataProvider.addImageIdToUIDs(frameImageId, {
|
||||
StudyInstanceUID: 'study-frame',
|
||||
SeriesInstanceUID: 'series-frame',
|
||||
SOPInstanceUID: 'sop-frame',
|
||||
frameNumber: '3',
|
||||
});
|
||||
|
||||
expect(metadataProvider.getUIDsFromImageID(frameImageId)).toEqual({
|
||||
StudyInstanceUID: 'study-frame',
|
||||
SeriesInstanceUID: 'series-frame',
|
||||
SOPInstanceUID: 'sop-frame',
|
||||
frameNumber: '3',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import queryString from 'query-string';
|
||||
import dicomParser from 'dicom-parser';
|
||||
import { utilities } from '@cornerstonejs/core';
|
||||
import { utilities as csMetadataUtilities } from '@cornerstonejs/metadata';
|
||||
import { baseImageURIForMetadata } from '../utils/imageIdToURI';
|
||||
import DicomMetadataStore from '../services/DicomMetadataStore';
|
||||
import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData';
|
||||
@@ -8,6 +9,7 @@ import toNumber from '../utils/toNumber';
|
||||
import combineFrameInstance from '../utils/combineFrameInstance';
|
||||
|
||||
const { calibratedPixelSpacingMetadataProvider, getPixelSpacingInformation } = utilities;
|
||||
const { getUriModule } = csMetadataUtilities;
|
||||
|
||||
class MetadataProvider {
|
||||
private readonly imageURIToUIDs: Map<string, any> = new Map();
|
||||
@@ -60,7 +62,22 @@ class MetadataProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
return (frameNumber && combineFrameInstance(frameNumber, instance)) || instance;
|
||||
const result = (frameNumber && combineFrameInstance(frameNumber, instance)) || instance;
|
||||
|
||||
// We reassign the imageId on the instance because multiframe images processed
|
||||
// through combineFrameInstance will mistakenly get the first imageId.
|
||||
// This happens because the DICOM web data store only keeps the first instance.
|
||||
// Defined non-enumerable so spreading the instance into another object does
|
||||
// not carry the imageId over (it belongs to this frame only).
|
||||
if (result) {
|
||||
Object.defineProperty(result, 'imageId', {
|
||||
value: imageId,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
get(query, imageId, options = { fallback: false }) {
|
||||
@@ -423,37 +440,6 @@ class MetadataProvider {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the frameNumber information, depending on the url style
|
||||
* wadors /frames/1
|
||||
* wadouri &frame=1
|
||||
* @param {*} imageId
|
||||
* @returns
|
||||
*/
|
||||
getFrameInformationFromURL(imageId) {
|
||||
function getInformationFromURL(informationString, separator) {
|
||||
let result = '';
|
||||
const splittedStr = imageId.split(informationString)[1];
|
||||
if (splittedStr.includes(separator)) {
|
||||
result = splittedStr.split(separator)[0];
|
||||
} else {
|
||||
result = splittedStr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (imageId.includes('/frames')) {
|
||||
return getInformationFromURL('/frames', '/');
|
||||
}
|
||||
if (imageId.includes('?frame=')) {
|
||||
return getInformationFromURL('?frame=', '&');
|
||||
}
|
||||
if (imageId.includes('&frame=')) {
|
||||
return getInformationFromURL('&frame=', '&');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
getUIDsFromImageID(imageId) {
|
||||
if (imageId.startsWith('wadors:')) {
|
||||
const strippedImageId = imageId.split('/studies/')[1];
|
||||
@@ -467,23 +453,26 @@ class MetadataProvider {
|
||||
};
|
||||
} else if (imageId.includes('?requestType=WADO')) {
|
||||
const qs = queryString.parse(imageId);
|
||||
const frameNumber = qs.frameNumber || qs.frame;
|
||||
|
||||
return {
|
||||
StudyInstanceUID: qs.studyUID,
|
||||
SeriesInstanceUID: qs.seriesUID,
|
||||
SOPInstanceUID: qs.objectUID,
|
||||
frameNumber: qs.frameNumber,
|
||||
frameNumber,
|
||||
};
|
||||
}
|
||||
|
||||
const imageURI = baseImageURIForMetadata(imageId);
|
||||
const uids = this.imageURIToUIDs.get(imageURI);
|
||||
const frameNumber = this.getFrameInformationFromURL(imageId) || '1';
|
||||
|
||||
if (uids && frameNumber !== undefined) {
|
||||
return { ...uids, frameNumber };
|
||||
if (!uids) {
|
||||
return;
|
||||
}
|
||||
return uids;
|
||||
|
||||
const frameNumber = getUriModule(imageId)?.framesString || uids.frameNumber || '1';
|
||||
|
||||
return { ...uids, frameNumber };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user