/// <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(); }
/// <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(); }