Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(DataSource): Allow for dynamic data source configuration and creation #3543

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 14 additions & 16 deletions extensions/default/src/DicomJSONDataSource/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const mappings = {
patientId: 'PatientID',
};

let _data;
jbocce marked this conversation as resolved.
Show resolved Hide resolved
let _store = {
urls: [],
// {
Expand Down Expand Up @@ -41,10 +42,10 @@ const findStudies = (key, value) => {
};

function createDicomJSONApi(dicomJsonConfig) {
const { name, wadoRoot } = dicomJsonConfig;
const { wadoRoot } = dicomJsonConfig;

const implementation = {
initialize: async ({ params, query, url }) => {
initialize: async ({ query, url }) => {
if (!url) url = query.get('url');
let metaData = getMetaDataByURL(url);

Expand All @@ -58,15 +59,11 @@ function createDicomJSONApi(dicomJsonConfig) {
}

const response = await fetch(url);
let data = await response.json();

const studyInstanceUIDs = data.studies.map(
study => study.StudyInstanceUID
);
_data = await response.json();

let StudyInstanceUID;
let SeriesInstanceUID;
data.studies.forEach(study => {
_data.studies.forEach(study => {
StudyInstanceUID = study.StudyInstanceUID;

study.series.forEach(series => {
Expand All @@ -87,14 +84,12 @@ function createDicomJSONApi(dicomJsonConfig) {

_store.urls.push({
url,
studies: [...data.studies],
studies: [..._data.studies],
});

return studyInstanceUIDs;
},
query: {
studies: {
mapParams: () => { },
mapParams: () => {},
search: async param => {
const [key, value] = Object.entries(param)[0];
const mappedParam = mappings[key];
Expand Down Expand Up @@ -252,12 +247,15 @@ function createDicomJSONApi(dicomJsonConfig) {
return imageIds;
},
getImageIdsForInstance({ instance, frame }) {
const imageIds = getImageId({
instance,
frame,
});
const imageIds = getImageId({ instance, frame });
return imageIds;
},
getStudyInstanceUIDs: ({ params, query }) => {
const studyInstanceUIDs = _data.studies.map(
study => study.StudyInstanceUID
);
return studyInstanceUIDs;
},
};
return IWebApiDataSource.create(implementation);
}
Expand Down
43 changes: 24 additions & 19 deletions extensions/default/src/DicomLocalDataSource/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,7 @@ function createDicomLocalApi(dicomLocalConfig) {
const { name } = dicomLocalConfig;

const implementation = {
initialize: ({ params, query }) => {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = query.getAll('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;
},
initialize: ({ params, query }) => {},
query: {
studies: {
mapParams: () => {},
Expand Down Expand Up @@ -246,6 +228,29 @@ function createDicomLocalApi(dicomLocalConfig) {
deleteStudyMetadataPromise() {
console.log('deleteStudyMetadataPromise not implemented');
},
getStudyInstanceUIDs: ({ params, query }) => {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = query.getAll('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
let isStudyInCache = false;
StudyInstanceUIDsAsArray.forEach(StudyInstanceUID => {
const study = DicomMetadataStore.getStudy(StudyInstanceUID);
if (study) {
study.series = study.series.sort(customSort);
isStudyInCache = true;
}
});

return isStudyInCache ? StudyInstanceUIDsAsArray : [];
},
};
return IWebApiDataSource.create(implementation);
}
Expand Down
172 changes: 92 additions & 80 deletions extensions/default/src/DicomWebDataSource/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,87 +51,77 @@ const metadataProvider = classes.MetadataProvider;
* @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true
*/
function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
const {
qidoRoot,
wadoRoot,
enableStudyLazyLoad,
supportsFuzzyMatching,
supportsWildcard,
supportsReject,
staticWado,
singlepart,
omitQuotationForMultipartRequest,
acceptHeader,
requestTransferSyntaxUID,
} = dicomWebConfig;

const dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));

const getAuthrorizationHeader = () => {
const xhrRequestHeaders = {};
const authHeaders = userAuthenticationService.getAuthorizationHeader();
if (authHeaders && authHeaders.Authorization) {
xhrRequestHeaders.Authorization = authHeaders.Authorization;
}
return xhrRequestHeaders;
};
let dicomWebConfigCopy,
qidoConfig,
wadoConfig,
qidoDicomWebClient,
wadoDicomWebClient,
getAuthrorizationHeader,
generateWadoHeader;

const generateWadoHeader = () => {
let authorizationHeader = getAuthrorizationHeader();
//Generate accept header depending on config params
let formattedAcceptHeader = utils.generateAcceptHeader(
acceptHeader,
requestTransferSyntaxUID,
omitQuotationForMultipartRequest
);

return {
...authorizationHeader,
Accept: formattedAcceptHeader,
};
};
const implementation = {
initialize: ({ params, query }) => {
if (
dicomWebConfig.onConfiguration &&
typeof dicomWebConfig.onConfiguration === 'function'
) {
dicomWebConfig = dicomWebConfig.onConfiguration(dicomWebConfig, {
params,
query,
});
}

const qidoConfig = {
url: qidoRoot,
staticWado,
singlepart,
headers: getAuthrorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};
dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));

const wadoConfig = {
url: wadoRoot,
staticWado,
singlepart,
headers: generateWadoHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};
getAuthrorizationHeader = () => {
const xhrRequestHeaders = {};
const authHeaders = userAuthenticationService.getAuthorizationHeader();
if (authHeaders && authHeaders.Authorization) {
xhrRequestHeaders.Authorization = authHeaders.Authorization;
}
return xhrRequestHeaders;
};

// TODO -> Two clients sucks, but its better than 1000.
// TODO -> We'll need to merge auth later.
const qidoDicomWebClient = staticWado
? new StaticWadoClient(qidoConfig)
: new api.DICOMwebClient(qidoConfig);
generateWadoHeader = () => {
let authorizationHeader = getAuthrorizationHeader();
//Generate accept header depending on config params
let formattedAcceptHeader = utils.generateAcceptHeader(
dicomWebConfig.acceptHeader,
dicomWebConfig.requestTransferSyntaxUID,
dicomWebConfig.omitQuotationForMultipartRequest
);

const wadoDicomWebClient = staticWado
? new StaticWadoClient(wadoConfig)
: new api.DICOMwebClient(wadoConfig);
return {
...authorizationHeader,
Accept: formattedAcceptHeader,
};
};

const implementation = {
initialize: ({ params, query }) => {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = utils.splitComma(
query.getAll('StudyInstanceUIDs')
);
qidoConfig = {
url: dicomWebConfig.qidoRoot,
staticWado: dicomWebConfig.staticWado,
singlepart: dicomWebConfig.singlepart,
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};

const StudyInstanceUIDs =
(queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) ||
paramsStudyInstanceUIDs;
const StudyInstanceUIDsAsArray =
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
? StudyInstanceUIDs
: [StudyInstanceUIDs];
return StudyInstanceUIDsAsArray;
wadoConfig = {
url: dicomWebConfig.wadoRoot,
staticWado: dicomWebConfig.staticWado,
singlepart: dicomWebConfig.singlepart,
headers: userAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};

// TODO -> Two clients sucks, but its better than 1000.
// TODO -> We'll need to merge auth later.
qidoDicomWebClient = dicomWebConfig.staticWado
? new StaticWadoClient(qidoConfig)
: new api.DICOMwebClient(qidoConfig);

wadoDicomWebClient = dicomWebConfig.staticWado
? new StaticWadoClient(wadoConfig)
: new api.DICOMwebClient(wadoConfig);
},
query: {
studies: {
Expand All @@ -140,8 +130,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
qidoDicomWebClient.headers = getAuthrorizationHeader();
const { studyInstanceUid, seriesInstanceUid, ...mappedParams } =
mapParams(origParams, {
supportsFuzzyMatching,
supportsWildcard,
supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching,
supportsWildcard: dicomWebConfig.supportsWildcard,
}) || {};

const results = await qidoSearch(
Expand Down Expand Up @@ -194,7 +184,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
* or is already retrieved, or a promise to a URL for such use if a BulkDataURI
*/
directURL: params => {
return getDirectURL({ wadoRoot, singlepart }, params);
return getDirectURL(
{
wadoRoot: dicomWebConfig.wadoRoot,
singlepart: dicomWebConfig.singlepart,
},
params
);
},
bulkDataURI: async ({ StudyInstanceUID, BulkDataURI }) => {
qidoDicomWebClient.headers = getAuthrorizationHeader();
Expand Down Expand Up @@ -222,7 +218,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
);
}

if (enableStudyLazyLoad) {
if (dicomWebConfig.enableStudyLazyLoad) {
return implementation._retrieveSeriesMetadataAsync(
StudyInstanceUID,
filters,
Expand Down Expand Up @@ -522,10 +518,26 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
getConfig() {
return dicomWebConfigCopy;
},
getStudyInstanceUIDs({ params, query }) {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = utils.splitComma(
query.getAll('StudyInstanceUIDs')
);

const StudyInstanceUIDs =
(queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) ||
paramsStudyInstanceUIDs;
const StudyInstanceUIDsAsArray =
StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs)
? StudyInstanceUIDs
: [StudyInstanceUIDs];

return StudyInstanceUIDsAsArray;
},
};

if (supportsReject) {
implementation.reject = dcm4cheeReject(wadoRoot);
if (dicomWebConfig.supportsReject) {
implementation.reject = dcm4cheeReject(dicomWebConfig.wadoRoot);
}

return IWebApiDataSource.create(implementation);
Expand Down
26 changes: 14 additions & 12 deletions extensions/default/src/DicomWebProxyDataSource/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ function createDicomWebProxyApi(

const implementation = {
initialize: async ({ params, query }) => {
let studyInstanceUIDs = [];

// there seem to be a couple of variations of the case for this parameter
const queryStudyInstanceUIDs =
query.get('studyInstanceUIDs') || query.get('studyInstanceUids');
if (!queryStudyInstanceUIDs) {
throw new Error(`No studyInstanceUids in request for '${name}'`);
}

const url = query.get('url');

if (!url) {
Expand All @@ -39,12 +30,11 @@ function createDicomWebProxyApi(
}

dicomWebDelegate = createDicomWebApi(
data.servers.dicomWeb[0],
data.servers.dicomWeb[0].configuration,
UserAuthenticationService
);
studyInstanceUIDs = queryStudyInstanceUIDs.split(';');
dicomWebDelegate.initialize({ params, query });
}
return studyInstanceUIDs;
},
query: {
studies: {
Expand Down Expand Up @@ -77,6 +67,18 @@ function createDicomWebProxyApi(
dicomWebDelegate.getImageIdsForDisplaySet(...args),
getImageIdsForInstance: (...args) =>
dicomWebDelegate.getImageIdsForInstance(...args),
getStudyInstanceUIDs({ params, query }) {
let studyInstanceUIDs = [];

// there seem to be a couple of variations of the case for this parameter
const queryStudyInstanceUIDs =
query.get('studyInstanceUIDs') || query.get('studyInstanceUids');
if (!queryStudyInstanceUIDs) {
throw new Error(`No studyInstanceUids in request for '${name}'`);
}
studyInstanceUIDs = queryStudyInstanceUIDs.split(';');
return studyInstanceUIDs;
},
};
return IWebApiDataSource.create(implementation);
}
Expand Down
Loading