Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
 /// <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);
 }
		/// <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 AsyncVolumeSliceSopDataSource(VolumeSlice slice)
		{
			Slice = slice;

			DataSet = new DicomAttributeCollection();
			DataSet[DicomTags.Rows].SetInt32(0, Slice.Rows);
			DataSet[DicomTags.Columns].SetInt32(0, Slice.Colums);
			DataSet[DicomTags.NumberOfFrames].SetInt32(0, 1);
			DataSet[DicomTags.ImageOrientationPatient].SetStringValue(Slice.ImageOrientationPatient);
			DataSet[DicomTags.ImagePositionPatient].SetStringValue(Slice.ImagePositionPatient);
			DataSet[DicomTags.SopInstanceUid].SetString(0, 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();
            DataSet[DicomTags.Rows].SetInt32(0, Slice.Rows);
            DataSet[DicomTags.Columns].SetInt32(0, Slice.Colums);
            DataSet[DicomTags.NumberOfFrames].SetInt32(0, 1);
            DataSet[DicomTags.ImageOrientationPatient].SetStringValue(Slice.ImageOrientationPatient);
            DataSet[DicomTags.ImagePositionPatient].SetStringValue(Slice.ImagePositionPatient);
            DataSet[DicomTags.SopInstanceUid].SetString(0, DicomUid.GenerateUid().UID);
        }
Ejemplo n.º 5
0
		public IEnumerable<VolumeSlice> CreateSlices()
		{
			// get the slice spacing in voxel units
			var sliceSpacing = GetSliceSpacing();

			// get the normal to the plane of slicing (the plane of slicing is the XY plane in the slicing coordinate frame)
			var slicePlaneNormal = GetSliceNormalVector();

			// get a point through which the slices should pass
			var sliceThroughPoint = GetSliceThroughPoint();

			// compute the number of slices required in this slicing rotation, and the slice location at which to start
			int sliceCount;
			float startingSliceLocation;
			{
				// the algorithm for this involves computing the bounding cube for the volume *in the slicing coordinate frame*
				// the number of required slices is thus the span of the Z components (i.e. slice location) of the bounding cube, divided by the slice spacing
				// this algorithm reduces to determining the projection of each of the 8 corners of the volume onto the normal vector of the slice plane

				var minSliceLocation = float.MaxValue;
				var maxSliceLocation = float.MinValue;

				var volumeDimensions = _volume.Volume.Dimensions;
				foreach (var corner in new[]
				                       	{
				                       		new Vector3D(0, 0, 0),
				                       		new Vector3D(volumeDimensions.X, 0, 0),
				                       		new Vector3D(0, volumeDimensions.Y, 0),
				                       		new Vector3D(0, 0, volumeDimensions.Z),
				                       		new Vector3D(volumeDimensions.X, volumeDimensions.Y, 0),
				                       		new Vector3D(volumeDimensions.X, 0, volumeDimensions.Z),
				                       		new Vector3D(0, volumeDimensions.Y, volumeDimensions.Z),
				                       		new Vector3D(volumeDimensions.X, volumeDimensions.Y, volumeDimensions.Z)
				                       	})
				{
					// project the corner vector onto the slice plane normal vector
					var zCoord = slicePlaneNormal.Dot(corner);
					minSliceLocation = Math.Min(minSliceLocation, zCoord);
					maxSliceLocation = Math.Max(maxSliceLocation, zCoord);
				}

				// divide the span of the slice locations by the slice spacing to determine the required number of slices
				sliceCount = (int) Math.Ceiling((maxSliceLocation - minSliceLocation)/sliceSpacing);

				// the starting slice location could be either end, but we choose the larger end to be consistent with the original implementation
				startingSliceLocation = maxSliceLocation;
			}

			// compute the incremental spacing vector
			var spacingVector = sliceSpacing*slicePlaneNormal;

			// compute the slice location of the specified through point
			var throughPointSliceLocation = slicePlaneNormal.Dot(sliceThroughPoint);

			// compute the through point of the first slice
			// (subtract an extra spacing vector, because we're computing from the larger end of the volume voxels, while VTK draws slices from the smaller end of the voxels.
			var initialThroughPoint = sliceThroughPoint + (startingSliceLocation - throughPointSliceLocation)/sliceSpacing*spacingVector - spacingVector;

			var thicknessAndSpacing = Math.Abs(GetSliceSpacing());

			// generate the slice SOPs by computing additional through points
			for (var n = 0; n < sliceCount; n++)
			{
				var slice = new VolumeSlice(_volume.Clone(), _slicerParams, initialThroughPoint - n*spacingVector);
				slice[DicomTags.SliceThickness].SetFloat32(0, thicknessAndSpacing);
				slice[DicomTags.SpacingBetweenSlices].SetFloat32(0, thicknessAndSpacing);
				yield return slice;
			}
		}
Ejemplo n.º 6
0
        public IEnumerable <VolumeSlice> CreateSlices()
        {
            // get the slice spacing in voxel units
            var sliceSpacing = GetSliceSpacing();

            // get the normal to the plane of slicing (the plane of slicing is the XY plane in the slicing coordinate frame)
            var slicePlaneNormal = GetSliceNormalVector();

            // get a point through which the slices should pass
            var sliceThroughPoint = GetSliceThroughPoint();

            // compute the number of slices required in this slicing rotation, and the slice location at which to start
            int   sliceCount;
            float startingSliceLocation;
            {
                // the algorithm for this involves computing the bounding cube for the volume *in the slicing coordinate frame*
                // the number of required slices is thus the span of the Z components (i.e. slice location) of the bounding cube, divided by the slice spacing
                // this algorithm reduces to determining the projection of each of the 8 corners of the volume onto the normal vector of the slice plane

                var minSliceLocation = float.MaxValue;
                var maxSliceLocation = float.MinValue;

                var volumeDimensions = _volume.Volume.Dimensions;
                foreach (var corner in new[]
                {
                    new Vector3D(0, 0, 0),
                    new Vector3D(volumeDimensions.X, 0, 0),
                    new Vector3D(0, volumeDimensions.Y, 0),
                    new Vector3D(0, 0, volumeDimensions.Z),
                    new Vector3D(volumeDimensions.X, volumeDimensions.Y, 0),
                    new Vector3D(volumeDimensions.X, 0, volumeDimensions.Z),
                    new Vector3D(0, volumeDimensions.Y, volumeDimensions.Z),
                    new Vector3D(volumeDimensions.X, volumeDimensions.Y, volumeDimensions.Z)
                })
                {
                    // project the corner vector onto the slice plane normal vector
                    var zCoord = slicePlaneNormal.Dot(corner);
                    minSliceLocation = Math.Min(minSliceLocation, zCoord);
                    maxSliceLocation = Math.Max(maxSliceLocation, zCoord);
                }

                // divide the span of the slice locations by the slice spacing to determine the required number of slices
                sliceCount = (int)Math.Ceiling((maxSliceLocation - minSliceLocation) / sliceSpacing);

                // the starting slice location could be either end, but we choose the larger end to be consistent with the original implementation
                startingSliceLocation = maxSliceLocation;
            }

            // compute the incremental spacing vector
            var spacingVector = sliceSpacing * slicePlaneNormal;

            // compute the slice location of the specified through point
            var throughPointSliceLocation = slicePlaneNormal.Dot(sliceThroughPoint);

            // compute the through point of the first slice
            // (subtract an extra spacing vector, because we're computing from the larger end of the volume voxels, while VTK draws slices from the smaller end of the voxels.
            var initialThroughPoint = sliceThroughPoint + (startingSliceLocation - throughPointSliceLocation) / sliceSpacing * spacingVector - spacingVector;

            var thicknessAndSpacing = Math.Abs(GetSliceSpacing());

            // generate the slice SOPs by computing additional through points
            for (var n = 0; n < sliceCount; n++)
            {
                var slice = new VolumeSlice(_volume.Clone(), _slicerParams, initialThroughPoint - n * spacingVector);
                slice[DicomTags.SliceThickness].SetFloat32(0, thicknessAndSpacing);
                slice[DicomTags.SpacingBetweenSlices].SetFloat32(0, thicknessAndSpacing);
                yield return(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();
     FillDataSet(DataSet, slice);
 }