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

92.59% Statements 50/54
91.66% Branches 11/12
87.5% Functions 14/16
92.3% Lines 48/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                          6394x   6394x   6394x     6394x 6394x 6394x   6394x 2134x 1733x 1733x     401x   401x 555x     555x 401x     6394x 434x         434x   434x 265x 265x     169x 169x   169x 6x   6x 6x 6x       163x 163x       6394x 838x     6394x 838x 446x     392x 392x   392x   32x       10x         42x                     392x 392x             1960x 1296x         392x 2420x       6394x                  
import { useState, useEffect, useCallback } from 'react';
import { useSystem } from '@ohif/core/src';
import { useViewportDisplaySets } from './useViewportDisplaySets';
import { isVolumeViewportType } from '../utils/getLegacyViewportType';
 
/**
 * 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 (isVolumeViewportType(viewport)) {
      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(() => {
    if (!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;