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(url): Add SeriesInstanceUIDs wado query param #3746

Merged
merged 7 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
46 changes: 31 additions & 15 deletions extensions/default/src/DicomWebDataSource/retrieveStudyMetadata.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import retrieveMetadataFiltered from './utils/retrieveMetadataFiltered.js';
import RetrieveMetadata from './wado/retrieveMetadata.js';

const moduleName = 'RetrieveStudyMetadata';
// Cache for promises. Prevents unnecessary subsequent calls to the server
const StudyMetaDataPromises = new Map();

/**
* Retrieves study metadata
* Retrieves study metadata.
*
* @param {Object} server Object with server configuration parameters
* @param {Object} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {string} StudyInstanceUID The UID of the Study to be retrieved
* @param {boolean} enabledStudyLazyLoad Whether the study metadata should be loaded asynchronously.
* @param {function} storeInstancesCallback A callback used to store the retrieved instance metadata.
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
* @param {boolean} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously.
* @param {Object} [filters] Object containing filters to be applied on retrieve metadata process
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
* @param {function} [sortCriteria] Sort criteria function
* @param {function} [sortFunction] Sort function
*
* @returns {Promise} that will be resolved with the metadata or rejected with the error
*/
export function retrieveStudyMetadata(
Expand All @@ -39,19 +43,32 @@ export function retrieveStudyMetadata(
return StudyMetaDataPromises.get(StudyInstanceUID);
}

// Create a promise to handle the data retrieval
const promise = new Promise((resolve, reject) => {
RetrieveMetadata(
let promise;

if (filters && filters.SeriesInstanceUIDs) {
promise = retrieveMetadataFiltered(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
).then(function (data) {
resolve(data);
}, reject);
});
);
} else {
// Create a promise to handle the data retrieval
promise = new Promise((resolve, reject) => {
RetrieveMetadata(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
).then(function (data) {
resolve(data);
}, reject);
});
}

// Store the promise in cache
StudyMetaDataPromises.set(StudyInstanceUID, promise);
Expand All @@ -61,10 +78,9 @@ export function retrieveStudyMetadata(

/**
* Delete the cached study metadata retrieval promise to ensure that the browser will
* re-retrieve the study metadata when it is next requested
* re-retrieve the study metadata when it is next requested.
*
* @param {String} StudyInstanceUID The UID of the Study to be removed from cache
*
*/
export function deleteStudyMetadataPromise(StudyInstanceUID) {
if (StudyMetaDataPromises.has(StudyInstanceUID)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import RetrieveMetadata from '../wado/retrieveMetadata';

/**
* Retrieve metadata filtered.
*
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
* @param {object} filters Object containing filters to be applied on retrieve metadata process
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
* @param {function} [sortCriteria] Sort criteria function
* @param {function} [sortFunction] Sort function
*
* @returns
*/
function retrieveMetadataFiltered(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
filters,
sortCriteria,
sortFunction
) {
const { SeriesInstanceUIDs } = filters;

return new Promise((resolve, reject) => {
const promises = SeriesInstanceUIDs.map(uid => {
const seriesSpecificFilters = Object.assign({}, filters, {
seriesInstanceUID: uid,
});

return RetrieveMetadata(
dicomWebClient,
StudyInstanceUID,
enableStudyLazyLoad,
seriesSpecificFilters,
sortCriteria,
sortFunction
);
});

Promise.all(promises).then(results => {
const aggregatedResult = { preLoadData: [], promises: [] };

results.forEach(({ preLoadData, promises }) => {
aggregatedResult.preLoadData = aggregatedResult.preLoadData.concat(preLoadData);
aggregatedResult.promises = aggregatedResult.promises.concat(promises);
});

resolve(aggregatedResult);
}, reject);
});
}

export default retrieveMetadataFiltered;
19 changes: 12 additions & 7 deletions extensions/default/src/DicomWebDataSource/wado/retrieveMetadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ import RetrieveMetadataLoaderAsync from './retrieveMetadataLoaderAsync';
* Retrieve Study metadata from a DICOM server. If the server is configured to use lazy load, only the first series
* will be loaded and the property "studyLoader" will be set to let consumer load remaining series as needed.
*
* @param {Object} dicomWebClient The dicomweb-client.
* @param {string} studyInstanceUid The Study Instance UID of the study which needs to be loaded
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
* @returns {Object} A study descriptor object
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
* @param {object} filters Object containing filters to be applied on retrieve metadata process
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
* @param {function} [sortCriteria] Sort criteria function
* @param {function} [sortFunction] Sort function
*
* @returns {Promise} A promises that resolves the study descriptor object
*/
async function RetrieveMetadata(
dicomWebClient,
studyInstanceUid,
StudyInstanceUID,
enableStudyLazyLoad,
filters = {},
sortCriteria,
Expand All @@ -24,7 +29,7 @@ async function RetrieveMetadata(

const retrieveMetadataLoader = new RetrieveMetadataLoader(
dicomWebClient,
studyInstanceUid,
StudyInstanceUID,
filters,
sortCriteria,
sortFunction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { sortStudySeries, sortingCriteria } from '@ohif/core/src/utils/sortStudy
import RetrieveMetadataLoader from './retrieveMetadataLoader';

/**
* Creates an immutable series loader object which loads each series sequentially using the iterator interface
* 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) {
Expand Down
13 changes: 12 additions & 1 deletion platform/docs/docs/configuration/url.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ values.
:::


### SeriesInstanceUID and initialSeriesInstanceUID
### SeriesInstanceUID, SeriesInstanceUIDs and initialSeriesInstanceUID

Sometimes you need to only retrieve a specific series in a study, you can do
that by providing series level QIDO query parameters in the URL such as
Expand All @@ -134,6 +134,17 @@ http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.38
This will only open the viewer with one series (one displaySet) loaded, and no
queries made for any other series.

Sometimes you need to only retrieve a subset of series in a study, you can do
that by providing study level wado query parameters in the URL such as
SeriesInstanceUIDs. For example:

```js
http://localhost:3000/viewer?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1&SeriesInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113545.4,1.3.6.1.4.1.25403.345050719074.3824.20170125113545.5
```

This will only open the viewer with two series (two displaySets) loaded, and no
queries made for any other series.

Alternatively, sometimes you want to just open the study on a specified series
and/or display a particular sop instance, which you can accomplish using:
`initialSeriesInstanceUID` and/or `initialSOPInstanceUID`
Expand Down