All files / extensions/default/src init.ts

73.43% Statements 47/64
62.5% Branches 10/16
90% Functions 9/10
74.19% Lines 46/62

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              77x                       77x   77x       77x         77x       77x     77x     77x 77x 11852x 19114x         19114x 14524x   14524x 14354x     170x 119x   119x     170x         77x 7409x 7409x 300754x     300754x                 300754x 11852x           77x 447x   447x       447x   447x   447x 433x     658x 14x   14x                                                     14x 14x 658x 658x 658x       14x       14x 7x 329x             7x      
import { DicomMetadataStore, classes } from '@ohif/core';
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv';
 
import getPTImageIdInstanceMetadata from './getPTImageIdInstanceMetadata';
import { registerHangingProtocolAttributes } from './hangingprotocols';
import { HotkeysManager } from '@ohif/core';
 
const metadataProvider = classes.MetadataProvider;
 
/**
 *
 * @param {Object} servicesManager
 * @param {Object} configuration
 */
export default function init({
  servicesManager,
  commandsManager,
  hotkeysManager,
}: withAppTypes): void {
  const { toolbarService, cineService, viewportGridService } = servicesManager.services;
 
  toolbarService.registerEventForToolbarUpdate(cineService, [
    cineService.EVENTS.CINE_STATE_CHANGED,
  ]);
 
  toolbarService.registerEventForToolbarUpdate(hotkeysManager, [
    HotkeysManager.EVENTS.HOTKEY_PRESSED,
  ]);
 
  // Add
  DicomMetadataStore.subscribe(DicomMetadataStore.EVENTS.INSTANCES_ADDED, handleScalingModules);
 
  // If the metadata for PET has changed by the user (e.g. manually changing the PatientWeight)
  // we need to recalculate the SUV Scaling Factors
  DicomMetadataStore.subscribe(DicomMetadataStore.EVENTS.SERIES_UPDATED, handleScalingModules);
 
  // Adds extra custom attributes for use by hanging protocols
  registerHangingProtocolAttributes({ servicesManager });
 
  // Function to process and subscribe to events for a given set of commands and listeners
  const eventSubscriptions = [];
  const subscribeToEvents = listeners => {
    Object.entries(listeners).forEach(([event, commands]) => {
      const supportedEvents = [
        viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
        viewportGridService.EVENTS.VIEWPORTS_READY,
      ];
 
      if (supportedEvents.includes(event)) {
        const subscriptionKey = `${event}_${JSON.stringify(commands)}`;
 
        if (eventSubscriptions.includes(subscriptionKey)) {
          return;
        }
 
        viewportGridService.subscribe(event, eventData => {
          const viewportId = eventData?.viewportId ?? viewportGridService.getActiveViewportId();
 
          commandsManager.run(commands, { viewportId });
        });
 
        eventSubscriptions.push(subscriptionKey);
      }
    });
  };
 
  toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, state => {
    const { buttons } = state;
    for (const [id, button] of Object.entries(buttons)) {
      const { buttonSection, items, listeners } = button.props || {};
 
      // Handle group items' listeners
      Iif (buttonSection && items) {
        items.forEach(item => {
          Iif (item.listeners) {
            subscribeToEvents(item.listeners);
          }
        });
      }
 
      // Handle button listeners
      if (listeners) {
        subscribeToEvents(listeners);
      }
    }
  });
}
 
const handleScalingModules = ({ SeriesInstanceUID, StudyInstanceUID }) => {
  const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
 
  Iif (!instances?.length) {
    return;
  }
 
  const modality = instances[0].Modality;
 
  const allowedModality = ['PT', 'RTDOSE'];
 
  if (!allowedModality.includes(modality)) {
    return;
  }
 
  const imageIds = instances.map(instance => instance.imageId);
  const instanceMetadataArray = [];
 
  Iif (modality === 'RTDOSE') {
    const DoseGridScaling = instances[0].DoseGridScaling;
    const DoseSummation = instances[0].DoseSummation;
    const DoseType = instances[0].DoseType;
    const DoseUnit = instances[0].DoseUnit;
    const NumberOfFrames = instances[0].NumberOfFrames;
    const imageId = imageIds[0];
 
    // add scaling module to the metadata
    // since RTDOSE is always a multiframe we should add the scaling module to each frame
    for (let i = 0; i < NumberOfFrames; i++) {
      const frameIndex = i + 1;
 
      // Todo: we should support other things like wadouri, local etc
      const newImageId = `${imageId.replace(/\/frames\/\d+$/, '')}/frames/${frameIndex}`;
      metadataProvider.addCustomMetadata(newImageId, 'scalingModule', {
        DoseGridScaling,
        DoseSummation,
        DoseType,
        DoseUnit,
      });
    }
 
    return;
  }
 
  // try except block to prevent errors when the metadata is not correct
  try {
    imageIds.forEach(imageId => {
      const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
      if (instanceMetadata) {
        instanceMetadataArray.push(instanceMetadata);
      }
    });
 
    Iif (!instanceMetadataArray.length) {
      return;
    }
 
    const suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
    instanceMetadataArray.forEach((instanceMetadata, index) => {
      metadataProvider.addCustomMetadata(
        imageIds[index],
        'scalingModule',
        suvScalingFactors[index]
      );
    });
  } catch (error) {
    console.log(error);
  }
};