From d2ec3818b58947985c336eb2a8032592b153cfff Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Thu, 9 Mar 2023 16:00:49 -0500 Subject: [PATCH 1/5] fix: Scrolling failed to find the volume on 2cd segmentation --- packages/tools/src/utilities/cine/playClip.ts | 3 ++- packages/tools/src/utilities/scroll.ts | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/tools/src/utilities/cine/playClip.ts b/packages/tools/src/utilities/cine/playClip.ts index c09962cdb..dd21e8eb6 100644 --- a/packages/tools/src/utilities/cine/playClip.ts +++ b/packages/tools/src/utilities/cine/playClip.ts @@ -103,7 +103,7 @@ function playClip( targetImageIdIndex: viewport.getTargetImageIdIndex(), imageIds: viewport.getImageIds(), }; - + let newImageIdIndex = stackData.targetImageIdIndex; const imageCount = stackData.imageIds.length; @@ -182,6 +182,7 @@ function playClip( */ function stopClip(element: HTMLDivElement): void { const enabledElement = getEnabledElement(element); + if (!enabledElement) return; const { viewport } = enabledElement; const cineToolData = getToolState(viewport.element); diff --git a/packages/tools/src/utilities/scroll.ts b/packages/tools/src/utilities/scroll.ts index 1afe01a54..7dd3e9cf5 100644 --- a/packages/tools/src/utilities/scroll.ts +++ b/packages/tools/src/utilities/scroll.ts @@ -47,10 +47,13 @@ export function scrollVolume( ); } - const actorEntry = viewport.getActor(imageVolume.volumeId); + const actorEntry = viewport + .getActors() + .find((it) => it.referenceId === imageVolume.volumeId); if (!actorEntry) { console.warn('No actor found for with actorUID of', imageVolume.volumeId); + return; } const volumeActor = actorEntry.actor as Types.VolumeActor; From a9c609443ee633c9a4bd5429bb97ddab279f8677 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 10 Mar 2023 10:56:17 -0500 Subject: [PATCH 2/5] fix: Make scrolling work on segmentations that are slightly different spacing --- .../getTargetVolumeAndSpacingInNormalDir.ts | 17 ++++++++++++----- packages/tools/src/types/JumpToSliceOptions.ts | 1 + packages/tools/src/utilities/scroll.ts | 10 ++++------ .../tools/src/utilities/viewport/jumpToSlice.ts | 4 ++-- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts b/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts index 628e9f3b5..09b67b5ae 100644 --- a/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts +++ b/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts @@ -25,12 +25,13 @@ export default function getTargetVolumeAndSpacingInNormalDir( ): { imageVolume: IImageVolume; spacingInNormalDirection: number; + uid: string; } { const { viewPlaneNormal } = camera; const volumeActors = viewport.getActors(); if (!volumeActors || !volumeActors.length) { - return { spacingInNormalDirection: null, imageVolume: null }; + return { spacingInNormalDirection: null, imageVolume: null, uid: null }; } const imageVolumes = volumeActors @@ -44,26 +45,29 @@ export default function getTargetVolumeAndSpacingInNormalDir( // If a volumeId is defined, set that volume as the target if (targetVolumeId) { - const imageVolume = imageVolumes.find( + const imageVolumeIndex = imageVolumes.findIndex( (iv) => iv.volumeId === targetVolumeId ); + const imageVolume = imageVolumes[imageVolumeIndex]; + const { uid } = volumeActors[imageVolumeIndex]; const spacingInNormalDirection = getSpacingInNormalDirection( imageVolume, viewPlaneNormal ); - return { imageVolume, spacingInNormalDirection }; + return { imageVolume, spacingInNormalDirection, uid }; } if (!imageVolumes.length) { - return { spacingInNormalDirection: null, imageVolume: null }; + return { spacingInNormalDirection: null, imageVolume: null, uid: null }; } // Fetch volume actor with finest resolution in direction of projection. const smallest = { spacingInNormalDirection: Infinity, imageVolume: null, + uid: null, }; for (let i = 0; i < imageVolumes.length; i++) { @@ -74,9 +78,12 @@ export default function getTargetVolumeAndSpacingInNormalDir( viewPlaneNormal ); - if (spacingInNormalDirection < smallest.spacingInNormalDirection) { + // Allow for 1/1000 part larger requirement to prefer earlier volumes + // when the spacing is all essentially the same. + if (spacingInNormalDirection * 1.001 < smallest.spacingInNormalDirection) { smallest.spacingInNormalDirection = spacingInNormalDirection; smallest.imageVolume = imageVolume; + smallest.uid = volumeActors[i].uid; } } diff --git a/packages/tools/src/types/JumpToSliceOptions.ts b/packages/tools/src/types/JumpToSliceOptions.ts index 984570326..55812466a 100644 --- a/packages/tools/src/types/JumpToSliceOptions.ts +++ b/packages/tools/src/types/JumpToSliceOptions.ts @@ -1,6 +1,7 @@ type JumpToSliceOptions = { imageIndex: number; debounceLoading?: boolean; + volumeId?: string; }; export default JumpToSliceOptions; diff --git a/packages/tools/src/utilities/scroll.ts b/packages/tools/src/utilities/scroll.ts index 7dd3e9cf5..cc07f1f0d 100644 --- a/packages/tools/src/utilities/scroll.ts +++ b/packages/tools/src/utilities/scroll.ts @@ -38,21 +38,19 @@ export function scrollVolume( ) { const camera = viewport.getCamera(); const { focalPoint, viewPlaneNormal, position } = camera; - const { spacingInNormalDirection, imageVolume } = + const { spacingInNormalDirection, uid } = csUtils.getTargetVolumeAndSpacingInNormalDir(viewport, camera, volumeId); - if (!imageVolume) { + if (!uid) { throw new Error( `Could not find image volume with id ${volumeId} in the viewport` ); } - const actorEntry = viewport - .getActors() - .find((it) => it.referenceId === imageVolume.volumeId); + const actorEntry = viewport.getActor(uid); if (!actorEntry) { - console.warn('No actor found for with actorUID of', imageVolume.volumeId); + console.warn('No actor found for with actorUID of', uid); return; } diff --git a/packages/tools/src/utilities/viewport/jumpToSlice.ts b/packages/tools/src/utilities/viewport/jumpToSlice.ts index e810f58cf..7c589783f 100644 --- a/packages/tools/src/utilities/viewport/jumpToSlice.ts +++ b/packages/tools/src/utilities/viewport/jumpToSlice.ts @@ -23,7 +23,7 @@ async function jumpToSlice( element: HTMLDivElement, options = {} as JumpToSliceOptions ): Promise { - const { imageIndex, debounceLoading } = options; + const { imageIndex, debounceLoading, volumeId } = options; const enabledElement = getEnabledElement(element); if (!enabledElement) { @@ -40,7 +40,7 @@ async function jumpToSlice( const imageIndexToJump = _getImageIndexToJump(numberOfSlices, imageIndex); const delta = imageIndexToJump - currentImageIndex; - scroll(viewport, { delta, debounceLoading }); + scroll(viewport, { delta, debounceLoading, volumeId }); } function _getImageSliceData( From e81c18d68cf72f6d43c0fe4b5ea765bd0ce05288 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 10 Mar 2023 11:18:25 -0500 Subject: [PATCH 3/5] Update API --- common/reviews/api/core.api.md | 1 + common/reviews/api/tools.api.md | 1 + 2 files changed, 2 insertions(+) diff --git a/common/reviews/api/core.api.md b/common/reviews/api/core.api.md index a162ba8bd..091f7393f 100644 --- a/common/reviews/api/core.api.md +++ b/common/reviews/api/core.api.md @@ -709,6 +709,7 @@ function getSpacingInNormalDirection(imageVolume: IImageVolume, viewPlaneNormal: function getTargetVolumeAndSpacingInNormalDir(viewport: IVolumeViewport, camera: ICamera, targetVolumeId?: string): { imageVolume: IImageVolume; spacingInNormalDirection: number; + uid: string; }; // @public (undocumented) diff --git a/common/reviews/api/tools.api.md b/common/reviews/api/tools.api.md index 310dccc92..167865a1a 100644 --- a/common/reviews/api/tools.api.md +++ b/common/reviews/api/tools.api.md @@ -2943,6 +2943,7 @@ function jumpToSlice(element: HTMLDivElement, options?: JumpToSliceOptions): Pro type JumpToSliceOptions = { imageIndex: number; debounceLoading?: boolean; + volumeId?: string; }; // @public (undocumented) From 89f5447f09b32cc5bfa161f5da635b0bdbde1d72 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 10 Mar 2023 12:12:30 -0500 Subject: [PATCH 4/5] PR fixes --- .../getTargetVolumeAndSpacingInNormalDir.ts | 40 +++++++++++++------ packages/tools/src/utilities/scroll.ts | 8 ++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts b/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts index 09b67b5ae..41295ccdf 100644 --- a/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts +++ b/packages/core/src/utilities/getTargetVolumeAndSpacingInNormalDir.ts @@ -1,8 +1,12 @@ import cache from '../cache/cache'; +import { EPSILON } from '../constants'; // import type { VolumeViewport } from '../RenderingEngine' import { ICamera, IImageVolume, IVolumeViewport } from '../types'; import getSpacingInNormalDirection from './getSpacingInNormalDirection'; +// One EPSILON part larger multiplier +const EPSILON_PART = 1 + EPSILON; + /** * Given a volume viewport and camera, find the target volume. * The imageVolume is retrieved from cache for the specified targetVolumeId or @@ -25,21 +29,25 @@ export default function getTargetVolumeAndSpacingInNormalDir( ): { imageVolume: IImageVolume; spacingInNormalDirection: number; - uid: string; + actorUID: string; } { const { viewPlaneNormal } = camera; const volumeActors = viewport.getActors(); if (!volumeActors || !volumeActors.length) { - return { spacingInNormalDirection: null, imageVolume: null, uid: null }; + return { + spacingInNormalDirection: null, + imageVolume: null, + actorUID: null, + }; } const imageVolumes = volumeActors .map((va) => { // prefer the referenceUID if it is set, since it can be a derived actor // and the uid does not necessarily match the volumeId - const uid = va.referenceId ?? va.uid; - return cache.getVolume(uid); + const actorUID = va.referenceId ?? va.uid; + return cache.getVolume(actorUID); }) .filter((iv) => !!iv); @@ -50,24 +58,28 @@ export default function getTargetVolumeAndSpacingInNormalDir( ); const imageVolume = imageVolumes[imageVolumeIndex]; - const { uid } = volumeActors[imageVolumeIndex]; + const { uid: actorUID } = volumeActors[imageVolumeIndex]; const spacingInNormalDirection = getSpacingInNormalDirection( imageVolume, viewPlaneNormal ); - return { imageVolume, spacingInNormalDirection, uid }; + return { imageVolume, spacingInNormalDirection, actorUID }; } if (!imageVolumes.length) { - return { spacingInNormalDirection: null, imageVolume: null, uid: null }; + return { + spacingInNormalDirection: null, + imageVolume: null, + actorUID: null, + }; } // Fetch volume actor with finest resolution in direction of projection. const smallest = { spacingInNormalDirection: Infinity, imageVolume: null, - uid: null, + actorUID: null, }; for (let i = 0; i < imageVolumes.length; i++) { @@ -78,12 +90,16 @@ export default function getTargetVolumeAndSpacingInNormalDir( viewPlaneNormal ); - // Allow for 1/1000 part larger requirement to prefer earlier volumes - // when the spacing is all essentially the same. - if (spacingInNormalDirection * 1.001 < smallest.spacingInNormalDirection) { + // Allow for EPSILON part larger requirement to prefer earlier volumes + // when the spacing is within a factor of EPSILON. Use a factor because + // that deals with very small or very large volumes effectively. + if ( + spacingInNormalDirection * EPSILON_PART < + smallest.spacingInNormalDirection + ) { smallest.spacingInNormalDirection = spacingInNormalDirection; smallest.imageVolume = imageVolume; - smallest.uid = volumeActors[i].uid; + smallest.actorUID = volumeActors[i].uid; } } diff --git a/packages/tools/src/utilities/scroll.ts b/packages/tools/src/utilities/scroll.ts index cc07f1f0d..4ee520086 100644 --- a/packages/tools/src/utilities/scroll.ts +++ b/packages/tools/src/utilities/scroll.ts @@ -38,19 +38,19 @@ export function scrollVolume( ) { const camera = viewport.getCamera(); const { focalPoint, viewPlaneNormal, position } = camera; - const { spacingInNormalDirection, uid } = + const { spacingInNormalDirection, actorUID } = csUtils.getTargetVolumeAndSpacingInNormalDir(viewport, camera, volumeId); - if (!uid) { + if (!actorUID) { throw new Error( `Could not find image volume with id ${volumeId} in the viewport` ); } - const actorEntry = viewport.getActor(uid); + const actorEntry = viewport.getActor(actorUID); if (!actorEntry) { - console.warn('No actor found for with actorUID of', uid); + console.warn('No actor found for with actorUID of', actorUID); return; } From 91d7911646ca207fc692fc48b75c4d70fe36be6b Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Fri, 10 Mar 2023 12:29:20 -0500 Subject: [PATCH 5/5] Change the name of uid to actorUID to be more specific --- common/reviews/api/core.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/reviews/api/core.api.md b/common/reviews/api/core.api.md index 091f7393f..5f640876f 100644 --- a/common/reviews/api/core.api.md +++ b/common/reviews/api/core.api.md @@ -709,7 +709,7 @@ function getSpacingInNormalDirection(imageVolume: IImageVolume, viewPlaneNormal: function getTargetVolumeAndSpacingInNormalDir(viewport: IVolumeViewport, camera: ICamera, targetVolumeId?: string): { imageVolume: IImageVolume; spacingInNormalDirection: number; - uid: string; + actorUID: string; }; // @public (undocumented)