From eafa2efda5447c2d944ed44f3befca5c66ecefc5 Mon Sep 17 00:00:00 2001 From: Alireza Date: Fri, 28 Mar 2025 10:17:33 -0400 Subject: [PATCH] Revert "fix(measurement): fix for measurement jump is not switching series in 2DMPR (#4779)" (#4898) --- .../src/Viewport/OHIFCornerstoneViewport.tsx | 25 ++------ .../CornerstoneViewportService.ts | 17 ++++-- platform/app/src/components/ViewportGrid.tsx | 25 +++----- .../src/utils/getClosestOrientationFromIOP.ts | 59 ------------------- 4 files changed, 26 insertions(+), 100 deletions(-) delete mode 100644 platform/app/src/utils/getClosestOrientationFromIOP.ts diff --git a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx index 8045793c1..d7570200d 100644 --- a/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx +++ b/extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.tsx @@ -264,10 +264,11 @@ const OHIFCornerstoneViewport = React.memo( const presentations = getViewportPresentations(viewportId, viewportOptions); let measurement; - if (cacheJumpToMeasurementEvent?.cornerstoneViewport === viewportId) { + if (cacheJumpToMeasurementEvent?.viewportId === viewportId) { measurement = cacheJumpToMeasurementEvent.measurement; // Delete the position presentation so that viewport navigates direct presentations.positionPresentation = null; + cacheJumpToMeasurementEvent = null; } // Note: This is a hack to get the grid to re-render the OHIFCornerstoneViewport component @@ -280,7 +281,7 @@ const OHIFCornerstoneViewport = React.memo( viewportOptions.needsRerendering = false; } - await cornerstoneViewportService.setViewportData( + cornerstoneViewportService.setViewportData( viewportId, viewportData, viewportOptions, @@ -289,13 +290,7 @@ const OHIFCornerstoneViewport = React.memo( ); if (measurement) { - _checkForCachedJumpToMeasurementEvents( - elementRef, - viewportId, - displaySets, - servicesManager - ); - cacheJumpToMeasurementEvent = null; + cs3DTools.annotation.selection.setAnnotationSelected(measurement.uid); } }; @@ -323,6 +318,8 @@ const OHIFCornerstoneViewport = React.memo( servicesManager ); + _checkForCachedJumpToMeasurementEvents(elementRef, viewportId, displaySets, servicesManager); + return () => { unsubscribeFromJumpToMeasurementEvents(); }; @@ -454,16 +451,6 @@ function _subscribeToJumpToMeasurementEvents(elementRef, viewportId, servicesMan if (cacheJumpToMeasurementEvent.cornerstoneViewport !== viewportId) { return; } - const viewportInfo = cornerstoneViewportService.getViewportInfo(viewportId); - // Confirm viewportInfo matches measurement displaySetInstanceUID and referencedImageId - if ( - !viewportInfo?.contains( - measurement.displaySetInstanceUID, - measurement.referencedImageId || measurement.metadata?.referencedImageId - ) - ) { - return; - } _jumpToMeasurement(measurement, elementRef, viewportId, servicesManager); } ); diff --git a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts index bc3800928..82f7fbb03 100644 --- a/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts +++ b/extensions/cornerstone/src/services/ViewportService/CornerstoneViewportService.ts @@ -372,7 +372,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi * @param publicDisplaySetOptions - The public display set options. * @param presentations - The presentations to set. */ - public async setViewportData( + public setViewportData( viewportId: string, viewportData: StackViewportData | VolumeViewportData, publicViewportOptions: PublicViewportOptions, @@ -458,14 +458,21 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi this.viewportsById.set(viewportId, viewportInfo); const viewport = renderingEngine.getViewport(viewportId); - await this._setDisplaySets(viewport, viewportData, viewportInfo, presentations); + const displaySetPromise = this._setDisplaySets( + viewport, + viewportData, + viewportInfo, + presentations + ); // The broadcast event here ensures that listeners have a valid, up to date // viewport to access. Doing it too early can result in exceptions or // invalid data. - this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, { - viewportData, - viewportId, + displaySetPromise.then(() => { + this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, { + viewportData, + viewportId, + }); }); } diff --git a/platform/app/src/components/ViewportGrid.tsx b/platform/app/src/components/ViewportGrid.tsx index b00974fdc..53f8b2242 100644 --- a/platform/app/src/components/ViewportGrid.tsx +++ b/platform/app/src/components/ViewportGrid.tsx @@ -6,7 +6,6 @@ import { useViewportGrid } from '@ohif/ui-next'; import EmptyViewport from './EmptyViewport'; import classNames from 'classnames'; import { useAppConfig } from '@state'; -import getClosestOrientationFromIOP from '../utils/getClosestOrientationFromIOP'; function ViewerViewportGrid(props: withAppTypes) { const { servicesManager, viewportComponents = [], dataSource } = props; @@ -178,20 +177,7 @@ function ViewerViewportGrid(props: withAppTypes) { const { displaySetInstanceUID: referencedDisplaySetInstanceUID } = measurement; const updatedViewports = _getUpdatedViewports(viewportId, referencedDisplaySetInstanceUID); - let viewportToUpdate; - if (updatedViewports.length > 1) { - // To get the viewport which orientation is closest to IOP - const closestOrientation = getClosestOrientationFromIOP( - displaySetService, - referencedDisplaySetInstanceUID - ); - viewportToUpdate = updatedViewports.find( - viewport => viewport.viewportOptions?.orientation == closestOrientation - ); - } - // If closest orientation viewport is not find then choose 0 - viewportToUpdate = updatedViewports[0]; - if (!viewportToUpdate) { + if (!updatedViewports[0]) { console.warn( 'ViewportGrid::Unable to navigate to viewport containing', referencedDisplaySetInstanceUID @@ -199,9 +185,14 @@ function ViewerViewportGrid(props: withAppTypes) { return; } + // Arbitrarily assign the viewport to element 0 + // TODO - this should perform a search to find the most suitable viewport. + updatedViewports[0] = { ...updatedViewports[0] }; + const [viewport] = updatedViewports; + // Copy the viewport options to prevent modifying the internal data - viewportToUpdate.viewportOptions = { - ...viewportToUpdate.viewportOptions, + viewport.viewportOptions = { + ...viewport.viewportOptions, orientation: 'acquisition', // The preferred way to jump to the measurement view is to set the // view reference, as this can hold information such as the orientation diff --git a/platform/app/src/utils/getClosestOrientationFromIOP.ts b/platform/app/src/utils/getClosestOrientationFromIOP.ts deleted file mode 100644 index 735b9ba57..000000000 --- a/platform/app/src/utils/getClosestOrientationFromIOP.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { vec3 } from 'gl-matrix'; -import { Enums } from '@cornerstonejs/core'; -import OrientationAxis = Enums.OrientationAxis; - -/** - * Get the plane (orientation) to which the ImageOrientationPatient is most closely aligned - * - * @param displaySetService - * @param displaySetInstanceUID - * @returns orientation - */ -export default function getClosestOrientationFromIOP( - displaySetService, - displaySetInstanceUID -): OrientationAxis { - const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID); - const imageOrientationPatient = displaySet.instances[0].ImageOrientationPatient as Array; - // ImageOrientationPatient must be an array of length 6. - if (imageOrientationPatient?.length !== 6) { - return; - } - - // Take cross product to get vector coming "out" of image plane - const rowCosineVec = vec3.fromValues( - imageOrientationPatient[0], - imageOrientationPatient[1], - imageOrientationPatient[2] - ); - const colCosineVec = vec3.fromValues( - imageOrientationPatient[3], - imageOrientationPatient[4], - imageOrientationPatient[5] - ); - const scanAxisNormal = vec3.cross(vec3.create(), rowCosineVec, colCosineVec); - - // Define the reference vectors for axial, coronal, and sagittal planes - const unitVectors = { - [OrientationAxis.AXIAL]: vec3.fromValues(0, 0, 1), - [OrientationAxis.CORONAL]: vec3.fromValues(0, 1, 0), - [OrientationAxis.SAGITTAL]: vec3.fromValues(1, 0, 0), - }; - - // Compute dot products for each reference plane - // Because all vectors are normalized, dot product is bounded between -1 and 1 - let maxDot = 0; - let maxOrientation: string = ''; - for (const [k, v] of Object.entries(unitVectors)) { - // Absolute value of dot product because we only care about alignment with the axis - // For example, dot product of -1 for a given axis means perfect alignment - // but the image is pointing in the "opposite" direction - const res = Math.abs(vec3.dot(scanAxisNormal, v)); - if (res > maxDot) { - maxDot = res; - maxOrientation = k; - } - } - - return maxOrientation as OrientationAxis; -}