feat: Support for local DICOM drag and drop (#2445)

* Added drag and drop from local and local data source

* fix: dicom SR drag and drop from local
This commit is contained in:
Alireza authored and GitHub committed 2021-06-15 10:19:45 -04:00
1 parent 99b8dc4759
commit fdb6ca41d6
23 files changed
+656 -89

No files matched your search

@@ -43,7 +43,7 @@ function createDicomJSONApi(dicomJsonConfig) {
const { name } = dicomJsonConfig;
const implementation = {
parseRouteParams: async ({ params, query, url }) => {
initialize: async ({ params, query, url }) => {
if (!url) url = query.get('url');
let metaData = getMetaDataByURL(url);
@@ -93,11 +93,12 @@ function createDicomJSONApi(dicomJsonConfig) {
},
query: {
studies: {
mapParams: () => {},
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 => {
@@ -0,0 +1,204 @@
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core'
import OHIF from '@ohif/core'
import dcmjs from 'dcmjs';
const metadataProvider = OHIF.classes.MetadataProvider
const { EVENTS } = DicomMetadataStore
// Sorting SR modalities to be at the end of series list
function customSort(seriesA, seriesB) {
const modalityA = seriesA.instances[0].Modality
const modalityB = seriesB.instances[0].Modality
if (modalityA === "SR") {
return +1;
}
if (modalityB === "SR") {
return -1;
}
return 0;
}
function createDicomLocalApi(dicomLocalConfig) {
const { name } = dicomLocalConfig
const implementation = {
initialize: ({ params, query }) => {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params
const queryStudyInstanceUIDs = query.get('StudyInstanceUIDs')
const StudyInstanceUIDs =
queryStudyInstanceUIDs || paramsStudyInstanceUIDs
const StudyInstanceUIDsAsArray =
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
? StudyInstanceUIDs
: [StudyInstanceUIDs]
// Put SRs at the end of series list to make sure images are loaded first
StudyInstanceUIDsAsArray.forEach(StudyInstanceUID => {
const study = DicomMetadataStore.getStudy(StudyInstanceUID)
study.series = study.series.sort(customSort)
})
return StudyInstanceUIDsAsArray
},
query: {
studies: {
mapParams: () => { },
search: (params) => {
const studyUIDs = DicomMetadataStore.getStudyInstanceUIDs()
return studyUIDs.map(StudyInstanceUID => {
let numInstances = 0
const modalities = new Set()
// Calculating the number of instances in the study and modalities
// present in the study
const study = DicomMetadataStore.getStudy(StudyInstanceUID)
study.series.forEach(aSeries => {
numInstances += aSeries.instances.length
modalities.add(aSeries.Modality);
})
// first instance in the first series
const firstInstance = study?.series[0]?.instances[0]
if (firstInstance) {
return {
accession: firstInstance.AccessionNumber,
date: firstInstance.StudyDate,
description: firstInstance.StudyDescription,
mrn: firstInstance.PatientID,
patientName: { Alphabetic: firstInstance.PatientName },
studyInstanceUid: firstInstance.StudyInstanceUID,
time: firstInstance.StudyTime,
//
instances: numInstances,
modalities: Array.from(modalities).join('/'),
NumInstances: numInstances,
};
}
})
},
processResults: () => {
console.debug(' DICOMLocal QUERY processResults')
},
},
series: {
// mapParams: mapParams.bind(),
search: () => {
console.debug(' DICOMLocal QUERY SERIES SEARCH')
},
},
instances: {
search: () => {
console.debug(' DICOMLocal QUERY instances SEARCH')
},
},
},
retrieve: {
series: {
metaData: () => {
console.debug(' DICOMLocal retrieve series metadata')
},
},
},
store: {
dicom: (naturalizedReport) => {
const reportBlob = dcmjs.data.datasetToBlob(naturalizedReport);
//Create a URL for the binary.
var objectUrl = URL.createObjectURL(reportBlob);
window.location.assign(objectUrl);
},
},
retrieveSeriesMetadata: async ({
StudyInstanceUID,
madeInClient = false,
} = {}) => {
if (!StudyInstanceUID) {
throw new Error(
'Unable to query for SeriesMetadata without StudyInstanceUID'
)
}
// Instances metadata already added via local upload
const study = DicomMetadataStore.getStudy(StudyInstanceUID, madeInClient)
// Series metadata already added via local upload
DicomMetadataStore._broadcastEvent(EVENTS.SERIES_ADDED, {
StudyInstanceUID,
madeInClient,
})
study.series.forEach((aSeries) => {
const { SeriesInstanceUID } = aSeries
aSeries.instances.forEach((instance) => {
const {
url: imageId,
StudyInstanceUID,
SeriesInstanceUID,
SOPInstanceUID,
} = instance
// Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
metadataProvider.addImageIdToUIDs(imageId, {
StudyInstanceUID,
SeriesInstanceUID,
SOPInstanceUID,
})
})
DicomMetadataStore._broadcastEvent(EVENTS.INSTANCES_ADDED, {
StudyInstanceUID,
SeriesInstanceUID,
madeInClient,
})
})
},
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 = this.getImageIdsForInstance({
instance,
frame: i,
})
imageIds.push(imageId)
}
} else {
const imageId = this.getImageIdsForInstance({ instance })
imageIds.push(imageId)
}
})
return imageIds
},
getImageIdsForInstance({ instance, frame }) {
const { StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID } = instance
const storedInstance = DicomMetadataStore.getInstance(StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID)
if (storedInstance.url) {
return storedInstance.url
}
},
deleteStudyMetadataPromise() {
console.log("deleteStudyMetadataPromise not implemented")
}
}
return IWebApiDataSource.create(implementation)
}
export { createDicomLocalApi }
@@ -63,7 +63,7 @@ function createDicomWebApi(dicomWebConfig) {
const wadoDicomWebClient = new api.DICOMwebClient(wadoConfig);
const implementation = {
parseRouteParams: ({ params, query }) => {
initialize: ({ params, query }) => {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = query.get('StudyInstanceUIDs');
@@ -78,7 +78,7 @@ function createDicomWebApi(dicomWebConfig) {
query: {
studies: {
mapParams: mapParams.bind(),
search: async function(origParams) {
search: async function (origParams) {
const { studyInstanceUid, seriesInstanceUid, ...mappedParams } =
mapParams(origParams, {
supportsFuzzyMatching,
@@ -98,7 +98,7 @@ function createDicomWebApi(dicomWebConfig) {
},
series: {
// mapParams: mapParams.bind(),
search: async function(studyInstanceUid) {
search: async function (studyInstanceUid) {
const results = await seriesInStudy(
qidoDicomWebClient,
studyInstanceUid
@@ -4,6 +4,7 @@
import { createDicomWebApi } from './DicomWebDataSource/index.js';
import { createDicomJSONApi } from './DicomJSONDataSource/index.js';
import { createDicomLocalApi } from './DicomLocalDataSource/index.js';
/**
*
@@ -20,6 +21,11 @@ function getDataSourcesModule() {
type: 'jsonApi',
createDataSource: createDicomJSONApi,
},
{
name: 'dicomlocal',
type: 'localApi',
createDataSource: createDicomLocalApi,
},
];
}