Beispiel #1
0
        public void Apply(IPresentationImage image)
        {
            IImageSpatialTransform transform          = (IImageSpatialTransform)_operation.GetOriginator(image);
            IImageSpatialTransform referenceTransform = (IImageSpatialTransform)this.SelectedSpatialTransformProvider.SpatialTransform;

            transform.Scale      = referenceTransform.Scale;
            transform.ScaleToFit = referenceTransform.ScaleToFit;

            if (GetCheckedSync() == false)
            {
                return;
            }
            //
            IVoiLutLinear selectedLut = (IVoiLutLinear)this.SelectedVoiLutProvider.VoiLutManager.VoiLut;

            IVoiLutProvider provider = ((IVoiLutProvider)image);

            if (!(provider.VoiLutManager.VoiLut is IBasicVoiLutLinear))
            {
                BasicVoiLutLinear installLut = new BasicVoiLutLinear(selectedLut.WindowWidth, selectedLut.WindowCenter);
                provider.VoiLutManager.InstallVoiLut(installLut);
            }

            IBasicVoiLutLinear lut = (IBasicVoiLutLinear)provider.VoiLutManager.VoiLut;

            lut.WindowWidth  = selectedLut.WindowWidth;
            lut.WindowCenter = selectedLut.WindowCenter;
            //
            transform.TranslationX = this.SelectedSpatialTransformProvider.SpatialTransform.TranslationX;
            transform.TranslationY = this.SelectedSpatialTransformProvider.SpatialTransform.TranslationY;
        }
		public void AlterWindowLevel()
		{
			const double windowWidth = 4096;
			const double windowLevel = 2047;

			BasicVoiLutLinear lut = new BasicVoiLutLinear();
			lut.MinInputValue = 0;
			lut.MaxInputValue = 4095;

			lut.WindowWidth = windowWidth;
			lut.WindowCenter = windowLevel;

			const double delta = 0.0001;

			Assert.AreEqual(1.0, lut[0], delta);
			Assert.AreEqual(2048.0, lut[2047], delta);
			Assert.AreEqual(4095.0, lut[4095], delta);

			lut.WindowWidth = 512;
			lut.WindowCenter = 1023;

			Assert.AreEqual(512, lut.WindowWidth, delta);
			Assert.AreEqual(1023, lut.WindowCenter, delta);
			Assert.AreEqual(0, lut[767], delta);
			Assert.AreEqual(4095, lut[1279]);
		}
        public void TestPipelineSigned12()
        {
            var composer = new LutComposer(12, true);

            composer.ModalityLut = new ModalityLutLinear(12, true, 1, 0);
            var voiLUT = new BasicVoiLutLinear(4096, 0);

            composer.VoiLut = voiLUT;

            Assert.AreEqual(-2048, voiLUT[-2048], _tolerance);
            Assert.AreEqual(0, voiLUT[0], _tolerance);
            Assert.AreEqual(2047, voiLUT[2047], _tolerance);

            var output = composer.GetOutputLut(0, byte.MaxValue);

            Assert.AreEqual(0, output[-2048]);
            Assert.AreEqual(128, output[0]);
            Assert.AreEqual(255, output[2047]);

            //10-bit display
            output = composer.GetOutputLut(0, 1023);
            Assert.AreEqual(0, output[-2048]);
            Assert.AreEqual(512, output[0]);
            Assert.AreEqual(1023, output[2047]);

            //Theoretical 12-bit display with signed output
            output = composer.GetOutputLut(-2048, 2047);
            Assert.AreEqual(-2048, output[-2048]);
            Assert.AreEqual(0, output[0]);
            Assert.AreEqual(2047, output[2047]);
        }
