/// <summary> /// Validates and prepares the provided frames for the <see cref="VolumeBuilder"/>. /// </summary> /// <exception cref="CreateVolumeException">Thrown if something is wrong with the source frames.</exception> public static void PrepareFrames(List <IFrameReference> frames) { // ensure we have at least 3 frames if (frames.Count < 3) { throw new InsufficientFramesException(); } // ensure all frames have are from the same series, and have the same frame of reference string studyInstanceUid = frames[0].Frame.StudyInstanceUid; string seriesInstanceUid = frames[0].Frame.SeriesInstanceUid; string frameOfReferenceUid = frames[0].Frame.FrameOfReferenceUid; if (string.IsNullOrEmpty(studyInstanceUid) || string.IsNullOrEmpty(seriesInstanceUid)) { throw new NullSourceSeriesException(); } if (string.IsNullOrEmpty(frameOfReferenceUid)) { throw new NullFrameOfReferenceException(); } foreach (IFrameReference frame in frames) { if (frame.Frame.StudyInstanceUid != studyInstanceUid) { throw new MultipleSourceSeriesException(); } if (frame.Frame.SeriesInstanceUid != seriesInstanceUid) { throw new MultipleSourceSeriesException(); } if (frame.Frame.FrameOfReferenceUid != frameOfReferenceUid) { throw new MultipleFramesOfReferenceException(); } } // ensure all frames are of the same supported format if (frames.Any(frame => frame.Frame.BitsAllocated != 16)) { throw new UnsupportedPixelFormatSourceImagesException(); } // ensure all frames have the same rescale function units if (frames.Select(frame => frame.Frame.RescaleUnits).Distinct().Count() > 1) { throw new InconsistentRescaleFunctionTypeException(); } // ensure all frames have the same orientation var orient = frames[0].Frame.ImageOrientationPatient; var laterality = frames[0].Frame.Laterality; foreach (IFrameReference frame in frames) { if (frame.Frame.ImageOrientationPatient.IsNull) { throw new NullImageOrientationException(); } if (!frame.Frame.ImageOrientationPatient.EqualsWithinTolerance(orient, _orientationTolerance)) { throw new MultipleImageOrientationsException(); } if (frame.Frame.PixelSpacing.IsNull) { throw new UncalibratedFramesException(); } if (Math.Abs(frame.Frame.PixelSpacing.AspectRatio - 1) > _sliceSpacingTolerance) { throw new AnisotropicPixelAspectRatioException(); } if (laterality != frame.Frame.Laterality) { throw new InconsistentImageLateralityException(); } } // ensure all frames are sorted by slice location SliceLocationComparer sliceLocationComparer = new SliceLocationComparer(); frames.Sort((x, y) => sliceLocationComparer.Compare(x.Frame, y.Frame)); // ensure all frames are evenly spaced var spacing = new float[frames.Count - 1]; for (int i = 1; i < frames.Count; i++) { float currentSpacing = CalcSpaceBetweenPlanes(frames[i].Frame, frames[i - 1].Frame); if (currentSpacing < _minimumSliceSpacing) { throw new UnevenlySpacedFramesException(); } spacing[i - 1] = currentSpacing; } if (spacing.Max() - spacing.Min() > 2 * _sliceSpacingTolerance) { throw new UnevenlySpacedFramesException(); } // ensure frames are not skewed about unsupported axis combinations (this volume builder only normalizes for skew between the Y-axis and XZ-plane in the source data) if (!IsSupportedSourceSkew(frames)) { throw new UnsupportedGantryTiltAxisException(); } }
/// <summary> /// Validates and prepares the provided frames for the <see cref="VolumeBuilder"/>. /// </summary> /// <exception cref="CreateVolumeException">Thrown if something is wrong with the source frames.</exception> public static void PrepareFrames(List <IFrameReference> _frames) { // ensure we have at least 3 frames if (_frames.Count < 3) { throw new InsufficientFramesException(); } // ensure all frames have are from the same series, and have the same frame of reference string studyInstanceUid = _frames[0].Frame.StudyInstanceUid; string seriesInstanceUid = _frames[0].Frame.SeriesInstanceUid; string frameOfReferenceUid = _frames[0].Frame.FrameOfReferenceUid; if (string.IsNullOrEmpty(studyInstanceUid) || string.IsNullOrEmpty(seriesInstanceUid)) { throw new NullSourceSeriesException(); } if (string.IsNullOrEmpty(frameOfReferenceUid)) { throw new NullFrameOfReferenceException(); } foreach (IFrameReference frame in _frames) { if (frame.Frame.StudyInstanceUid != studyInstanceUid) { throw new MultipleSourceSeriesException(); } if (frame.Frame.SeriesInstanceUid != seriesInstanceUid) { throw new MultipleSourceSeriesException(); } if (frame.Frame.FrameOfReferenceUid != frameOfReferenceUid) { throw new MultipleFramesOfReferenceException(); } } // ensure all frames are of the same supported format foreach (IFrameReference frame in _frames) { if (frame.Frame.BitsAllocated != 16) { throw new UnsupportedPixelFormatSourceImagesException(); } } // ensure all frames have the same orientation ImageOrientationPatient orient = _frames[0].Frame.ImageOrientationPatient; foreach (IFrameReference frame in _frames) { if (frame.Frame.ImageOrientationPatient.IsNull) { if (frame.ImageSop.NumberOfFrames > 1) { throw new UnsupportedMultiFrameSourceImagesException(new NullImageOrientationException()); } throw new NullImageOrientationException(); } if (!frame.Frame.ImageOrientationPatient.EqualsWithinTolerance(orient, _orientationTolerance)) { throw new MultipleImageOrientationsException(); } if (frame.Frame.PixelSpacing.IsNull) { throw new UncalibratedFramesException(); } if (Math.Abs(frame.Frame.PixelSpacing.AspectRatio - 1) > _minimumSliceSpacing) { throw new AnisotropicPixelAspectRatioException(); } } // ensure all frames are sorted by slice location SliceLocationComparer sliceLocationComparer = new SliceLocationComparer(); _frames.Sort(delegate(IFrameReference x, IFrameReference y) { return(sliceLocationComparer.Compare(x.Frame, y.Frame)); }); // ensure all frames are equally spaced float?nominalSpacing = null; for (int i = 1; i < _frames.Count; i++) { float currentSpacing = CalcSpaceBetweenPlanes(_frames[i].Frame, _frames[i - 1].Frame); if (currentSpacing < _minimumSliceSpacing) { if (_frames[i].ImageSop.NumberOfFrames > 1) { throw new UnsupportedMultiFrameSourceImagesException(new UnevenlySpacedFramesException()); } throw new UnevenlySpacedFramesException(); } if (!nominalSpacing.HasValue) { nominalSpacing = currentSpacing; } if (!FloatComparer.AreEqual(currentSpacing, nominalSpacing.Value, _sliceSpacingTolerance)) { throw new UnevenlySpacedFramesException(); } } // ensure frames are not tilted about unsupposed axis combinations (the gantry correction algorithm only supports rotations about X) if (!IsSupportedGantryTilt(_frames)) // suffices to check first one... they're all co-planar now!! { throw new UnsupportedGantryTiltAxisException(); } }