All files / tools/src/utilities defaultGetTextLines.ts

12.12% Statements 4/33
0% Branches 0/16
14.28% Functions 1/7
12.12% Lines 4/33

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    128x               128x                                 256x                                                                                 128x                                                                                                          
import { utilities as csUtils } from '@cornerstonejs/core';
 
const { isEqual } = csUtils;
 
export interface MetricDefinition {
  name: string;
  attribute: string;
  unitAttribute: string;
}
 
export const AREA_METRICS: MetricDefinition[] = [
  { name: 'Area', attribute: 'area', unitAttribute: 'areaUnit' },
  { name: 'Mean', attribute: 'mean', unitAttribute: 'modalityUnit' },
  { name: 'Max', attribute: 'max', unitAttribute: 'modalityUnit' },
  { name: 'Min', attribute: 'min', unitAttribute: 'modalityUnit' },
  { name: 'Std Dev', attribute: 'stdDev', unitAttribute: 'modalityUnit' },
];
 
/**
 * Creates a function that returns text lines for the specified metrics in the given ordering.
 *
 * @param metrics - Array of metric definitions specifying name, attribute, and unitAttribute
 * @returns A function that processes annotation data and returns text lines
 */
export function createGetTextLines(
  metrics: MetricDefinition[]
): (data, targetId: string | string[]) => string[] {
  return function (data, targetId: string | string[]): string[] {
    const targetIds = Array.isArray(targetId) ? targetId : [targetId];
    const cachedVolumeStats = targetIds
      .map((id) => data.cachedStats[id])
      .filter((stats) =>
        metrics.some(
          ({ attribute }) =>
            stats?.[attribute] !== undefined && stats?.[attribute] !== null
        )
      );
 
    if (!cachedVolumeStats.length) {
      return;
    }
 
    const textLines: string[] = [];
 
    for (const metric of metrics) {
      pushResult(
        textLines,
        createMultiResultLine(
          cachedVolumeStats,
          targetIds,
          metric.name,
          metric.attribute,
          metric.unitAttribute
        )
      );
    }
 
    return textLines;
  };
}
 
/**
 * _getTextLines - Returns the Area, mean and std deviation of the area of the
 * target volume enclosed by the rectangle.
 *
 * @param data - The annotation tool-specific data.
 * @param targetId - The volumeId of the volume to display the stats for.
 */
export const defaultAreaGetTextLines = createGetTextLines(AREA_METRICS);
 
function pushResult(textLines: string[], value: string) {
  if (value) {
    textLines.push(value);
  }
}
 
/**
 * Creates a formatted multi-result line string for a given metric across multiple target volumes.
 *
 * Formats the result as "Name: value1 unit1 value2 unit2 ..." where each value-unit pair
 * corresponds to a different target volume. Only includes values that are valid numbers.
 *
 * @param cachedVolumeStats - Object containing cached statistics for each target volume,
 *                            keyed by target ID
 * @param targetIds - Array of target volume IDs to include in the result
 * @param name - Display name for the metric (e.g., "Area", "Mean", "Max")
 * @param attribute - The attribute name to read from the stats object (e.g., "area", "mean", "max")
 * @param unitAttribute - The attribute name containing the unit for this metric
 *                       (e.g., "areaUnit", "modalityUnit")
 * @returns A formatted string like "Name: value1 unit1 value2 unit2", or undefined if
 *          no valid numeric values are found for any target
 */
export function createMultiResultLine(
  cachedVolumeStats,
  targetIds: string[],
  name: string,
  attribute: string,
  unitAttribute: string
) {
  const result = [`${name}:`];
  let lastValue = null;
  let lastUnit = null;
 
  for (const stats of cachedVolumeStats) {
    if (!csUtils.isNumber(stats?.[attribute])) {
      continue;
    }
    const attributeValue = stats[attribute];
    const unitValue = stats[unitAttribute];
    if (isEqual(lastValue, attributeValue) && lastUnit === unitValue) {
      continue;
    }
    result.push(`${csUtils.roundNumber(attributeValue)} ${unitValue}`);
    lastValue = attributeValue;
    lastUnit = unitValue;
  }
  if (result.length <= 1) {
    return;
  }
  return result.join(' ');
}