ohif-viewer/extensions/default/src/DicomJSONDataSource/index.js
Joe Boccanfuso ae4183852f
fix: Patient name handling as either Alphabetic object or simply string object
- formatPN should accept a string person name as well as an object with a Alphabetic field.
- For DICOM JSON data sources, spread in the patient data from the study object into the instance.
2023-02-16 13:50:59 -05:00

266 lines
7.5 KiB
JavaScript

import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
import OHIF from '@ohif/core';
import getImageId from '../DicomWebDataSource/utils/getImageId';
import getDirectURL from '../utils/getDirectURL';
const metadataProvider = OHIF.classes.MetadataProvider;
const mappings = {
studyInstanceUid: 'StudyInstanceUID',
patientId: 'PatientID',
};
let _store = {
urls: [],
// {
// url: url1
// studies: [Study1, Study2], // if multiple studies
// }
// {
// url: url2
// studies: [Study1],
// }
// }
};
const getMetaDataByURL = url => {
return _store.urls.find(metaData => metaData.url === url);
};
const findStudies = (key, value) => {
let studies = [];
_store.urls.map(metaData => {
metaData.studies.map(aStudy => {
if (aStudy[key] === value) {
studies.push(aStudy);
}
});
});
return studies;
};
function createDicomJSONApi(dicomJsonConfig) {
const { name, wadoRoot } = dicomJsonConfig;
const implementation = {
initialize: async ({ params, query, url }) => {
if (!url) url = query.get('url');
let metaData = getMetaDataByURL(url);
// if we have already cached the data from this specific url
// We are only handling one StudyInstanceUID to run; however,
// all studies for patientID will be put in the correct tab
if (metaData) {
return metaData.studies.map(aStudy => {
return aStudy.StudyInstanceUID;
});
}
const response = await fetch(url);
let data = await response.json();
const studyInstanceUIDs = data.studies.map(
study => study.StudyInstanceUID
);
let StudyInstanceUID;
let SeriesInstanceUID;
data.studies.forEach(study => {
StudyInstanceUID = study.StudyInstanceUID;
study.series.forEach(series => {
SeriesInstanceUID = series.SeriesInstanceUID;
series.instances.forEach(instance => {
const { url: imageId, metadata: naturalizedDicom } = instance;
// Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI.
metadataProvider.addImageIdToUIDs(imageId, {
StudyInstanceUID,
SeriesInstanceUID,
SOPInstanceUID: naturalizedDicom.SOPInstanceUID,
});
});
});
});
_store.urls.push({
url,
studies: [...data.studies],
});
return studyInstanceUIDs;
},
query: {
studies: {
mapParams: () => { },
search: async param => {
const [key, value] = Object.entries(param)[0];
const mappedParam = mappings[key];
// todo: should fetch from dicomMetadataStore
const studies = findStudies(mappedParam, value);
return studies.map(aStudy => {
return {
accession: aStudy.AccessionNumber,
date: aStudy.StudyDate,
description: aStudy.StudyDescription,
instances: aStudy.NumInstances,
modalities: aStudy.Modalities,
mrn: aStudy.PatientID,
patientName: aStudy.PatientName,
studyInstanceUid: aStudy.StudyInstanceUID,
NumInstances: aStudy.NumInstances,
time: aStudy.StudyTime,
};
});
},
processResults: () => {
console.debug(' DICOMJson QUERY processResults');
},
},
series: {
// mapParams: mapParams.bind(),
search: () => {
console.debug(' DICOMJson QUERY SERIES SEARCH');
},
},
instances: {
search: () => {
console.debug(' DICOMJson QUERY instances SEARCH');
},
},
},
retrieve: {
/**
* Generates a URL that can be used for direct retrieve of the bulkdata
*
* @param {object} params
* @param {string} params.tag is the tag name of the URL to retrieve
* @param {string} params.defaultPath path for the pixel data url
* @param {object} params.instance is the instance object that the tag is in
* @param {string} params.defaultType is the mime type of the response
* @param {string} params.singlepart is the type of the part to retrieve
* @param {string} params.fetchPart unknown?
* @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart,
* or is already retrieved, or a promise to a URL for such use if a BulkDataURI
*/
directURL: params => {
return getDirectURL(wadoRoot, params);
},
series: {
metadata: ({
StudyInstanceUID,
madeInClient = false,
customSort,
} = {}) => {
if (!StudyInstanceUID) {
throw new Error(
'Unable to query for SeriesMetadata without StudyInstanceUID'
);
}
const study = findStudies('StudyInstanceUID', StudyInstanceUID)[0];
let series;
if (customSort) {
series = customSort(study.series);
} else {
series = study.series;
}
const seriesSummaryMetadata = series.map(series => {
const seriesSummary = {
StudyInstanceUID: study.StudyInstanceUID,
...series,
};
delete seriesSummary.instances;
return seriesSummary;
});
// Async load series, store as retrieved
function storeInstances(naturalizedInstances) {
DicomMetadataStore.addInstances(naturalizedInstances, madeInClient);
}
DicomMetadataStore.addSeriesMetadata(
seriesSummaryMetadata,
madeInClient
);
function setSuccessFlag() {
const study = DicomMetadataStore.getStudy(
StudyInstanceUID,
madeInClient
);
study.isLoaded = true;
}
const numberOfSeries = series.length;
series.forEach((series, index) => {
const instances = series.instances.map(instance => {
const obj = {
...instance.metadata,
url: instance.url,
imageId: instance.url,
...series,
...study,
};
delete obj.instances;
delete obj.series;
return obj;
});
storeInstances(instances);
if (index === numberOfSeries - 1) setSuccessFlag();
});
},
},
},
store: {
dicom: () => {
console.debug(' DICOMJson store dicom');
},
},
getImageIdsForDisplaySet(displaySet) {
const images = displaySet.images;
const imageIds = [];
if (!images) {
return imageIds;
}
displaySet.images.forEach(instance => {
const NumberOfFrames = instance.NumberOfFrames;
if (NumberOfFrames > 1) {
for (let i = 0; i < NumberOfFrames; i++) {
const imageId = getImageId({
instance,
frame: i,
config: dicomJsonConfig,
});
imageIds.push(imageId);
}
} else {
const imageId = getImageId({ instance, config: dicomJsonConfig });
imageIds.push(imageId);
}
});
return imageIds;
},
getImageIdsForInstance({ instance, frame }) {
const imageIds = getImageId({
instance,
frame,
});
return imageIds;
},
};
return IWebApiDataSource.create(implementation);
}
export { createDicomJSONApi };