UNPKG

@cornerstonejs/core

Version:
113 lines (112 loc) 5.24 kB
import { vec3 } from 'gl-matrix'; import * as metaData from '../metaData.js'; import { MetadataModules } from '../enums/index.js'; import { getConfiguration } from '../init.js'; const DEFAULT_THICKNESS_SINGLE_SLICE = 1; function getPixelSpacingForCubicVoxel(metadata) { if (metadata.columnPixelSpacing !== undefined) { return metadata.columnPixelSpacing; } if (metadata.rowPixelSpacing !== undefined) { return metadata.rowPixelSpacing; } if (metadata.pixelSpacing?.[1] !== undefined) { return metadata.pixelSpacing[1]; } if (metadata.pixelSpacing?.[0] !== undefined) { return metadata.pixelSpacing[0]; } return undefined; } export default function calculateSpacingBetweenImageIds(imageIds) { const { imagePositionPatient: referenceImagePositionPatient, imageOrientationPatient, } = metaData.get(MetadataModules.IMAGE_PLANE, imageIds[0]); if (imageIds.length === 1) { const { sliceThickness, spacingBetweenSlices, columnPixelSpacing, rowPixelSpacing, pixelSpacing, } = metaData.get(MetadataModules.IMAGE_PLANE, imageIds[0]); if (sliceThickness) return sliceThickness; if (spacingBetweenSlices) return spacingBetweenSlices; const pixelSpacingValue = getPixelSpacingForCubicVoxel({ columnPixelSpacing, rowPixelSpacing, pixelSpacing, }); if (pixelSpacingValue !== undefined) { return pixelSpacingValue; } return DEFAULT_THICKNESS_SINGLE_SLICE; } const rowCosineVec = vec3.fromValues(imageOrientationPatient[0], imageOrientationPatient[1], imageOrientationPatient[2]); const colCosineVec = vec3.fromValues(imageOrientationPatient[3], imageOrientationPatient[4], imageOrientationPatient[5]); const scanAxisNormal = vec3.create(); vec3.cross(scanAxisNormal, rowCosineVec, colCosineVec); const refIppVec = vec3.fromValues(referenceImagePositionPatient[0], referenceImagePositionPatient[1], referenceImagePositionPatient[2]); const usingWadoUri = imageIds[0].split(':')[0] === 'wadouri'; let spacing; function getDistance(imageId) { const { imagePositionPatient } = metaData.get(MetadataModules.IMAGE_PLANE, imageId); const positionVector = vec3.create(); const ippVec = vec3.fromValues(imagePositionPatient[0], imagePositionPatient[1], imagePositionPatient[2]); vec3.sub(positionVector, refIppVec, ippVec); return vec3.dot(positionVector, scanAxisNormal); } if (!usingWadoUri) { const distanceImagePairs = imageIds.map((imageId) => { const distance = getDistance(imageId); return { distance, imageId, }; }); distanceImagePairs.sort((a, b) => b.distance - a.distance); const numImages = distanceImagePairs.length; spacing = Math.abs(distanceImagePairs[numImages - 1].distance - distanceImagePairs[0].distance) / (numImages - 1); } else { const prefetchedImageIds = [ imageIds[0], imageIds[Math.floor(imageIds.length / 2)], ]; const metadataForMiddleImage = metaData.get(MetadataModules.IMAGE_PLANE, prefetchedImageIds[1]); if (!metadataForMiddleImage) { throw new Error('Incomplete metadata required for volume construction.'); } const positionVector = vec3.create(); const middleIppVec = vec3.fromValues(metadataForMiddleImage.imagePositionPatient[0], metadataForMiddleImage.imagePositionPatient[1], metadataForMiddleImage.imagePositionPatient[2]); vec3.sub(positionVector, refIppVec, middleIppVec); const distanceBetweenFirstAndMiddleImages = vec3.dot(positionVector, scanAxisNormal); spacing = Math.abs(distanceBetweenFirstAndMiddleImages) / Math.floor(imageIds.length / 2); } const { sliceThickness, spacingBetweenSlices, columnPixelSpacing, rowPixelSpacing, pixelSpacing, } = metaData.get(MetadataModules.IMAGE_PLANE, imageIds[0]); const { strictZSpacingForVolumeViewport } = getConfiguration().rendering; if ((spacing === 0 || isNaN(spacing)) && !strictZSpacingForVolumeViewport) { if (spacingBetweenSlices) { console.debug('Could not calculate spacing. Using spacingBetweenSlices'); spacing = spacingBetweenSlices; } else if (sliceThickness) { console.debug('Could not calculate spacing and no spacingBetweenSlices. Using sliceThickness'); spacing = sliceThickness; } else { const pixelSpacingValue = getPixelSpacingForCubicVoxel({ columnPixelSpacing, rowPixelSpacing, pixelSpacing, }); if (pixelSpacingValue) { spacing = pixelSpacingValue; } else { console.debug(`Could not calculate spacing and no pixel spacing found. Using default thickness (${DEFAULT_THICKNESS_SINGLE_SLICE} mm)`); spacing = DEFAULT_THICKNESS_SINGLE_SLICE; } } } return spacing; }