All files / core/src/utilities sortImageIdsAndGetSpacing.ts

65.51% Statements 19/29
33.33% Branches 2/6
100% Functions 5/5
62.96% Lines 17/27

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                                                    116x   116x                                 116x   116x         8000x   8000x   8000x           8000x                   116x 116x 8000x   8000x           19911x 8000x                                 116x         116x           116x    
import { vec3 } from 'gl-matrix';
import * as metaData from '../metaData';
import calculateSpacingBetweenImageIds from './calculateSpacingBetweenImageIds';
import type { Point3 } from '../types';
 
interface SortedImageIdsItem {
  zSpacing: number;
  origin: Point3;
  sortedImageIds: string[];
}
/**
 * Given an array of imageIds, sort them based on their imagePositionPatient, and
 * also returns the spacing between images and the origin of the reference image
 *
 * @param imageIds - array of imageIds
 * @param scanAxisNormal - [x, y, z] array or gl-matrix vec3
 *
 * @returns The sortedImageIds, spacing, and origin of the first image in the series.
 */
export default function sortImageIdsAndGetSpacing(
  imageIds: string[],
  scanAxisNormal?: vec3
): SortedImageIdsItem {
  const {
    imagePositionPatient: referenceImagePositionPatient,
    imageOrientationPatient,
  } = metaData.get('imagePlaneModule', imageIds[0]);
 
  Iif (!scanAxisNormal) {
    const rowCosineVec = vec3.fromValues(
      imageOrientationPatient[0],
      imageOrientationPatient[1],
      imageOrientationPatient[2]
    );
    const colCosineVec = vec3.fromValues(
      imageOrientationPatient[3],
      imageOrientationPatient[4],
      imageOrientationPatient[5]
    );
 
    scanAxisNormal = vec3.create();
    vec3.cross(scanAxisNormal, rowCosineVec, colCosineVec);
  }
 
  // Check if we are using wadouri scheme
  const usingWadoUri = imageIds[0].split(':')[0] === 'wadouri';
 
  const zSpacing = calculateSpacingBetweenImageIds(imageIds);
 
  let sortedImageIds: string[];
 
  function getDistance(imageId: string) {
    const { imagePositionPatient } = metaData.get('imagePlaneModule', imageId);
 
    const positionVector = vec3.create();
 
    vec3.sub(
      positionVector,
      referenceImagePositionPatient,
      imagePositionPatient
    );
 
    return vec3.dot(positionVector, scanAxisNormal);
  }
 
  /**
   * If we are using wadors and so have all image metadata cached ahead of time,
   * then sort by image position in 3D space, and calculate average slice
   * spacing from the entire volume. If not, then use the sampled images (1st
   * and middle) to calculate slice spacing, and use the provided imageId order.
   * Correct sorting must be done ahead of time.
   */
  if (!usingWadoUri) {
    const distanceImagePairs = imageIds.map((imageId) => {
      const distance = getDistance(imageId);
 
      return {
        distance,
        imageId,
      };
    });
 
    distanceImagePairs.sort((a, b) => b.distance - a.distance);
    sortedImageIds = distanceImagePairs.map((a) => a.imageId);
  } else E{
    // Using wadouri, so we have only prefetched the first, middle, and last
    // images for metadata. Assume initial imageId array order is pre-sorted,
    // but check orientation.
    const prefetchedImageIds = [
      imageIds[0],
      imageIds[Math.floor(imageIds.length / 2)],
    ];
    sortedImageIds = imageIds;
    const firstImageDistance = getDistance(prefetchedImageIds[0]);
    const middleImageDistance = getDistance(prefetchedImageIds[1]);
    if (firstImageDistance - middleImageDistance < 0) {
      sortedImageIds.reverse();
    }
  }
 
  const { imagePositionPatient: origin } = metaData.get(
    'imagePlaneModule',
    sortedImageIds[0]
  );
 
  const result: SortedImageIdsItem = {
    zSpacing,
    origin,
    sortedImageIds,
  };
 
  return result;
}