All files / tools/src/stateManagement/segmentation/helpers normalizeSegmentationInput.ts

86.48% Statements 32/37
56.25% Branches 18/32
88.88% Functions 8/9
86.48% Lines 32/37

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 147 148 149 150 151 152 153 154 155 156 157                                          182x 182x 182x   182x       182x 16x   182x     182x   182x                                   16x 16x                             182x   182x                         182x 16x       166x 4x         162x     182x                       16x 16x 8x 8x 8x 8x                           4x 4x 4x 4x 4x 4x                   162x                    
import { SegmentationRepresentations } from '../../../enums';
import type {
  SegmentationPublicInput,
  Segmentation,
  Segment,
  RepresentationData,
} from '../../../types/SegmentationStateTypes';
import type { ContourSegmentationData } from '../../../types/ContourTypes';
import type { Types } from '@cornerstonejs/core';
import { cache } from '@cornerstonejs/core';
import type { SurfaceSegmentationData } from '../../../types/SurfaceTypes';
 
/**
 * It takes in a segmentation input and returns a segmentation with default values
 * @param segmentationInput - The input to the segmentation.
 * @returns A Segmentation object.
 * @internal
 */
function normalizeSegmentationInput(
  segmentationInput: SegmentationPublicInput
): Segmentation {
  const { segmentationId, representation, config } = segmentationInput;
  const { type, data: inputData } = representation;
  const data = inputData ? { ...inputData } : {};
 
  Iif (!data) {
    throw new Error('Segmentation representation data may not be undefined');
  }
 
  if (type === SegmentationRepresentations.Contour) {
    normalizeContourData(data as ContourSegmentationData);
  }
  const normalizedSegments = normalizeSegments(config?.segments, type, data);
 
  // since we normalize the segments, we don't need the segments config in the final object
  delete config?.segments;
 
  return {
    segmentationId,
    label: config?.label ?? null,
    cachedStats: config?.cachedStats ?? {},
    segments: normalizedSegments,
    representationData: {
      [type]: {
        ...data,
      },
    },
  };
}
 
/**
 * Normalize contour segmentation data to ensure compatibility and default values.
 * @param contourData - ContourSegmentationData to be normalized.
 */
function normalizeContourData(contourData: ContourSegmentationData): void {
  contourData.geometryIds = contourData.geometryIds ?? [];
  contourData.annotationUIDsMap = contourData.annotationUIDsMap ?? new Map();
}
 
/**
 * Normalize segments based on the segmentation type and provided configuration.
 * @param segmentsConfig - Configured segments, if any.
 * @param type - Segmentation representation type.
 * @param data - Representation data used for segment creation if needed.
 * @returns A normalized segments object.
 */
function normalizeSegments(
  segmentsConfig: { [key: number]: Partial<Segment> } | undefined,
  type: SegmentationRepresentations,
  data: RepresentationData
): { [key: number]: Segment } {
  const normalizedSegments: { [key: number]: Segment } = {};
 
  Iif (segmentsConfig) {
    Object.entries(segmentsConfig).forEach(([segmentIndex, segment]) => {
      const { label, locked, cachedStats, active, ...rest } = segment;
      const normalizedSegment = {
        segmentIndex: Number(segmentIndex),
        label: label ?? `Segment ${segmentIndex}`,
        locked: locked ?? false,
        cachedStats: cachedStats ?? {},
        active: active ?? false,
        ...rest,
      } as Segment;
      normalizedSegments[segmentIndex] = normalizedSegment;
    });
  } else if (type === SegmentationRepresentations.Contour) {
    normalizeContourSegments(
      normalizedSegments,
      data as ContourSegmentationData
    );
  } else if (type === SegmentationRepresentations.Surface) {
    normalizeSurfaceSegments(
      normalizedSegments,
      data as SurfaceSegmentationData
    );
  } else {
    normalizedSegments[1] = createDefaultSegment();
  }
 
  return normalizedSegments;
}
 
/**
 * Normalize surface segmentation segments using geometry data from cache.
 * @param normalizedSegments - The object to store normalized segments.
 * @param surfaceData - SurfaceSegmentationData to extract geometry information.
 */
function normalizeContourSegments(
  normalizedSegments: { [key: number]: Segment },
  contourData: ContourSegmentationData
): void {
  const { geometryIds } = contourData;
  geometryIds?.forEach((geometryId) => {
    const geometry = cache.getGeometry(geometryId) as Types.IGeometry;
    Eif (geometry?.data) {
      const { segmentIndex } = geometry.data as Types.IContourSet;
      normalizedSegments[segmentIndex] = { segmentIndex } as Segment;
    }
  });
}
 
/**
 * Normalize surface segmentation segments using geometry data from cache.
 * @param normalizedSegments - The object to store normalized segments.
 * @param surfaceData - SurfaceSegmentationData to extract geometry information.
 */
function normalizeSurfaceSegments(
  normalizedSegments: { [key: number]: Segment },
  surfaceData: SurfaceSegmentationData
): void {
  const { geometryIds } = surfaceData;
  geometryIds?.forEach((geometryId) => {
    const geometry = cache.getGeometry(geometryId) as Types.IGeometry;
    Eif (geometry?.data) {
      const { segmentIndex } = geometry.data as Types.ISurface;
      normalizedSegments[segmentIndex] = { segmentIndex } as Segment;
    }
  });
}
 
/**
 * Create a default labelmap segment.
 * @returns A default Segment object for Labelmap representation.
 */
function createDefaultSegment(): Segment {
  return {
    segmentIndex: 1,
    label: 'Segment 1',
    locked: false,
    cachedStats: {},
    active: true,
  } as Segment;
}
 
export default normalizeSegmentationInput;