Beispiel #4
0
        public void TestDicomExampleC()
        {
            const double windowCentre = 0;
            const double windowWidth  = 100;

            var lut = new BasicVoiLutLinear(windowWidth, windowCentre)
            {
                MinInputValue = short.MinValue, MaxInputValue = short.MaxValue
            };

            Assert.AreEqual((int)lut.MinInputValue, lut.MinOutputValue, "LUT output range min");
            Assert.AreEqual((int)lut.MaxInputValue, lut.MaxOutputValue, "LUT output range max");

            Assert.AreEqual(DicomReferenceFunction(-50 - 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-50 - 1e-6], "LUT output for value X < C-0.5 - (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(-50, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-50], "LUT output for value X == C-0.5 - (W-1)/2");

            Assert.AreEqual(DicomReferenceFunction(49 + 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[49 + 1e-6], "LUT output for value X > C-0.5 + (W-1)/2");

            Assert.AreEqual(DicomReferenceFunction(-49.9, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-49.9], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(-49, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-49], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(-44, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-44], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(0, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(43, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[43], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(48.9, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[48.9], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(49, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[49], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
        }
        private void SetWindow(double windowWidth, double windowCenter, out IBasicVoiLutLinear voiLut)
        {
            voiLut = null;
            if (!CanWindowLevel())
            {
                return;
            }

            IVoiLutManager manager     = SelectedVoiLutProvider.VoiLutManager;
            var            linearLut   = manager.VoiLut as IVoiLutLinear;
            var            standardLut = linearLut as IBasicVoiLutLinear;

            if (standardLut == null)
            {
                standardLut = new BasicVoiLutLinear(windowWidth, windowCenter);
                manager.InstallVoiLut(standardLut);
            }
            else
            {
                standardLut.WindowWidth  = windowWidth;
                standardLut.WindowCenter = windowCenter;
            }

            voiLut = standardLut;
            SelectedVoiLutProvider.Draw();
        }
Beispiel #6
0
        public void TestDicomExampleA()
        {
            const double windowCentre = 2048;
            const double windowWidth  = 4096;

            var lut = new BasicVoiLutLinear(windowWidth, windowCentre)
            {
                MinInputValue = short.MinValue, MaxInputValue = short.MaxValue
            };

            Assert.AreEqual(lut.MinInputValue, lut.MinOutputValue, "LUT output range min");
            Assert.AreEqual(lut.MaxInputValue, lut.MaxOutputValue, "LUT output range max");

            Assert.AreEqual(DicomReferenceFunction(0 - 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0 - 1e-6], "LUT output for value X < C-0.5 - (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(0, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0], "LUT output for value X == C-0.5 - (W-1)/2");

            Assert.AreEqual(DicomReferenceFunction(4095 + 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4095 + 1e-6], "LUT output for value X > C-0.5 + (W-1)/2");

            Assert.AreEqual(DicomReferenceFunction(0.1, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0.1], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(1, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[1], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(5, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[5], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(2048, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[2048], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(4090, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4090], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(4094.9, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4094.9], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(4095, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4095], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
        }
Beispiel #7
0
        public void AlterWindowLevel()
        {
            const double windowWidth = 4096;
            const double windowLevel = 2047;

            BasicVoiLutLinear lut = new BasicVoiLutLinear();

            lut.MinInputValue = 0;
            lut.MaxInputValue = 4095;

            lut.WindowWidth  = windowWidth;
            lut.WindowCenter = windowLevel;

            const double delta = 0.0001;

            Assert.AreEqual(1.0, lut[0], delta);
            Assert.AreEqual(2048.0, lut[2047], delta);
            Assert.AreEqual(4095.0, lut[4095], delta);

            lut.WindowWidth  = 512;
            lut.WindowCenter = 1023;

            Assert.AreEqual(512, lut.WindowWidth, delta);
            Assert.AreEqual(1023, lut.WindowCenter, delta);
            Assert.AreEqual(0, lut[767], delta);
            Assert.AreEqual(4095, lut[1279]);
        }
        public override bool Track(IMouseInformation mouseInformation)
        {
            base.Track(mouseInformation);

            IVoiLutManager manager = SelectedVoiLutProvider.VoiLutManager;

            IVoiLutLinear      linearLut   = manager.VoiLut as IVoiLutLinear;
            IBasicVoiLutLinear standardLut = linearLut as IBasicVoiLutLinear;

            if (standardLut == null)
            {
                BasicVoiLutLinear installLut = new BasicVoiLutLinear(linearLut.WindowWidth, linearLut.WindowCenter);
                manager.InstallVoiLut(installLut);
            }
            standardLut = manager.VoiLut as IBasicVoiLutLinear;

            double sensitivity = CurrentSensitivity;

            if ((Math.Abs(standardLut.WindowCenter) + Math.Abs(standardLut.WindowWidth)) < 1000)
            {
                sensitivity = 1.0;
            }

            IncrementWindow(DeltaX * sensitivity, DeltaY * sensitivity);

            return(true);
        }
		public void TestLookupValues()
		{
			const double windowWidth = 4096;
			const double windowLevel = -2047;

			var lut = new BasicVoiLutLinear(windowWidth, windowLevel);

			lut.AssertLookupValues(-10000, 10000);
		}
Beispiel #10
0
        public void ComposeUnsigned16()
        {
            const int    bitsStored       = 16;
            const bool   isSigned         = false;
            const double windowWidth      = 350;
            const double windowLevel      = 40;
            const double rescaleSlope     = 1;
            const double rescaleIntercept = -1024;

            IModalityLut modalityLut = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(0, modalityLut.MinInputValue);
            Assert.AreEqual(65535, modalityLut.MaxInputValue);
            Assert.AreEqual(-1024, modalityLut.MinOutputValue, _tolerance);
            Assert.AreEqual(64511, modalityLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(-1024, modalityLut[0], _tolerance);
            Assert.AreEqual(64511, modalityLut[65535], _tolerance);

            BasicVoiLutLinear voiLut = new BasicVoiLutLinear(
                modalityLut.MinOutputValue,
                modalityLut.MaxOutputValue);

            voiLut.WindowWidth  = windowWidth;
            voiLut.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLut;
            lutComposer.VoiLut      = voiLut;

            Assert.AreEqual(-1024, voiLut.MinInputValue, _tolerance);
            Assert.AreEqual(64511, voiLut.MaxInputValue, _tolerance);
            Assert.AreEqual(-1024, voiLut.MinOutputValue, _tolerance);
            Assert.AreEqual(64511, voiLut.MaxOutputValue, _tolerance);

            // Left Window
            Assert.AreEqual(-1024, voiLut[-135], _tolerance);

            // Right Window
            Assert.AreEqual(64511, voiLut[215], _tolerance);

            // Window center
            // 31837 is correct according to DICOM: See PS 3.3 C.11.2.1.2 for the calculation.
            // Although you might think it should be 31744 (65535/2 - 1024), it is not.
            Assert.AreEqual(31837.38968, voiLut[40], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLut.MinOutputValue), (int)Math.Round(voiLut.MaxOutputValue));

            Assert.AreEqual(-1024, output.Data[0]);
            Assert.AreEqual(64511, output.Data[65535]);
            Assert.AreEqual(31837, output.Data[1064]);
        }
Beispiel #11
0
        public void TestLookupValues()
        {
            const double windowWidth = 4096;
            const double windowLevel = -2047;

            var lut = new BasicVoiLutLinear(windowWidth, windowLevel);

            lut.AssertLookupValues(-10000, 10000);
        }
        public void TestPipelineUnsigned16()
        {
            var composer = new LutComposer(16, false);

            composer.ModalityLut = new ModalityLutLinear(16, false, 1, 0);
            var voiLUT = new BasicVoiLutLinear(65536, 32768);

            composer.VoiLut = voiLUT;

            Assert.AreEqual(0, voiLUT[0], _tolerance);
            Assert.AreEqual(32768, voiLUT[32768], _tolerance);
            Assert.AreEqual(65535, voiLUT[65535], _tolerance);

            Assert.AreEqual(0, voiLUT[-1], _tolerance);
            Assert.AreEqual(65535, voiLUT[65536], _tolerance);

            var output = composer.GetOutputLut(0, byte.MaxValue);

            Assert.AreEqual(0, output[0]);
            Assert.AreEqual(128, output[32768]);
            Assert.AreEqual(255, output[65535]);

            //Make sure the output of the grayscale color map works with all the different "display" output ranges.
            var colorMap = LutFactory.Create().GetGrayscaleColorMap();

            colorMap.MinInputValue = output.MinOutputValue;
            colorMap.MaxInputValue = output.MaxOutputValue;
            Assert.AreEqual(0, 0x000000FF & colorMap[output[0]]);
            Assert.AreEqual(128, 0x000000FF & colorMap[output[32768]]);
            Assert.AreEqual(255, 0x000000FF & colorMap[output[65535]]);

            //10-bit display
            output = composer.GetOutputLut(0, 1023);
            Assert.AreEqual(0, output[0]);
            Assert.AreEqual(512, output[32768]);
            Assert.AreEqual(1023, output[65535]);

            colorMap.MinInputValue = output.MinOutputValue;
            colorMap.MaxInputValue = output.MaxOutputValue;
            Assert.AreEqual(0, 0x000000FF & colorMap[output[0]]);
            Assert.AreEqual(128, 0x000000FF & colorMap[output[32768]]);
            Assert.AreEqual(255, 0x000000FF & colorMap[output[65535]]);

            //Theoretical 12-bit display with signed output
            output = composer.GetOutputLut(-2048, 2047);
            Assert.AreEqual(-2048, output[0]);
            Assert.AreEqual(0, output[32768]);
            Assert.AreEqual(2047, output[65535]);

            colorMap.MinInputValue = output.MinOutputValue;
            colorMap.MaxInputValue = output.MaxOutputValue;
            Assert.AreEqual(0, 0x000000FF & colorMap[output[0]]);
            Assert.AreEqual(128, 0x000000FF & colorMap[output[32768]]);
            Assert.AreEqual(255, 0x000000FF & colorMap[output[65535]]);
        }
Beispiel #13
0
        public void ComposeUnsigned8()
        {
            const int    bitsStored       = 8;
            const bool   isSigned         = false;
            const double windowWidth      = 128;
            const double windowLevel      = 74;
            const double rescaleSlope     = 0.5;
            const double rescaleIntercept = 10;

            IModalityLut modalityLut = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(0, modalityLut.MinInputValue);
            Assert.AreEqual(255, modalityLut.MaxInputValue);
            Assert.AreEqual(10, modalityLut.MinOutputValue, _tolerance);
            Assert.AreEqual(137.5, modalityLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(10, modalityLut[0], _tolerance);
            Assert.AreEqual(137.5, modalityLut[255], _tolerance);

            BasicVoiLutLinear voiLut = new BasicVoiLutLinear();

            voiLut.WindowWidth  = windowWidth;
            voiLut.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLut;
            lutComposer.VoiLut      = voiLut;

            Assert.AreEqual(10, voiLut.MinInputValue, _tolerance);
            Assert.AreEqual(137.5, voiLut.MaxInputValue, _tolerance);
            Assert.AreEqual(10, voiLut.MinOutputValue);
            Assert.AreEqual(137.5, voiLut.MaxOutputValue);
            Assert.AreEqual(10, voiLut[10], _tolerance);
            Assert.AreEqual(137.5, voiLut[138], _tolerance);
            Assert.AreEqual(73.24803, voiLut[73], _tolerance);

            Assert.AreEqual(0, lutComposer.MinInputValue);
            Assert.AreEqual(255, lutComposer.MaxInputValue);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLut.MinOutputValue), (int)Math.Round(voiLut.MaxOutputValue));

            Assert.AreEqual(10, output.MinOutputValue);
            Assert.AreEqual(138, output.MaxOutputValue);

            Assert.AreEqual(10, output[0], _tolerance);
            Assert.AreEqual(138, output[255], _tolerance);
            Assert.AreEqual(74, output[127], _tolerance);
        }
Beispiel #14
0
        public void ComposeUnsigned16()
        {
            int    bitsStored       = 16;
            bool   isSigned         = false;
            double windowWidth      = 350;
            double windowLevel      = 40;
            double rescaleSlope     = 1;
            double rescaleIntercept = -1024;

            IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(0, modalityLUT.MinInputValue);
            Assert.AreEqual(65535, modalityLUT.MaxInputValue);
            Assert.AreEqual(-1024, modalityLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(64511, modalityLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(-1024, modalityLUT[0], _tolerance);
            Assert.AreEqual(64511, modalityLUT[65535], _tolerance);

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear(
                modalityLUT.MinOutputValue,
                modalityLUT.MaxOutputValue);

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLUT;
            lutComposer.VoiLut      = voiLUT;

            Assert.AreEqual(-1024, voiLUT.MinInputValue, _tolerance);
            Assert.AreEqual(64511, voiLUT.MaxInputValue, _tolerance);
            Assert.AreEqual(-1024, voiLUT.MinOutputValue);
            Assert.AreEqual(64511, voiLUT.MaxOutputValue);

            // Left Window
            Assert.AreEqual(-1024, voiLUT[-135]);
            // Right Window
            Assert.AreEqual(64511, voiLUT[215]);
            // Window center
            // 31837 is correct according to DICOM: See PS 3.3 C.11.2.1.2 for the calculation.
            // Although you might think it should be 31744 (65535/2 - 1024), it is not.
            Assert.AreEqual(31837, voiLUT[40]);

            Assert.AreEqual(-1024, lutComposer.Data[0]);
            Assert.AreEqual(64511, lutComposer.Data[65535]);
            Assert.AreEqual(31837, lutComposer.Data[1064]);
        }
Beispiel #15
0
		public void ComposeUnsigned8()
		{
			int bitsStored = 8;
			bool isSigned = false;
			double windowWidth = 128;
			double windowLevel = 74;
			double rescaleSlope = 0.5;
			double rescaleIntercept = 10;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(0, modalityLUT.MinInputValue);
			Assert.AreEqual(255, modalityLUT.MaxInputValue);
			Assert.AreEqual(10, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(137.5, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(10, modalityLUT[0], _tolerance);
			Assert.AreEqual(137.5, modalityLUT[255], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(10, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(137.5, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(10, voiLUT.MinOutputValue);
			Assert.AreEqual(137.5, voiLUT.MaxOutputValue);
            Assert.AreEqual(10, voiLUT[10], _tolerance);
			Assert.AreEqual(137.5, voiLUT[138], _tolerance);
            Assert.AreEqual(73.24803, voiLUT[73], _tolerance);

			Assert.AreEqual(0, lutComposer.MinInputValue);
			Assert.AreEqual(255, lutComposer.MaxInputValue);

            //For this, we want the output range to be the same as the VOI.
		    var output = lutComposer.GetOutputLut((int)Math.Round(voiLUT.MinOutputValue), (int)Math.Round(voiLUT.MaxOutputValue));

            Assert.AreEqual(10, output.MinOutputValue);
            Assert.AreEqual(138, output.MaxOutputValue);

            Assert.AreEqual(10, output[0], _tolerance);
            Assert.AreEqual(138, output[255], _tolerance);
            Assert.AreEqual(74, output[127], _tolerance);
		}
Beispiel #16
0
        private static IVoiLut CloneVoiLut(IVoiLut source)
        {
            var clone = source.Clone();

            if (clone == null)
            {
                var linearLut = source as IVoiLutLinear;
                if (linearLut != null)
                {
                    clone = new BasicVoiLutLinear(linearLut.WindowWidth, linearLut.WindowCenter);
                }
            }
            return(clone);
        }
Beispiel #17
0
        public void ComposeUnsignedSubnormalModalityLut()
        {
            const int    bitsStored       = 13;
            const bool   isSigned         = false;
            const double windowWidth      = 8192;
            const double windowLevel      = 4096;
            const double rescaleSlope     = 3.1415926535897932384626433832795e-6;
            const double rescaleIntercept = -10;

            var modalityLut      = _lutFactory.GetModalityLutLinear(bitsStored, isSigned, rescaleSlope, rescaleIntercept);
            var normalizationLut = new NormalizationLutLinear(rescaleSlope, rescaleIntercept);
            var voiLut           = new BasicVoiLutLinear {
                WindowWidth = windowWidth, WindowCenter = windowLevel
            };
            var lutComposer = new LutComposer(bitsStored, isSigned)
            {
                ModalityLut = modalityLut, VoiLut = voiLut, NormalizationLut = normalizationLut
            };

            Assert.AreEqual(0, modalityLut.MinInputValue);
            Assert.AreEqual(8191, modalityLut.MaxInputValue);
            Assert.AreEqual(-10, modalityLut.MinOutputValue, _tolerance);
            Assert.AreEqual(-9.9742672145744464, modalityLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(-10, modalityLut[0], _tolerance);
            Assert.AreEqual(-9.9742672145744464, modalityLut[8191], _tolerance);

            Assert.AreEqual(-10, normalizationLut.MinInputValue, _tolerance);
            Assert.AreEqual(-9.9742672145744464, normalizationLut.MaxInputValue, _tolerance);
            Assert.AreEqual(0, normalizationLut.MinOutputValue, _tolerance);
            Assert.AreEqual(8191, normalizationLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(0, normalizationLut[-10], _tolerance);
            Assert.AreEqual(8191, normalizationLut[-9.9742672145744464], _tolerance);

            Assert.AreEqual(0, voiLut.MinInputValue, _tolerance);
            Assert.AreEqual(8191, voiLut.MaxInputValue, _tolerance);
            Assert.AreEqual(0, voiLut.MinOutputValue, _tolerance);
            Assert.AreEqual(8191, voiLut.MaxOutputValue, _tolerance);

            Assert.AreEqual(1543, voiLut[1543], _tolerance);
            Assert.AreEqual(5164, voiLut[5164], _tolerance);
            Assert.AreEqual(7074, voiLut[7074], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLut.MinOutputValue), (int)Math.Round(voiLut.MaxOutputValue));

            Assert.AreEqual(1543, output.Data[1543]);
            Assert.AreEqual(5164, output.Data[5164]);
            Assert.AreEqual(7074, output.Data[7074]);
        }
Beispiel #18
0
        public void ComposeSigned12()
        {
            int    bitsStored       = 12;
            bool   isSigned         = true;
            double windowWidth      = 16384;
            double windowLevel      = 4096;
            double rescaleSlope     = 1.0;
            double rescaleIntercept = 0;

            IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(-2048, modalityLUT.MinInputValue);
            Assert.AreEqual(2047, modalityLUT.MaxInputValue);
            Assert.AreEqual(-2048, modalityLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(2047, modalityLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(-2048, modalityLUT[-2048], _tolerance);
            Assert.AreEqual(2047, modalityLUT[2047], _tolerance);

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLUT;
            lutComposer.VoiLut      = voiLUT;

            Assert.AreEqual(-2048, voiLUT.MinInputValue, _tolerance);
            Assert.AreEqual(2047, voiLUT.MaxInputValue, _tolerance);
            Assert.AreEqual(-2048, voiLUT.MinOutputValue);
            Assert.AreEqual(2047, voiLUT.MaxOutputValue);
            Assert.AreEqual(-1536, voiLUT[-2047]);
            Assert.AreEqual(-1024, voiLUT[0]);
            Assert.AreEqual(-513, voiLUT[2047]);

            //This test is a little different from the others, it tests the output using a grayscale color map.
            var colorMap = _lutFactory.GetGrayscaleColorMap();

            colorMap.MaxInputValue = lutComposer.MaxOutputValue;
            colorMap.MinInputValue = lutComposer.MinOutputValue;
            Assert.AreEqual(31, 0x000000ff & colorMap[lutComposer.Data[0]]);
            Assert.AreEqual(63, 0x000000ff & colorMap[lutComposer.Data[2048]]);
            Assert.AreEqual(95, 0x000000ff & colorMap[lutComposer.Data[4095]]);
        }
Beispiel #19
0
        public void ComposeSignedSubnormalModalityLut()
        {
            const int    bitsStored       = 15;
            const bool   isSigned         = true;
            const double windowWidth      = 32768;
            const double windowLevel      = 0;
            const double rescaleSlope     = 2.7182818284590452353602874713527e-6;
            const double rescaleIntercept = 0;

            var modalityLut      = _lutFactory.GetModalityLutLinear(bitsStored, isSigned, rescaleSlope, rescaleIntercept);
            var normalizationLut = new NormalizationLutLinear(rescaleSlope, rescaleIntercept);
            var voiLut           = new BasicVoiLutLinear {
                WindowWidth = windowWidth, WindowCenter = windowLevel
            };
            var lutComposer = new LutComposer(bitsStored, isSigned)
            {
                ModalityLut = modalityLut, VoiLut = voiLut, NormalizationLut = normalizationLut
            };

            Assert.AreEqual(-16384, modalityLut.MinInputValue);
            Assert.AreEqual(16383, modalityLut.MaxInputValue);
            Assert.AreEqual(-0.044536329477473, modalityLut.MinOutputValue, _tolerance);
            Assert.AreEqual(0.044533611195644536, modalityLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(-0.044536329477473, modalityLut[-16384], _tolerance);
            Assert.AreEqual(0.044533611195644536, modalityLut[16383], _tolerance);

            Assert.AreEqual(-0.044536329477473, normalizationLut.MinInputValue, _tolerance);
            Assert.AreEqual(0.044533611195644536, normalizationLut.MaxInputValue, _tolerance);
            Assert.AreEqual(-16384, normalizationLut.MinOutputValue, _tolerance);
            Assert.AreEqual(16383, normalizationLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(-16384, normalizationLut[-0.044536329477473], _tolerance);
            Assert.AreEqual(16383, normalizationLut[0.044533611195644536], _tolerance);

            Assert.AreEqual(-16384, voiLut.MinInputValue, _tolerance);
            Assert.AreEqual(16383, voiLut.MaxInputValue, _tolerance);
            Assert.AreEqual(-16384, voiLut.MinOutputValue, _tolerance);
            Assert.AreEqual(16383, voiLut.MaxOutputValue, _tolerance);

            Assert.AreEqual(-13543, voiLut[-13543], _tolerance);
            Assert.AreEqual(12564, voiLut[12564], _tolerance);
            Assert.AreEqual(-4074, voiLut[-4074], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLut.MinOutputValue), (int)Math.Round(voiLut.MaxOutputValue));

            Assert.AreEqual(-13543, output.Data[-13543 + 16384]);
            Assert.AreEqual(12564, output.Data[12564 + 16384]);
            Assert.AreEqual(-4074, output.Data[-4074 + 16384]);
        }
Beispiel #20
0
        public void ComposeUnsigned8()
        {
            int    bitsStored       = 8;
            bool   isSigned         = false;
            double windowWidth      = 128;
            double windowLevel      = 74;
            double rescaleSlope     = 0.5;
            double rescaleIntercept = 10;

            IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(0, modalityLUT.MinInputValue);
            Assert.AreEqual(255, modalityLUT.MaxInputValue);
            Assert.AreEqual(10, modalityLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(137.5, modalityLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(10, modalityLUT[0], _tolerance);
            Assert.AreEqual(137.5, modalityLUT[255], _tolerance);

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLUT;
            lutComposer.VoiLut      = voiLUT;

            Assert.AreEqual(10, voiLUT.MinInputValue, _tolerance);
            Assert.AreEqual(137.5, voiLUT.MaxInputValue, _tolerance);
            Assert.AreEqual(10, voiLUT.MinOutputValue);
            Assert.AreEqual(138, voiLUT.MaxOutputValue);
            Assert.AreEqual(10, voiLUT[10]);
            Assert.AreEqual(138, voiLUT[138]);
            Assert.AreEqual(73, voiLUT[73]);

            Assert.AreEqual(0, lutComposer.MinInputValue);
            Assert.AreEqual(255, lutComposer.MaxInputValue);
            Assert.AreEqual(10, lutComposer.MinOutputValue);
            Assert.AreEqual(138, lutComposer.MaxOutputValue);

            Assert.AreEqual(10, lutComposer[0]);
            Assert.AreEqual(138, lutComposer[255]);
            Assert.AreEqual(74, lutComposer[127]);
        }
Beispiel #21
0
        public void ComposeSigned8()
        {
            // Use case:  Window width is 1
            const int    bitsStored       = 8;
            const bool   isSigned         = true;
            const double windowWidth      = 1;
            const double windowLevel      = 0;
            const double rescaleSlope     = 0.5;
            const double rescaleIntercept = 10;

            IModalityLut modalityLut = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(-128, modalityLut.MinInputValue);
            Assert.AreEqual(127, modalityLut.MaxInputValue);
            Assert.AreEqual(-54, modalityLut.MinOutputValue, _tolerance);
            Assert.AreEqual(73.5, modalityLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(-54, modalityLut[-128], _tolerance);
            Assert.AreEqual(73.5, modalityLut[127], _tolerance);

            BasicVoiLutLinear voiLut = new BasicVoiLutLinear();

            voiLut.WindowWidth  = windowWidth;
            voiLut.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLut;
            lutComposer.VoiLut      = voiLut;

            Assert.AreEqual(-54, voiLut.MinInputValue, _tolerance);
            Assert.AreEqual(73.5, voiLut.MaxInputValue, _tolerance);
            Assert.AreEqual(-54, voiLut.MinOutputValue, _tolerance);
            Assert.AreEqual(73.5, voiLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(-54, voiLut[-1], _tolerance);
            Assert.AreEqual(73.5, voiLut[0], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLut.MinOutputValue), (int)Math.Round(voiLut.MaxOutputValue));

            Assert.AreEqual(-54, output.Data[0]);
            Assert.AreEqual(-54, output.Data[106]);
            Assert.AreEqual(-54, output.Data[107]);             // stored pixel -21 which, if you don't round off the modality LUT, is actually -0.5 and therefore has a VOI value of -54
            Assert.AreEqual(74, output.Data[108]);
        }
		public void BasicTest()
		{
			const double windowWidth = 4096;
			const double windowLevel = 0;

			BasicVoiLutLinear lut = new BasicVoiLutLinear();
			lut.MinInputValue = -2048;
			lut.MaxInputValue = 2047;

			lut.WindowWidth = windowWidth;
			lut.WindowCenter = windowLevel;

			Assert.AreEqual(-2048, lut[-2048]);
			Assert.AreEqual(0, lut[0]);
			Assert.AreEqual(2047, lut[2047]);
		}
        /// <summary>
        /// Attempts to install an appropriate equivalent of the specified <paramref name="sourceVoiLut"/> to a fusion image. If the LUT is not linear, computes a dummy LUT.
        /// </summary>
        private static void InstallVoiLut(FusionPresentationImage fusionImage, IVoiLut sourceVoiLut, Frame sourceFrame, bool applyToOverlay)
        {
            IVoiLut newVoiLut;

            if (sourceVoiLut is MinMaxPixelCalculatedLinearLut)
            {
                if (applyToOverlay)
                {
                    // if the overlay source image is using a min/max calculated LUT, install a custom calculated LUT that delay-computes min/max from the fusion data
                    // we need to delay-compute this because the fusion image graphic is delay-generated, and thus not necessarily available until just before rendering!
                    var skipModalityLut = sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale;
                    newVoiLut = new FusionOverlayMinMaxVoiLutLinear(fusionImage, !skipModalityLut);
                }
                else
                {
                    // if the base source image is using a min/max calculated LUT, install a similarly min/max calculated LUT for the base of the fusion image
                    newVoiLut = new MinMaxPixelCalculatedLinearLut(fusionImage.ImageGraphic.PixelData);
                }
            }
            else if (sourceVoiLut is IVoiLutLinear)
            {
                var voiLutLinear           = (IVoiLutLinear)sourceVoiLut;
                var normalizedVoiSlope     = 1.0;
                var normalizedVoiIntercept = 0.0;
                if (applyToOverlay && sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale)
                {
                    // for subnormal PET rescale slope cases, the original VOI windows must be transformed through the same process as what MPR did to the pixel data
                    normalizedVoiSlope     = sourceFrame.RescaleSlope / fusionImage.OverlayFrameData.OverlayRescaleSlope;
                    normalizedVoiIntercept = (sourceFrame.RescaleIntercept - fusionImage.OverlayFrameData.OverlayRescaleIntercept) / fusionImage.OverlayFrameData.OverlayRescaleSlope;
                }
                newVoiLut = new BasicVoiLutLinear(voiLutLinear.WindowWidth * normalizedVoiSlope, voiLutLinear.WindowCenter * normalizedVoiSlope + normalizedVoiIntercept);
            }
            else
            {
                // if the source image is using some non-linear LUT, just install a default pass-through LUT
                newVoiLut = new IdentityVoiLinearLut();
            }

            if (applyToOverlay)
            {
                fusionImage.OverlayVoiLutManager.InstallVoiLut(newVoiLut);
            }
            else
            {
                fusionImage.BaseVoiLutManager.InstallVoiLut(newVoiLut);
            }
        }
Beispiel #24
0
        public void ComposeUnsigned12()
        {
            const int    bitsStored       = 12;
            const bool   isSigned         = false;
            const double windowWidth      = 2800;
            const double windowLevel      = 1600;
            const double rescaleSlope     = 0.683760684;
            const double rescaleIntercept = 200;

            IModalityLut modalityLut = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(0, modalityLut.MinInputValue);
            Assert.AreEqual(4095, modalityLut.MaxInputValue);
            Assert.AreEqual(200, modalityLut.MinOutputValue, _tolerance);
            Assert.AreEqual(3000, modalityLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(200, modalityLut[0], _tolerance);
            Assert.AreEqual(3000, modalityLut[4095], _tolerance);

            BasicVoiLutLinear voiLut = new BasicVoiLutLinear();

            voiLut.WindowWidth  = windowWidth;
            voiLut.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLut;
            lutComposer.VoiLut      = voiLut;

            Assert.AreEqual(200, voiLut.MinInputValue, _tolerance);
            Assert.AreEqual(3000, voiLut.MaxInputValue, _tolerance);
            Assert.AreEqual(200, voiLut.MinOutputValue, _tolerance);
            Assert.AreEqual(3000, voiLut.MaxOutputValue, _tolerance);
            Assert.AreEqual(200, voiLut[200], _tolerance);
            Assert.AreEqual(3000, voiLut[3000], _tolerance);
            Assert.AreEqual(1600.50018, voiLut[1600], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLut.MinOutputValue), (int)Math.Round(voiLut.MaxOutputValue));

            Assert.AreEqual(200, output.Data[0]);
            Assert.AreEqual(3000, output.Data[4095]);
            Assert.AreEqual(1601, output.Data[2048]);
        }
		public void ComposeUnsigned8()
		{
			int bitsStored = 8;
			bool isSigned = false;
			double windowWidth = 128;
			double windowLevel = 74;
			double rescaleSlope = 0.5;
			double rescaleIntercept = 10;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(0, modalityLUT.MinInputValue);
			Assert.AreEqual(255, modalityLUT.MaxInputValue);
			Assert.AreEqual(10, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(137.5, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(10, modalityLUT[0], _tolerance);
			Assert.AreEqual(137.5, modalityLUT[255], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(10, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(137.5, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(10, voiLUT.MinOutputValue);
			Assert.AreEqual(138, voiLUT.MaxOutputValue);
			Assert.AreEqual(10, voiLUT[10]);
			Assert.AreEqual(138, voiLUT[138]);
			Assert.AreEqual(73, voiLUT[73]);

			Assert.AreEqual(0, lutComposer.MinInputValue);
			Assert.AreEqual(255, lutComposer.MaxInputValue);
			Assert.AreEqual(10, lutComposer.MinOutputValue);
			Assert.AreEqual(138, lutComposer.MaxOutputValue);

			Assert.AreEqual(10, lutComposer[0]);
			Assert.AreEqual(138, lutComposer[255]);
			Assert.AreEqual(74, lutComposer[127]);
		}
Beispiel #26
0
		public void Threshold()
		{
			const double windowWidth = 1;
			const double windowLevel = 0;

			BasicVoiLutLinear lut = new BasicVoiLutLinear();
			lut.MinInputValue = -2048;
			lut.MaxInputValue = 2047;

			lut.WindowWidth = windowWidth;
			lut.WindowCenter = windowLevel;

			Assert.AreEqual(-2048, lut[-2]);
			Assert.AreEqual(-2048, lut[-1]);
			Assert.AreEqual(2047, lut[0]);
			Assert.AreEqual(2047, lut[1]);
		}
Beispiel #27
0
        public void BasicTest()
        {
            const double windowWidth = 4096;
            const double windowLevel = 0;

            BasicVoiLutLinear lut = new BasicVoiLutLinear();

            lut.MinInputValue = -2048;
            lut.MaxInputValue = 2047;

            lut.WindowWidth  = windowWidth;
            lut.WindowCenter = windowLevel;

            Assert.AreEqual(-2048, lut[-2048]);
            Assert.AreEqual(0, lut[0]);
            Assert.AreEqual(2047, lut[2047]);
        }
        private void Apply(IPresentationImage image)
        {
            IVoiLutLinear selectedLut = (IVoiLutLinear)SelectedVoiLutProvider.VoiLutManager.VoiLut;

            IVoiLutProvider provider = ((IVoiLutProvider)image);

            if (!(provider.VoiLutManager.VoiLut is IBasicVoiLutLinear))
            {
                BasicVoiLutLinear installLut = new BasicVoiLutLinear(selectedLut.WindowWidth, selectedLut.WindowCenter);
                provider.VoiLutManager.InstallVoiLut(installLut);
            }

            IBasicVoiLutLinear lut = (IBasicVoiLutLinear)provider.VoiLutManager.VoiLut;

            lut.WindowWidth  = selectedLut.WindowWidth;
            lut.WindowCenter = selectedLut.WindowCenter;
        }
Beispiel #29
0
        public void ComposeSigned8()
        {
            // Use case:  Window width is 1
            int    bitsStored       = 8;
            bool   isSigned         = true;
            double windowWidth      = 1;
            double windowLevel      = 0;
            double rescaleSlope     = 0.5;
            double rescaleIntercept = 10;

            IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(-128, modalityLUT.MinInputValue);
            Assert.AreEqual(127, modalityLUT.MaxInputValue);
            Assert.AreEqual(-54, modalityLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(73.5, modalityLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(-54, modalityLUT[-128], _tolerance);
            Assert.AreEqual(73.5, modalityLUT[127], _tolerance);

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLUT;
            lutComposer.VoiLut      = voiLUT;

            Assert.AreEqual(-54, voiLUT.MinInputValue, _tolerance);
            Assert.AreEqual(73.5, voiLUT.MaxInputValue, _tolerance);
            Assert.AreEqual(-54, voiLUT.MinOutputValue);
            Assert.AreEqual(74, voiLUT.MaxOutputValue);
            Assert.AreEqual(-54, voiLUT[-1]);
            Assert.AreEqual(74, voiLUT[0]);

            Assert.AreEqual(-54, lutComposer.Data[0]);
            Assert.AreEqual(-54, lutComposer.Data[106]);
            Assert.AreEqual(-54, lutComposer.Data[107]);             // stored pixel -21 which, if you don't round off the modality LUT, is actually -0.5 and therefore has a VOI value of -54
            Assert.AreEqual(74, lutComposer.Data[108]);
        }
Beispiel #30
0
        public void ComposeSingleLUT()
        {
            double windowWidth = 350;
            double windowLevel = 40;

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();

            voiLUT.MinInputValue = 0;
            voiLUT.MaxInputValue = 4095;

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(0, 4095);

            lutComposer.VoiLut = voiLUT;
            int[] data = lutComposer.Data;
        }
Beispiel #31
0
        public void TestDicomExampleD()
        {
            const double windowCentre = 0;
            const double windowWidth  = 1;

            var lut = new BasicVoiLutLinear(windowWidth, windowCentre)
            {
                MinInputValue = short.MinValue, MaxInputValue = short.MaxValue
            };

            Assert.AreEqual((int)lut.MinInputValue, lut.MinOutputValue, "LUT output range min");
            Assert.AreEqual((int)lut.MaxInputValue, lut.MaxOutputValue, "LUT output range max");

            Assert.AreEqual(DicomReferenceFunction(-0.5 - 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-0.5 - 1e-6], "LUT output for value X < C-0.5 - (W-1)/2");
            Assert.AreEqual(DicomReferenceFunction(-0.5, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-0.5], "LUT output for value X == C-0.5 - (W-1)/2");

            Assert.AreEqual(DicomReferenceFunction(-0.5 + 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-0.5 + 1e-6], "LUT output for value X > C-0.5 + (W-1)/2");
        }
Beispiel #32
0
        public void Threshold()
        {
            const double windowWidth = 1;
            const double windowLevel = 0;

            BasicVoiLutLinear lut = new BasicVoiLutLinear();

            lut.MinInputValue = -2048;
            lut.MaxInputValue = 2047;

            lut.WindowWidth  = windowWidth;
            lut.WindowCenter = windowLevel;

            Assert.AreEqual(-2048, lut[-2]);
            Assert.AreEqual(-2048, lut[-1]);
            Assert.AreEqual(2047, lut[0]);
            Assert.AreEqual(2047, lut[1]);
        }
Beispiel #33
0
        public void ComposeSigned16()
        {
            int    bitsStored       = 16;
            bool   isSigned         = true;
            double windowWidth      = 350;
            double windowLevel      = 40;
            double rescaleSlope     = 1;
            double rescaleIntercept = -1024;

            IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(-32768, modalityLUT.MinInputValue);
            Assert.AreEqual(32767, modalityLUT.MaxInputValue);
            Assert.AreEqual(-33792, modalityLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(31743, modalityLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(-33792, modalityLUT[-32768], _tolerance);
            Assert.AreEqual(31743, modalityLUT[32767], _tolerance);

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLUT;
            lutComposer.VoiLut      = voiLUT;

            Assert.AreEqual(-33792, voiLUT.MinInputValue, _tolerance);
            Assert.AreEqual(31743, voiLUT.MaxInputValue, _tolerance);
            Assert.AreEqual(-33792, voiLUT.MinOutputValue);
            Assert.AreEqual(31743, voiLUT.MaxOutputValue);

            // Left Window
            Assert.AreEqual(-33792, voiLUT[-135]);
            // Right Window
            Assert.AreEqual(31743, voiLUT[215]);
            // Window center
            Assert.AreEqual(-931, voiLUT[40]);
        }
Beispiel #34
0
        public void ComposeUnsigned12()
        {
            int    bitsStored       = 12;
            bool   isSigned         = false;
            double windowWidth      = 2800;
            double windowLevel      = 1600;
            double rescaleSlope     = 0.683760684;
            double rescaleIntercept = 200;

            IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
                bitsStored,
                isSigned,
                rescaleSlope,
                rescaleIntercept);

            Assert.AreEqual(0, modalityLUT.MinInputValue);
            Assert.AreEqual(4095, modalityLUT.MaxInputValue);
            Assert.AreEqual(200, modalityLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(3000, modalityLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(200, modalityLUT[0], _tolerance);
            Assert.AreEqual(3000, modalityLUT[4095], _tolerance);

            BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();

            voiLUT.WindowWidth  = windowWidth;
            voiLUT.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(bitsStored, isSigned);

            lutComposer.ModalityLut = modalityLUT;
            lutComposer.VoiLut      = voiLUT;

            Assert.AreEqual(200, voiLUT.MinInputValue, _tolerance);
            Assert.AreEqual(3000, voiLUT.MaxInputValue, _tolerance);
            Assert.AreEqual(200, voiLUT.MinOutputValue);
            Assert.AreEqual(3000, voiLUT.MaxOutputValue);
            Assert.AreEqual(200, voiLUT[200]);
            Assert.AreEqual(3000, voiLUT[3000]);
            Assert.AreEqual(1601, voiLUT[1600]);

            Assert.AreEqual(200, lutComposer.Data[0]);
            Assert.AreEqual(3000, lutComposer.Data[4095]);
            Assert.AreEqual(1601, lutComposer.Data[2048]);
        }
        public void Apply(IPresentationImage image)
        {
            if (image == ReferenceImage)
            {
                return;
            }

            //Turn off scale to fit and start with scale=1, then adjust it.
            //We do this because images that have been "scaled to fit", but have not been shown yet,
            //have no client rectangle and their scale is often very small.  This is safer
            //and could produce a more accurate result.
            IImageSpatialTransform matchTransform = GetImageTransform(image);

            matchTransform.ScaleToFit = false;
            matchTransform.Scale      = 1;

            //get the displayed width (in mm) for the same size display rectangle in the image to be matched.
            float matchDisplayedWidth = GetDisplayedWidth(image, _referenceDisplayRectangle);
            float rescaleAmount       = matchDisplayedWidth / _referenceDisplayedWidth;

            matchTransform.Scale *= rescaleAmount;

            //ISpatialTransform transform = (ISpatialTransform)_operation.GetOriginator(image);
            matchTransform.TranslationX = this.SelectedSpatialTransformProvider.SpatialTransform.TranslationX;
            matchTransform.TranslationY = this.SelectedSpatialTransformProvider.SpatialTransform.TranslationY;

            IVoiLutLinear selectedLut = (IVoiLutLinear)this.SelectedVoiLutProvider.VoiLutManager.VoiLut;

            IVoiLutProvider provider = ((IVoiLutProvider)image);

            if (!(provider.VoiLutManager.VoiLut is IBasicVoiLutLinear))
            {
                BasicVoiLutLinear installLut = new BasicVoiLutLinear(selectedLut.WindowWidth, selectedLut.WindowCenter);
                provider.VoiLutManager.InstallVoiLut(installLut);
            }

            IBasicVoiLutLinear lut = (IBasicVoiLutLinear)provider.VoiLutManager.VoiLut;

            lut.WindowWidth  = selectedLut.WindowWidth;
            lut.WindowCenter = selectedLut.WindowCenter;
        }
Beispiel #36
0
        public void ComposeSingleLut()
        {
            const double windowWidth = 350;
            const double windowLevel = 40;

            BasicVoiLutLinear voiLut = new BasicVoiLutLinear();

            voiLut.MinInputValue = 0;
            voiLut.MaxInputValue = 4095;

            voiLut.WindowWidth  = windowWidth;
            voiLut.WindowCenter = windowLevel;

            LutComposer lutComposer = new LutComposer(0, 4095);

            lutComposer.VoiLut = voiLut;

            var output = lutComposer.GetOutputLut(0, 255);

            Assert.IsNotNull(output);
        }
		private void Apply(IPresentationImage image)
		{
			IVoiLutLinear selectedLut = (IVoiLutLinear)SelectedVoiLutProvider.VoiLutManager.VoiLut;

			IVoiLutProvider provider = ((IVoiLutProvider)image);
			if (!(provider.VoiLutManager.VoiLut is IBasicVoiLutLinear))
			{
				BasicVoiLutLinear installLut = new BasicVoiLutLinear(selectedLut.WindowWidth, selectedLut.WindowCenter);
				provider.VoiLutManager.InstallVoiLut(installLut);
			}

			IBasicVoiLutLinear lut = (IBasicVoiLutLinear)provider.VoiLutManager.VoiLut;
			lut.WindowWidth = selectedLut.WindowWidth;
			lut.WindowCenter = selectedLut.WindowCenter;
		}
		private void IncrementWindow(double windowIncrement, double levelIncrement)
		{
			if (!CanWindowLevel())
				return;

			IVoiLutManager manager = SelectedVoiLutProvider.VoiLutManager;

			IVoiLutLinear linearLut = manager.VoiLut as IVoiLutLinear;
			IBasicVoiLutLinear standardLut = linearLut as IBasicVoiLutLinear;
			if (standardLut == null)
			{
				BasicVoiLutLinear installLut = new BasicVoiLutLinear(linearLut.WindowWidth, linearLut.WindowCenter);
				manager.InstallVoiLut(installLut);
			}

			standardLut = manager.VoiLut as IBasicVoiLutLinear; 
			standardLut.WindowWidth += windowIncrement;
			standardLut.WindowCenter += levelIncrement;
			SelectedVoiLutProvider.Draw();
		}
        private void SetWindow(double windowWidth, double windowCenter, out IBasicVoiLutLinear voiLut)
        {
            voiLut = null;
            if (!CanWindowLevel())
                return;

            IVoiLutManager manager = SelectedVoiLutProvider.VoiLutManager;
            var linearLut = manager.VoiLut as IVoiLutLinear;
            var standardLut = linearLut as IBasicVoiLutLinear;
            if (standardLut == null)
            {
                standardLut = new BasicVoiLutLinear(windowWidth, windowCenter);
                manager.InstallVoiLut(standardLut);
            }
            else
            {
                standardLut.WindowWidth = windowWidth;
                standardLut.WindowCenter = windowCenter;
            }

            voiLut = standardLut;
            SelectedVoiLutProvider.Draw();
        }
		public void TestDicomExampleD()
		{
			const double windowCentre = 0;
			const double windowWidth = 1;

			var lut = new BasicVoiLutLinear(windowWidth, windowCentre) {MinInputValue = short.MinValue, MaxInputValue = short.MaxValue};
			Assert.AreEqual((int) lut.MinInputValue, lut.MinOutputValue, "LUT output range min");
			Assert.AreEqual((int) lut.MaxInputValue, lut.MaxOutputValue, "LUT output range max");

			Assert.AreEqual(DicomReferenceFunction(-0.5 - 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-0.5 - 1e-6], "LUT output for value X < C-0.5 - (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(-0.5, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-0.5], "LUT output for value X == C-0.5 - (W-1)/2");

			Assert.AreEqual(DicomReferenceFunction(-0.5 + 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-0.5 + 1e-6], "LUT output for value X > C-0.5 + (W-1)/2");
		}
		public void ComposeUnsigned12()
		{
			int bitsStored = 12;
			bool isSigned = false;
			double windowWidth = 2800;
			double windowLevel = 1600;
			double rescaleSlope = 0.683760684;
			double rescaleIntercept = 200;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(0, modalityLUT.MinInputValue);
			Assert.AreEqual(4095, modalityLUT.MaxInputValue);
			Assert.AreEqual(200, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(3000, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(200, modalityLUT[0], _tolerance);
			Assert.AreEqual(3000, modalityLUT[4095], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(200, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(3000, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(200, voiLUT.MinOutputValue);
			Assert.AreEqual(3000, voiLUT.MaxOutputValue);
			Assert.AreEqual(200, voiLUT[200]);
			Assert.AreEqual(3000, voiLUT[3000]);
			Assert.AreEqual(1601, voiLUT[1600]);

			Assert.AreEqual(200, lutComposer.Data[0]);
			Assert.AreEqual(3000, lutComposer.Data[4095]);
			Assert.AreEqual(1601, lutComposer.Data[2048]);
		}
        public void TestPipelineUnsigned16()
        {
            var composer = new LutComposer(16, false);
            composer.ModalityLut = new ModalityLutLinear(16, false, 1, 0);
            var voiLUT = new BasicVoiLutLinear(65536, 32768);
            composer.VoiLut = voiLUT;

            Assert.AreEqual(0, voiLUT[0], _tolerance);
            Assert.AreEqual(32768, voiLUT[32768], _tolerance);
            Assert.AreEqual(65535, voiLUT[65535], _tolerance);

            Assert.AreEqual(0, voiLUT[-1], _tolerance);
            Assert.AreEqual(65535, voiLUT[65536], _tolerance);

            var output = composer.GetOutputLut(0, byte.MaxValue);
            Assert.AreEqual(0, output[0]);
            Assert.AreEqual(128, output[32768]);
            Assert.AreEqual(255, output[65535]);

            //Make sure the output of the grayscale color map works with all the different "display" output ranges.
            var colorMap = LutFactory.Create().GetGrayscaleColorMap();
            colorMap.MinInputValue = output.MinOutputValue;
            colorMap.MaxInputValue = output.MaxOutputValue;
            Assert.AreEqual(0, 0x000000FF & colorMap[output[0]]);
            Assert.AreEqual(128, 0x000000FF & colorMap[output[32768]]);
            Assert.AreEqual(255, 0x000000FF & colorMap[output[65535]]);

            //10-bit display
            output = composer.GetOutputLut(0, 1023);
            Assert.AreEqual(0, output[0]);
            Assert.AreEqual(512, output[32768]);
            Assert.AreEqual(1023, output[65535]);

            colorMap.MinInputValue = output.MinOutputValue;
            colorMap.MaxInputValue = output.MaxOutputValue;
            Assert.AreEqual(0, 0x000000FF & colorMap[output[0]]);
            Assert.AreEqual(128, 0x000000FF & colorMap[output[32768]]);
            Assert.AreEqual(255, 0x000000FF & colorMap[output[65535]]);

            //Theoretical 12-bit display with signed output
            output = composer.GetOutputLut(-2048, 2047);
            Assert.AreEqual(-2048, output[0]);
            Assert.AreEqual(0, output[32768]);
            Assert.AreEqual(2047, output[65535]);

            colorMap.MinInputValue = output.MinOutputValue;
            colorMap.MaxInputValue = output.MaxOutputValue;
            Assert.AreEqual(0, 0x000000FF & colorMap[output[0]]);
            Assert.AreEqual(128, 0x000000FF & colorMap[output[32768]]);
            Assert.AreEqual(255, 0x000000FF & colorMap[output[65535]]);
        }
		public void ComposeSignedSubnormalModalityLut()
		{
			const int bitsStored = 15;
			const bool isSigned = true;
			const double windowWidth = 32768;
			const double windowLevel = 0;
			const double rescaleSlope = 2.7182818284590452353602874713527e-6;
			const double rescaleIntercept = 0;

			var modalityLut = _lutFactory.GetModalityLutLinear(bitsStored, isSigned, rescaleSlope, rescaleIntercept);
			var normalizationLut = new NormalizationLutLinear(rescaleSlope, rescaleIntercept);
			var voiLut = new BasicVoiLutLinear {WindowWidth = windowWidth, WindowCenter = windowLevel};
			var lutComposer = new LutComposer(bitsStored, isSigned) {ModalityLut = modalityLut, VoiLut = voiLut, NormalizationLut = normalizationLut};

			Assert.AreEqual(-16384, modalityLut.MinInputValue);
			Assert.AreEqual(16383, modalityLut.MaxInputValue);
			Assert.AreEqual(-0.044536329477473, modalityLut.MinOutputValue, _tolerance);
			Assert.AreEqual(0.044533611195644536, modalityLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(-0.044536329477473, modalityLut[-16384], _tolerance);
			Assert.AreEqual(0.044533611195644536, modalityLut[16383], _tolerance);

			Assert.AreEqual(-0.044536329477473, normalizationLut.MinInputValue, _tolerance);
			Assert.AreEqual(0.044533611195644536, normalizationLut.MaxInputValue, _tolerance);
			Assert.AreEqual(-16384, normalizationLut.MinOutputValue, _tolerance);
			Assert.AreEqual(16383, normalizationLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(-16384, normalizationLut[-0.044536329477473], _tolerance);
			Assert.AreEqual(16383, normalizationLut[0.044533611195644536], _tolerance);

			Assert.AreEqual(-16384, voiLut.MinInputValue, _tolerance);
			Assert.AreEqual(16383, voiLut.MaxInputValue, _tolerance);
			Assert.AreEqual(-16384, voiLut.MinOutputValue);
			Assert.AreEqual(16383, voiLut.MaxOutputValue);

			Assert.AreEqual(-13543, voiLut[-13543]);
			Assert.AreEqual(12564, voiLut[12564]);
			Assert.AreEqual(-4074, voiLut[-4074]);

			Assert.AreEqual(-13543, lutComposer.Data[-13543 + 16384]);
			Assert.AreEqual(12564, lutComposer.Data[12564 + 16384]);
			Assert.AreEqual(-4074, lutComposer.Data[-4074 + 16384]);
		}
		public void ComposeSigned8()
		{
			// Use case:  Window width is 1
			int bitsStored = 8;
			bool isSigned = true;
			double windowWidth = 1;
			double windowLevel = 0;
			double rescaleSlope = 0.5;
			double rescaleIntercept = 10;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(-128, modalityLUT.MinInputValue);
			Assert.AreEqual(127, modalityLUT.MaxInputValue);
			Assert.AreEqual(-54, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(73.5, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(-54, modalityLUT[-128], _tolerance);
			Assert.AreEqual(73.5, modalityLUT[127], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(-54, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(73.5, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(-54, voiLUT.MinOutputValue);
			Assert.AreEqual(74, voiLUT.MaxOutputValue);
			Assert.AreEqual(-54, voiLUT[-1]);
			Assert.AreEqual(74, voiLUT[0]);

			Assert.AreEqual(-54, lutComposer.Data[0]);
			Assert.AreEqual(-54, lutComposer.Data[106]);
			Assert.AreEqual(-54, lutComposer.Data[107]); // stored pixel -21 which, if you don't round off the modality LUT, is actually -0.5 and therefore has a VOI value of -54
			Assert.AreEqual(74, lutComposer.Data[108]);
		}
		public void TestDicomExampleA()
		{
			const double windowCentre = 2048;
			const double windowWidth = 4096;

			var lut = new BasicVoiLutLinear(windowWidth, windowCentre) {MinInputValue = short.MinValue, MaxInputValue = short.MaxValue};
			Assert.AreEqual(lut.MinInputValue, lut.MinOutputValue, "LUT output range min");
			Assert.AreEqual(lut.MaxInputValue, lut.MaxOutputValue, "LUT output range max");

			Assert.AreEqual(DicomReferenceFunction(0 - 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0 - 1e-6], "LUT output for value X < C-0.5 - (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(0, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0], "LUT output for value X == C-0.5 - (W-1)/2");

			Assert.AreEqual(DicomReferenceFunction(4095 + 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4095 + 1e-6], "LUT output for value X > C-0.5 + (W-1)/2");

			Assert.AreEqual(DicomReferenceFunction(0.1, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0.1], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(1, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[1], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(5, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[5], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(2048, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[2048], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(4090, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4090], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(4094.9, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4094.9], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(4095, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[4095], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
		}
		private static IVoiLut CloneVoiLut(IVoiLut source)
		{
			var clone = source.Clone();
			if (clone == null)
			{
				var linearLut = source as IVoiLutLinear;
				if (linearLut != null)
					clone = new BasicVoiLutLinear(linearLut.WindowWidth, linearLut.WindowCenter);
			}
			return clone;
		}
		public void ComposeSingleLUT()
		{
			double windowWidth = 350;
			double windowLevel = 40;

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.MinInputValue = 0;
			voiLUT.MaxInputValue = 4095;

			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(0, 4095);
			lutComposer.VoiLut = voiLUT;
			int[] data = lutComposer.Data;
		}
		public void TestDicomExampleC()
		{
			const double windowCentre = 0;
			const double windowWidth = 100;

			var lut = new BasicVoiLutLinear(windowWidth, windowCentre) {MinInputValue = short.MinValue, MaxInputValue = short.MaxValue};
			Assert.AreEqual((int) lut.MinInputValue, lut.MinOutputValue, "LUT output range min");
			Assert.AreEqual((int) lut.MaxInputValue, lut.MaxOutputValue, "LUT output range max");

			Assert.AreEqual(DicomReferenceFunction(-50 - 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-50 - 1e-6], "LUT output for value X < C-0.5 - (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(-50, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-50], "LUT output for value X == C-0.5 - (W-1)/2");

			Assert.AreEqual(DicomReferenceFunction(49 + 1e-6, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[49 + 1e-6], "LUT output for value X > C-0.5 + (W-1)/2");

			Assert.AreEqual(DicomReferenceFunction(-49.9, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-49.9], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(-49, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-49], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(-44, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[-44], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(0, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[0], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(43, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[43], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(48.9, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[48.9], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
			Assert.AreEqual(DicomReferenceFunction(49, windowWidth, windowCentre, lut.MinOutputValue, lut.MaxOutputValue), lut[49], "LUT output for value between C-0.5 - (W-1)/2 and C-0.5 + (W-1)/2");
		}
		public void ComposeSigned12()
		{
			int bitsStored = 12;
			bool isSigned = true;
			double windowWidth = 16384;
			double windowLevel = 4096;
			double rescaleSlope = 1.0;
			double rescaleIntercept = 0;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(-2048, modalityLUT.MinInputValue);
			Assert.AreEqual(2047, modalityLUT.MaxInputValue);
			Assert.AreEqual(-2048, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(2047, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(-2048, modalityLUT[-2048], _tolerance);
			Assert.AreEqual(2047, modalityLUT[2047], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(-2048, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(2047, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(-2048, voiLUT.MinOutputValue);
			Assert.AreEqual(2047, voiLUT.MaxOutputValue);
			Assert.AreEqual(-1536, voiLUT[-2047]);
			Assert.AreEqual(-1024, voiLUT[0]);
			Assert.AreEqual(-513, voiLUT[2047]);

			//This test is a little different from the others, it tests the output using a grayscale color map.
			var colorMap = _lutFactory.GetGrayscaleColorMap();
			colorMap.MaxInputValue = lutComposer.MaxOutputValue;
			colorMap.MinInputValue = lutComposer.MinOutputValue;
			Assert.AreEqual(31, 0x000000ff & colorMap[lutComposer.Data[0]]);
			Assert.AreEqual(63, 0x000000ff & colorMap[lutComposer.Data[2048]]);
			Assert.AreEqual(95, 0x000000ff & colorMap[lutComposer.Data[4095]]);
		}
Beispiel #50
0
		public void ComposeUnsigned12()
		{
			int bitsStored = 12;
			bool isSigned = false;
			double windowWidth = 2800;
			double windowLevel = 1600;
			double rescaleSlope = 0.683760684;
			double rescaleIntercept = 200;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(0, modalityLUT.MinInputValue);
			Assert.AreEqual(4095, modalityLUT.MaxInputValue);
			Assert.AreEqual(200, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(3000, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(200, modalityLUT[0], _tolerance);
			Assert.AreEqual(3000, modalityLUT[4095], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(200, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(3000, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(200, voiLUT.MinOutputValue, _tolerance);
            Assert.AreEqual(3000, voiLUT.MaxOutputValue, _tolerance);
            Assert.AreEqual(200, voiLUT[200], _tolerance);
            Assert.AreEqual(3000, voiLUT[3000], _tolerance);
            Assert.AreEqual(1600.50018, voiLUT[1600], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLUT.MinOutputValue), (int)Math.Round(voiLUT.MaxOutputValue));

            Assert.AreEqual(200, output.Data[0]);
            Assert.AreEqual(3000, output.Data[4095]);
            Assert.AreEqual(1601, output.Data[2048]);
		}
Beispiel #51
0
    private static Bitmap DrawLutFrame(Frame f, double ww, double wc)
    {
        IPresentationImage pres = PresentationImageFactory.Create(f);
        IVoiLutProvider provider = ((IVoiLutProvider)pres);
        IVoiLutManager manager = provider.VoiLutManager;
        var linearLut = manager.VoiLut as IVoiLutLinear;
        if (linearLut != null)
        {

            var standardLut = linearLut as IBasicVoiLutLinear;

            if (standardLut == null)
            {
                var installLut = new BasicVoiLutLinear(ww, wc);

                manager.InstallVoiLut(installLut);
            }
            else
            {
                standardLut.WindowWidth = ww;
                standardLut.WindowCenter = wc;
            }
            provider.Draw();
        }
        try
        {
            var bmp = pres.DrawToBitmap(f.Columns, f.Rows);
            if (f.Columns == f.Rows)
            {
                if (f.Columns < 512)
                {
                    bmp = ResizeBitmap(bmp, 512, 512);
                }
            }
            return bmp;
        }
        catch { return null; }
    }
		public void ComposeUnsigned16()
		{
			int bitsStored = 16;
			bool isSigned = false;
			double windowWidth = 350;
			double windowLevel = 40;
			double rescaleSlope = 1;
			double rescaleIntercept = -1024;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(0, modalityLUT.MinInputValue);
			Assert.AreEqual(65535, modalityLUT.MaxInputValue);
			Assert.AreEqual(-1024, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(64511, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(-1024, modalityLUT[0], _tolerance);
			Assert.AreEqual(64511, modalityLUT[65535], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear(
				modalityLUT.MinOutputValue,
				modalityLUT.MaxOutputValue);

			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(-1024, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(64511, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(-1024, voiLUT.MinOutputValue);
			Assert.AreEqual(64511, voiLUT.MaxOutputValue);

			// Left Window
			Assert.AreEqual(-1024, voiLUT[-135]);
			// Right Window
			Assert.AreEqual(64511, voiLUT[215]);
			// Window center
			// 31837 is correct according to DICOM: See PS 3.3 C.11.2.1.2 for the calculation.
			// Although you might think it should be 31744 (65535/2 - 1024), it is not.
			Assert.AreEqual(31837, voiLUT[40]);
			
			Assert.AreEqual(-1024, lutComposer.Data[0]);
			Assert.AreEqual(64511, lutComposer.Data[65535]);
			Assert.AreEqual(31837, lutComposer.Data[1064]);
		}
Beispiel #53
0
		public void ComposeSigned12()
		{
			int bitsStored = 12;
			bool isSigned = true;
			double windowWidth = 16384;
			double windowLevel = 4096;
			double rescaleSlope = 1.0;
			double rescaleIntercept = 0;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(-2048, modalityLUT.MinInputValue);
			Assert.AreEqual(2047, modalityLUT.MaxInputValue);
			Assert.AreEqual(-2048, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(2047, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(-2048, modalityLUT[-2048], _tolerance);
			Assert.AreEqual(2047, modalityLUT[2047], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(-2048, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(2047, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(-2048, voiLUT.MinOutputValue);
			Assert.AreEqual(2047, voiLUT.MaxOutputValue);

            Assert.AreEqual(-1535.84380, voiLUT[-2047], _tolerance);
            Assert.AreEqual(-1024.18751, voiLUT[0], _tolerance);
            Assert.AreEqual(-512.53122, voiLUT[2047], _tolerance);

            //For this, we want the output range to be the same as the VOI.
            var output = lutComposer.GetOutputLut((int)Math.Round(voiLUT.MinOutputValue), (int)Math.Round(voiLUT.MaxOutputValue));

            Assert.AreEqual(-1536, output[-2047]);
            Assert.AreEqual(-1024, output[0]);
            Assert.AreEqual(-513, output[2047]);

            Assert.AreEqual(voiLUT.MinOutputValue, output.MinInputValue);
            Assert.AreEqual(voiLUT.MaxOutputValue, output.MaxInputValue);
            Assert.AreEqual(voiLUT.MinOutputValue, output.MinOutputValue);
            Assert.AreEqual(voiLUT.MaxOutputValue, output.MaxOutputValue);

            //This test is a little different from the others, it tests the output using a grayscale color map.
			var colorMap = _lutFactory.GetGrayscaleColorMap();
			colorMap.MaxInputValue = output.MaxOutputValue;
            colorMap.MinInputValue = output.MinOutputValue;

            Assert.AreEqual(32, 0x000000ff & colorMap[output.Data[0]]);
            Assert.AreEqual(64, 0x000000ff & colorMap[output.Data[2048]]);
            Assert.AreEqual(96, 0x000000ff & colorMap[output.Data[4095]]);
		}
		public void ComposeSigned16()
		{
			int bitsStored = 16;
			bool isSigned = true;
			double windowWidth = 350;
			double windowLevel = 40;
			double rescaleSlope = 1;
			double rescaleIntercept = -1024;

			IModalityLut modalityLUT = _lutFactory.GetModalityLutLinear(
				bitsStored, 
				isSigned, 
				rescaleSlope, 
				rescaleIntercept);

			Assert.AreEqual(-32768, modalityLUT.MinInputValue);
			Assert.AreEqual(32767, modalityLUT.MaxInputValue);
			Assert.AreEqual(-33792, modalityLUT.MinOutputValue, _tolerance);
			Assert.AreEqual(31743, modalityLUT.MaxOutputValue, _tolerance);
			Assert.AreEqual(-33792, modalityLUT[-32768], _tolerance);
			Assert.AreEqual(31743, modalityLUT[32767], _tolerance);

			BasicVoiLutLinear voiLUT = new BasicVoiLutLinear();
			voiLUT.WindowWidth = windowWidth;
			voiLUT.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLUT;
			lutComposer.VoiLut = voiLUT;

			Assert.AreEqual(-33792, voiLUT.MinInputValue, _tolerance);
			Assert.AreEqual(31743, voiLUT.MaxInputValue, _tolerance);
			Assert.AreEqual(-33792, voiLUT.MinOutputValue);
			Assert.AreEqual(31743, voiLUT.MaxOutputValue);

			// Left Window
			Assert.AreEqual(-33792, voiLUT[-135]);
			// Right Window
			Assert.AreEqual(31743, voiLUT[215]);
			// Window center
			Assert.AreEqual(-931, voiLUT[40]);
		}
		public void ComposeSingleLut()
		{
			const double windowWidth = 350;
			const double windowLevel = 40;

			BasicVoiLutLinear voiLut = new BasicVoiLutLinear();
			voiLut.MinInputValue = 0;
			voiLut.MaxInputValue = 4095;

			voiLut.WindowWidth = windowWidth;
			voiLut.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(0, 4095);
			lutComposer.VoiLut = voiLut;

			var output = lutComposer.GetOutputLut(0, 255);
			Assert.IsNotNull(output);
		}
		public void ComposeSigned8()
		{
			// Use case:  Window width is 1
			const int bitsStored = 8;
			const bool isSigned = true;
			const double windowWidth = 1;
			const double windowLevel = 0;
			const double rescaleSlope = 0.5;
			const double rescaleIntercept = 10;

			IModalityLut modalityLut = _lutFactory.GetModalityLutLinear(
				bitsStored,
				isSigned,
				rescaleSlope,
				rescaleIntercept);

			Assert.AreEqual(-128, modalityLut.MinInputValue);
			Assert.AreEqual(127, modalityLut.MaxInputValue);
			Assert.AreEqual(-54, modalityLut.MinOutputValue, _tolerance);
			Assert.AreEqual(73.5, modalityLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(-54, modalityLut[-128], _tolerance);
			Assert.AreEqual(73.5, modalityLut[127], _tolerance);

			BasicVoiLutLinear voiLut = new BasicVoiLutLinear();
			voiLut.WindowWidth = windowWidth;
			voiLut.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLut;
			lutComposer.VoiLut = voiLut;

			Assert.AreEqual(-54, voiLut.MinInputValue, _tolerance);
			Assert.AreEqual(73.5, voiLut.MaxInputValue, _tolerance);
			Assert.AreEqual(-54, voiLut.MinOutputValue, _tolerance);
			Assert.AreEqual(73.5, voiLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(-54, voiLut[-1], _tolerance);
			Assert.AreEqual(73.5, voiLut[0], _tolerance);

			//For this, we want the output range to be the same as the VOI.
			var output = lutComposer.GetOutputLut((int) Math.Round(voiLut.MinOutputValue), (int) Math.Round(voiLut.MaxOutputValue));

			Assert.AreEqual(-54, output.Data[0]);
			Assert.AreEqual(-54, output.Data[106]);
			Assert.AreEqual(-54, output.Data[107]); // stored pixel -21 which, if you don't round off the modality LUT, is actually -0.5 and therefore has a VOI value of -54
			Assert.AreEqual(74, output.Data[108]);
		}
		public void ComposeUnsignedSubnormalModalityLut()
		{
			const int bitsStored = 13;
			const bool isSigned = false;
			const double windowWidth = 8192;
			const double windowLevel = 4096;
			const double rescaleSlope = 3.1415926535897932384626433832795e-6;
			const double rescaleIntercept = -10;

			var modalityLut = _lutFactory.GetModalityLutLinear(bitsStored, isSigned, rescaleSlope, rescaleIntercept);
			var normalizationLut = new NormalizationLutLinear(rescaleSlope, rescaleIntercept);
			var voiLut = new BasicVoiLutLinear {WindowWidth = windowWidth, WindowCenter = windowLevel};
			var lutComposer = new LutComposer(bitsStored, isSigned) {ModalityLut = modalityLut, VoiLut = voiLut, NormalizationLut = normalizationLut};

			Assert.AreEqual(0, modalityLut.MinInputValue);
			Assert.AreEqual(8191, modalityLut.MaxInputValue);
			Assert.AreEqual(-10, modalityLut.MinOutputValue, _tolerance);
			Assert.AreEqual(-9.9742672145744464, modalityLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(-10, modalityLut[0], _tolerance);
			Assert.AreEqual(-9.9742672145744464, modalityLut[8191], _tolerance);

			Assert.AreEqual(-10, normalizationLut.MinInputValue, _tolerance);
			Assert.AreEqual(-9.9742672145744464, normalizationLut.MaxInputValue, _tolerance);
			Assert.AreEqual(0, normalizationLut.MinOutputValue, _tolerance);
			Assert.AreEqual(8191, normalizationLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(0, normalizationLut[-10], _tolerance);
			Assert.AreEqual(8191, normalizationLut[-9.9742672145744464], _tolerance);

			Assert.AreEqual(0, voiLut.MinInputValue, _tolerance);
			Assert.AreEqual(8191, voiLut.MaxInputValue, _tolerance);
			Assert.AreEqual(0, voiLut.MinOutputValue);
			Assert.AreEqual(8191, voiLut.MaxOutputValue);

			Assert.AreEqual(1543, voiLut[1543]);
			Assert.AreEqual(5164, voiLut[5164]);
			Assert.AreEqual(7074, voiLut[7074]);

			Assert.AreEqual(1543, lutComposer.Data[1543]);
			Assert.AreEqual(5164, lutComposer.Data[5164]);
			Assert.AreEqual(7074, lutComposer.Data[7074]);
		}
		public void ComposeUnsigned16()
		{
			const int bitsStored = 16;
			const bool isSigned = false;
			const double windowWidth = 350;
			const double windowLevel = 40;
			const double rescaleSlope = 1;
			const double rescaleIntercept = -1024;

			IModalityLut modalityLut = _lutFactory.GetModalityLutLinear(
				bitsStored,
				isSigned,
				rescaleSlope,
				rescaleIntercept);

			Assert.AreEqual(0, modalityLut.MinInputValue);
			Assert.AreEqual(65535, modalityLut.MaxInputValue);
			Assert.AreEqual(-1024, modalityLut.MinOutputValue, _tolerance);
			Assert.AreEqual(64511, modalityLut.MaxOutputValue, _tolerance);
			Assert.AreEqual(-1024, modalityLut[0], _tolerance);
			Assert.AreEqual(64511, modalityLut[65535], _tolerance);

			BasicVoiLutLinear voiLut = new BasicVoiLutLinear(
				modalityLut.MinOutputValue,
				modalityLut.MaxOutputValue);

			voiLut.WindowWidth = windowWidth;
			voiLut.WindowCenter = windowLevel;

			LutComposer lutComposer = new LutComposer(bitsStored, isSigned);
			lutComposer.ModalityLut = modalityLut;
			lutComposer.VoiLut = voiLut;

			Assert.AreEqual(-1024, voiLut.MinInputValue, _tolerance);
			Assert.AreEqual(64511, voiLut.MaxInputValue, _tolerance);
			Assert.AreEqual(-1024, voiLut.MinOutputValue, _tolerance);
			Assert.AreEqual(64511, voiLut.MaxOutputValue, _tolerance);

			// Left Window
			Assert.AreEqual(-1024, voiLut[-135], _tolerance);

			// Right Window
			Assert.AreEqual(64511, voiLut[215], _tolerance);

			// Window center
			// 31837 is correct according to DICOM: See PS 3.3 C.11.2.1.2 for the calculation.
			// Although you might think it should be 31744 (65535/2 - 1024), it is not.
			Assert.AreEqual(31837.38968, voiLut[40], _tolerance);

			//For this, we want the output range to be the same as the VOI.
			var output = lutComposer.GetOutputLut((int) Math.Round(voiLut.MinOutputValue), (int) Math.Round(voiLut.MaxOutputValue));

			Assert.AreEqual(-1024, output.Data[0]);
			Assert.AreEqual(64511, output.Data[65535]);
			Assert.AreEqual(31837, output.Data[1064]);
		}
Beispiel #59
0
		/// <summary>
		/// Constructor.
		/// </summary>
		public AdjustableDataLut(DataLut dataLut)
		{
			Platform.CheckForNullReference(dataLut, "dataLut");

			_dataLut = dataLut;
			_dataLut.LutChanged += OnDataLutChanged;

			_linearLut = new BasicVoiLutLinear();
			_linearLut.LutChanged += OnLinearLutChanged;

			Reset();
		}
		/// <summary>
		/// Attempts to install an appropriate equivalent of the specified <paramref name="sourceVoiLut"/> to a fusion image. If the LUT is not linear, computes a dummy LUT.
		/// </summary>
		private static void InstallVoiLut(FusionPresentationImage fusionImage, IVoiLut sourceVoiLut, Frame sourceFrame, bool applyToOverlay)
		{
			IVoiLut newVoiLut;
			if (sourceVoiLut is MinMaxPixelCalculatedLinearLut)
			{
				if (applyToOverlay)
				{
					// if the overlay source image is using a min/max calculated LUT, install a custom calculated LUT that delay-computes min/max from the fusion data
					// we need to delay-compute this because the fusion image graphic is delay-generated, and thus not necessarily available until just before rendering!
					var skipModalityLut = sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale;
					newVoiLut = new FusionOverlayMinMaxVoiLutLinear(fusionImage, !skipModalityLut);
				}
				else
				{
					// if the base source image is using a min/max calculated LUT, install a similarly min/max calculated LUT for the base of the fusion image
					newVoiLut = new MinMaxPixelCalculatedLinearLut(fusionImage.ImageGraphic.PixelData);
				}
			}
			else if (sourceVoiLut is IVoiLutLinear)
			{
				var voiLutLinear = (IVoiLutLinear) sourceVoiLut;
				var normalizedVoiSlope = 1.0;
				var normalizedVoiIntercept = 0.0;
				if (applyToOverlay && sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale)
				{
					// for subnormal PET rescale slope cases, the original VOI windows must be transformed through the same process as what MPR did to the pixel data
					normalizedVoiSlope = sourceFrame.RescaleSlope/fusionImage.OverlayFrameData.OverlayRescaleSlope;
					normalizedVoiIntercept = (sourceFrame.RescaleIntercept - fusionImage.OverlayFrameData.OverlayRescaleIntercept)/fusionImage.OverlayFrameData.OverlayRescaleSlope;
				}
				newVoiLut = new BasicVoiLutLinear(voiLutLinear.WindowWidth*normalizedVoiSlope, voiLutLinear.WindowCenter*normalizedVoiSlope + normalizedVoiIntercept);
			}
			else
			{
				// if the source image is using some non-linear LUT, just install a default pass-through LUT
				newVoiLut = new IdentityVoiLinearLut();
			}

			if (applyToOverlay)
				fusionImage.OverlayVoiLutManager.InstallVoiLut(newVoiLut);
			else
				fusionImage.BaseVoiLutManager.InstallVoiLut(newVoiLut);
		}