private static void AssertVolumeSlice(VolumeSlice actualSlice,
                                              int expectedRows, int expectedColumns,
                                              Vector3D expectedPositionPatient,
                                              Vector3D expectedRowOrientationPatient, Vector3D expectedColumnOrientationPatient,
                                              float expectedRowSpacing, float expectedColumnSpacing,
                                              float expectedSliceThickness, float?expectedSpacingBetweenSlices,
                                              string message = null, params object[] args)
        {
            const float tolerance = 1e-5f;
            var         msg       = !string.IsNullOrEmpty(message) ? "{0} (" + string.Format(message, args) + ")" : "{0}";

            Assert.AreEqual(expectedRows, actualSlice.Rows, msg, "Rows");
            Assert.AreEqual(expectedColumns, actualSlice.Columns, msg, "Columns");

            var imagePositionPatient = ImagePositionPatient.FromString(actualSlice.ImagePositionPatient);

            Assert.IsNotNull(imagePositionPatient, "ImagePositionPatient");

            var actualPositionPatient = new Vector3D((float)imagePositionPatient.X, (float)imagePositionPatient.Y, (float)imagePositionPatient.Z);

            if (!Vector3D.AreEqual(expectedPositionPatient, actualPositionPatient, tolerance))
            {
                Assert.AreEqual(expectedPositionPatient, actualPositionPatient, msg, "ImagePositionPatient");
            }

            var imageOrientationPatient = ImageOrientationPatient.FromString(actualSlice.ImageOrientationPatient);

            Assert.IsNotNull(imageOrientationPatient, "ImageOrientationPatient");

            var actualRowOrientationPatient    = new Vector3D((float)imageOrientationPatient.RowX, (float)imageOrientationPatient.RowY, (float)imageOrientationPatient.RowZ);
            var actualColumnOrientationPatient = new Vector3D((float)imageOrientationPatient.ColumnX, (float)imageOrientationPatient.ColumnY, (float)imageOrientationPatient.ColumnZ);

            if (!Vector3D.AreEqual(expectedRowOrientationPatient, actualRowOrientationPatient, tolerance))
            {
                Assert.AreEqual(expectedRowOrientationPatient, actualRowOrientationPatient, msg, "ImageOrientationPatient.Row");
            }
            if (!Vector3D.AreEqual(expectedColumnOrientationPatient, actualColumnOrientationPatient, tolerance))
            {
                Assert.AreEqual(expectedColumnOrientationPatient, actualColumnOrientationPatient, msg, "ImageOrientationPatient.Column");
            }

            var actualPixelSpacing = PixelSpacing.FromString(actualSlice.PixelSpacing);

            Assert.IsNotNull(actualPixelSpacing, "PixelSpacing");
            Assert.AreEqual(expectedRowSpacing, actualPixelSpacing.Row, tolerance, msg, "PixelSpacing.Row");
            Assert.AreEqual(expectedColumnSpacing, actualPixelSpacing.Column, tolerance, msg, "PixelSpacing.Column");

            Assert.AreEqual(expectedSliceThickness, float.Parse(actualSlice.SliceThickness), tolerance, msg, "SliceThickness");

            if (expectedSpacingBetweenSlices.HasValue)
            {
                Assert.AreEqual(expectedSpacingBetweenSlices.Value, float.Parse(actualSlice.SpacingBetweenSlices), tolerance, msg, "SpacingBetweenSlices");
            }
            else
            {
                Assert.IsEmpty(actualSlice.SpacingBetweenSlices, msg, "SpacingBetweenSlices");
            }
        }
		private static void AssertVolumeSlice(VolumeSlice actualSlice,
		                                      int expectedRows, int expectedColumns,
		                                      Vector3D expectedPositionPatient,
		                                      Vector3D expectedRowOrientationPatient, Vector3D expectedColumnOrientationPatient,
		                                      float expectedRowSpacing, float expectedColumnSpacing,
		                                      float expectedSliceThickness, float? expectedSpacingBetweenSlices,
		                                      string message = null, params object[] args)
		{
			const float tolerance = 1e-5f;
			var msg = !string.IsNullOrEmpty(message) ? "{0} (" + string.Format(message, args) + ")" : "{0}";

			Assert.AreEqual(expectedRows, actualSlice.Rows, msg, "Rows");
			Assert.AreEqual(expectedColumns, actualSlice.Columns, msg, "Columns");

			var imagePositionPatient = ImagePositionPatient.FromString(actualSlice.ImagePositionPatient);
			Assert.IsNotNull(imagePositionPatient, "ImagePositionPatient");

			var actualPositionPatient = new Vector3D((float) imagePositionPatient.X, (float) imagePositionPatient.Y, (float) imagePositionPatient.Z);
			if (!Vector3D.AreEqual(expectedPositionPatient, actualPositionPatient, tolerance))
				Assert.AreEqual(expectedPositionPatient, actualPositionPatient, msg, "ImagePositionPatient");

			var imageOrientationPatient = ImageOrientationPatient.FromString(actualSlice.ImageOrientationPatient);
			Assert.IsNotNull(imageOrientationPatient, "ImageOrientationPatient");

			var actualRowOrientationPatient = new Vector3D((float) imageOrientationPatient.RowX, (float) imageOrientationPatient.RowY, (float) imageOrientationPatient.RowZ);
			var actualColumnOrientationPatient = new Vector3D((float) imageOrientationPatient.ColumnX, (float) imageOrientationPatient.ColumnY, (float) imageOrientationPatient.ColumnZ);
			if (!Vector3D.AreEqual(expectedRowOrientationPatient, actualRowOrientationPatient, tolerance))
				Assert.AreEqual(expectedRowOrientationPatient, actualRowOrientationPatient, msg, "ImageOrientationPatient.Row");
			if (!Vector3D.AreEqual(expectedColumnOrientationPatient, actualColumnOrientationPatient, tolerance))
				Assert.AreEqual(expectedColumnOrientationPatient, actualColumnOrientationPatient, msg, "ImageOrientationPatient.Column");

			var actualPixelSpacing = PixelSpacing.FromString(actualSlice.PixelSpacing);
			Assert.IsNotNull(actualPixelSpacing, "PixelSpacing");
			Assert.AreEqual(expectedRowSpacing, actualPixelSpacing.Row, tolerance, msg, "PixelSpacing.Row");
			Assert.AreEqual(expectedColumnSpacing, actualPixelSpacing.Column, tolerance, msg, "PixelSpacing.Column");

			Assert.AreEqual(expectedSliceThickness, float.Parse(actualSlice.SliceThickness), tolerance, msg, "SliceThickness");

			if (expectedSpacingBetweenSlices.HasValue)
				Assert.AreEqual(expectedSpacingBetweenSlices.Value, float.Parse(actualSlice.SpacingBetweenSlices), tolerance, msg, "SpacingBetweenSlices");
			else
				Assert.IsEmpty(actualSlice.SpacingBetweenSlices, msg, "SpacingBetweenSlices");
		}
		internal static void FillDataSet(IDicomAttributeProvider dataSet, VolumeSlice slice)
		{
			// generate values for SC Equipment Module
			var scEquipment = new ScEquipmentModuleIod(dataSet);
			scEquipment.ConversionType = @"WSD";
			scEquipment.SecondaryCaptureDeviceManufacturer = @"ClearCanvas Inc.";
			scEquipment.SecondaryCaptureDeviceManufacturersModelName = ProductInformation.GetName(false, false);
			scEquipment.SecondaryCaptureDeviceSoftwareVersions = new[] {ProductInformation.GetVersion(true, true, true, true)};

			// generate values for the General Image Module
			dataSet[DicomTags.ImageType].SetStringValue(@"DERIVED\SECONDARY");
			dataSet[DicomTags.DerivationDescription].SetStringValue(@"Multiplanar Reformatting");
			dataSet[DicomTags.DerivationCodeSequence].Values = new[] {ImageDerivationContextGroup.MultiplanarReformatting.AsDicomSequenceItem()};

			// update the Image Plane Module
			dataSet[DicomTags.PixelSpacing].SetStringValue(slice.PixelSpacing);
			dataSet[DicomTags.ImageOrientationPatient].SetStringValue(slice.ImageOrientationPatient);
			dataSet[DicomTags.ImagePositionPatient].SetStringValue(slice.ImagePositionPatient);
			dataSet[DicomTags.SliceThickness].SetStringValue(slice.SliceThickness);

			// update the spacing between slices, even though it's only part of modality-specific modules
			dataSet[DicomTags.SpacingBetweenSlices].SetStringValue(slice.SpacingBetweenSlices);

			// update the Image Pixel Module
			dataSet[DicomTags.Rows].SetInt32(0, slice.Rows);
			dataSet[DicomTags.Columns].SetInt32(0, slice.Columns);

			// generate values for Multi-Frame Module
			dataSet[DicomTags.NumberOfFrames].SetInt32(0, 1);

			// generate values for SOP Common Module
			dataSet[DicomTags.SopClassUid].SetStringValue(SopClass.SecondaryCaptureImageStorageUid);
			dataSet[DicomTags.SopInstanceUid].SetStringValue(DicomUid.GenerateUid().UID);
		}
		/// <summary>
		/// Initializes a new <see cref="ISopDataSource"/> for the given volume slice.
		/// </summary>
		/// <param name="slice">A volume slice. This instance will be disposed when the <see cref="VolumeSliceSopDataSource"/> instance is disposed.</param>
		public VolumeSliceSopDataSource(VolumeSlice slice)
		{
			Slice = slice;
			DataSet = new DicomAttributeCollection();
			FillDataSet(DataSet, slice);
		}
		/// <summary>
		/// Initializes a new <see cref="ISopDataSource"/> for the given volume slice.
		/// </summary>
		/// <param name="slice">A volume slice. This instance will be disposed when the <see cref="VolumeSliceSopDataSource"/> instance is disposed.</param>
		public VolumeSliceSopDataSource(VolumeSlice slice)
		{
			Slice = slice;
		    DataSet = new DicomAttributeCollection() {ValidateVrLengths = false, ValidateVrValues = false};
			FillDataSet(DataSet, slice);
		}