161 lines
4.6 KiB
JavaScript
161 lines
4.6 KiB
JavaScript
import dcmjs from 'dcmjs';
|
|
import { sortStudySeries } from '@ohif/core/src/utils/sortStudy';
|
|
import RetrieveMetadataLoader from './retrieveMetadataLoader';
|
|
|
|
// Series Date, Series Time, Series Description and Series Number to be included
|
|
// in the series metadata query result
|
|
const includeField = ['00080021', '00080031', '0008103E', '00200011'].join(',');
|
|
|
|
export class DeferredPromise {
|
|
metadata = undefined;
|
|
processFunction = undefined;
|
|
internalPromise = undefined;
|
|
thenFunction = undefined;
|
|
rejectFunction = undefined;
|
|
|
|
setMetadata(metadata) {
|
|
this.metadata = metadata;
|
|
}
|
|
setProcessFunction(func) {
|
|
this.processFunction = func;
|
|
}
|
|
getPromise() {
|
|
return this.start();
|
|
}
|
|
start() {
|
|
if (this.internalPromise) {
|
|
return this.internalPromise;
|
|
}
|
|
this.internalPromise = this.processFunction();
|
|
// in case then and reject functions called before start
|
|
if (this.thenFunction) {
|
|
this.then(this.thenFunction);
|
|
this.thenFunction = undefined;
|
|
}
|
|
if (this.rejectFunction) {
|
|
this.reject(this.rejectFunction);
|
|
this.rejectFunction = undefined;
|
|
}
|
|
return this.internalPromise;
|
|
}
|
|
then(func) {
|
|
if (this.internalPromise) {
|
|
return this.internalPromise.then(func);
|
|
} else {
|
|
this.thenFunction = func;
|
|
}
|
|
}
|
|
reject(func) {
|
|
if (this.internalPromise) {
|
|
return this.internalPromise.reject(func);
|
|
} else {
|
|
this.rejectFunction = func;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Creates an immutable series loader object which loads each series sequentially using the iterator interface.
|
|
*
|
|
* @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load
|
|
* @param {string} studyInstanceUID The Study Instance UID from which series will be loaded
|
|
* @param {Array} seriesInstanceUIDList A list of Series Instance UIDs
|
|
*
|
|
* @returns {Object} Returns an object which supports loading of instances from each of given Series Instance UID
|
|
*/
|
|
function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList) {
|
|
return Object.freeze({
|
|
hasNext() {
|
|
return seriesInstanceUIDList.length > 0;
|
|
},
|
|
next() {
|
|
const { seriesInstanceUID, metadata } = seriesInstanceUIDList.shift();
|
|
const promise = new DeferredPromise();
|
|
promise.setMetadata(metadata);
|
|
promise.setProcessFunction(() => {
|
|
return client.retrieveSeriesMetadata({
|
|
studyInstanceUID,
|
|
seriesInstanceUID,
|
|
});
|
|
});
|
|
return promise;
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Class for async load of study metadata.
|
|
* It inherits from RetrieveMetadataLoader
|
|
*
|
|
* It loads the one series and then append to seriesLoader the others to be consumed/loaded
|
|
*/
|
|
export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader {
|
|
/**
|
|
* @returns {Array} Array of preLoaders. To be consumed as queue
|
|
*/
|
|
*getPreLoaders() {
|
|
const preLoaders = [];
|
|
const { studyInstanceUID, filters: { seriesInstanceUID } = {}, client } = this;
|
|
|
|
// asking to include Series Date, Series Time, Series Description
|
|
// and Series Number in the series metadata returned to better sort series
|
|
// in preLoad function
|
|
let options = {
|
|
studyInstanceUID,
|
|
queryParams: {
|
|
includefield: includeField,
|
|
},
|
|
};
|
|
|
|
if (seriesInstanceUID) {
|
|
options.queryParams.SeriesInstanceUID = seriesInstanceUID;
|
|
preLoaders.push(client.searchForSeries.bind(client, options));
|
|
}
|
|
// Fallback preloader
|
|
preLoaders.push(client.searchForSeries.bind(client, options));
|
|
|
|
yield* preLoaders;
|
|
}
|
|
|
|
async preLoad() {
|
|
const preLoaders = this.getPreLoaders();
|
|
const result = await this.runLoaders(preLoaders);
|
|
console.log('Raw QIDO series result:', result); // Debug: Check if '0008103E' is present
|
|
const sortCriteria = this.sortCriteria;
|
|
const sortFunction = this.sortFunction;
|
|
|
|
const { naturalizeDataset } = dcmjs.data.DicomMetaDictionary;
|
|
const naturalized = result.map(naturalizeDataset);
|
|
|
|
return sortStudySeries(naturalized, sortCriteria, sortFunction);
|
|
}
|
|
|
|
async load(preLoadData) {
|
|
const { client, studyInstanceUID } = this;
|
|
|
|
const seriesInstanceUIDs = preLoadData.map(seriesMetadata => {
|
|
return { seriesInstanceUID: seriesMetadata.SeriesInstanceUID, metadata: seriesMetadata };
|
|
});
|
|
|
|
const seriesAsyncLoader = makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDs);
|
|
|
|
const promises = [];
|
|
|
|
while (seriesAsyncLoader.hasNext()) {
|
|
const promise = seriesAsyncLoader.next();
|
|
promises.push(promise);
|
|
}
|
|
|
|
return {
|
|
preLoadData,
|
|
promises,
|
|
};
|
|
}
|
|
|
|
async posLoad({ preLoadData, promises }) {
|
|
return {
|
|
preLoadData,
|
|
promises,
|
|
};
|
|
}
|
|
}
|