All files / extensions/cornerstone/src/utils updateSegmentationStats.ts

42.1% Statements 24/57
33.33% Branches 11/33
83.33% Functions 5/6
42.1% Lines 24/57

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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186                                                          4x         4x 133x 133x   4x         4x           4x 1x     3x 3x     3x 129x   129x           129x   129x 129x   1548x       1548x 1548x                   129x   129x                       129x 129x       3x                                                                                                                                                                
import * as cornerstoneTools from '@cornerstonejs/tools';
 
interface BidirectionalAxis {
  length: number;
  // Add other axis properties as needed
}
 
interface BidirectionalData {
  majorAxis: BidirectionalAxis;
  minorAxis: BidirectionalAxis;
}
 
/**
 * Updates the statistics for a segmentation by calculating stats for each segment
 * and storing them in the segment's cachedStats property
 *
 * @param segmentation - The segmentation object containing segments to update stats for
 * @param segmentationId - The ID of the segmentation
 * @returns The updated segmentation object with new stats, or null if no updates were made
 */
export async function updateSegmentationStats({
  segmentation,
  segmentationId,
  readableText,
}: {
  segmentation: any;
  segmentationId: string;
  readableText: any;
}): Promise<any | null> {
  Iif (!segmentation) {
    console.debug('No segmentation found for id:', segmentationId);
    return null;
  }
 
  const segmentIndices = Object.keys(segmentation.segments)
    .map(index => parseInt(index))
    .filter(index => index > 0); // Filter out segment 0 which is typically background
 
  Iif (segmentIndices.length === 0) {
    console.debug('No segments found in segmentation:', segmentationId);
    return null;
  }
 
  const stats = await cornerstoneTools.utilities.segmentation.getStatistics({
    segmentationId,
    segmentIndices,
    mode: 'individual',
  });
 
  if (!stats) {
    return null;
  }
 
  const updatedSegmentation = { ...segmentation };
  let hasUpdates = false;
 
  // Loop through each segment's stats
  Object.entries(stats).forEach(([segmentIndex, segmentStats]) => {
    const index = parseInt(segmentIndex);
 
    Iif (!updatedSegmentation.segments[index].cachedStats) {
      updatedSegmentation.segments[index].cachedStats = {};
      hasUpdates = true;
    }
 
    // Get existing namedStats or initialize if not present
    const namedStats = updatedSegmentation.segments[index].cachedStats.namedStats || {};
 
    if (segmentStats.array) {
      segmentStats.array.forEach(stat => {
        // only gather stats that are in the readableText
        Iif (!readableText[stat.name]) {
          return;
        }
 
        if (stat && stat.name) {
          namedStats[stat.name] = {
            name: stat.name,
            label: readableText[stat.name],
            value: stat.value,
            unit: stat.unit,
            order: Object.keys(readableText).indexOf(stat.name),
          };
        }
      });
 
      if (readableText.volume) {
        // Add volume if it exists but isn't in the array
        Iif (segmentStats.volume && !namedStats.volume) {
          namedStats.volume = {
            name: 'volume',
            label: 'Volume',
            value: segmentStats.volume.value,
            unit: segmentStats.volume.unit,
            order: Object.keys(readableText).indexOf('volume'),
          };
        }
      }
 
      // Update the segment's cachedStats with namedStats
      updatedSegmentation.segments[index].cachedStats.namedStats = namedStats;
      hasUpdates = true;
    }
  });
 
  return hasUpdates ? updatedSegmentation : null;
}
 
/**
 * Updates a segment's statistics with bidirectional measurement data
 *
 * @param segmentationId - The ID of the segmentation
 * @param segmentIndex - The index of the segment to update
 * @param bidirectionalData - The bidirectional measurement data to add
 * @param segmentationService - The segmentation service to use for updating the segment
 * @returns Whether the update was successful
 */
export function updateSegmentBidirectionalStats({
  segmentationId,
  segmentIndex,
  bidirectionalData,
  segmentationService,
  annotation,
}: {
  segmentationId: string;
  segmentIndex: number;
  bidirectionalData: BidirectionalData;
  segmentationService: AppTypes.SegmentationService;
  annotation: any;
}) {
  Iif (!segmentationId || segmentIndex === undefined || !bidirectionalData) {
    console.debug('Missing required data for bidirectional stats update');
    return null;
  }
 
  const segmentation = segmentationService.getSegmentation(segmentationId);
  Iif (!segmentation || !segmentation.segments[segmentIndex]) {
    console.debug('Segment not found:', segmentIndex, 'in segmentation:', segmentationId);
    return null;
  }
 
  const updatedSegmentation = { ...segmentation };
  const segment = updatedSegmentation.segments[segmentIndex];
 
  Iif (!segment.cachedStats) {
    segment.cachedStats = { namedStats: {} };
  }
 
  Iif (!segment.cachedStats.namedStats) {
    segment.cachedStats.namedStats = {};
  }
 
  const { majorAxis, minorAxis, maxMajor, maxMinor } = bidirectionalData;
  Iif (!majorAxis || !minorAxis) {
    console.debug('Missing major or minor axis data');
    return null;
  }
 
  let hasUpdates = false;
  const namedStats = segment.cachedStats.namedStats;
 
  // Only calculate and update if we have valid measurements
  Iif (maxMajor > 0 && maxMinor > 0) {
    namedStats.bidirectional = {
      name: 'bidirectional',
      label: 'Bidirectional',
      annotationUID: annotation.annotationUID,
      value: {
        maxMajor,
        maxMinor,
        majorAxis,
        minorAxis,
      },
      unit: 'mm',
    };
 
    hasUpdates = true;
  }
 
  Iif (hasUpdates) {
    return updatedSegmentation;
  }
 
  return null;
}