diff --git a/extensions/default/src/DicomWebDataSource/index.js b/extensions/default/src/DicomWebDataSource/index.js index c3fcd3bb9..1db6782ee 100644 --- a/extensions/default/src/DicomWebDataSource/index.js +++ b/extensions/default/src/DicomWebDataSource/index.js @@ -70,6 +70,7 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) { const wadoConfig = { url: wadoRoot, + staticWado, singlepart, headers: UserAuthenticationService.getAuthorizationHeader(), errorInterceptor: errorHandler.getHTTPErrorHandler(), @@ -80,7 +81,10 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) { const qidoDicomWebClient = staticWado ? new StaticWadoClient(qidoConfig) : new api.DICOMwebClient(qidoConfig); - const wadoDicomWebClient = new api.DICOMwebClient(wadoConfig); + + const wadoDicomWebClient = staticWado + ? new StaticWadoClient(wadoConfig) + : new api.DICOMwebClient(wadoConfig); const implementation = { initialize: ({ params, query }) => { diff --git a/extensions/default/src/DicomWebDataSource/qido.js b/extensions/default/src/DicomWebDataSource/qido.js index 263c61d8a..2ac8b1fcf 100644 --- a/extensions/default/src/DicomWebDataSource/qido.js +++ b/extensions/default/src/DicomWebDataSource/qido.js @@ -171,7 +171,7 @@ function mapParams(params, options = {}) { // Named PatientName: withWildcard(params.patientName), //PatientID: withWildcard(params.patientId), - "00100020": withWildcard(params.patientId), // Temporarily to make the tests pass with dicomweb-server.. Apparently it's broken? + '00100020': withWildcard(params.patientId), // Temporarily to make the tests pass with dicomweb-server.. Apparently it's broken? AccessionNumber: withWildcard(params.accessionNumber), StudyDescription: withWildcard(params.studyDescription), ModalitiesInStudy: params.modalitiesInStudy, diff --git a/extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.js b/extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.js index d250ecacc..99eb556c4 100644 --- a/extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.js +++ b/extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.js @@ -8,14 +8,19 @@ import { api } from 'dicomweb-client'; * by manually implementing a query option. */ export default class StaticWadoClient extends api.DICOMwebClient { - static filterKeys = { - "StudyInstanceUID": "0020000D", - "PatientName": "00100010", - "00100020": "mrn", - "StudyDescription": "00081030", - "StudyDate": "00080020", - "ModalitiesInStudy": "00080061", - AccessionNumber: "00080050", + static studyFilterKeys = { + StudyInstanceUID: '0020000D', + PatientName: '00100010', + '00100020': 'mrn', + StudyDescription: '00081030', + StudyDate: '00080020', + ModalitiesInStudy: '00080061', + AccessionNumber: '00080050', + }; + + static seriesFilterKeys = { + SeriesInstanceUID: '0020000E', + SeriesNumber: '00200011', }; constructor(qidoConfig) { @@ -36,7 +41,7 @@ export default class StaticWadoClient extends api.DICOMwebClient { const { queryParams } = options; if (!queryParams) return searchResult; const filtered = searchResult.filter(study => { - for (const key of Object.keys(StaticWadoClient.filterKeys)) { + for (const key of Object.keys(StaticWadoClient.studyFilterKeys)) { if (!this.filterItem(key, queryParams, study)) return false; } return true; @@ -44,6 +49,22 @@ export default class StaticWadoClient extends api.DICOMwebClient { return filtered; } + async searchForSeries(options) { + if (!this.staticWado) return super.searchForSeries(options); + + let searchResult = await super.searchForSeries(options); + const { queryParams } = options; + if (!queryParams) return searchResult; + const filtered = searchResult.filter(study => { + for (const key of Object.keys(StaticWadoClient.studyFilterKeys)) { + if (!this.filterItem(key, queryParams, study)) return false; + } + return true; + }); + + return filtered; + } + /** * Compares values, matching any instance of desired to any instance of * actual by recursively go through the paired set of values. That is, @@ -66,7 +87,7 @@ export default class StaticWadoClient extends api.DICOMwebClient { if (actual?.Alphabetic) { actual = actual.Alphabetic; } - if (typeof (actual) == 'string') { + if (typeof actual == 'string') { if (actual.length === 0) return true; if (desired.length === 0 || desired === '*') return true; if (desired[0] === '*' && desired[desired.length - 1] === '*') { @@ -75,7 +96,10 @@ export default class StaticWadoClient extends api.DICOMwebClient { } else if (desired[desired.length - 1] === '*') { return actual.indexOf(desired.substring(0, desired.length - 1)) != -1; } else if (desired[0] === '*') { - return actual.indexOf(desired.substring(1)) === actual.length - desired.length + 1; + return ( + actual.indexOf(desired.substring(1)) === + actual.length - desired.length + 1 + ); } } return desired === actual; @@ -88,8 +112,7 @@ export default class StaticWadoClient extends api.DICOMwebClient { if (dash === -1) return this.compareValues(range, value); const start = range.substring(0, dash); const end = range.substring(dash + 1); - return (!start || value >= start) && - (!end || value <= end); + return (!start || value >= start) && (!end || value <= end); } /** @@ -101,13 +124,15 @@ export default class StaticWadoClient extends api.DICOMwebClient { * @returns */ filterItem(key, queryParams, study) { - const altKey = StaticWadoClient.filterKeys[key] || key; + const altKey = StaticWadoClient.studyFilterKeys[key] || key; if (!queryParams) return true; const testValue = queryParams[key] || queryParams[altKey]; if (!testValue) return true; const valueElem = study[key] || study[altKey]; if (!valueElem) return false; - if (valueElem.vr == 'DA') return this.compareDateRange(testValue, valueElem.Value[0]); + if (valueElem.vr == 'DA') { + return this.compareDateRange(testValue, valueElem.Value[0]); + } const value = valueElem.Value; return this.compareValues(testValue, value) && true; } diff --git a/platform/viewer/src/routes/Mode/Mode.tsx b/platform/viewer/src/routes/Mode/Mode.tsx index 3c772939b..f7159fc53 100644 --- a/platform/viewer/src/routes/Mode/Mode.tsx +++ b/platform/viewer/src/routes/Mode/Mode.tsx @@ -15,10 +15,11 @@ import Compose from './Compose'; * @param props.servicesManager to read services from * @param props.studyInstanceUIDs for a list of studies to read * @param props.dataSource to read the data from + * @param props.filters filters from query params to read the data from * @returns array of subscriptions to cancel */ function defaultRouteInit( - { servicesManager, studyInstanceUIDs, dataSource }, + { servicesManager, studyInstanceUIDs, dataSource, filters }, hangingProtocol ) { const { @@ -44,7 +45,10 @@ function defaultRouteInit( unsubscriptions.push(instanceAddedUnsubscribe); const allRetrieves = studyInstanceUIDs.map(StudyInstanceUID => - dataSource.retrieve.series.metadata({ StudyInstanceUID }) + dataSource.retrieve.series.metadata({ + StudyInstanceUID, + filters, + }) ); // The hanging protocol matching service is fairly expensive to run multiple @@ -230,6 +234,7 @@ export default function ModeRoute({ if (!layoutTemplateData.current) { return; } + // TODO: For some reason this is running before the Providers // are calling setServiceImplementation // TODO -> iterate through services. @@ -250,8 +255,32 @@ export default function ModeRoute({ hangingProtocolService.setActiveProtocols(hangingProtocol); mode?.onModeEnter({ servicesManager, extensionManager, commandsManager }); - const setupRouteInit = async () => { + /** + * The next line should get all the query parameters provided by the URL + * - except the StudyInstaceUIDs - and create an object called filters + * used to filtering the study as the user wants otherwise it will return + * a empty object. + * + * Example: + * const filters = { + * seriesInstaceUID: 1.2.276.0.7230010.3.1.3.1791068887.5412.1620253993.114611 + * } + */ + const filters = + Array.from(query.keys()).reduce( + (acc: Record, val: string) => { + if (val !== 'StudyInstanceUIDs') { + if (['seriesInstanceUID', 'SeriesInstanceUID'].includes(val)) { + return { ...acc, seriesInstanceUID: query.get(val) }; + } + + return { ...acc, [val]: query.get(val) }; + } + }, + {} + ) ?? {}; + if (route.init) { return await route.init( { @@ -260,6 +289,7 @@ export default function ModeRoute({ hotkeysManager, studyInstanceUIDs, dataSource, + filters, }, hangingProtocol ); @@ -270,6 +300,7 @@ export default function ModeRoute({ servicesManager, studyInstanceUIDs, dataSource, + filters, }, hangingProtocol );