Example #1
0
        public void TestGetWindowsWithExplanations()
        {
            var windows = new[]
            {
                new VoiWindow(1, 2),
                new VoiWindow(100, 200),
                new VoiWindow(100.1, 200.2),
                new VoiWindow(123.1, 456.2),
                new VoiWindow(123.567890123, -23.567890123)
            };

            var dataset = new DicomAttributeCollection();

            dataset[DicomTags.WindowCenter].SetStringValue(@"2\200\200.2\456.2\-23.567890123");
            dataset[DicomTags.WindowWidth].SetStringValue(@"1\100\100.1\123.1\123.567890123");
            dataset[DicomTags.WindowCenterWidthExplanation].SetStringValue(@"bob\alice\eve\james");

            var actualWindows = VoiWindow.GetWindows(dataset).ToArray();

            Assert.AreEqual(windows, actualWindows);
            Assert.AreEqual("bob", actualWindows[0].Explanation);
            Assert.AreEqual("alice", actualWindows[1].Explanation);
            Assert.AreEqual("eve", actualWindows[2].Explanation);
            Assert.AreEqual("james", actualWindows[3].Explanation);
            Assert.AreEqual("", actualWindows[4].Explanation);
        }
Example #2
0
            /// <summary>
            /// Creates the <see cref="VolumeHeaderData"/> for the builder's source frames.
            /// </summary>
            /// <returns></returns>
            public VolumeHeaderData BuildVolumeHeader()
            {
                if (_volumeHeaderData != null)
                {
                    return(_volumeHeaderData);
                }

                PrepareFrames(_frames);                 // this also sorts the frames into order by slice location

                // compute modality LUT parameters normalized for all frames
                double normalizedSlope, normalizedIntercept;
                var    normalizedUnits = _frames[0].Frame.RescaleUnits;

                ComputeNormalizedModalityLut(_frames, out normalizedSlope, out normalizedIntercept);

                // determine an appropriate pixel padding value
                var pixelPaddingValue = ComputePixelPaddingValue(_frames, normalizedSlope, normalizedIntercept);

                // get the laterality of the anatomy being constructed
                var laterality = _frames[0].Frame.Laterality;

                // Construct a model SOP data source based on the first frame's DICOM header
                var header = new VolumeHeaderData(_frames.Select(f => (IDicomAttributeProvider)f.Frame).ToList(), VolumeSize, VoxelSpacing, VolumePositionPatient, VolumeOrientationPatient, 16, 16, false, pixelPaddingValue, normalizedSlope, normalizedIntercept, normalizedUnits, laterality);

                // determine how the normalized modality LUT affects VOI windows and update the header
                VoiWindow.SetWindows(ComputeAggregateNormalizedVoiWindows(_frames, normalizedSlope, normalizedIntercept), header);

                return(_volumeHeaderData = header);
            }
            /// <summary>
            /// Creates and populates a <see cref="Volume"/> from the builder's source frames.
            /// </summary>
            public Volume Build()
            {
                PrepareFrames(_frames);                 // this also sorts the frames into order by slice location

                // Construct a model SOP data source based on the first frame's DICOM header
                var sopDataSourcePrototype = VolumeSopDataSourcePrototype.Create(_frames.Select(f => (IDicomAttributeProvider)f.Sop.DataSource).ToList(), 16, 16, false);

                // compute normalized modality LUT
                double normalizedSlope, normalizedIntercept;

                ComputeNormalizedModalityLut(_frames, out normalizedSlope, out normalizedIntercept);
                sopDataSourcePrototype[DicomTags.RescaleSlope].SetFloat64(0, normalizedSlope);
                sopDataSourcePrototype[DicomTags.RescaleIntercept].SetFloat64(0, normalizedIntercept);
                sopDataSourcePrototype[DicomTags.RescaleType] = _frames[0].Sop.DataSource[DicomTags.RescaleType].Copy();
                sopDataSourcePrototype[DicomTags.Units]       = _frames[0].Sop.DataSource[DicomTags.Units].Copy();           // PET series use this attribute to designate rescale units

                // compute normalized VOI windows
                VoiWindow.SetWindows(ComputeNormalizedVoiWindows(_frames, normalizedSlope, normalizedIntercept), sopDataSourcePrototype);

                // compute the volume padding value
                var pixelPaddingValue = ComputePixelPaddingValue(_frames, normalizedSlope, normalizedIntercept);

                int minVolumeValue, maxVolumeValue;
                var volumeArray = BuildVolumeArray(pixelPaddingValue, normalizedSlope, normalizedIntercept, out minVolumeValue, out maxVolumeValue);
                var volume      = new Volume(null, volumeArray, VolumeSize, VoxelSpacing, ImagePositionPatient, ImageOrientationPatient, sopDataSourcePrototype, pixelPaddingValue, _frames[0].Frame.SeriesInstanceUid, minVolumeValue, maxVolumeValue);

                return(volume);
            }
