Skip to content

Commit

Permalink
feat: Add lockedSegments and global segmentation config update
Browse files Browse the repository at this point in the history
  • Loading branch information
sedghi authored and swederik committed Mar 21, 2022
1 parent 792fa36 commit 2ea8579
Show file tree
Hide file tree
Showing 10 changed files with 434 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ async function addNewLabelmap({
labelmapState = {
volumeUID: labelmapUID,
activeSegmentIndex: 1,
segmentsHidden: [],
segmentsHidden: new Set(),
segmentsLocked: new Set(),
colorLUTIndex: 0,
labelmapConfig: {},
cfun: vtkColorTransferFunction.newInstance(),
ofun: vtkPiecewiseFunction.newInstance(),
}
Expand Down
23 changes: 22 additions & 1 deletion packages/cornerstone-tools/src/store/SegmentationModule/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ import {
setActiveSegmentIndex,
getActiveSegmentIndex,
} from './activeSegmentIndex'
// import * as segmentationConfig from './segmentationConfig'
import {
setSegmentIndexLockedForElement,
setSegmentIndexUnlockedForElement,
getSegmentIndexLockedStatusForElement,
getSegmentsLockedForElement,
toggleSegmentIndexLockedForElement,
toggleSegmentIndexLockedForLabelmapUID,
} from './lockSegmentIndex'
import config, { setGlobalConfig } from './segmentationConfig'
import { addNewLabelmap } from './addNewLabelmap'
import { setColorLUT, getColorForSegmentIndexColorLUT } from './colorLUT'
Expand All @@ -40,6 +47,12 @@ export {
getActiveSegmentIndexForLabelmapUID,
config,
setGlobalConfig,
setSegmentIndexLockedForElement,
setSegmentIndexUnlockedForElement,
getSegmentIndexLockedStatusForElement,
getSegmentsLockedForElement,
toggleSegmentIndexLockedForElement,
toggleSegmentIndexLockedForLabelmapUID,
}

export default {
Expand Down Expand Up @@ -75,4 +88,12 @@ export default {
getNextLabelmapIndex,
getActiveSegmentIndexForLabelmapUID,
triggerLabelmapsUpdated,

// Locked segment index
setSegmentIndexLockedForElement,
setSegmentIndexUnlockedForElement,
getSegmentIndexLockedStatusForElement,
getSegmentsLockedForElement,
toggleSegmentIndexLockedForElement,
toggleSegmentIndexLockedForLabelmapUID,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import { getEnabledElement } from '@ohif/cornerstone-render'
import { getActiveLabelmapIndex } from './activeLabelmapIndex'
import state from './state'

/**
* Update the locked status of the segmentIndex for the viewportUID based
* on the provided lockedStatus
* @param viewportUIDs viewportUID
* @param labelmapIndex labelmapIndex in the viewport state
* @param segmentIndex segment index
* @param lockedStatus is locked or not
*/
function updateSegmentIndexLockStatus(
viewportUIDs,
labelmapIndex,
segmentIndex,
lockedStatus
) {
viewportUIDs.forEach((viewportUID) => {
const viewportLabelmaps = state.volumeViewports[viewportUID].labelmaps
if (lockedStatus === true) {
viewportLabelmaps[labelmapIndex].segmentsLocked.add(segmentIndex)
} else {
viewportLabelmaps[labelmapIndex].segmentsLocked.delete(segmentIndex)
}
})
}

/**
* Set the segmentIndex to be locked of the canvas's labelmap based on its index
* If no labelmapIndex is provided it uses the active labelmap
*
* @param canvas HTML Canvas
* @param segmentIndex segment index
* @param labelmapIndex labelmapIndex in the viewport state
*/
function setSegmentIndexLockedForElement(
canvas: HTMLCanvasElement,
segmentIndex: number,
labelmapIndex?: number
): void {
let index = labelmapIndex
if (!labelmapIndex) {
index = getActiveLabelmapIndex(canvas)
}

const { sceneUID, scene } = getEnabledElement(canvas)
if (!sceneUID) {
throw new Error('Segmentation not implemented for stack viewport yet')
}

const viewportUIDs = scene.getViewportUIDs()
const lockedStatus = true
updateSegmentIndexLockStatus(viewportUIDs, index, segmentIndex, lockedStatus)
}

/**
* Set the segmentIndex to be unlocked of the canvas's labelmap based on its index
* If no labelmapIndex is provided it uses the active labelmap
*
* @param canvas HTML Canvas
* @param segmentIndex segment index
* @param labelmapIndex labelmapIndex in the viewport state
*/
function setSegmentIndexUnlockedForElement(
canvas: HTMLCanvasElement,
segmentIndex: number,
labelmapIndex?: number
): void {
let index = labelmapIndex
if (!labelmapIndex) {
index = getActiveLabelmapIndex(canvas)
}

const { sceneUID, scene } = getEnabledElement(canvas)
if (!sceneUID) {
throw new Error('Segmentation not implemented for stack viewport yet')
}

const viewportUIDs = scene.getViewportUIDs()
const lockedStatus = false
updateSegmentIndexLockStatus(viewportUIDs, index, segmentIndex, lockedStatus)
}

/**
* Returns the lock status of the segment index for the canvas's labelmapIndex-th labelmap.
* If no labelmapIndex is provided it uses the active labelmap
* @param canvas HTML Canvas
* @param segmentIndex segment Index
* @param labelmapIndex? labelmap Index
* @returns
*/
function getSegmentIndexLockedStatusForElement(
canvas: HTMLCanvasElement,
segmentIndex: number,
labelmapIndex?: number
): boolean {
let index = labelmapIndex
if (!labelmapIndex) {
index = getActiveLabelmapIndex(canvas)
}

const { sceneUID, viewportUID } = getEnabledElement(canvas)
if (!sceneUID) {
throw new Error('Segmentation not implemented for stack viewport yet')
}

const viewportState = state.volumeViewports[viewportUID]

if (!viewportState) {
return false
}

const viewportLabelmaps = viewportState.labelmaps
return viewportLabelmaps[index].segmentsLocked.has(segmentIndex)
}

/**
* Returns the locked segments for the canvas's labelmapIndex-th labelmap
* If no labelmapIndex is provided it uses the active labelmap
*
* @param canvas HTML canvas
* @param labelmapIndex labelmap Index
* @returns
*/
function getSegmentsLockedForElement(
canvas: HTMLCanvasElement,
labelmapIndex?: number
): number[] {
let index = labelmapIndex
if (!labelmapIndex) {
index = getActiveLabelmapIndex(canvas)
}

const { sceneUID, viewportUID } = getEnabledElement(canvas)
if (!sceneUID) {
throw new Error('Segmentation not implemented for stack viewport yet')
}

const viewportLabelmaps = state.volumeViewports[viewportUID].labelmaps
return Array.from(viewportLabelmaps[index].segmentsLocked)
}

/**
* Toggles the locked status of segments for the canvas's labelmapIndex-th labelmap
* If no labelmapIndex is provided it uses the active labelmap
* @param canvas HTML Canvas
* @param segmentIndex segment index
* @param labelmapIndex labelmap index
* @returns
*/
function toggleSegmentIndexLockedForElement(
canvas: HTMLCanvasElement,
segmentIndex: number,
labelmapIndex?: number
): void {
const lockedStatus = getSegmentIndexLockedStatusForElement(
canvas,
segmentIndex,
labelmapIndex
)

const toggledStatus = !lockedStatus

if (toggledStatus === true) {
setSegmentIndexLockedForElement(canvas, segmentIndex, labelmapIndex)
return
}

setSegmentIndexUnlockedForElement(canvas, segmentIndex, labelmapIndex)
}

/**
* Toggles the locked status of segments for labelmapUID
* @param labelmapUID labelmap volumeUID
* @param segmentIndex segment index
* @returns
*/
function toggleSegmentIndexLockedForLabelmapUID(
labelmapUID: string,
segmentIndex: number
): void {
if (!labelmapUID) {
throw new Error('LabelmapUID should be provided')
}
// todo: stack viewport

Object.keys(state.volumeViewports).forEach((viewportUID) => {
const viewportLabelmaps = state.volumeViewports[viewportUID].labelmaps
viewportLabelmaps.forEach(({ volumeUID, segmentsLocked }) => {
if (volumeUID === labelmapUID) {
if (segmentsLocked.has(segmentIndex)) {
segmentsLocked.delete(segmentIndex)
} else {
segmentsLocked.add(segmentIndex)
}
}
})
})
}

export {
// Element-wise locking
setSegmentIndexLockedForElement,
setSegmentIndexUnlockedForElement,
getSegmentsLockedForElement,
// labelmap-wise locking
toggleSegmentIndexLockedForLabelmapUID,
//
getSegmentIndexLockedStatusForElement,
toggleSegmentIndexLockedForElement,
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function setLabelmapColorAndOpacity(
): void {
ofun.addPoint(0, 0)

// Todo: this should be moved a level up
let config = _cloneDeep(defaultConfig)

// if custom config per labelmap
Expand Down Expand Up @@ -49,7 +50,7 @@ function setLabelmapColorAndOpacity(

// Set the opacity per label.
const segmentOpacity = (color[3] / 255) * fillAlpha
ofun.addPointLong(i, segmentOpacity, 0.5, 1.0)
ofun.addPoint(i, segmentOpacity)
}

ofun.setClamping(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import setLabelmapColorAndOpacity from './setLabelmapColorAndOpacity'
import { CornerstoneTools3DEvents as EVENTS } from '../../enums'

import { getActiveLabelmapIndex } from './activeLabelmapIndex'
import { getLockedSegmentsForLabelmapUID } from './utils'

type LabelmapEvent = {
canvas: HTMLCanvasElement
Expand Down Expand Up @@ -115,6 +116,9 @@ function updateStateForVolumeViewports(
labelmapIndex,
labelmapUID
) {
// Set the locked segments if labelmap already exists in another viewport
const lockedSegments = getLockedSegmentsForLabelmapUID(labelmapUID)

viewportsUIDs.forEach((viewportUID) => {
let viewportState = state.volumeViewports[viewportUID]

Expand All @@ -137,7 +141,8 @@ function updateStateForVolumeViewports(
volumeUID: labelmapUID,
activeSegmentIndex: 1,
colorLUTIndex: 0,
segmentsHidden: [],
segmentsHidden: new Set(),
segmentsLocked: new Set(lockedSegments),
cfun: vtkColorTransferFunction.newInstance(),
ofun: vtkPiecewiseFunction.newInstance(),
labelmapConfig: {},
Expand Down
Loading

0 comments on commit 2ea8579

Please sign in to comment.