[OHIF 284] - JumpToMeasurement + prevent layout change on scroll Prevent layout change on scroll (#1889)
* No more setting on debounce, jumpToMeasurement service set up. * Fix bug causing a race condition sometimes if you click super fast. * Optimise rendering of Tracking viewport slightly. * element => targetElement * Remove complete TODO * Respond to reviewer comments. * Fix e2e workflow. * Fix regression that removed highlighting on jump to. * Make sure jump to works from panel as well as viewport. * Fix typo and remove debugger. Co-authored-by: Danny Brown <danny.ri.brown@gmail.com>
This commit is contained in:
1 parent
4985fbf5a6
commit
a4f286feee
26 files changed
+438
-196
No files matched your search
@@ -35,7 +35,7 @@
|
||||
"cornerstone-math": "^0.1.8",
|
||||
"cornerstone-tools": "4.18.1",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dcmjs": "0.16.0",
|
||||
"dcmjs": "0.16.1",
|
||||
"dicom-parser": "^1.8.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
|
||||
@@ -83,8 +83,6 @@ const commandsModule = ({ servicesManager }) => {
|
||||
const enabledElement = _getActiveViewportsEnabledElement();
|
||||
|
||||
if (enabledElement) {
|
||||
debugger;
|
||||
|
||||
const cancelActiveManipulatorsForElement = cornerstoneTools.getModule(
|
||||
'manipulatorState'
|
||||
).setters.cancelActiveManipulatorsForElement;
|
||||
@@ -284,32 +282,6 @@ const commandsModule = ({ servicesManager }) => {
|
||||
cornerstone.setViewport(enabledElement, viewport);
|
||||
}
|
||||
},
|
||||
jumpToImage: ({
|
||||
StudyInstanceUID,
|
||||
SOPInstanceUID,
|
||||
imageIndex,
|
||||
activeViewportIndex,
|
||||
}) => {
|
||||
const study = studyMetadataManager.get(StudyInstanceUID);
|
||||
|
||||
const displaySet = study.findDisplaySet(ds => {
|
||||
return (
|
||||
ds.images &&
|
||||
ds.images.find(i => i.getSOPInstanceUID() === SOPInstanceUID)
|
||||
);
|
||||
});
|
||||
|
||||
displaySet.SOPInstanceUID = SOPInstanceUID;
|
||||
displaySet.imageIndex = imageIndex;
|
||||
|
||||
window.store.dispatch(
|
||||
setViewportSpecificData(activeViewportIndex, displaySet)
|
||||
);
|
||||
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
|
||||
@@ -18,7 +18,11 @@ import { setEnabledElement } from './state';
|
||||
* @param {Object|Array} configuration.csToolsConfig
|
||||
*/
|
||||
export default function init({ servicesManager, configuration }) {
|
||||
const { UIDialogService, MeasurementService } = servicesManager.services;
|
||||
const {
|
||||
UIDialogService,
|
||||
MeasurementService,
|
||||
DisplaySetService,
|
||||
} = servicesManager.services;
|
||||
|
||||
const callInputDialog = (data, event, callback) => {
|
||||
if (UIDialogService) {
|
||||
@@ -137,7 +141,7 @@ export default function init({ servicesManager, configuration }) {
|
||||
);
|
||||
|
||||
/* Measurement Service */
|
||||
_connectToolsToMeasurementService(MeasurementService);
|
||||
_connectToolsToMeasurementService(MeasurementService, DisplaySetService);
|
||||
|
||||
/* Add extension tools configuration here. */
|
||||
const internalToolsConfig = {
|
||||
@@ -220,21 +224,21 @@ export default function init({ servicesManager, configuration }) {
|
||||
csTools.setToolEnabled('Overlay', {});
|
||||
}
|
||||
|
||||
const _initMeasurementService = measurementService => {
|
||||
const _initMeasurementService = (MeasurementService, DisplaySetService) => {
|
||||
/* Initialization */
|
||||
const {
|
||||
Length,
|
||||
Bidirectional,
|
||||
EllipticalRoi,
|
||||
ArrowAnnotate,
|
||||
} = measurementServiceMappingsFactory(measurementService);
|
||||
const csToolsVer4MeasurementSource = measurementService.createSource(
|
||||
} = measurementServiceMappingsFactory(MeasurementService, DisplaySetService);
|
||||
const csToolsVer4MeasurementSource = MeasurementService.createSource(
|
||||
'CornerstoneTools',
|
||||
'4'
|
||||
);
|
||||
|
||||
/* Mappings */
|
||||
measurementService.addMapping(
|
||||
MeasurementService.addMapping(
|
||||
csToolsVer4MeasurementSource,
|
||||
'Length',
|
||||
Length.matchingCriteria,
|
||||
@@ -242,7 +246,7 @@ const _initMeasurementService = measurementService => {
|
||||
Length.toMeasurement
|
||||
);
|
||||
|
||||
measurementService.addMapping(
|
||||
MeasurementService.addMapping(
|
||||
csToolsVer4MeasurementSource,
|
||||
'Bidirectional',
|
||||
Bidirectional.matchingCriteria,
|
||||
@@ -250,7 +254,7 @@ const _initMeasurementService = measurementService => {
|
||||
Bidirectional.toMeasurement
|
||||
);
|
||||
|
||||
measurementService.addMapping(
|
||||
MeasurementService.addMapping(
|
||||
csToolsVer4MeasurementSource,
|
||||
'EllipticalRoi',
|
||||
EllipticalRoi.matchingCriteria,
|
||||
@@ -258,7 +262,7 @@ const _initMeasurementService = measurementService => {
|
||||
EllipticalRoi.toMeasurement
|
||||
);
|
||||
|
||||
measurementService.addMapping(
|
||||
MeasurementService.addMapping(
|
||||
csToolsVer4MeasurementSource,
|
||||
'ArrowAnnotate',
|
||||
ArrowAnnotate.matchingCriteria,
|
||||
@@ -269,12 +273,16 @@ const _initMeasurementService = measurementService => {
|
||||
return csToolsVer4MeasurementSource;
|
||||
};
|
||||
|
||||
const _connectToolsToMeasurementService = measurementService => {
|
||||
const _connectToolsToMeasurementService = (
|
||||
MeasurementService,
|
||||
DisplaySetService
|
||||
) => {
|
||||
const csToolsVer4MeasurementSource = _initMeasurementService(
|
||||
measurementService
|
||||
MeasurementService,
|
||||
DisplaySetService
|
||||
);
|
||||
_connectMeasurementServiceToTools(
|
||||
measurementService,
|
||||
MeasurementService,
|
||||
csToolsVer4MeasurementSource
|
||||
);
|
||||
const { addOrUpdate, remove } = csToolsVer4MeasurementSource;
|
||||
@@ -330,9 +338,9 @@ const _connectToolsToMeasurementService = measurementService => {
|
||||
}
|
||||
}
|
||||
|
||||
const { MEASUREMENTS_CLEARED } = measurementService.EVENTS;
|
||||
const { MEASUREMENTS_CLEARED } = MeasurementService.EVENTS;
|
||||
|
||||
measurementService.subscribe(MEASUREMENTS_CLEARED, () => {
|
||||
MeasurementService.subscribe(MEASUREMENTS_CLEARED, () => {
|
||||
cornerstoneTools.globalImageIdSpecificToolStateManager.restoreToolState(
|
||||
{}
|
||||
);
|
||||
@@ -350,16 +358,16 @@ const _connectToolsToMeasurementService = measurementService => {
|
||||
};
|
||||
|
||||
const _connectMeasurementServiceToTools = (
|
||||
measurementService,
|
||||
MeasurementService,
|
||||
measurementSource
|
||||
) => {
|
||||
const {
|
||||
MEASUREMENTS_CLEARED,
|
||||
MEASUREMENT_REMOVED,
|
||||
} = measurementService.EVENTS;
|
||||
} = MeasurementService.EVENTS;
|
||||
const sourceId = measurementSource.id;
|
||||
|
||||
measurementService.subscribe(MEASUREMENTS_CLEARED, () => {
|
||||
MeasurementService.subscribe(MEASUREMENTS_CLEARED, () => {
|
||||
cornerstoneTools.globalImageIdSpecificToolStateManager.restoreToolState({});
|
||||
cornerstone.getEnabledElements().forEach(enabledElement => {
|
||||
cornerstone.updateImage(enabledElement.element);
|
||||
@@ -367,7 +375,7 @@ const _connectMeasurementServiceToTools = (
|
||||
});
|
||||
|
||||
/* TODO: Remove per measurement
|
||||
measurementService.subscribe(MEASUREMENT_REMOVED,
|
||||
MeasurementService.subscribe(MEASUREMENT_REMOVED,
|
||||
({ source, measurement }) => {
|
||||
if ([sourceId].includes(source.id)) {
|
||||
// const annotation = getAnnotation('Length', measurement.id);
|
||||
@@ -380,9 +388,9 @@ const _connectMeasurementServiceToTools = (
|
||||
// const {
|
||||
// MEASUREMENT_ADDED,
|
||||
// MEASUREMENT_UPDATED,
|
||||
// } = measurementService.EVENTS;
|
||||
// } = MeasurementService.EVENTS;
|
||||
|
||||
// measurementService.subscribe(
|
||||
// MeasurementService.subscribe(
|
||||
// MEASUREMENT_ADDED,
|
||||
// ({ source, measurement }) => {
|
||||
// if (![sourceId].includes(source.id)) {
|
||||
@@ -397,7 +405,7 @@ const _connectMeasurementServiceToTools = (
|
||||
// }
|
||||
// );
|
||||
|
||||
// measurementService.subscribe(
|
||||
// MeasurementService.subscribe(
|
||||
// MEASUREMENT_UPDATED,
|
||||
// ({ source, measurement }) => {
|
||||
// if (![sourceId].includes(source.id)) {
|
||||
|
||||
@@ -6,7 +6,11 @@ const ArrowAnnotate = {
|
||||
toAnnotation: (measurement, definition) => {
|
||||
// TODO -> Implement when this is needed.
|
||||
},
|
||||
toMeasurement: (csToolsAnnotation, getValueTypeFromToolType) => {
|
||||
toMeasurement: (
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
getValueTypeFromToolType
|
||||
) => {
|
||||
const { element, measurementData } = csToolsAnnotation;
|
||||
const tool =
|
||||
csToolsAnnotation.toolType ||
|
||||
@@ -26,6 +30,11 @@ const ArrowAnnotate = {
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(element);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID
|
||||
);
|
||||
|
||||
const points = [];
|
||||
points.push(measurementData.handles);
|
||||
|
||||
@@ -35,6 +44,7 @@ const ArrowAnnotate = {
|
||||
FrameOfReferenceUID,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
label: measurementData.text,
|
||||
description: measurementData.description,
|
||||
unit: measurementData.unit,
|
||||
|
||||
@@ -5,7 +5,11 @@ const Bidirectional = {
|
||||
toAnnotation: (measurement, definition) => {
|
||||
// TODO -> Implement when this is needed.
|
||||
},
|
||||
toMeasurement: (csToolsAnnotation, getValueTypeFromToolType) => {
|
||||
toMeasurement: (
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
getValueTypeFromToolType
|
||||
) => {
|
||||
const { element, measurementData } = csToolsAnnotation;
|
||||
const tool =
|
||||
csToolsAnnotation.toolType ||
|
||||
@@ -25,6 +29,11 @@ const Bidirectional = {
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(element);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID
|
||||
);
|
||||
|
||||
const { handles } = measurementData;
|
||||
|
||||
const longAxis = [handles.start, handles.end];
|
||||
@@ -36,6 +45,7 @@ const Bidirectional = {
|
||||
FrameOfReferenceUID,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
label: measurementData.text,
|
||||
description: measurementData.description,
|
||||
unit: measurementData.unit,
|
||||
|
||||
@@ -5,7 +5,11 @@ const EllipticalRoi = {
|
||||
toAnnotation: (measurement, definition) => {
|
||||
// TODO -> Implement when this is needed.
|
||||
},
|
||||
toMeasurement: (csToolsAnnotation, getValueTypeFromToolType) => {
|
||||
toMeasurement: (
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
getValueTypeFromToolType
|
||||
) => {
|
||||
const { element, measurementData } = csToolsAnnotation;
|
||||
const tool =
|
||||
csToolsAnnotation.toolType ||
|
||||
@@ -25,6 +29,11 @@ const EllipticalRoi = {
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(element);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID
|
||||
);
|
||||
|
||||
const { start, end } = measurementData.handles;
|
||||
|
||||
const halfXLength = Math.abs(start.x - end.x) / 2;
|
||||
@@ -58,6 +67,7 @@ const EllipticalRoi = {
|
||||
FrameOfReferenceUID,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
label: measurementData.text,
|
||||
description: measurementData.description,
|
||||
unit: measurementData.unit,
|
||||
|
||||
@@ -37,7 +37,11 @@ const Length = {
|
||||
* @param {Object} cornerstone Cornerstone event data
|
||||
* @return {Measurement} Measurement instance
|
||||
*/
|
||||
toMeasurement: (csToolsAnnotation, getValueTypeFromToolType) => {
|
||||
toMeasurement: (
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
getValueTypeFromToolType
|
||||
) => {
|
||||
const { element, measurementData } = csToolsAnnotation;
|
||||
const tool =
|
||||
csToolsAnnotation.toolType ||
|
||||
@@ -57,12 +61,18 @@ const Length = {
|
||||
StudyInstanceUID,
|
||||
} = getSOPInstanceAttributes(element);
|
||||
|
||||
const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID(
|
||||
SOPInstanceUID,
|
||||
SeriesInstanceUID
|
||||
);
|
||||
|
||||
return {
|
||||
id: measurementData.id,
|
||||
SOPInstanceUID: SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
label: measurementData.text,
|
||||
description: measurementData.description,
|
||||
unit: measurementData.unit,
|
||||
|
||||
+18
-8
@@ -3,7 +3,10 @@ import Bidirectional from './Bidirectional';
|
||||
import ArrowAnnotate from './ArrowAnnotate';
|
||||
import EllipticalRoi from './EllipticalRoi';
|
||||
|
||||
const measurementServiceMappingsFactory = measurementService => {
|
||||
const measurementServiceMappingsFactory = (
|
||||
MeasurementService,
|
||||
DisplaySetService
|
||||
) => {
|
||||
/**
|
||||
* Maps measurement service format object to cornerstone annotation object.
|
||||
*
|
||||
@@ -18,7 +21,7 @@ const measurementServiceMappingsFactory = measurementService => {
|
||||
ELLIPSE,
|
||||
POINT,
|
||||
BIDIRECTIONAL,
|
||||
} = measurementService.VALUE_TYPES;
|
||||
} = MeasurementService.VALUE_TYPES;
|
||||
|
||||
// TODO -> I get why this was attemped, but its not nearly flexible enough.
|
||||
// A single measurement may have an ellipse + a bidirectional measurement, for instances.
|
||||
@@ -37,10 +40,14 @@ const measurementServiceMappingsFactory = measurementService => {
|
||||
Length: {
|
||||
toAnnotation: Length.toAnnotation,
|
||||
toMeasurement: csToolsAnnotation =>
|
||||
Length.toMeasurement(csToolsAnnotation, _getValueTypeFromToolType),
|
||||
Length.toMeasurement(
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
_getValueTypeFromToolType
|
||||
),
|
||||
matchingCriteria: [
|
||||
{
|
||||
valueType: measurementService.VALUE_TYPES.POLYLINE,
|
||||
valueType: MeasurementService.VALUE_TYPES.POLYLINE,
|
||||
points: 2,
|
||||
},
|
||||
],
|
||||
@@ -50,17 +57,18 @@ const measurementServiceMappingsFactory = measurementService => {
|
||||
toMeasurement: csToolsAnnotation =>
|
||||
Bidirectional.toMeasurement(
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
_getValueTypeFromToolType
|
||||
),
|
||||
matchingCriteria: [
|
||||
// TODO -> We should eventually do something like shortAxis + longAxis,
|
||||
// But its still a little unclear how these automatic interpretations will work.
|
||||
{
|
||||
valueType: measurementService.VALUE_TYPES.POLYLINE,
|
||||
valueType: MeasurementService.VALUE_TYPES.POLYLINE,
|
||||
points: 2,
|
||||
},
|
||||
{
|
||||
valueType: measurementService.VALUE_TYPES.POLYLINE,
|
||||
valueType: MeasurementService.VALUE_TYPES.POLYLINE,
|
||||
points: 2,
|
||||
},
|
||||
],
|
||||
@@ -70,11 +78,12 @@ const measurementServiceMappingsFactory = measurementService => {
|
||||
toMeasurement: csToolsAnnotation =>
|
||||
ArrowAnnotate.toMeasurement(
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
_getValueTypeFromToolType
|
||||
),
|
||||
matchingCriteria: [
|
||||
{
|
||||
valueType: measurementService.VALUE_TYPES.POINT,
|
||||
valueType: MeasurementService.VALUE_TYPES.POINT,
|
||||
points: 1,
|
||||
},
|
||||
],
|
||||
@@ -84,11 +93,12 @@ const measurementServiceMappingsFactory = measurementService => {
|
||||
toMeasurement: csToolsAnnotation =>
|
||||
EllipticalRoi.toMeasurement(
|
||||
csToolsAnnotation,
|
||||
DisplaySetService,
|
||||
_getValueTypeFromToolType
|
||||
),
|
||||
matchingCriteria: [
|
||||
{
|
||||
valueType: measurementService.VALUE_TYPES.ELLIPSE,
|
||||
valueType: MeasurementService.VALUE_TYPES.ELLIPSE,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user