fix(dicomjson): Update getUIDsFromImageID to work with json data source + update getDisplaySetImageUIDs to work with mixed sop class json (#4322)

This commit is contained in:
Igor Octaviano 2024-10-17 10:38:40 -03:00 committed by GitHub
parent d5bcf54e23
commit 3dd0666c0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 43 deletions

View File

@ -1,5 +1,6 @@
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core'; import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
import OHIF from '@ohif/core'; import OHIF from '@ohif/core';
import qs from 'query-string';
import getImageId from '../DicomWebDataSource/utils/getImageId'; import getImageId from '../DicomWebDataSource/utils/getImageId';
import getDirectURL from '../utils/getDirectURL'; import getDirectURL from '../utils/getDirectURL';
@ -90,11 +91,14 @@ function createDicomJSONApi(dicomJsonConfig) {
const { metadata: naturalizedDicom } = instance; const { metadata: naturalizedDicom } = instance;
const imageId = getImageId({ instance, config: dicomJsonConfig }); const imageId = getImageId({ instance, config: dicomJsonConfig });
const { query } = qs.parseUrl(instance.url);
// Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI. // Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI.
metadataProvider.addImageIdToUIDs(imageId, { metadataProvider.addImageIdToUIDs(imageId, {
StudyInstanceUID, StudyInstanceUID,
SeriesInstanceUID, SeriesInstanceUID,
SOPInstanceUID: naturalizedDicom.SOPInstanceUID, SOPInstanceUID: naturalizedDicom.SOPInstanceUID,
frameNumber: query.frame ? parseInt(query.frame) : undefined,
}); });
}); });
}); });
@ -258,26 +262,27 @@ function createDicomJSONApi(dicomJsonConfig) {
const { StudyInstanceUID, SeriesInstanceUID } = displaySet; const { StudyInstanceUID, SeriesInstanceUID } = displaySet;
const study = findStudies('StudyInstanceUID', StudyInstanceUID)[0]; const study = findStudies('StudyInstanceUID', StudyInstanceUID)[0];
const series = study.series.find(s => s.SeriesInstanceUID === SeriesInstanceUID); const series = study.series.find(s => s.SeriesInstanceUID === SeriesInstanceUID) || [];
let instances = displaySet.images;
if (series.instances.length > displaySet.images.length) {
instances = series.instances;
}
instances.forEach(instance => { const instanceMap = new Map();
const NumberOfFrames = instance.NumberOfFrames; series.instances.forEach(instance => {
if (instance?.metadata?.SOPInstanceUID) {
const { metadata, url } = instance;
const existingInstances = instanceMap.get(metadata.SOPInstanceUID) || [];
existingInstances.push({ ...metadata, url });
instanceMap.set(metadata.SOPInstanceUID, existingInstances);
}
});
if (NumberOfFrames > 1) { displaySet.images.forEach(instance => {
for (let i = 0; i < NumberOfFrames; i++) { const NumberOfFrames = instance.NumberOfFrames || 1;
const imageId = getImageId({ const instances = instanceMap.get(instance.SOPInstanceUID) || [instance];
instance, for (let i = 0; i < NumberOfFrames; i++) {
frame: i, const imageId = getImageId({
config: dicomJsonConfig, instance: instances[Math.min(i, instances.length - 1)],
}); frame: NumberOfFrames > 1 ? i : undefined,
imageIds.push(imageId); config: dicomJsonConfig,
} });
} else {
const imageId = getImageId({ instance, config: dicomJsonConfig });
imageIds.push(imageId); imageIds.push(imageId);
} }
}); });

View File

@ -8,31 +8,13 @@ import toNumber from '../utils/toNumber';
import combineFrameInstance from '../utils/combineFrameInstance'; import combineFrameInstance from '../utils/combineFrameInstance';
class MetadataProvider { class MetadataProvider {
constructor() { private readonly studies: Map<string, any> = new Map();
// Define the main "metadataLookup" private property as an immutable property. private readonly imageURIToUIDs: Map<string, any> = new Map();
Object.defineProperty(this, 'studies', { private readonly imageUIDsByImageId: Map<string, any> = new Map();
configurable: false, // Can be used to store custom metadata for a specific type.
enumerable: false, // For instance, the scaling metadata for PET can be stored here
writable: false, // as type "scalingModule"
value: new Map(), private readonly customMetadata: Map<string, any> = new Map();
});
Object.defineProperty(this, 'imageURIToUIDs', {
configurable: false,
enumerable: false,
writable: false,
value: 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"
//
Object.defineProperty(this, 'customMetadata', {
configurable: false,
enumerable: false,
writable: false,
value: new Map(),
});
}
addImageIdToUIDs(imageId, uids) { addImageIdToUIDs(imageId, uids) {
// This method is a fallback for when you don't have WADO-URI or WADO-RS. // This method is a fallback for when you don't have WADO-URI or WADO-RS.
@ -40,6 +22,7 @@ class MetadataProvider {
// An example would be dicom hosted at some random site. // An example would be dicom hosted at some random site.
const imageURI = imageIdToURI(imageId); const imageURI = imageIdToURI(imageId);
this.imageURIToUIDs.set(imageURI, uids); this.imageURIToUIDs.set(imageURI, uids);
this.imageUIDsByImageId.set(imageId, uids);
} }
addCustomMetadata(imageId, type, metadata) { addCustomMetadata(imageId, type, metadata) {
@ -482,6 +465,12 @@ class MetadataProvider {
// SOPInstanceUID, // SOPInstanceUID,
// }) // })
// somewhere else // somewhere else
const cachedUIDs = this.imageUIDsByImageId.get(imageId);
if (cachedUIDs) {
return cachedUIDs;
}
if (imageId.startsWith('wadors:')) { if (imageId.startsWith('wadors:')) {
const strippedImageId = imageId.split('/studies/')[1]; const strippedImageId = imageId.split('/studies/')[1];
const splitImageId = strippedImageId.split('/'); const splitImageId = strippedImageId.split('/');