All files / utils/test testUtilsVolumeLoader.js

100% Statements 25/25
100% Branches 18/18
100% Functions 2/2
100% Lines 24/24

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                                                                                      1x 52x 52x                                 447x       52x 52x 5x     52x   52x   52x                             52x 2x 50x 5x                         45x     52x           52x 52x 52x 52x 52x 52x   52x                         52x            
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
import { ImageVolume } from '@cornerstonejs/core';
import {
  getVerticalBarRGBVolume,
  getVerticalBarVolume,
  getExactRegionVolume,
} from './testUtilsPixelData';
 
/**
 * It creates a volume based on the volumeId name for testing purposes. It splits the volumeId
 * based on "_" and deciphers each field of [ scheme, rows, columns, slices, x_spacing, y_spacing, z_spacing, rgb,
 * startX, startY, startZ, endX, endY, endZ, and valueForSegmentIndex ].
 *
 * If scheme is not equal to "volumeURIExact", then the volume is created with number of
 * provided rows, columns, and slices, with spacing in x, y, and z direction, and with
 * each slice having one vertical bar spanning [width/slices] of the image. So for instance
 * myVolume_100_100_10_1_1_1_0 will generate a volume of size 100 by 100 by 10 with spacing
 * of 1 mm in x and y direction and 1 mm in z direction. The volume will have 10 slices, and
 * first slice will have a vertical bar spanning 10 pixels in the first 10% of the image (since
 * there are 10 slices), the second slice will have a vertical bar of value 255 spanning 10 pixels in the
 * second 10% of the image, and so on.
 *
 * If volumeURIExact is provided as the scheme, there will be no automatic generation of the vertical bars
 * for each slice and using the provided startX, startY, startZ, endX, endY, endZ, and valueForSegmentIndex
 * will be used to create the volume that has the exact region specified with value of valueForSegmentIndex
 * (instead of 255).
 *
 * If rgb is true, then the volume will be created with RGB values.
 *
 * Note: fakeVolumeLoader should be registered for each test
 *
 * @example
 * ```
 * registerVolumeLoader('fakeVolumeLoader', fakeVolumeLoader)
 * ````
 *
 * then you can use imageId like: 'fakeVolumeLoader: myVolume_64_64_10_1_1_1_0'
 *
 *
 * @param {volumeId} volumeId
 * @returns Promise that resolves to the image
 */
const fakeVolumeLoader = (volumeId) => {
  const volumeURI = volumeId.split(':')[1];
  const uriName = volumeURI.split('_')[0];
  const [
    _,
    rows,
    columns,
    slices,
    x_spacing,
    y_spacing,
    z_spacing,
    rgb,
    startX,
    startY,
    startZ,
    endX,
    endY,
    endZ,
    valueForSegmentIndex,
  ] = volumeURI.split('_').map((v) => parseFloat(v));
 
  // If uri name is volumeURIExact, it means that the metadata provided
  // has the start and end indices of the region of interest.
  let useExactRegion = false;
  if (uriName === 'volumeURIExact') {
    useExactRegion = true;
  }
 
  const dimensions = [rows, columns, slices];
 
  const photometricInterpretation = rgb ? 'RGB' : 'MONOCHROME2';
 
  const volumeMetadata = {
    BitsAllocated: rgb ? 24 : 8,
    BitsStored: rgb ? 24 : 8,
    SamplesPerPixel: rgb ? 3 : 1,
    HighBit: rgb ? 24 : 8,
    PixelRepresentation: 0,
    PhotometricInterpretation: photometricInterpretation,
    FrameOfReferenceUID: 'Volume_Frame_Of_Reference',
    ImageOrientationPatient: [1, 0, 0, 0, 1, 0],
    PixelSpacing: [x_spacing, y_spacing, z_spacing],
    Columns: columns,
    Rows: rows,
  };
 
  let pixelData;
  if (rgb) {
    pixelData = getVerticalBarRGBVolume(rows, columns, slices);
  } else if (useExactRegion) {
    pixelData = getExactRegionVolume(
      rows,
      columns,
      slices,
      startX,
      startY,
      startZ,
      endX,
      endY,
      endZ,
      valueForSegmentIndex
    );
  } else {
    pixelData = getVerticalBarVolume(rows, columns, slices);
  }
 
  const scalarArray = vtkDataArray.newInstance({
    name: 'Pixels',
    numberOfComponents: rgb ? 3 : 1,
    values: pixelData,
  });
 
  const imageData = vtkImageData.newInstance();
  imageData.setDimensions(dimensions);
  imageData.setSpacing([1, 1, 1]);
  imageData.setDirection([1, 0, 0, 0, 1, 0, 0, 0, 1]);
  imageData.setOrigin([0, 0, 0]);
  imageData.getPointData().setScalars(scalarArray);
 
  const imageVolume = new ImageVolume({
    volumeId,
    metadata: volumeMetadata,
    dimensions: dimensions,
    spacing: [1, 1, 1],
    origin: [0, 0, 0],
    direction: [1, 0, 0, 0, 1, 0, 0, 0, 1],
    scalarData: pixelData,
    sizeInBytes: pixelData.byteLength,
    imageData: imageData,
    imageIds: [],
  });
 
  return {
    promise: Promise.resolve(imageVolume),
  };
};
 
export { fakeVolumeLoader };