From 2ea8579d3ad58a208f9b59f05eb4b594eebb79dd Mon Sep 17 00:00:00 2001 From: Alireza Date: Wed, 29 Sep 2021 23:35:48 -0400 Subject: [PATCH] feat: Add lockedSegments and global segmentation config update --- .../SegmentationModule/addNewLabelmap.ts | 4 +- .../src/store/SegmentationModule/index.ts | 23 +- .../SegmentationModule/lockSegmentIndex.ts | 212 ++++++++++++++++++ .../setLabelmapColorAndOpacity.ts | 3 +- .../setLabelmapForElement.ts | 7 +- .../src/store/SegmentationModule/state.ts | 30 ++- .../src/store/SegmentationModule/utils.ts | 43 +++- .../segmentation/RectangleScissorsTool.ts | 15 +- .../strategies/fillInsideRectangle.ts | 11 +- .../demo/src/ExampleSegmentationRender.tsx | 128 +++++++++-- 10 files changed, 434 insertions(+), 42 deletions(-) create mode 100644 packages/cornerstone-tools/src/store/SegmentationModule/lockSegmentIndex.ts diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/addNewLabelmap.ts b/packages/cornerstone-tools/src/store/SegmentationModule/addNewLabelmap.ts index 3de9d3a1e..3fd34379e 100644 --- a/packages/cornerstone-tools/src/store/SegmentationModule/addNewLabelmap.ts +++ b/packages/cornerstone-tools/src/store/SegmentationModule/addNewLabelmap.ts @@ -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(), } diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/index.ts b/packages/cornerstone-tools/src/store/SegmentationModule/index.ts index 878368f0a..28627b048 100644 --- a/packages/cornerstone-tools/src/store/SegmentationModule/index.ts +++ b/packages/cornerstone-tools/src/store/SegmentationModule/index.ts @@ -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' @@ -40,6 +47,12 @@ export { getActiveSegmentIndexForLabelmapUID, config, setGlobalConfig, + setSegmentIndexLockedForElement, + setSegmentIndexUnlockedForElement, + getSegmentIndexLockedStatusForElement, + getSegmentsLockedForElement, + toggleSegmentIndexLockedForElement, + toggleSegmentIndexLockedForLabelmapUID, } export default { @@ -75,4 +88,12 @@ export default { getNextLabelmapIndex, getActiveSegmentIndexForLabelmapUID, triggerLabelmapsUpdated, + + // Locked segment index + setSegmentIndexLockedForElement, + setSegmentIndexUnlockedForElement, + getSegmentIndexLockedStatusForElement, + getSegmentsLockedForElement, + toggleSegmentIndexLockedForElement, + toggleSegmentIndexLockedForLabelmapUID, } diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/lockSegmentIndex.ts b/packages/cornerstone-tools/src/store/SegmentationModule/lockSegmentIndex.ts new file mode 100644 index 000000000..37a95249d --- /dev/null +++ b/packages/cornerstone-tools/src/store/SegmentationModule/lockSegmentIndex.ts @@ -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, +} diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapColorAndOpacity.ts b/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapColorAndOpacity.ts index e29633387..3f2a41dfa 100644 --- a/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapColorAndOpacity.ts +++ b/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapColorAndOpacity.ts @@ -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 @@ -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) diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapForElement.ts b/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapForElement.ts index bc6b54ee9..9ed7c0a18 100644 --- a/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapForElement.ts +++ b/packages/cornerstone-tools/src/store/SegmentationModule/setLabelmapForElement.ts @@ -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 @@ -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] @@ -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: {}, diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/state.ts b/packages/cornerstone-tools/src/store/SegmentationModule/state.ts index dd2e69b7a..b5dbd4968 100644 --- a/packages/cornerstone-tools/src/store/SegmentationModule/state.ts +++ b/packages/cornerstone-tools/src/store/SegmentationModule/state.ts @@ -5,7 +5,8 @@ import { ISegmentationConfig } from './segmentationConfig' type LabelmapState = { volumeUID: string activeSegmentIndex: number - segmentsHidden: number[] + segmentsHidden: Set + segmentsLocked: Set colorLUTIndex: number cfun: vtkColorTransferFunction ofun: vtkPiecewiseFunction @@ -47,7 +48,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // ], @@ -61,7 +63,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // { @@ -70,7 +73,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // ], @@ -84,7 +88,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // { @@ -93,7 +98,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // ], @@ -110,7 +116,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // { @@ -119,7 +126,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // ], @@ -133,7 +141,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // { @@ -142,7 +151,8 @@ const state: SegmentationState = { // colorLUTIndex: 0, // cfun: new cfun // ofun: new ofun - // segmentsHidden: [], + // segmentsHidden: Set(), + // segmentsLocked: Set(), // labelmapConfig: ISegmentationConfig // }, // ], diff --git a/packages/cornerstone-tools/src/store/SegmentationModule/utils.ts b/packages/cornerstone-tools/src/store/SegmentationModule/utils.ts index fcb3a8541..b32158b41 100644 --- a/packages/cornerstone-tools/src/store/SegmentationModule/utils.ts +++ b/packages/cornerstone-tools/src/store/SegmentationModule/utils.ts @@ -10,8 +10,10 @@ import { CornerstoneTools3DEvents as EVENTS } from '../../enums' /** * Triggers a re-render for all labelmaps, this method can be used to make the - * a modified global configuration applied on all labelmaps + * a modified global configuration applied on all labelmaps for now + * */ +// Todo: add implementation for only one labelmap function triggerLabelmapsUpdated(labelmapUID?: string): void { const { volumeViewports } = state @@ -59,7 +61,7 @@ function triggerLabelmapsUpdated(labelmapUID?: string): void { * @param canvas HTMLCanvasElement * @returns next LabelmapIndex */ -function getNextLabelmapIndex(canvas) { +function getNextLabelmapIndex(canvas: HTMLCanvasElement): number { const enabledElement = getEnabledElement(canvas) if (!enabledElement) { @@ -83,6 +85,12 @@ function getNextLabelmapIndex(canvas) { return numLabelmaps } +/** + * Returns the active segment index for the canvas based on the labelmapUID it renders + * @param canvas HTML Canvas + * @param labelmapUID volumeUID of the labelmap + * @returns + */ function getActiveSegmentIndexForLabelmapUID( canvas: HTMLCanvasElement, labelmapUID: string @@ -106,6 +114,11 @@ function getActiveSegmentIndexForLabelmapUID( return labelmapState.activeSegmentIndex } +/** + * Returns all the labelmapUIDs of the HTML element (active and inactive) + * @param canvas HTML canvas + * @returns + */ function getLabelmapUIDsForElement(canvas: HTMLCanvasElement): string[] { const enabledElement = getEnabledElement(canvas) @@ -129,6 +142,11 @@ function getLabelmapUIDsForElement(canvas: HTMLCanvasElement): string[] { return viewportState.labelmaps.map(({ volumeUID }) => volumeUID) } +/** + * Returns the labelmapUIDs that the viewport with the provided viewportUID contains + * @param viewportUID Viewport UID + * @returns + */ function getLabelmapUIDsForViewportUID(viewportUID: string): string[] { const viewportState = state.volumeViewports[viewportUID] @@ -139,10 +157,31 @@ function getLabelmapUIDsForViewportUID(viewportUID: string): string[] { return viewportState.labelmaps.map(({ volumeUID }) => volumeUID) } +/** + * Returns an array of locked segment indices for the provided labelmapUID + * @param labelmapUID Labelmap volumeUID + * @returns + */ +function getLockedSegmentsForLabelmapUID(labelmapUID: string): number[] { + for (const viewportUID of Object.keys(state.volumeViewports)) { + const viewportLabelmaps = state.volumeViewports[viewportUID].labelmaps + const labelmapState = viewportLabelmaps.find( + ({ volumeUID }) => volumeUID === labelmapUID + ) + + // since segments are locked labelmap-wise + // Todo: change this if segments can be locked per element (scene) + if (labelmapState) { + return Array.from(labelmapState.segmentsLocked) + } + } +} + export { getNextLabelmapIndex, getLabelmapUIDsForElement, getLabelmapUIDsForViewportUID, getActiveSegmentIndexForLabelmapUID, triggerLabelmapsUpdated, + getLockedSegmentsForLabelmapUID, } diff --git a/packages/cornerstone-tools/src/tools/segmentation/RectangleScissorsTool.ts b/packages/cornerstone-tools/src/tools/segmentation/RectangleScissorsTool.ts index f9e99f138..f4d596c0c 100644 --- a/packages/cornerstone-tools/src/tools/segmentation/RectangleScissorsTool.ts +++ b/packages/cornerstone-tools/src/tools/segmentation/RectangleScissorsTool.ts @@ -27,6 +27,7 @@ import { getActiveLabelmapIndex, getActiveSegmentIndex, getColorForSegmentIndexColorLUT, + getSegmentsLockedForElement, } from '../../store/SegmentationModule' /** @@ -42,6 +43,7 @@ export default class RectangleScissorsTool extends BaseTool { toolData: any labelmap: any segmentIndex: number + segmentsLocked: number[] segmentColor: [number, number, number, number] viewportUIDsToRender: string[] handleIndex?: number @@ -87,6 +89,7 @@ export default class RectangleScissorsTool extends BaseTool { } const labelmapUID = await setActiveLabelmapIndex(element, labelmapIndex) const segmentIndex = getActiveSegmentIndex(element) + const segmentsLocked = getSegmentsLockedForElement(element) const segmentColor = getColorForSegmentIndexColorLUT( element, labelmapUID, @@ -132,6 +135,7 @@ export default class RectangleScissorsTool extends BaseTool { toolData, labelmap, segmentIndex, + segmentsLocked, segmentColor, viewportUIDsToRender, handleIndex: 3, @@ -233,8 +237,14 @@ export default class RectangleScissorsTool extends BaseTool { const eventData = evt.detail const { element } = eventData - const { toolData, newAnnotation, hasMoved, labelmap, segmentIndex } = - this.editData + const { + toolData, + newAnnotation, + hasMoved, + labelmap, + segmentIndex, + segmentsLocked, + } = this.editData const { data } = toolData if (newAnnotation && !hasMoved) { @@ -262,6 +272,7 @@ export default class RectangleScissorsTool extends BaseTool { points: data.handles.points, labelmap, segmentIndex, + segmentsLocked, } const eventDetail = { diff --git a/packages/cornerstone-tools/src/tools/segmentation/strategies/fillInsideRectangle.ts b/packages/cornerstone-tools/src/tools/segmentation/strategies/fillInsideRectangle.ts index 79e9d5c06..c202585fd 100644 --- a/packages/cornerstone-tools/src/tools/segmentation/strategies/fillInsideRectangle.ts +++ b/packages/cornerstone-tools/src/tools/segmentation/strategies/fillInsideRectangle.ts @@ -1,13 +1,12 @@ -import { Viewport, cache, ImageVolume } from '@ohif/cornerstone-render' +import { ImageVolume } from '@ohif/cornerstone-render' import { IEnabledElement } from 'cornerstone-render/src/types' -import { vec3 } from 'gl-matrix' -import vtkPaintFilter from 'vtk.js/Sources/Filters/General/PaintFilter' import { Point3 } from '../../../types' type OperationData = { points: [Point3, Point3, Point3, Point3] labelmap: ImageVolume segmentIndex: number + segmentsLocked: number[] } type FillRectangleEvent = { @@ -27,7 +26,7 @@ function fillRectangle( operationData: OperationData, inside = true ): void { - const { labelmap, points, segmentIndex } = operationData + const { labelmap, points, segmentIndex, segmentsLocked } = operationData const { enabledElement } = evt const { renderingEngine } = enabledElement @@ -45,13 +44,13 @@ function fillRectangle( const [[xMin, yMin], [xMax, yMax], [zMin, zMax]] = getBoundingBoxAroundPolygon(rectangleCornersIJK, vtkImageData) - // Todo: this doesn't support oblique or sagittal or coronal for now or rectangles that are not drawn from top left to bottom right // Todo: only handle ijk , and throw for oblique + // Todo: Coronal seems to have some error!!!!! for (let x = xMin; x <= xMax; x++) { for (let y = yMin; y <= yMax; y++) { for (let z = zMin; z <= zMax; z++) { const offset = vtkImageData.computeOffsetIndex([x, y, z]) - if (values[offset] === 1) { + if (segmentsLocked.includes(values[offset])) { continue } values[offset] = segmentIndex diff --git a/packages/demo/src/ExampleSegmentationRender.tsx b/packages/demo/src/ExampleSegmentationRender.tsx index 2308c572f..295cc3e54 100644 --- a/packages/demo/src/ExampleSegmentationRender.tsx +++ b/packages/demo/src/ExampleSegmentationRender.tsx @@ -102,6 +102,9 @@ class MPRExample extends Component { selectedLabelmapUID: '', availableLabelmaps: [], activeSegmentIndex: 1, + fillAlpha: 0.9, + fillAlphaInactive: 0.8, + segmentLocked: false, } constructor(props) { @@ -479,6 +482,8 @@ class MPRExample extends Component { } preLoadSegmentations = async () => { + this.setState({ segmentationStatus: '(Calculating...)' }) + // Use ct as background for segmentation threshold const ctViewport = this.renderingEngine.getViewport('ctAxial') const { vtkImageData: backgroundImageData } = ctViewport.getImageData() @@ -501,7 +506,7 @@ class MPRExample extends Component { 'fatTissue', ]) - this.setState({ segmentationStatus: '(ready!)' }) + this.setState({ segmentationStatus: 'done' }) } loadSegmentation = async (sceneUID, labelmapUID) => { @@ -509,7 +514,6 @@ class MPRExample extends Component { const { uid } = scene.getViewports()[0] const { canvas } = this.renderingEngine.getViewport(uid) - const labelmapIndex = SegmentationModule.getNextLabelmapIndex(canvas) const labelmap = cache.getVolume(labelmapUID) @@ -519,14 +523,37 @@ class MPRExample extends Component { labelmapIndex, }) + const activeSegmentIndex = SegmentationModule.getActiveSegmentIndex(canvas) + const segmentLocked = + SegmentationModule.getSegmentIndexLockedStatusForElement( + canvas, + activeSegmentIndex + ) + this.setState((prevState) => ({ segmentationToolActive: true, selectedLabelmapUID: SegmentationModule.getActiveLabelmapUID(canvas), - activeSegmentIndex: SegmentationModule.getActiveSegmentIndex(canvas), + activeSegmentIndex, + segmentLocked, availableLabelmaps: [...prevState.availableLabelmaps, labelmapUID], })) } + toggleLockedSegmentIndex = (evt) => { + const checked = evt.target.checked + console.debug('checked', checked) + // Todo: Don't have active viewport concept + const sceneUID = this.state.sceneForSegmentation + const scene = this.renderingEngine.getScene(sceneUID) + const { canvas } = scene.getViewports()[0] + const activeLabelmapUID = SegmentationModule.getActiveLabelmapUID(canvas) + SegmentationModule.toggleSegmentIndexLockedForLabelmapUID( + activeLabelmapUID, + this.state.activeSegmentIndex + ) + this.setState({ segmentLocked: checked }) + } + changeActiveSegmentIndex = (direction) => { // Todo: Don't have active viewport concept const sceneUID = this.state.sceneForSegmentation @@ -540,7 +567,10 @@ class MPRExample extends Component { } SegmentationModule.setActiveSegmentIndex(canvas, newIndex) - this.setState({ activeSegmentIndex: newIndex }) + const segmentLocked = + SegmentationModule.getSegmentIndexLockedStatusForElement(canvas, newIndex) + console.debug('segmentLocked', segmentLocked) + this.setState({ activeSegmentIndex: newIndex, segmentLocked }) } swapPtCtTool = (evt) => { @@ -655,14 +685,22 @@ class MPRExample extends Component { onChange={(evt) => { const sceneUID = evt.target.value const scene = this.renderingEngine.getScene(sceneUID) - const { uid } = scene.getViewports()[0] + const { uid, canvas } = scene.getViewports()[0] const labelmapUIDs = SegmentationModule.getLabelmapUIDsForViewportUID(uid) - console.debug(labelmapUIDs) - this.setState((prevState) => ({ + const index = SegmentationModule.getActiveSegmentIndex(canvas) + const segmentLocked = + SegmentationModule.getSegmentIndexLockedStatusForElement( + canvas, + index + ) + + this.setState({ sceneForSegmentation: sceneUID, availableLabelmaps: labelmapUIDs, - })) + activeSegmentIndex: index, + segmentLocked, + }) }} > {[SCENE_IDS.CT, SCENE_IDS.PT, SCENE_IDS.PTMIP].map( @@ -710,16 +748,15 @@ class MPRExample extends Component { this.state.sceneForSegmentation ) const { canvas } = scene.getViewports()[0] - const activeSegmentIndex = - SegmentationModule.getActiveSegmentIndexForLabelmapUID( - canvas, - selectedLabelmapUID - ) + SegmentationModule.setActiveLabelmapByLabelmapUID( canvas, selectedLabelmapUID ) + const activeSegmentIndex = + SegmentationModule.getActiveSegmentIndex(canvas) + this.setState({ selectedLabelmapUID, activeSegmentIndex: activeSegmentIndex, @@ -741,8 +778,20 @@ class MPRExample extends Component { > Previous Segment - + {`Active Segment Index ${this.state.activeSegmentIndex}`} +
+ this.toggleLockedSegmentIndex(evt)} + /> + +
- {this.state.segmentationStatus === '' ? null : ( + {this.state.segmentationStatus} + {this.state.segmentationStatus !== 'done' ? null : ( <> - {this.state.segmentationStatus}