All files / packages/tools/src/eventListeners/segmentation/labelmap onLabelmapSegmentationDataModified.ts

42.85% Statements 18/42
43.75% Branches 7/16
42.85% Functions 3/7
42.85% Lines 18/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146                                    1x     9x     9x     9x   9x   9x   9x             9x                               9x       9x         9x       9x 1x   8x 8x     9x 90x       9x                                                                                                                                
import {
  cache,
  getEnabledElementByIds,
  utilities as csUtils,
  VolumeViewport,
} from '@cornerstonejs/core';
 
import * as SegmentationState from '../../../stateManagement/segmentation/segmentationState';
import { SegmentationDataModifiedEventType } from '../../../types/EventTypes';
import {
  LabelmapSegmentationDataStack,
  LabelmapSegmentationDataVolume,
} from '../../../types/LabelmapTypes';
import { getToolGroup } from '../../../store/ToolGroupManager';
 
/** A callback function that is called when the segmentation data is modified which
 *  often is as a result of tool interactions e.g., scissors, eraser, etc.
 */
const onLabelmapSegmentationDataModified = function (
  evt: SegmentationDataModifiedEventType
): void {
  const { segmentationId, modifiedSlicesToUse } = evt.detail;
 
  const { representationData, type } =
    SegmentationState.getSegmentation(segmentationId);
 
  const toolGroupIds =
    SegmentationState.getToolGroupIdsWithSegmentation(segmentationId);
 
  const labelmapRepresentationData = representationData[type];
 
  Eif ('volumeId' in labelmapRepresentationData) {
    // get the volume from cache, we need the openGLTexture to be updated to GPU
    performVolumeLabelmapUpdate({
      modifiedSlicesToUse,
      representationData,
      type,
    });
  }
 
  Iif ('imageIdReferenceMap' in labelmapRepresentationData) {
    // get the stack from cache, we need the imageData to be updated to GPU
    performStackLabelmapUpdate({
      toolGroupIds,
      segmentationId,
      representationData,
      type,
    });
  }
};
 
function performVolumeLabelmapUpdate({
  modifiedSlicesToUse,
  representationData,
  type,
}) {
  const segmentationVolume = cache.getVolume(
    (representationData[type] as LabelmapSegmentationDataVolume).volumeId
  );
 
  Iif (!segmentationVolume) {
    console.warn('segmentation not found in cache');
    return;
  }
 
  const { imageData, vtkOpenGLTexture } = segmentationVolume;
 
  // Update the texture for the volume in the GPU
  let slicesToUpdate;
  if (modifiedSlicesToUse && Array.isArray(modifiedSlicesToUse)) {
    slicesToUpdate = modifiedSlicesToUse;
  } else {
    const numSlices = imageData.getDimensions()[2];
    slicesToUpdate = [...Array(numSlices).keys()];
  }
 
  slicesToUpdate.forEach((i) => {
    vtkOpenGLTexture.setUpdatedFrame(i);
  });
 
  // Trigger modified on the imageData to update the image
  imageData.modified();
}
 
function performStackLabelmapUpdate({
  toolGroupIds,
  segmentationId,
  representationData,
  type,
}) {
  toolGroupIds.forEach((toolGroupId) => {
    const toolGroupSegmentationRepresentations =
      SegmentationState.getSegmentationRepresentations(toolGroupId);
 
    const toolGroup = getToolGroup(toolGroupId);
    const viewportsInfo = toolGroup.getViewportsInfo();
 
    toolGroupSegmentationRepresentations.forEach((representation) => {
      if (representation.segmentationId !== segmentationId) {
        return;
      }
 
      viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
        const viewport = getEnabledElementByIds(
          viewportId,
          renderingEngineId
        ).viewport;
 
        if (viewport instanceof VolumeViewport) {
          return;
        }
 
        const actorEntry = viewport.getActor(
          representation.segmentationRepresentationUID
        );
 
        if (!actorEntry) {
          return;
        }
 
        const currentImageId = viewport.getCurrentImageId();
 
        const segImageData = actorEntry.actor.getMapper().getInputData();
 
        const { imageIdReferenceMap } = representationData[
          type
        ] as LabelmapSegmentationDataStack;
 
        const currentSegmentationImageId =
          imageIdReferenceMap.get(currentImageId);
 
        const segmentationImage = cache.getImage(currentSegmentationImageId);
        segImageData.modified();
 
        // update the cache with the new image data
        csUtils.updateVTKImageDataWithCornerstoneImage(
          segImageData,
          segmentationImage
        );
      });
    });
  });
}
 
export default onLabelmapSegmentationDataModified;