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

12% Statements 3/25
0% Branches 0/10
0% Functions 0/5
12% Lines 3/25

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                          428x   428x 428x                                                                                                                                                        
import type { Types } from '@cornerstonejs/core';
import type { NamedStatistics } from '../../types';
import { InstanceVolumetricCalculator } from './VolumetricCalculator';
 
/**
 * A calculator that manages statistics for multiple segments.
 * This class acts as a container for multiple VolumetricCalculator instances,
 * one for each segment index.
 */
export default class SegmentStatsCalculator {
  private static calculators: Map<
    number | number[],
    InstanceVolumetricCalculator
  > = new Map();
 
  private static indices: number[] = [];
  private static mode: 'collective' | 'individual' = 'collective';
 
  public static statsInit(options: {
    storePointData: boolean;
    indices: number[];
    mode: 'collective' | 'individual';
  }) {
    const { storePointData, indices, mode } = options;
    this.mode = mode;
    this.indices = indices;
 
    // Clear existing calculators
    this.calculators.clear();
 
    if (this.mode === 'individual') {
      // Create individual calculator for each segment index
      indices.forEach((index) => {
        this.calculators.set(
          index,
          new InstanceVolumetricCalculator({ storePointData })
        );
      });
    } else {
      // Create single calculator for all indices
      this.calculators.set(
        indices,
        new InstanceVolumetricCalculator({ storePointData })
      );
    }
  }
 
  public static statsCallback(data: {
    value: number | Types.RGB;
    pointLPS?: Types.Point3;
    pointIJK?: Types.Point3;
    segmentIndex?: number;
  }) {
    const { segmentIndex, ...statsData } = data;
 
    if (!segmentIndex) {
      throw new Error('Segment index is required for stats calculation');
    }
 
    const calculator =
      this.mode === 'individual'
        ? this.calculators.get(segmentIndex)
        : this.calculators.get(this.indices);
 
    if (!calculator) {
      throw new Error(`No calculator found for segment ${segmentIndex}`);
    }
 
    calculator.statsCallback(statsData);
  }
 
  /**
   * Get statistics for all segments or a specific segment
   */
  public static getStatistics(options?: {
    spacing?: number[] | number;
    unit?: string;
    calibration?: unknown;
    hasPixelSpacing?: boolean;
  }): NamedStatistics | { [segmentIndex: number]: NamedStatistics } {
    if (this.mode === 'individual') {
      const result: { [segmentIndex: number]: NamedStatistics } = {};
      this.calculators.forEach((calculator, segmentIndex) => {
        result[segmentIndex as number] = calculator.getStatistics(options);
      });
      return result;
    }
 
    const calculator = this.calculators.get(this.indices);
    return calculator.getStatistics(options);
  }
}