Skip to content

Commit

Permalink
fix: remove the need for volumeUID to be passed in the configuration (#…
Browse files Browse the repository at this point in the history
…337)

* fix: remove the need for volumeUID to be passed in the configuration

* fix class methods
  • Loading branch information
sedghi authored and swederik committed Mar 22, 2022
1 parent 3f296ae commit 301d3ab
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 229 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,16 @@ class VolumeViewport extends Viewport {

// One actor per volume
for (let i = 0; i < volumeInputArray.length; i++) {
const { volumeUID, slabThickness } = volumeInputArray[i]
const { volumeUID, slabThickness, actorUID } = volumeInputArray[i]
const volumeActor = await createVolumeActor(volumeInputArray[i])

volumeActors.push({ uid: volumeUID, volumeActor, slabThickness })
// We cannot use only volumeUID since then we cannot have for instance more
// than one representation of the same volume (since actors would have the
// same name, and we don't allow that) AND We cannot use only any uid, since
// we rely on the volume in the cache for mapper. So we prefer actorUID if
// it is defined, otherwise we use volumeUID for the actor name.
const uid = actorUID || volumeUID
volumeActors.push({ uid, volumeActor, slabThickness })

if (
slabThickness !== undefined &&
Expand Down
2 changes: 1 addition & 1 deletion packages/cornerstone-render/src/types/IVolumeInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type VolumeInputCallback = (params: {
type IVolumeInput = {
volumeUID: string
// actorUID for segmentations, since two segmentations with the same volumeUID
// can have different represetnations
// can have different representations
actorUID?: string
visibility?: boolean
callback?: VolumeInputCallback
Expand Down
22 changes: 1 addition & 21 deletions packages/cornerstone-tools/src/tools/MIPJumpToClickTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default class MIPJumpToClickTool extends BaseTool {
const { viewport, renderingEngine } = enabledElement

// 2. Getting the target volume that is clicked on
const targetVolumeUID = this._getTargetVolumeUID(viewport as VolumeViewport)
const targetVolumeUID = this.getTargetUID(viewport as VolumeViewport)

// 3. Criteria function to search for the point (maximum intensity)
let maxIntensity = -Infinity
Expand Down Expand Up @@ -75,24 +75,4 @@ export default class MIPJumpToClickTool extends BaseTool {
jumpToWorld(viewport, brightestPoint)
})
}

/**
* Returns the volume UID in the viewport. It returns the first volume.
* @param viewport viewport
* @returns volume UID
*/
_getTargetVolumeUID = (viewport: VolumeViewport): string => {
if (this.configuration.volumeUID) {
return this.configuration.volumeUID
}

const actors = viewport.getActors()

if (!actors && !actors.length) {
// No stack to scroll through
return
}

return actors[0].uid
}
}
10 changes: 8 additions & 2 deletions packages/cornerstone-tools/src/tools/StackScrollTool.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { getEnabledElementByUIDs } from '@precisionmetrics/cornerstone-render'
import { BaseTool } from './base'
import { scrollThroughStack } from '../util/stackScrollTool'

Expand All @@ -19,9 +20,14 @@ export default class StackScrollTool extends BaseTool {
}

_dragCallback(evt) {
const { deltaPoints } = evt.detail
const { deltaPoints, viewportUID, renderingEngineUID } = evt.detail
const deltaFrames = deltaPoints.canvas[1]
const { volumeUID, invert } = this.configuration
const { viewport } = getEnabledElementByUIDs(
renderingEngineUID,
viewportUID
)
const volumeUID = this.getTargetUID(viewport)
const { invert } = this.configuration

scrollThroughStack(evt, deltaFrames, volumeUID, invert)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ export default class StackScrollMouseWheelTool extends BaseTool {
mouseWheelCallback(evt) {
const { wheel } = evt.detail
const { direction: deltaFrames } = wheel

const { volumeUID, invert } = this.configuration
const { invert, volumeUID } = this.configuration
scrollThroughStack(evt, deltaFrames, volumeUID, invert)
}
}
2 changes: 1 addition & 1 deletion packages/cornerstone-tools/src/tools/WindowLevelTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default class WindowLevelTool extends BaseTool {
let useDynamicRange = false

if (viewport instanceof VolumeViewport) {
volumeUID = this.configuration.volumeUID
volumeUID = this.getTargetUID(viewport as VolumeViewport)
;({ volumeActor } = viewport.getActor(volumeUID))
rgbTransferFunction = volumeActor.getProperty().getRGBTransferFunction(0)
viewportsContainingVolumeUID = getVolumeViewportsContainingVolumeUID(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default class BidirectionalTool extends BaseAnnotationTool {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId()
} else {
const { volumeUID } = this.configuration
const volumeUID = this.getTargetUID(viewport)
const imageVolume = getVolume(volumeUID)
referencedImageId = getImageIdForTool(
worldPos,
Expand Down Expand Up @@ -972,14 +972,7 @@ export default class BidirectionalTool extends BaseAnnotationTool {
}

const { viewport } = enabledElement
let targetUID
if (viewport.type === VIEWPORT_TYPE.STACK) {
targetUID = this._getTargetStackUID(viewport)
} else if (viewport.type === VIEWPORT_TYPE.ORTHOGRAPHIC) {
targetUID = this._getTargetVolumeUID(viewport)
} else {
throw new Error(`Viewport Type not supported: ${viewport.type}`)
}
const targetUID = this.getTargetUID(viewport)

const renderingEngine = viewport.getRenderingEngine()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export default class EllipticalRoiTool extends BaseAnnotationTool {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId()
} else {
const { volumeUID } = this.configuration
const volumeUID = this.getTargetUID(viewport)
const imageVolume = getVolume(volumeUID)
referencedImageId = getImageIdForTool(
worldPos,
Expand Down Expand Up @@ -708,15 +708,8 @@ export default class EllipticalRoiTool extends BaseAnnotationTool {
}

const { viewport } = enabledElement
const targetUID = this.getTargetUID(viewport)

let targetUID
if (viewport instanceof StackViewport) {
targetUID = this._getTargetStackUID(viewport)
} else if (viewport instanceof VolumeViewport) {
targetUID = this._getTargetVolumeUID(viewport)
} else {
throw new Error(`Viewport Type not supported: ${viewport.type}`)
}
const renderingEngine = viewport.getRenderingEngine()

for (let i = 0; i < toolState.length; i++) {
Expand Down Expand Up @@ -769,7 +762,7 @@ export default class EllipticalRoiTool extends BaseAnnotationTool {
// at the referencedImageId
const viewports = renderingEngine.getViewports()
viewports.forEach((vp) => {
const stackTargetUID = this._getTargetStackUID(vp)
const stackTargetUID = this.getTargetUID(vp)
// only delete the cachedStats for the stackedViewports if the tool
// is dragged inside the volume and the stackViewports are not at the
// referencedImageId for the tool
Expand Down
11 changes: 2 additions & 9 deletions packages/cornerstone-tools/src/tools/annotation/LengthTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class LengthTool extends BaseAnnotationTool {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId()
} else {
const { volumeUID } = this.configuration
const volumeUID = this.getTargetUID(viewport)
const imageVolume = getVolume(volumeUID)
referencedImageId = getImageIdForTool(
worldPos,
Expand Down Expand Up @@ -554,14 +554,7 @@ class LengthTool extends BaseAnnotationTool {
}

const { viewport } = enabledElement
let targetUID
if (viewport.type === VIEWPORT_TYPE.STACK) {
targetUID = this._getTargetStackUID(viewport)
} else if (viewport.type === VIEWPORT_TYPE.ORTHOGRAPHIC) {
targetUID = this._getTargetVolumeUID(viewport)
} else {
throw new Error(`Viewport Type not supported: ${viewport.type}`)
}
const targetUID = this.getTargetUID(viewport)

const renderingEngine = viewport.getRenderingEngine()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export default class SUVPeakTool extends EllipticalRoiTool {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId()
} else {
const { volumeUID } = this.configuration
const volumeUID = this.getTargetUID(viewport)
const imageVolume = getVolume(volumeUID)
referencedImageId = getImageIdForTool(
worldPos,
Expand Down Expand Up @@ -615,7 +615,8 @@ export default class SUVPeakTool extends EllipticalRoiTool {
}

// Todo: should this be inside the constructor?
const volume = getVolume(this.configuration.volumeUID)
const volumeUID = this.getTargetUID(viewport)
const volume = getVolume(volumeUID)
const operationData = {
points: data.handles.points,
viewPlaneNormal,
Expand Down
13 changes: 3 additions & 10 deletions packages/cornerstone-tools/src/tools/annotation/ProbeTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default class ProbeTool extends BaseAnnotationTool {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId()
} else {
const { volumeUID } = this.configuration
const volumeUID = this.getTargetUID(viewport)
const imageVolume = getVolume(volumeUID)
referencedImageId = getImageIdForTool(
worldPos,
Expand Down Expand Up @@ -354,14 +354,7 @@ export default class ProbeTool extends BaseAnnotationTool {

const { viewport } = enabledElement

let targetUID
if (viewport instanceof StackViewport) {
targetUID = this._getTargetStackUID(viewport)
} else if (viewport instanceof VolumeViewport) {
targetUID = this._getTargetVolumeUID(viewport)
} else {
throw new Error(`Viewport Type not supported: ${viewport.type}`)
}
const targetUID = this.getTargetUID(viewport)

const renderingEngine = viewport.getRenderingEngine()

Expand Down Expand Up @@ -395,7 +388,7 @@ export default class ProbeTool extends BaseAnnotationTool {
// at the referencedImageId
const viewports = renderingEngine.getViewports()
viewports.forEach((vp) => {
const stackTargetUID = this._getTargetStackUID(vp)
const stackTargetUID = this.getTargetUID(vp)
// only delete the cachedStats for the stackedViewports if the tool
// is dragged inside the volume and the stackViewports are not at the
// referencedImageId for the tool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export default class RectangleRoiTool extends BaseAnnotationTool {
referencedImageId =
viewport.getCurrentImageId && viewport.getCurrentImageId()
} else {
const { volumeUID } = this.configuration
const volumeUID = this.getTargetUID(viewport)
const imageVolume = getVolume(volumeUID)
referencedImageId = getImageIdForTool(
worldPos,
Expand Down Expand Up @@ -616,15 +616,7 @@ export default class RectangleRoiTool extends BaseAnnotationTool {
}

const { viewport } = enabledElement

let targetUID
if (viewport instanceof StackViewport) {
targetUID = this._getTargetStackUID(viewport)
} else if (viewport instanceof VolumeViewport) {
targetUID = this._getTargetVolumeUID(viewport)
} else {
throw new Error(`Viewport Type not supported: ${viewport.type}`)
}
const targetUID = this.getTargetUID(viewport)

const renderingEngine = viewport.getRenderingEngine()

Expand Down Expand Up @@ -676,7 +668,7 @@ export default class RectangleRoiTool extends BaseAnnotationTool {
// at the referencedImageId
const viewports = renderingEngine.getViewports()
viewports.forEach((vp) => {
const stackTargetUID = this._getTargetStackUID(vp)
const stackTargetUID = this.getTargetUID(vp)
// only delete the cachedStats for the stackedViewports if the tool
// is dragged inside the volume and the stackViewports are not at the
// referencedImageId for the tool
Expand Down
20 changes: 1 addition & 19 deletions packages/cornerstone-tools/src/tools/base/BaseAnnotationTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ abstract class BaseAnnotationTool extends BaseTool {
* @param {CustomEvent} evt The event.
* @param {ToolSpecificToolData} toolData - The toolData selected.
* @param {any} handle - The selected handle.
* @param {string} interactionType - The intraction type the handle was selected with.
* @param {string} interactionType - The interaction type the handle was selected with.
*/
public abstract handleSelectedCallback(
evt,
Expand Down Expand Up @@ -330,24 +330,6 @@ abstract class BaseAnnotationTool extends BaseTool {
lineDash: this.getStyle(settings, 'textBox.link.lineDash', toolData),
}
}

_getTargetStackUID(viewport) {
return `stackTarget:${viewport.uid}`
}

_getTargetVolumeUID = (viewport) => {
if (this.configuration.volumeUID) {
return this.configuration.volumeUID
}

const actors = viewport.getActors()

if (!actors && !actors.length) {
return
}

return actors[0].volumeActor.uid
}
}

export default BaseAnnotationTool
59 changes: 59 additions & 0 deletions packages/cornerstone-tools/src/tools/base/BaseTool.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
StackViewport,
Types,
VolumeViewport,
} from '@precisionmetrics/cornerstone-render'
import deepMerge from '../../util/deepMerge'
import { ToolModes } from '../../enums'

Expand Down Expand Up @@ -74,6 +79,60 @@ abstract class BaseTool {
public setActiveStrategy(strategyName: string): void {
this.setConfiguration({ activeStrategy: strategyName })
}

/**
* Returns the volumeUID for the volume viewport. It will grabbed the volumeUID
* from the volumeUID if particularly specified in the tool configuration, or if
* not, the first actorUID in the viewport is returned as the volumeUID. NOTE: for
* segmentations, actorUID is not necessarily the volumeUID since the segmentation
* can have multiple representations, use SegmentationModule to get the volumeUID
* based on the actorUID.
*
* @param viewport - Volume viewport
* @returns the volumeUID for the viewport if specified in the tool configuration,
* or the first actorUID in the viewport if not.
*/
private getTargetVolumeUID(viewport: Types.IViewport): string | undefined {
if (!(viewport instanceof VolumeViewport)) {
throw new Error('getTargetVolumeUID: viewport must be a VolumeViewport')
}

if (this.configuration.volumeUID) {
return this.configuration.volumeUID
}

// If volume not specified, then return the actorUID for the
// default actor - first actor
const actors = viewport.getActors()

if (!actors && !actors.length) {
return
}

return actors[0].uid
}

/**
* Get the target UID for the viewport which will be used to store the cached
* statistics scoped to that target in the toolState.
* For StackViewport, targetUID is the viewportUID, but for the volume viewport,
* the targetUID will be grabbed from the volumeUID if particularly specified
* in the tool configuration, or if not, the first actorUID in the viewport.
*
* @param viewport - viewport to get the targetUID for
* @returns targetUID
*/
protected getTargetUID(viewport: Types.IViewport): string | undefined {
if (viewport instanceof StackViewport) {
return `stackTarget:${viewport.uid}`
} else if (viewport instanceof VolumeViewport) {
return this.getTargetVolumeUID(viewport)
} else {
throw new Error(
'getTargetUID: viewport must be a StackViewport or VolumeViewport'
)
}
}
}

export default BaseTool
Original file line number Diff line number Diff line change
Expand Up @@ -324,19 +324,4 @@ export default class CircleScissorsTool extends BaseTool {
}
)
}

_getTargetVolumeUID = (viewport) => {
if (this.configuration.volumeUID) {
return this.configuration.volumeUID
}

const actors = viewport.getActors()

if (!actors && !actors.length) {
// No stack to scroll through
return
}

return actors[0].uid
}
}
Loading

0 comments on commit 301d3ab

Please sign in to comment.