fix: Call load if necessary before rehydration prompt. Jump to first measurement on rehydration (OHIF-369) (#2184)

This commit is contained in:
Erik Ziegler 2020-11-25 13:35:43 +01:00 committed by GitHub
parent 2f4cba28a5
commit e0a31caebf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 59 additions and 49 deletions

View File

@ -122,9 +122,7 @@ function _load(displaySet, servicesManager, extensionManager) {
); );
displaySet.isHydrated = false; displaySet.isHydrated = false;
displaySet.isRehydratable = isRehydratable(displaySet, mappings) displaySet.isRehydratable = isRehydratable(displaySet, mappings);
? true
: false;
displaySet.isLoaded = true; displaySet.isLoaded = true;
// Check currently added displaySets and add measurements if the sources exist. // Check currently added displaySets and add measurements if the sources exist.

View File

@ -3,7 +3,7 @@ import { adapters } from 'dcmjs';
const cornerstoneAdapters = adapters.Cornerstone; const cornerstoneAdapters = adapters.Cornerstone;
/** /**
* Checks if the given `displySet`can be rehydrated into the `MeasurementService`. * Checks if the given `displaySet`can be rehydrated into the `MeasurementService`.
* *
* @param {object} displaySet The SR `displaySet` to check. * @param {object} displaySet The SR `displaySet` to check.
* @param {object[]} mappings The CornerstoneTools 4 mappings to the `MeasurementService`. * @param {object[]} mappings The CornerstoneTools 4 mappings to the `MeasurementService`.

View File

@ -205,6 +205,8 @@ function OHIFCornerstoneSRViewport({
setTrackingUniqueIdentifiersForElement(targetElement); setTrackingUniqueIdentifiersForElement(targetElement);
setElement(targetElement); setElement(targetElement);
// TODO: Enabled Element appears to be incorrect here, it should be called
// 'element' since it is the DOM element, not the enabledElement object
const OHIFCornerstoneEnabledElementEvent = new CustomEvent( const OHIFCornerstoneEnabledElementEvent = new CustomEvent(
'ohif-cornerstone-enabled-element-event', 'ohif-cornerstone-enabled-element-event',
{ {

View File

@ -3,7 +3,7 @@ import cornerstoneTools from 'cornerstone-tools';
const { globalImageIdSpecificToolStateManager } = cornerstoneTools; const { globalImageIdSpecificToolStateManager } = cornerstoneTools;
export default function setMeasurementActive(measurement) { export default function setCornerstoneMeasurementActive(measurement) {
const { id } = measurement; const { id } = measurement;
const toolState = globalImageIdSpecificToolStateManager.saveToolState(); const toolState = globalImageIdSpecificToolStateManager.saveToolState();

View File

@ -18,6 +18,8 @@ const TrackedMeasurementsContext = React.createContext();
TrackedMeasurementsContext.displayName = 'TrackedMeasurementsContext'; TrackedMeasurementsContext.displayName = 'TrackedMeasurementsContext';
const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext); const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext);
const SR_SOPCLASSHANDLERID = "org.ohif.dicom-sr.sopClassHandlerModule.dicom-sr";
/** /**
* *
* @param {*} param0 * @param {*} param0
@ -31,21 +33,19 @@ function TrackedMeasurementsContextProvider(
const machineOptions = Object.assign({}, defaultOptions); const machineOptions = Object.assign({}, defaultOptions);
machineOptions.actions = Object.assign({}, machineOptions.actions, { machineOptions.actions = Object.assign({}, machineOptions.actions, {
showSeriesInActiveViewport: (ctx, evt) => { jumpToFirstMeasurementInActiveViewport: (ctx, evt) => {
const { DisplaySetService } = servicesManager.services; const { DisplaySetService, MeasurementService } = servicesManager.services;
const displaySetsForHydratedSeries = DisplaySetService.getDisplaySetsForSeries( const { trackedStudy, trackedSeries } = ctx;
ctx.trackedSeries[0] const measurements = MeasurementService.getMeasurements();
const trackedMeasurements = measurements.filter(
m =>
trackedStudy === m.referenceStudyUID &&
trackedSeries.includes(m.referenceSeriesUID)
); );
if (displaySetsForHydratedSeries.length > 0) { const id = trackedMeasurements[0].id;
const firstDisplaySetInstanceUID =
displaySetsForHydratedSeries[0].displaySetInstanceUID;
viewportGridService.setDisplaysetForViewport({ MeasurementService.jumpToMeasurement(viewportGrid.activeViewportIndex, id);
viewportIndex: evt.data.viewportIndex,
displaySetInstanceUID: firstDisplaySetInstanceUID,
});
}
}, },
showStructuredReportDisplaySetInActiveViewport: (ctx, evt) => { showStructuredReportDisplaySetInActiveViewport: (ctx, evt) => {
if (evt.data.createdDisplaySetInstanceUIDs.length > 0) { if (evt.data.createdDisplaySetInstanceUIDs.length > 0) {
@ -136,11 +136,29 @@ function TrackedMeasurementsContextProvider(
activeViewport.displaySetInstanceUID activeViewport.displaySetInstanceUID
); );
// If this is an SR produced by our SR SOPClassHandler,
// and it hasn't been loaded yet, do that now so we
// can check if it can be rehydrated or not.
//
// Note: This happens:
// - If the viewport is not currently an OHIFCornerstoneSRViewport
// - If the displaySet has never been hung
//
// Otherwise, the displaySet will be loaded by the useEffect handler
// listening to displaySet changes inside OHIFCornerstoneSRViewport.
// The issue here is that this handler in TrackedMeasurementsContext
// ends up occurring before the Viewport is created, so the displaySet
// is not loaded yet, and isRehydratable is undefined unless we call load().
if (displaySet.SOPClassHandlerId === SR_SOPCLASSHANDLERID &&
!displaySet.isLoaded &&
displaySet.load) {
displaySet.load();
}
// Magic string // Magic string
// load function added by our sopClassHandler module // load function added by our sopClassHandler module
if ( if (
displaySet.SOPClassHandlerId === displaySet.SOPClassHandlerId === SR_SOPCLASSHANDLERID &&
'org.ohif.dicom-sr.sopClassHandlerModule.dicom-sr' &&
displaySet.isRehydratable === true displaySet.isRehydratable === true
) { ) {
console.log('sending event...', trackedMeasurements); console.log('sending event...', trackedMeasurements);

View File

@ -211,7 +211,7 @@ const machineConfiguration = {
target: 'tracking', target: 'tracking',
actions: [ actions: [
'setTrackedStudyAndMultipleSeries', 'setTrackedStudyAndMultipleSeries',
'showSeriesInActiveViewport', 'jumpToFirstMeasurementInActiveViewport',
'setIsDirtyToClean', 'setIsDirtyToClean',
], ],
cond: 'shouldHydrateStructuredReport', cond: 'shouldHydrateStructuredReport',
@ -248,8 +248,8 @@ const defaultOptions = {
clearAllMeasurements: (ctx, evt) => { clearAllMeasurements: (ctx, evt) => {
console.log('clearAllMeasurements: not implemented'); console.log('clearAllMeasurements: not implemented');
}, },
showSeriesInActiveViewport: (ctx, evt) => { jumpToFirstMeasurementInActiveViewport: (ctx, evt) => {
console.warn('showSeriesInActiveViewport: not implemented'); console.warn('jumpToFirstMeasurementInActiveViewport: not implemented');
}, },
showStructuredReportDisplaySetInActiveViewport: (ctx, evt) => { showStructuredReportDisplaySetInActiveViewport: (ctx, evt) => {
console.warn( console.warn(

View File

@ -78,7 +78,7 @@ function TrackedCornerstoneViewport({
}, [viewportIndex]); }, [viewportIndex]);
useEffect(() => { useEffect(() => {
const unsubcribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents( const unsubscribeFromJumpToMeasurementEvents = _subscribeToJumpToMeasurementEvents(
MeasurementService, MeasurementService,
DisplaySetService, DisplaySetService,
element, element,
@ -95,7 +95,7 @@ function TrackedCornerstoneViewport({
); );
return () => { return () => {
unsubcribeFromJumpToMeasurementEvents(); unsubscribeFromJumpToMeasurementEvents();
}; };
}, [element, displaySet]); }, [element, displaySet]);
@ -605,7 +605,6 @@ function _jumpToMeasurement(
if (targetElement !== null) { if (targetElement !== null) {
const enabledElement = cornerstone.getEnabledElement(targetElement); const enabledElement = cornerstone.getEnabledElement(targetElement);
if (enabledElement.image) {
// Wait for the image to update or we get a race condition when the element has only just been enabled. // Wait for the image to update or we get a race condition when the element has only just been enabled.
const scrollToHandler = evt => { const scrollToHandler = evt => {
scrollToIndex(targetElement, imageIndex); scrollToIndex(targetElement, imageIndex);
@ -618,6 +617,8 @@ function _jumpToMeasurement(
'cornerstoneimagerendered', 'cornerstoneimagerendered',
scrollToHandler scrollToHandler
); );
if (enabledElement.image) {
cornerstone.updateImage(targetElement); cornerstone.updateImage(targetElement);
} }

View File

@ -37,9 +37,8 @@
"docs:preview": "lerna run docs:preview --stream", "docs:preview": "lerna run docs:preview --stream",
"docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh", "docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh",
"release": "yarn run lerna:version && yarn run lerna:publish", "release": "yarn run lerna:version && yarn run lerna:publish",
"lerna:cache": "[ $NETLIFY_RESTORE = 1 ] && ./netlify-lerna-cache.sh || :", "lerna:cache": "./netlify-lerna-cache.sh",
"lerna:restore": "[ $NETLIFY_RESTORE = 1 ] && ./netlify-lerna-restore.sh || :", "lerna:restore": "./netlify-lerna-restore.sh",
"preinstall": "yarn lerna:restore",
"lerna:version": "npx lerna version prerelease --force-publish", "lerna:version": "npx lerna version prerelease --force-publish",
"lerna:publish": "lerna publish from-package --canary --dist-tag canary", "lerna:publish": "lerna publish from-package --canary --dist-tag canary",
"link-list": "npm ls --depth=0 --link=true" "link-list": "npm ls --depth=0 --link=true"

View File

@ -7907,18 +7907,10 @@ cornerstone-math@^0.1.8:
resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5" resolved "https://registry.yarnpkg.com/cornerstone-math/-/cornerstone-math-0.1.8.tgz#68ab1f9e4fdcd7c5cb23a0d2eb4263f9f894f1c5"
integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw== integrity sha512-x7NEQHBtVG7j1yeyj/aRoKTpXv1Vh2/H9zNLMyqYJDtJkNng8C4Q8M3CgZ1qer0Yr7eVq2x+Ynmj6kfOm5jXKw==
cornerstone-tools@4.20.1: cornerstone-tools@5.1.2:
version "4.20.1" version "5.1.2"
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-4.20.1.tgz#90f6c28356622eac037683b19f9175f85d33dff7" resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-5.1.2.tgz#d2a03341c837c9288e2b70e314136d31e85c8c46"
integrity sha512-SyQsrg3bnGHUvWGZpUq7ia7/gj12S9zQFK2VMhpyAYxK9pWz+PRv8HBi0eEe/fWGAo/Vc62IRkdP3uF9MJlqiQ== integrity sha512-MrOXOxkEuLPHd6cqJ0mwU+R9OaNk08XC1yKjUS9dF6UbIq9HdwFJ6Fj0rcIA2MXYYjVN6tFwMM8H+0k7R3KxCA==
dependencies:
"@babel/runtime" "7.1.2"
cornerstone-math "0.1.7"
cornerstone-tools@^4.22.0:
version "4.22.0"
resolved "https://registry.yarnpkg.com/cornerstone-tools/-/cornerstone-tools-4.22.0.tgz#760f895ed1a02ec457dda23f8cb6abb20df77378"
integrity sha512-EKUvTqwiN6i5AwPOTvc/iiWEqOZUzEOX7hM8kBnV8E7G2o+0jAEQkNqy+3J+TpBUWHQ3qF2G1Hktmi60tspwow==
dependencies: dependencies:
"@babel/runtime" "7.1.2" "@babel/runtime" "7.1.2"
cornerstone-math "0.1.7" cornerstone-math "0.1.7"