feat(URL): add param for initial series and sop uids to display (#3265)

* feat: Allow navigating to a specified series and sop instance

This was a feature in OHIF v2, so adding it to v3, albeit with new
parameters.

feat: Allow comma separated as well as repeated args params

* docs

* Test fixes

* feat: Navigate to SOP selected - PR fixes

* Updated docs

* PR fixes
This commit is contained in:
Bill Wallace authored and GitHub committed 2023-04-05 12:59:56 -04:00
1 parent 226244a26c
commit 50ed96ff73
16 files changed
+284 -47

No files matched your search

@@ -22,8 +22,8 @@ import {
retrieveStudyMetadata,
deleteStudyMetadataPromise,
} from './retrieveStudyMetadata.js';
import StaticWadoClient from './utils/StaticWadoClient.js';
import getDirectURL from '../utils/getDirectURL.js';
import StaticWadoClient from './utils/StaticWadoClient';
import getDirectURL from '../utils/getDirectURL';
const { DicomMetaDictionary, DicomDict } = dcmjs.data;
@@ -90,7 +90,9 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
const implementation = {
initialize: ({ params, query }) => {
const { StudyInstanceUIDs: paramsStudyInstanceUIDs } = params;
const queryStudyInstanceUIDs = query.getAll('StudyInstanceUIDs');
const queryStudyInstanceUIDs = utils.splitComma(
query.getAll('StudyInstanceUIDs')
);
const StudyInstanceUIDs =
(queryStudyInstanceUIDs.length && queryStudyInstanceUIDs) ||
@@ -9,18 +9,19 @@ import { api } from 'dicomweb-client';
*/
export default class StaticWadoClient extends api.DICOMwebClient {
static studyFilterKeys = {
StudyInstanceUID: '0020000D',
PatientName: '00100010',
studyinstanceuid: '0020000D',
patientname: '00100010',
'00100020': 'mrn',
StudyDescription: '00081030',
StudyDate: '00080020',
ModalitiesInStudy: '00080061',
AccessionNumber: '00080050',
studydescription: '00081030',
studydate: '00080020',
modalitiesinstudy: '00080061',
accessionnumber: '00080050',
};
static seriesFilterKeys = {
SeriesInstanceUID: '0020000E',
SeriesNumber: '00200011',
seriesinstanceuid: '0020000E',
seriesnumber: '00200011',
modality: '00080060',
};
constructor(qidoConfig) {
@@ -37,15 +38,18 @@ export default class StaticWadoClient extends api.DICOMwebClient {
async searchForStudies(options) {
if (!this.staticWado) return super.searchForStudies(options);
let searchResult = await super.searchForStudies(options);
const searchResult = await super.searchForStudies(options);
const { queryParams } = options;
if (!queryParams) return searchResult;
const lowerParams = this.toLowerParams(queryParams);
const filtered = searchResult.filter(study => {
for (const key of Object.keys(StaticWadoClient.studyFilterKeys)) {
if (
!this.filterItem(
key,
queryParams,
lowerParams,
study,
StaticWadoClient.studyFilterKeys
)
@@ -61,16 +65,18 @@ export default class StaticWadoClient extends api.DICOMwebClient {
async searchForSeries(options) {
if (!this.staticWado) return super.searchForSeries(options);
let searchResult = await super.searchForSeries(options);
const searchResult = await super.searchForSeries(options);
const { queryParams } = options;
if (!queryParams) return searchResult;
const filtered = searchResult.filter(study => {
const lowerParams = this.toLowerParams(queryParams);
const filtered = searchResult.filter(series => {
for (const key of Object.keys(StaticWadoClient.seriesFilterKeys)) {
if (
!this.filterItem(
key,
queryParams,
study,
lowerParams,
series,
StaticWadoClient.seriesFilterKeys
)
) {
@@ -136,13 +142,13 @@ export default class StaticWadoClient extends api.DICOMwebClient {
/**
* Filters the return list by the query parameters.
*
* @param {*} key
* @param {*} queryParams
* @param anyCaseKey - a possible search key
* @param queryParams -
* @param {*} study
* @param {*} sourceFilterMap
* @returns
*/
filterItem(key, queryParams, study, sourceFilterMap) {
filterItem(key: string, queryParams, study, sourceFilterMap) {
const altKey = sourceFilterMap[key] || key;
if (!queryParams) return true;
const testValue = queryParams[key] || queryParams[altKey];
@@ -153,6 +159,15 @@ export default class StaticWadoClient extends api.DICOMwebClient {
return this.compareDateRange(testValue, valueElem.Value[0]);
}
const value = valueElem.Value;
return this.compareValues(testValue, value) && true;
return this.compareValues(testValue, value);
}
/** Converts the query parameters to lower case query parameters */
toLowerParams(queryParams: Record<string, unknown>): Record<string, unknown> {
const lowerParams = {};
Object.entries(queryParams).forEach(([key, value]) => {
lowerParams[key.toLowerCase()] = value;
});
return lowerParams;
}
}
@@ -7,7 +7,7 @@ const defaultProtocol = {
hasUpdatedPriorsInformation: false,
name: 'Default',
createdDate: '2021-02-23T19:22:08.894Z',
modifiedDate: '2021-02-23T19:22:08.894Z',
modifiedDate: '2023-04-01',
availableTo: {},
editableBy: {},
protocolMatchingRules: [],
@@ -33,8 +33,6 @@ const defaultProtocol = {
},
displaySetSelectors: {
defaultDisplaySetId: {
// Unused currently
imageMatchingRules: [],
// Matches displaysets, NOT series
seriesMatchingRules: [
// Try to match series with images by default, to prevent weird display
@@ -45,6 +43,15 @@ const defaultProtocol = {
greaterThan: { value: 0 },
},
},
// This display set will select the specified items by preference
// It has no affect if nothing is specified in the URL.
{
attribute: 'isDisplaySetFromUrl',
weight: 10,
constraint: {
equals: true,
},
},
],
// Can be used to select matching studies
// studyMatchingRules: [],
@@ -65,7 +72,13 @@ const defaultProtocol = {
viewportOptions: {
viewportType: 'stack',
toolGroupId: 'default',
// initialImageOptions: {
// This will specify the initial image options index if it matches in the URL
// and will otherwise not specify anything.
initialImageOptions: {
custom: 'sopInstanceLocation',
},
// Other options for initialImageOptions, which can be included in the default
// custom attribute, or can be provided directly.
// index: 180,
// preset: 'middle', // 'first', 'last', 'middle'
// },