Example #4
0
        public void TestGetWindowsMissingWidths()
        {
            var dataset = new DicomAttributeCollection();

            dataset[DicomTags.WindowCenter].SetStringValue(@"2\200\200.2\456.2\-23.567890123");
            dataset[DicomTags.WindowWidth].SetEmptyValue();

            var windows = VoiWindow.GetWindows(dataset).ToArray();

            Assert.AreEqual(new VoiWindow[0], windows);
        }
Example #5
0
        public void TestSetWindowsEmpty()
        {
            var windows = new VoiWindow[0];

            var dataset = new DicomAttributeCollection();

            VoiWindow.SetWindows(windows, dataset);

            Assert.IsTrue(dataset[DicomTags.WindowCenter].IsEmpty);
            Assert.IsTrue(dataset[DicomTags.WindowWidth].IsEmpty);
        }
Example #6
0
        public FusionOverlayData(IEnumerable <Frame> overlaySource)
        {
            var frames = new List <IFrameReference>();

            foreach (Frame frame in overlaySource)
            {
                frames.Add(frame.CreateTransientReference());
            }
            _frames = frames.AsReadOnly();

            if (frames.Count > 0)
            {
                _voiWindows = new List <VoiWindow>(VoiWindow.GetWindows(frames[0].Sop.DataSource)).AsReadOnly();
            }
        }
Example #7
0
		public void TestExplanations()
		{
			var window0 = new VoiWindow(123.1, 456.2);
			Assert.AreEqual(string.Empty, window0.Explanation);

			var window1 = new VoiWindow(123.1, 456.2, null);
			Assert.AreEqual(string.Empty, window1.Explanation);
			Assert.AreEqual(window1, window0);

			var window2 = new VoiWindow(123.1, 456.2, "explanation");
			Assert.AreEqual("explanation", window2.Explanation);
			Assert.AreEqual(window1, window2);

			var window3 = new VoiWindow(4132, 324, "explanation");
			Assert.AreNotEqual(window2, window3);
		}
Example #8
0
            private static IEnumerable <VoiWindow> ComputeNormalizedVoiWindows(IImageSopProvider frame, double normalizedSlope, double normalizedIntercept)
            {
                var normalizedWindows = new List <VoiWindow>(VoiWindow.GetWindows(frame.Frame));

                if (frame.ImageSop.Modality == @"PT" && frame.Frame.IsSubnormalRescale)
                {
                    // for PET images with subnormal rescale, the VOI window will always be applied directly to the original stored pixel values
                    // since MPR will not have access to original stored pixel values, we compute the VOI window through original modality LUT and inverted normalized modality LUT
                    var normalizedVoiSlope     = frame.Frame.RescaleSlope / normalizedSlope;
                    var normalizedVoiIntercept = (frame.Frame.RescaleIntercept - normalizedIntercept) / normalizedSlope;
                    for (var i = 0; i < normalizedWindows.Count; ++i)
                    {
                        var window = normalizedWindows[i];                         // round the computed windows - the extra precision is not useful for display anyway
                        normalizedWindows[i] = new VoiWindow(Math.Ceiling(window.Width * normalizedVoiSlope), Math.Round(window.Center * normalizedVoiSlope + normalizedVoiIntercept), window.Explanation);
                    }
                }
                return(normalizedWindows);
            }
