All files / packages/tools/src/utilities/segmentation utilities.ts

20.45% Statements 9/44
33.33% Branches 4/12
33.33% Functions 2/6
22.5% Lines 9/40

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                          2x   2x       2x   2x       2x         2x 4x     2x     1x                                                                                                                                                                          
import { Types } from '@cornerstonejs/core';
import { utilities as csUtils } from '@cornerstonejs/core';
import { getToolGroup } from '../../store/ToolGroupManager';
import BrushTool from '../../tools/segmentation/BrushTool';
import { getBoundingBoxAroundShapeIJK } from '../boundingBox/getBoundingBoxAroundShape';
 
export type ThresholdInformation = {
  volume: Types.IImageVolume;
  lower: number;
  upper: number;
};
 
export function getBrushToolInstances(toolGroupId: string, toolName?: string) {
  const toolGroup = getToolGroup(toolGroupId);
 
  Iif (toolGroup === undefined) {
    return;
  }
 
  const toolInstances = toolGroup._toolInstances;
 
  Iif (!Object.keys(toolInstances).length) {
    return;
  }
 
  Iif (toolName && toolInstances[toolName]) {
    return [toolInstances[toolName]];
  }
 
  // For each tool that has BrushTool as base class, set the brush size.
  const brushBasedToolInstances = Object.values(toolInstances).filter(
    (toolInstance) => toolInstance instanceof BrushTool
  ) as BrushTool[];
 
  return brushBasedToolInstances;
}
 
const equalsCheck = (a, b) => {
  return JSON.stringify(a) === JSON.stringify(b);
};
 
/**
 * Given the center of a voxel in world coordinates, calculate the voxel
 * corners in world coords to calculate the voxel overlap in another volume
 */
export function getVoxelOverlap(
  imageData,
  dimensions,
  voxelSpacing,
  voxelCenter
) {
  const voxelCornersWorld = [];
  for (let i = 0; i < 2; i++) {
    for (let j = 0; j < 2; j++) {
      for (let k = 0; k < 2; k++) {
        const point = [...voxelCenter]; // Create a new point from voxelCenter
        point[0] = point[0] + ((i * 2 - 1) * voxelSpacing[0]) / 2;
        point[1] = point[1] + ((j * 2 - 1) * voxelSpacing[1]) / 2;
        point[2] = point[2] + ((k * 2 - 1) * voxelSpacing[2]) / 2;
        voxelCornersWorld.push(point);
      }
    }
  }
  const voxelCornersIJK = voxelCornersWorld.map(
    (world) => csUtils.transformWorldToIndex(imageData, world) as Types.Point3
  );
  const overlapBounds = getBoundingBoxAroundShapeIJK(
    voxelCornersIJK,
    dimensions
  );
 
  return overlapBounds;
}
 
/**
 * Prepare a list of volume information objects for callback functions
 */
export function processVolumes(
  segmentationVolume: Types.IImageVolume,
  thresholdVolumeInformation: ThresholdInformation[]
) {
  const { spacing: segmentationSpacing } = segmentationVolume;
  const scalarData = segmentationVolume.getScalarData();
 
  // prepare a list of volume information objects for callback functions
  const volumeInfoList = [];
  let baseVolumeIdx = 0;
  for (let i = 0; i < thresholdVolumeInformation.length; i++) {
    const { imageData, spacing, dimensions } =
      thresholdVolumeInformation[i].volume;
 
    const volumeSize =
      thresholdVolumeInformation[i].volume.getScalarData().length;
    // discover the index of the volume the segmentation data is based on
    if (
      volumeSize === scalarData.length &&
      equalsCheck(spacing, segmentationSpacing)
    ) {
      baseVolumeIdx = i;
    }
 
    // prepare information used in callback functions
    const referenceValues = imageData.getPointData().getScalars().getData();
    const lower = thresholdVolumeInformation[i].lower;
    const upper = thresholdVolumeInformation[i].upper;
 
    volumeInfoList.push({
      imageData,
      referenceValues,
      lower,
      upper,
      spacing,
      dimensions,
      volumeSize,
    });
  }
 
  return {
    volumeInfoList,
    baseVolumeIdx,
  };
}