All files / extensions/cornerstone/src/hooks useMeasurementTracking.ts

88.88% Statements 48/54
83.33% Branches 10/12
81.25% Functions 13/16
88.46% Lines 46/52

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                          537x   537x   537x     537x 537x 537x   537x 224x 176x 176x     48x   48x 60x     60x 48x     537x 135x         135x   135x 81x 81x     54x 54x   54x 6x   6x 6x 6x       48x 48x       537x 124x     537x 124x       124x 124x   124x   11x                 11x                     124x 124x             620x 100x         124x 730x       537x                  
import { useState, useEffect, useCallback } from 'react';
import { useSystem } from '@ohif/core/src';
import { useViewportDisplaySets } from './useViewportDisplaySets';
import { BaseVolumeViewport } from '@cornerstonejs/core';
 
/**
 * Hook that provides measurement tracking information for a viewport
 *
 * @param options - The hook options
 * @param options.viewportId - The ID of the viewport to track
 * @returns An object containing the tracking state, related information, and tracked measurement UIDs
 */
export function useMeasurementTracking({ viewportId }: { viewportId: string }) {
  const { servicesManager } = useSystem();
  const { cornerstoneViewportService, trackedMeasurementsService, measurementService } =
    servicesManager.services;
 
  const { backgroundDisplaySet } = useViewportDisplaySets(viewportId);
 
  // Tracking states
  const [isTracked, setIsTracked] = useState(false);
  const [isLocked, setIsLocked] = useState(false);
  const [trackedMeasurementUIDs, setTrackedMeasurementUIDs] = useState<string[]>([]);
 
  const updateTrackedMeasurements = useCallback(() => {
    if (!measurementService || !backgroundDisplaySet?.SeriesInstanceUID || !isTracked) {
      setTrackedMeasurementUIDs([]);
      return;
    }
 
    const seriesInstanceUID = backgroundDisplaySet.SeriesInstanceUID;
 
    const seriesMeasurements = measurementService.getMeasurements(
      measurement => measurement.referenceSeriesUID === seriesInstanceUID
    );
 
    const uids = seriesMeasurements.map(measurement => measurement.uid);
    setTrackedMeasurementUIDs(uids);
  }, [measurementService, backgroundDisplaySet, isTracked]);
 
  const updateIsTracked = useCallback(() => {
    Iif (!trackedMeasurementsService || !backgroundDisplaySet?.SeriesInstanceUID) {
      setIsTracked(false);
      return;
    }
 
    const trackedSeries = trackedMeasurementsService.getTrackedSeries();
 
    if (!trackedSeries?.length) {
      setIsTracked(false);
      return;
    }
 
    const viewport = cornerstoneViewportService?.getCornerstoneViewport(viewportId);
    const SeriesInstanceUID = backgroundDisplaySet.SeriesInstanceUID;
 
    if (viewport instanceof BaseVolumeViewport) {
      const currentImageId = viewport?.getCurrentImageId();
 
      if (!currentImageId) {
        setIsTracked(false);
        return;
      }
    }
 
    const seriesIsTracked = trackedSeries.includes(SeriesInstanceUID);
    setIsTracked(seriesIsTracked);
  }, [viewportId, backgroundDisplaySet, cornerstoneViewportService, trackedMeasurementsService]);
 
  // Update tracked measurements whenever tracking state changes
  useEffect(() => {
    updateTrackedMeasurements();
  }, [isTracked, updateTrackedMeasurements]);
 
  useEffect(() => {
    Iif (!trackedMeasurementsService) {
      return;
    }
 
    setIsLocked(trackedMeasurementsService.isTrackingEnabled());
    updateIsTracked();
 
    const subscriptions = [
      trackedMeasurementsService.subscribe(trackedMeasurementsService.EVENTS.TRACKING_ENABLED, () =>
        setIsLocked(true)
      ),
      trackedMeasurementsService.subscribe(
        trackedMeasurementsService.EVENTS.TRACKING_DISABLED,
        () => setIsLocked(false)
      ),
 
      trackedMeasurementsService.subscribe(
        trackedMeasurementsService.EVENTS.TRACKED_SERIES_CHANGED,
        () => updateIsTracked()
      ),
      trackedMeasurementsService.subscribe(trackedMeasurementsService.EVENTS.SERIES_ADDED, () =>
        updateIsTracked()
      ),
      trackedMeasurementsService.subscribe(trackedMeasurementsService.EVENTS.SERIES_REMOVED, () =>
        updateIsTracked()
      ),
    ];
 
    // Subscribe to measurement service events to update trackedMeasurementUIDs
    if (measurementService) {
      [
        measurementService.EVENTS.MEASUREMENT_ADDED,
        measurementService.EVENTS.RAW_MEASUREMENT_ADDED,
        measurementService.EVENTS.MEASUREMENT_UPDATED,
        measurementService.EVENTS.MEASUREMENT_REMOVED,
        measurementService.EVENTS.MEASUREMENTS_CLEARED,
      ].forEach(eventType => {
        subscriptions.push(
          measurementService.subscribe(eventType, () => updateTrackedMeasurements())
        );
      });
    }
 
    return () => {
      subscriptions.forEach(sub => sub.unsubscribe());
    };
  }, [trackedMeasurementsService, measurementService, updateIsTracked, updateTrackedMeasurements]);
 
  return {
    isTracked,
    isLocked,
    seriesInstanceUID: backgroundDisplaySet?.SeriesInstanceUID,
    trackedMeasurementUIDs,
  };
}
 
export default useMeasurementTracking;