Example #9
0
		public void TestBasics()
		{
			var window1 = new VoiWindow(123.1, 456.2);
			Assert.AreEqual(123.1, window1.Width);
			Assert.AreEqual(456.2, window1.Center);
			Assert.AreEqual("123.10/456.20", window1.ToString());

			Assert.IsFalse(window1.Equals(new object()));

			var window2 = new VoiWindow(1.231, 456.2);
			Assert.AreNotEqual(window1, window2);

			var window3 = new VoiWindow(123.1, 4.562);
			Assert.AreNotEqual(window1, window3);

			var window4 = new VoiWindow(123.1, 456.2);
			Assert.AreEqual(window1, window4);
		}
Example #10
0
        public void TestGetWindowsMismatchedPairs()
        {
            var windows = new[]
            {
                new VoiWindow(1, 2),
                new VoiWindow(100, 200),
                new VoiWindow(100.1, 200.2),
                new VoiWindow(123.1, 456.2)
            };

            var dataset = new DicomAttributeCollection();

            dataset[DicomTags.WindowCenter].SetStringValue(@"2\200\200.2\456.2\-23.567890123");
            dataset[DicomTags.WindowWidth].SetStringValue(@"1\100\100.1\123.1");

            var actualWindows = VoiWindow.GetWindows(dataset).ToArray();

            Assert.AreEqual(windows, actualWindows);
        }
Example #11
0
        public FusionOverlayData(IEnumerable <Frame> overlaySource)
        {
            var frames = new List <IFrameReference>();

            foreach (Frame frame in overlaySource)
            {
                frames.Add(frame.CreateTransientReference());
            }
            _frames = frames.AsReadOnly();

            if (frames.Count > 0)
            {
                // TODO: should this VOI window be based on volume header's normalized VOI windows?
                _voiWindows             = new List <VoiWindow>(VoiWindow.GetWindows(frames[0].Frame)).AsReadOnly();
                SourceSeriesInstanceUid = frames[0].Frame.SeriesInstanceUid;
                FrameOfReferenceUid     = frames[0].Frame.FrameOfReferenceUid;
                Modality = frames[0].Sop.Modality;
            }
        }
Example #12
0
        public void TestExplanations()
        {
            var window0 = new VoiWindow(123.1, 456.2);

            Assert.AreEqual(string.Empty, window0.Explanation);

            var window1 = new VoiWindow(123.1, 456.2, null);

            Assert.AreEqual(string.Empty, window1.Explanation);
            Assert.AreEqual(window1, window0);

            var window2 = new VoiWindow(123.1, 456.2, "explanation");

            Assert.AreEqual("explanation", window2.Explanation);
            Assert.AreEqual(window1, window2);

            var window3 = new VoiWindow(4132, 324, "explanation");

            Assert.AreNotEqual(window2, window3);
        }
Example #13
0
        public void TestSetWindows()
        {
            var windows = new[]
            {
                new VoiWindow(1, 2),
                new VoiWindow(100, 200),
                new VoiWindow(100.1, 200.2),
                new VoiWindow(123.1, 456.2),
                new VoiWindow(123.567890123, -23.567890123)
            };

            var dataset = new DicomAttributeCollection();

            VoiWindow.SetWindows(windows, dataset);

            Assert.AreEqual(5, dataset[DicomTags.WindowCenter].Count);
            Assert.AreEqual(dataset[DicomTags.WindowCenter].ToString(), @"2\200\200.2\456.2\-23.567890123");

            Assert.AreEqual(5, dataset[DicomTags.WindowWidth].Count);
            Assert.AreEqual(dataset[DicomTags.WindowWidth].ToString(), @"1\100\100.1\123.1\123.567890123");
        }
