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