OHIF-285/OHIF-274: Fix default hanging of display sets into the ViewportGrid (#1917)
* OHIF-285/OHIF-274: Fix default hanging of display sets into the ViewportGrid Co-authored-by: James A. Petts <jamesapetts@gmail.com>
This commit is contained in:
1 parent
9df57e7f7f
commit
55cf9f2306
33 files changed
+548
-208
No files matched your search
@@ -34,6 +34,7 @@ import {
|
||||
ToolBarSerivce, // TODO: Typo
|
||||
MeasurementService,
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
} from './services';
|
||||
|
||||
import IWebApiDataSource from './DataSources/IWebApiDataSource';
|
||||
@@ -80,6 +81,7 @@ const OHIF = {
|
||||
MeasurementService,
|
||||
ToolBarSerivce, // TODO: TYPO
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
IWebApiDataSource,
|
||||
DicomMetadataStore,
|
||||
//
|
||||
@@ -123,6 +125,7 @@ export {
|
||||
MeasurementService,
|
||||
ToolBarSerivce,
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
IWebApiDataSource,
|
||||
DicomMetadataStore,
|
||||
ViewModelProvider,
|
||||
|
||||
@@ -72,7 +72,7 @@ const BaseImplementation = {
|
||||
study = _model.studies[_model.studies.length - 1];
|
||||
}
|
||||
|
||||
study.addSeries(instances);
|
||||
study.addInstancesToSeries(instances);
|
||||
|
||||
// Broadcast an event even if we used cached data.
|
||||
// This is because the mode needs to listen to instances that are added to build up its active displaySets.
|
||||
@@ -83,6 +83,24 @@ const BaseImplementation = {
|
||||
SeriesInstanceUID,
|
||||
});
|
||||
},
|
||||
addSeriesMetadata(seriesSummaryMetadata) {
|
||||
const { StudyInstanceUID } = seriesSummaryMetadata[0];
|
||||
let study = _getStudy(StudyInstanceUID);
|
||||
if (!study) {
|
||||
study = createStudyMetadata(StudyInstanceUID);
|
||||
_model.studies.push(study);
|
||||
}
|
||||
|
||||
seriesSummaryMetadata.forEach(series => {
|
||||
const { SeriesInstanceUID } = series;
|
||||
|
||||
study.setSeriesMetadata(SeriesInstanceUID, series);
|
||||
});
|
||||
|
||||
this._broadcastEvent(EVENTS.SERIES_ADDED, {
|
||||
StudyInstanceUID,
|
||||
});
|
||||
},
|
||||
addStudy(study) {
|
||||
const { StudyInstanceUID } = study;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const EVENTS = {
|
||||
INSTANCES_ADDED: 'event::dicomMetadataStore:instancesAdded',
|
||||
SERIES_ADDED: 'event::dicomMetadataStore:seriesAdded',
|
||||
};
|
||||
|
||||
export default EVENTS;
|
||||
@@ -10,19 +10,31 @@ function createStudyMetadata(StudyInstanceUID) {
|
||||
* @param {string} instances[].SeriesInstanceUID
|
||||
* @returns {bool} true if series were added; false if series already exist
|
||||
*/
|
||||
addSeries: function(instances) {
|
||||
addInstancesToSeries: function(instances) {
|
||||
const { SeriesInstanceUID } = instances[0];
|
||||
const seriesExists = this.series.some(
|
||||
const existingSeries = this.series.find(
|
||||
s => s.SeriesInstanceUID === SeriesInstanceUID
|
||||
);
|
||||
|
||||
if (!seriesExists) {
|
||||
if (existingSeries) {
|
||||
existingSeries.instances.push(...instances);
|
||||
} else {
|
||||
const series = createSeriesMetadata(instances);
|
||||
this.series.push(series);
|
||||
}
|
||||
|
||||
return !seriesExists;
|
||||
},
|
||||
|
||||
setSeriesMetadata: function (SeriesInstanceUID, seriesMetadata) {
|
||||
let existingSeries = this.series.find(
|
||||
s => s.SeriesInstanceUID === SeriesInstanceUID
|
||||
);
|
||||
|
||||
if (existingSeries) {
|
||||
existingSeries = Object.assign(existingSeries, seriesMetadata);
|
||||
} else {
|
||||
this.series.push(Object.assign({ instances: [] }, seriesMetadata));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
const name = 'HangingProtocolService';
|
||||
|
||||
const publicAPI = {
|
||||
name,
|
||||
getState: _getState,
|
||||
setHangingProtocol: _setHangingProtocol,
|
||||
setHangingProtocolAppliedForViewport: _setHangingProtocolAppliedForViewport,
|
||||
setServiceImplementation,
|
||||
reset: _reset,
|
||||
set: _set,
|
||||
};
|
||||
|
||||
const serviceImplementation = {
|
||||
_getState: () => console.warn('getState() NOT IMPLEMENTED'),
|
||||
_setHangingProtocol: () =>
|
||||
console.warn('_setHangingProtocol() NOT IMPLEMENTED'),
|
||||
_setHangingProtocolAppliedForViewport: () =>
|
||||
console.warn('_setHangingProtocolAppliedForViewport() NOT IMPLEMENTED'),
|
||||
_reset: () => console.warn('reset() NOT IMPLEMENTED'),
|
||||
_set: () => console.warn('set() NOT IMPLEMENTED'),
|
||||
};
|
||||
|
||||
function _getState() {
|
||||
return serviceImplementation._getState();
|
||||
}
|
||||
|
||||
function _setHangingProtocol(hangingProtocol) {
|
||||
return serviceImplementation._setHangingProtocol(hangingProtocol);
|
||||
}
|
||||
|
||||
function _setHangingProtocolAppliedForViewport(hpAlreadyApplied) {
|
||||
return serviceImplementation._setHangingProtocolAppliedForViewport(
|
||||
hpAlreadyApplied
|
||||
);
|
||||
}
|
||||
|
||||
function _set(state) {
|
||||
return serviceImplementation._set(state);
|
||||
}
|
||||
|
||||
function _reset() {
|
||||
return serviceImplementation._reset({});
|
||||
}
|
||||
|
||||
function setServiceImplementation({
|
||||
getState: getStateImplementation,
|
||||
setHangingProtocol: setHangingProtocolImplementation,
|
||||
setHangingProtocolAppliedForViewport: setHangingProtocolAppliedForViewportImplementation,
|
||||
reset: resetImplementation,
|
||||
set: setImplementation,
|
||||
}) {
|
||||
if (getStateImplementation) {
|
||||
serviceImplementation._getState = getStateImplementation;
|
||||
}
|
||||
if (setHangingProtocolImplementation) {
|
||||
serviceImplementation._setHangingProtocol = setHangingProtocolImplementation;
|
||||
}
|
||||
if (setHangingProtocolAppliedForViewportImplementation) {
|
||||
serviceImplementation._setHangingProtocolAppliedForViewport = setHangingProtocolAppliedForViewportImplementation;
|
||||
}
|
||||
if (resetImplementation) {
|
||||
serviceImplementation._reset = resetImplementation;
|
||||
}
|
||||
if (setImplementation) {
|
||||
serviceImplementation._set = setImplementation;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name,
|
||||
create: ({ configuration = {} }) => {
|
||||
return publicAPI;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
import HangingProtocolService from './HangingProtocolService';
|
||||
|
||||
export default HangingProtocolService;
|
||||
@@ -42,7 +42,6 @@ export default class ToolBarService {
|
||||
}
|
||||
|
||||
_buttonTypes() {
|
||||
console.log(this.extensionManager.modules);
|
||||
const buttonTypes = {};
|
||||
const registeredToolbarModules = this.extensionManager.modules[
|
||||
'toolbarModule'
|
||||
|
||||
@@ -8,6 +8,7 @@ import DicomMetadataStore from './DicomMetadataStore';
|
||||
import DisplaySetService from './DisplaySetService';
|
||||
import ToolBarSerivce from './ToolBarService';
|
||||
import ViewportGridService from './ViewportGridService';
|
||||
import HangingProtocolService from './HangingProtocolService';
|
||||
|
||||
export {
|
||||
MeasurementService,
|
||||
@@ -20,4 +21,5 @@ export {
|
||||
DisplaySetService,
|
||||
ToolBarSerivce,
|
||||
ViewportGridService,
|
||||
HangingProtocolService,
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import DICOMWeb from '../DICOMWeb/';
|
||||
import isLowPriorityModality from '../utils/isLowPriorityModality';
|
||||
|
||||
const INFO = Symbol('INFO');
|
||||
|
||||
/**
|
||||
* Creates an object with processed series information and saves its reference
|
||||
* inside the series object itself.
|
||||
* @param {Object} series The raw series object
|
||||
* @returns {Object} object containing some useful info from given series
|
||||
*/
|
||||
export default function getSeriesInfo(series) {
|
||||
let info = series[INFO];
|
||||
if (!info) {
|
||||
const Modality = DICOMWeb.getString(series['00080060'], '').toUpperCase();
|
||||
info = Object.freeze({
|
||||
Modality,
|
||||
isLowPriority: isLowPriorityModality(Modality),
|
||||
SeriesInstanceUID: DICOMWeb.getString(series['0020000E']),
|
||||
SeriesNumber: DICOMWeb.getNumber(series['00200011'], 0) || 0,
|
||||
});
|
||||
series[INFO] = info;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import getStudyBoxData from './getStudyBoxData';
|
||||
import retrieveStudiesMetadata from './retrieveStudiesMetadata.js';
|
||||
import searchStudies from './searchStudies';
|
||||
import sortStudy from './sortStudy';
|
||||
import { sortStudy, sortStudySeries, sortStudyInstances, sortingCriteria } from './sortStudy';
|
||||
|
||||
const studies = {
|
||||
services: {
|
||||
@@ -21,6 +21,9 @@ const studies = {
|
||||
getStudyBoxData,
|
||||
searchStudies,
|
||||
sortStudy,
|
||||
sortStudySeries,
|
||||
sortStudyInstances,
|
||||
sortingCriteria,
|
||||
};
|
||||
|
||||
export default studies;
|
||||
@@ -3,7 +3,6 @@ import dcmjs from 'dcmjs';
|
||||
import DICOMWeb from '../../../DICOMWeb/';
|
||||
import RetrieveMetadataLoader from './retrieveMetadataLoader';
|
||||
import { sortStudySeries, sortingCriteria } from '../../sortStudy';
|
||||
import getSeriesInfo from '../../getSeriesInfo';
|
||||
import {
|
||||
createStudyFromSOPInstanceList,
|
||||
addInstancesToStudy,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import getSeriesInfo from './getSeriesInfo';
|
||||
import isLowPriorityModality from '../utils/isLowPriorityModality';
|
||||
|
||||
/**
|
||||
* Series sorting criteria: series considered low priority are moved to the end
|
||||
@@ -7,15 +7,16 @@ import getSeriesInfo from './getSeriesInfo';
|
||||
* @param {Object} secondSeries
|
||||
*/
|
||||
function seriesInfoSortingCriteria(firstSeries, secondSeries) {
|
||||
const a = getSeriesInfo(firstSeries);
|
||||
const b = getSeriesInfo(secondSeries);
|
||||
if (!a.isLowPriority && b.isLowPriority) {
|
||||
const aLowPriority = isLowPriorityModality(firstSeries.Modality);
|
||||
const bLowPriority = isLowPriorityModality(secondSeries.Modality);
|
||||
if (!aLowPriority && bLowPriority) {
|
||||
return -1;
|
||||
}
|
||||
if (a.isLowPriority && !b.isLowPriority) {
|
||||
if (aLowPriority && !bLowPriority) {
|
||||
return 1;
|
||||
}
|
||||
return a.SeriesNumber - b.SeriesNumber;
|
||||
|
||||
return firstSeries.SeriesNumber - secondSeries.SeriesNumber;
|
||||
}
|
||||
|
||||
const seriesSortCriteria = {
|
||||
@@ -93,4 +94,4 @@ export default function sortStudy(
|
||||
return study;
|
||||
}
|
||||
|
||||
export { sortStudySeries, sortStudyInstances, sortingCriteria };
|
||||
export { sortStudy, sortStudySeries, sortStudyInstances, sortingCriteria };
|
||||
@@ -20,6 +20,7 @@ import formatPN from './formatPN';
|
||||
import resolveObjectPath from './resolveObjectPath';
|
||||
import * as hierarchicalListUtils from './hierarchicalListUtils';
|
||||
import * as progressTrackingUtils from './progressTrackingUtils';
|
||||
import isLowPriorityModality from './isLowPriorityModality';
|
||||
|
||||
const utils = {
|
||||
guid,
|
||||
@@ -44,6 +45,7 @@ const utils = {
|
||||
resolveObjectPath,
|
||||
hierarchicalListUtils,
|
||||
progressTrackingUtils,
|
||||
isLowPriorityModality
|
||||
};
|
||||
|
||||
export {
|
||||
@@ -68,6 +70,7 @@ export {
|
||||
resolveObjectPath,
|
||||
hierarchicalListUtils,
|
||||
progressTrackingUtils,
|
||||
isLowPriorityModality
|
||||
};
|
||||
|
||||
export default utils;
|
||||
@@ -1,4 +1,4 @@
|
||||
const LOW_PRIORITY_MODALITIES = Object.freeze(['SEG', 'KO', 'PR']);
|
||||
const LOW_PRIORITY_MODALITIES = Object.freeze(['SEG', 'KO', 'PR', 'SR', 'RTSTRUCT']);
|
||||
|
||||
export default function isLowPriorityModality(Modality) {
|
||||
return LOW_PRIORITY_MODALITIES.includes(Modality);
|
||||
|
||||
Reference in new issue
Block a user