Example #14
0
        public void TestBasics()
        {
            var window1 = new VoiWindow(123.1, 456.2);

            Assert.AreEqual(123.1, window1.Width);
            Assert.AreEqual(456.2, window1.Center);
            Assert.AreEqual("123.10/456.20", window1.ToString());

            Assert.IsFalse(window1.Equals(new object()));

            var window2 = new VoiWindow(1.231, 456.2);

            Assert.AreNotEqual(window1, window2);

            var window3 = new VoiWindow(123.1, 4.562);

            Assert.AreNotEqual(window1, window3);

            var window4 = new VoiWindow(123.1, 456.2);

            Assert.AreEqual(window1, window4);
        }
Example #15
0
        public void TestSetWindowsWithExplanations()
        {
            var windows = new[]
            {
                new VoiWindow(1, 2, "bob"),
                new VoiWindow(100, 200, "alice"),
                new VoiWindow(100.1, 200.2, "eve"),
                new VoiWindow(123.1, 456.2, "james"),
                new VoiWindow(123.567890123, -23.567890123)
            };

            var dataset = new DicomAttributeCollection();

            VoiWindow.SetWindows(windows, dataset);

            Assert.AreEqual(5, dataset[DicomTags.WindowCenter].Count);
            Assert.AreEqual(dataset[DicomTags.WindowCenter].ToString(), @"2\200\200.2\456.2\-23.567890123");

            Assert.AreEqual(5, dataset[DicomTags.WindowWidth].Count);
            Assert.AreEqual(dataset[DicomTags.WindowWidth].ToString(), @"1\100\100.1\123.1\123.567890123");

            Assert.AreEqual(5, dataset[DicomTags.WindowCenterWidthExplanation].Count);
            Assert.AreEqual(dataset[DicomTags.WindowCenterWidthExplanation].ToString(), @"bob\alice\eve\james\");
        }
Example #16
0
			private static IEnumerable<VoiWindow> ComputeNormalizedVoiWindows(IList<IFrameReference> frames, double normalizedSlope, double normalizedIntercept)
			{
				var normalizedWindows = new List<VoiWindow>(VoiWindow.GetWindows(frames[0].Sop.DataSource));
				if (frames[0].ImageSop.Modality == @"PT" && frames[0].Frame.IsSubnormalRescale)
				{
					// for PET images with subnormal rescale, the VOI window will always be applied directly to the original stored pixel values
					// since MPR will not have access to original stored pixel values, we compute the VOI window through original modality LUT and inverted normalized modality LUT
					var normalizedVoiSlope = frames[0].Frame.RescaleSlope/normalizedSlope;
					var normalizedVoiIntercept = (frames[0].Frame.RescaleIntercept - normalizedIntercept)/normalizedSlope;
					for (var i = 0; i < normalizedWindows.Count; ++i)
					{
						var window = normalizedWindows[i]; // round the computed windows - the extra precision is not useful for display anyway
						normalizedWindows[i] = new VoiWindow(Math.Ceiling(window.Width*normalizedVoiSlope), Math.Round(window.Center*normalizedVoiSlope + normalizedVoiIntercept), window.Explanation);
					}
				}
				return normalizedWindows;
			}
Example #17
0
		public void TestSetWindowsEmpty()
		{
			var windows = new VoiWindow[0];

			var dataset = new DicomAttributeCollection();
			VoiWindow.SetWindows(windows, dataset);

			Assert.IsTrue(dataset[DicomTags.WindowCenter].IsEmpty);
			Assert.IsTrue(dataset[DicomTags.WindowWidth].IsEmpty);
		}