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 | import type { Types } from '@cornerstonejs/core'; import { state } from '../../stateManagement/annotation'; import { RectangleROIStartEndThresholdTool, RectangleROIThresholdTool, } from '../../tools'; import thresholdVolumeByRange from './thresholdVolumeByRange'; import getBoundsIJKFromRectangleAnnotations from '../rectangleROITool/getBoundsIJKFromRectangleAnnotations'; export type ThresholdInformation = { volume: Types.IImageVolume; lower: number; upper: number; }; export type ThresholdOptions = { numSlicesToProject?: number; // number of slices to project before and after current slice overwrite: boolean; overlapType?: number; // type of the voxel overlap }; export type AnnotationForThresholding = { data: { handles: { points: Types.Point3[]; }; cachedStats?: { projectionPoints?: Types.Point3[][]; }; }; }; /** * It uses the provided rectangleROI annotations (either RectangleROIThreshold, or * RectangleROIStartEndThreshold) to compute an ROI that is the intersection of * all the annotations. Then it uses the rectangleROIThreshold utility to threshold * the volume. * @param annotationUIDs - rectangleROI annotationsUIDs to use for ROI * @param segmentationVolume - the segmentation volume * @param thresholdVolumeInformation - object array containing the volume data and range threshold values * @param options - options for thresholding * @returns */ function rectangleROIThresholdVolumeByRange( annotationUIDs: string[], segmentationVolume: Types.IImageVolume, thresholdVolumeInformation: ThresholdInformation[], options: ThresholdOptions ): Types.IImageVolume { const annotations = annotationUIDs.map((annotationUID) => { return state.getAnnotation(annotationUID); }); _validateAnnotations(annotations); let boundsIJK; for (let i = 0; i < thresholdVolumeInformation.length; i++) { // make sure that the boundsIJK are generated by the correct volume const volumeSize = thresholdVolumeInformation[i].volume.scalarData.length; if (volumeSize === segmentationVolume.scalarData.length || i === 0) { boundsIJK = getBoundsIJKFromRectangleAnnotations( annotations, thresholdVolumeInformation[i].volume, options ); } } const outputSegmentationVolume = thresholdVolumeByRange( segmentationVolume, thresholdVolumeInformation, { ...options, boundsIJK } ); return outputSegmentationVolume; } function _validateAnnotations(annotations) { const validToolNames = [ RectangleROIThresholdTool.toolName, RectangleROIStartEndThresholdTool.toolName, ]; for (const annotation of annotations) { const name = annotation.metadata.toolName; if (!validToolNames.includes(name)) { throw new Error( 'rectangleROIThresholdVolumeByRange only supports RectangleROIThreshold and RectangleROIStartEndThreshold annotations' ); } } } export default rectangleROIThresholdVolumeByRange; |