feat: Add Static WADO display (#2499)

* Rebased to have just the static view changes

* Changes based on the PR

* Couple more changes for the PR

* Removed an extraneous log

* Fix the study worklist display when returning to the page

* Added some documentation on the static wado data source setup, and a
bounds check change on the Queue test which was failing

* PR updates - change the undefined study description to '' and remove the aws deploy

* Fixed the e2e tests to actually pass/fail correctly on actual results
This commit is contained in:
Bill Wallace authored and Alireza committed 2021-08-24 17:53:03 -04:00
1 parent ca900f80e1
commit 2327b4ae12
21 files changed
+483 -41

No files matched your search

@@ -15,6 +15,7 @@ import {
retrieveStudyMetadata,
deleteStudyMetadataPromise,
} from './retrieveStudyMetadata.js';
import StaticWadoClient from './utils/StaticWadoClient.js';
const { DicomMetaDictionary, DicomDict } = dcmjs.data;
@@ -46,14 +47,14 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) {
supportsFuzzyMatching,
supportsWildcard,
supportsReject,
requestOptions,
staticWado,
} = dicomWebConfig;
const qidoConfig = {
url: qidoRoot,
staticWado,
headers: UserAuthenticationService.getAuthorizationHeader(),
errorInterceptor: errorHandler.getHTTPErrorHandler(),
};
const wadoConfig = {
@@ -64,7 +65,7 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) {
// TODO -> Two clients sucks, but its better than 1000.
// TODO -> We'll need to merge auth later.
const qidoDicomWebClient = new api.DICOMwebClient(qidoConfig);
const qidoDicomWebClient = staticWado ? new StaticWadoClient(qidoConfig) : new api.DICOMwebClient(wadoConfig);
const wadoDicomWebClient = new api.DICOMwebClient(wadoConfig);
const implementation = {
@@ -83,7 +84,7 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) {
query: {
studies: {
mapParams: mapParams.bind(),
search: async function(origParams) {
search: async function (origParams) {
const headers = UserAuthenticationService.getAuthorizationHeader();
if (headers) {
qidoDicomWebClient.headers = headers;
@@ -108,7 +109,7 @@ function createDicomWebApi(dicomWebConfig, UserAuthenticationService) {
},
series: {
// mapParams: mapParams.bind(),
search: async function(studyInstanceUid) {
search: async function (studyInstanceUid) {
const headers = UserAuthenticationService.getAuthorizationHeader();
if (headers) {
qidoDicomWebClient.headers = headers;
@@ -0,0 +1,49 @@
import { api } from 'dicomweb-client';
/**
* An implementation of the static wado client, that fetches data from
* a static response rather than actually doing real queries. This allows
* fast encoding of test data, but because it is static, anything actually
* performing searches doesn't work. This version fixes the query issue
* by manually implementing a query option.
*/
export default class StaticWadoClient extends api.DICOMwebClient {
static filterKeys = {
"StudyInstanceUID": "0020000D",
"PatientName": "00100010",
"00100020": "mrn",
"StudyDescription": "00081030",
"ModalitiesInStudy": "00080061",
};
constructor(qidoConfig) {
super(qidoConfig);
this.staticWado = qidoConfig.staticWado;
}
async searchForStudies(options) {
if (!this.staticWado) return super.searchForStudies(options);
let searchResult = await super.searchForStudies(options);
const { queryParams } = options;
if (!queryParams) return searchResult;
const filtered = searchResult.filter(study => {
for (const key of Object.keys(StaticWadoClient.filterKeys)) {
if (!this.filterItem(key, queryParams, study)) return false;
}
return true;
});
return filtered;
}
filterItem(key, queryParams, study) {
const altKey = StaticWadoClient.filterKeys[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;
const value = valueElem.Value;
return value === testValue || (value.indexOf && value.indexOf(testValue) >= 0);
}
}
@@ -6,7 +6,7 @@ function buildInstanceWadoRsUri(instance, config) {
function buildInstanceFrameWadoRsUri(instance, config, frame) {
const baseWadoRsUri = buildInstanceWadoRsUri(instance, config);
frame = frame != null || 1;
frame = frame || 1;
return `${baseWadoRsUri}/frames/${frame}`;
}
@@ -165,11 +165,11 @@ function PanelStudyBrowser({
);
const updatedExpandedStudyInstanceUIDs = shouldCollapseStudy
? // eslint-disable-next-line prettier/prettier
[
...expandedStudyInstanceUIDs.filter(
stdyUid => stdyUid !== StudyInstanceUID
),
]
[
...expandedStudyInstanceUIDs.filter(
stdyUid => stdyUid !== StudyInstanceUID
),
]
: [...expandedStudyInstanceUIDs, StudyInstanceUID];
setExpandedStudyInstanceUIDs(updatedExpandedStudyInstanceUIDs);
@@ -247,7 +247,7 @@ function _mapDisplaySets(displaySets, thumbnailImageSrcMap) {
array.push({
displaySetInstanceUID: ds.displaySetInstanceUID,
description: ds.SeriesDescription,
description: ds.SeriesDescription || '',
seriesNumber: ds.SeriesNumber,
modality: ds.Modality,
seriesDate: ds.SeriesDate,
@@ -20,9 +20,9 @@ const makeDisplaySet = instances => {
SeriesTime: instance.SeriesTime,
SeriesInstanceUID: instance.SeriesInstanceUID,
StudyInstanceUID: instance.StudyInstanceUID,
SeriesNumber: instance.SeriesNumber,
SeriesNumber: instance.SeriesNumber || 0,
FrameRate: instance.FrameTime,
SeriesDescription: instance.SeriesDescription,
SeriesDescription: instance.SeriesDescription || '',
Modality: instance.Modality,
isMultiFrame: isMultiFrame(instance),
numImageFrames: instances.length,