diff --git a/Modules/PhotoacousticsLib/src/SUFilter/mitkPASpectralUnmixingSO2.cpp b/Modules/PhotoacousticsLib/src/SUFilter/mitkPASpectralUnmixingSO2.cpp index 1dd1ae1eaf..907c784bcd 100644 --- a/Modules/PhotoacousticsLib/src/SUFilter/mitkPASpectralUnmixingSO2.cpp +++ b/Modules/PhotoacousticsLib/src/SUFilter/mitkPASpectralUnmixingSO2.cpp @@ -1,161 +1,165 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPASpectralUnmixingSO2.h" // ImageAccessor #include #include mitk::pa::SpectralUnmixingSO2::SpectralUnmixingSO2() { this->SetNumberOfIndexedInputs(2); this->SetNumberOfIndexedOutputs(1); this->SetNthOutput(0, mitk::Image::New()); } mitk::pa::SpectralUnmixingSO2::~SpectralUnmixingSO2() { } void mitk::pa::SpectralUnmixingSO2::Verbose(bool verbose) { m_Verbose = verbose; } void mitk::pa::SpectralUnmixingSO2::GenerateData() { MITK_INFO(m_Verbose) << "GENERATING DATA.."; // Get input image mitk::Image::Pointer inputHbO2 = GetInput(0); mitk::Image::Pointer inputHb = GetInput(1); CheckPreConditions(inputHbO2, inputHb); unsigned int xDim = inputHbO2->GetDimensions()[0]; unsigned int yDim = inputHbO2->GetDimensions()[1]; unsigned int zDim = inputHbO2->GetDimensions()[2]; InitializeOutputs(); mitk::ImageReadAccessor readAccessHbO2(inputHbO2); mitk::ImageReadAccessor readAccessHb(inputHb); const float* inputDataArrayHbO2 = ((const float*)readAccessHbO2.GetData()); const float* inputDataArrayHb = ((const float*)readAccessHb.GetData()); auto output = GetOutput(0); mitk::ImageWriteAccessor writeOutput(output); float* writeBuffer = (float *)writeOutput.GetData(); for (unsigned int x = 0; x < xDim; x++) { for (unsigned int y = 0; y < yDim; y++) { for (unsigned int z = 0;z < zDim; z++) { unsigned int pixelNumber = (xDim*yDim * z) + x * yDim + y; float pixelHb = inputDataArrayHb[pixelNumber]; float pixelHbO2 = inputDataArrayHbO2[pixelNumber]; float resultSO2 = CalculateSO2(pixelHb, pixelHbO2); writeBuffer[(xDim*yDim * z) + x * yDim + y] = resultSO2; } } } MITK_INFO(m_Verbose) << "GENERATING DATA...[DONE]"; } void mitk::pa::SpectralUnmixingSO2::CheckPreConditions(mitk::Image::Pointer inputHbO2, mitk::Image::Pointer inputHb) { unsigned int xDimHb = inputHb->GetDimensions()[0]; unsigned int yDimHb = inputHb->GetDimensions()[1]; unsigned int zDimHb = inputHb->GetDimensions()[2]; unsigned int xDimHbO2 = inputHbO2->GetDimensions()[0]; unsigned int yDimHbO2 = inputHbO2->GetDimensions()[1]; unsigned int zDimHbO2 = inputHbO2->GetDimensions()[2]; if (xDimHb != xDimHbO2 || yDimHb != yDimHbO2 || zDimHb != zDimHbO2) mitkThrow() << "DIMENTIONALITY ERROR!"; if (inputHbO2->GetPixelType() != mitk::MakeScalarPixelType()) mitkThrow() << "PIXELTYPE ERROR! FLOAT REQUIRED"; if (inputHb->GetPixelType() != mitk::MakeScalarPixelType()) mitkThrow() << "PIXELTYPE ERROR! FLOAT REQUIRED"; MITK_INFO(m_Verbose) << "CHECK PRECONDITIONS ...[DONE]"; } void mitk::pa::SpectralUnmixingSO2::InitializeOutputs() { unsigned int numberOfInputs = GetNumberOfIndexedInputs(); unsigned int numberOfOutputs = GetNumberOfIndexedOutputs(); mitk::PixelType pixelType = mitk::MakeScalarPixelType(); const int NUMBER_OF_SPATIAL_DIMENSIONS = 3; auto* dimensions = new unsigned int[NUMBER_OF_SPATIAL_DIMENSIONS]; for(unsigned int dimIdx=0; dimIdxGetDimensions()[dimIdx]; } for (unsigned int outputIdx = 0; outputIdx < numberOfOutputs; outputIdx++) { GetOutput(outputIdx)->Initialize(pixelType, NUMBER_OF_SPATIAL_DIMENSIONS, dimensions); } } float mitk::pa::SpectralUnmixingSO2::CalculateSO2(float Hb, float HbO2) { float result = HbO2 / (Hb + HbO2); if (result != result) { MITK_WARN(m_Verbose) << "SO2 VALUE NAN! WILL BE SET TO ZERO!"; return 0; } else { if (SO2ValueNotSiginificant(Hb, HbO2, result)) + { return 0; + } else return result; } } void mitk::pa::SpectralUnmixingSO2::AddSO2Settings(int value) { m_SO2Settings.push_back(value); } bool mitk::pa::SpectralUnmixingSO2::SO2ValueNotSiginificant(float Hb, float HbO2, float result) { - std::vector significant; + std::vector significant; significant.push_back(HbO2); significant.push_back(Hb); significant.push_back(HbO2 + Hb); significant.push_back(100*(result)); for (unsigned int i = 0; i < m_SO2Settings.size(); ++i) { - if (m_SO2Settings[i] >= significant[i]) + if (m_SO2Settings[i] > significant[i] && (std::abs(m_SO2Settings[i] - significant[i]) > 1e-7)) + { return true; + } } return false; } diff --git a/Plugins/org.mitk.gui.qt.photoacoustics.spectralunmixing/src/internal/SpectralUnmixingControls.ui b/Plugins/org.mitk.gui.qt.photoacoustics.spectralunmixing/src/internal/SpectralUnmixingControls.ui index f2fe2cbd40..16095add30 100644 --- a/Plugins/org.mitk.gui.qt.photoacoustics.spectralunmixing/src/internal/SpectralUnmixingControls.ui +++ b/Plugins/org.mitk.gui.qt.photoacoustics.spectralunmixing/src/internal/SpectralUnmixingControls.ui @@ -1,1097 +1,1232 @@ SpectralUnmixingControls 0 0 325 742 0 0 QmitkTemplate QLabel { color: rgb(255, 0, 0) } Please select an image! Qt::Horizontal 75 true Wavelengths settings 0 75 16777215 75 10 <html><head/><body><p>* \brief All values have to be intergers. They need to have the same order than the wavelength at the image.</p></body></html> true Qt::SolidLine 42 50 30 30 λ [nm] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 - 720 + 700 - 755 + 710 - 831 + 720 - 906 + 730 - 942 + 740 - + 750 - + 760 - + 770 - + 780 - + 790 - + 800 - + 810 - + 820 - + 830 - + 840 - + 850 - + 860 - + 870 - + 880 - + 890 - + 900 - + 910 - + 920 - + 930 - + 940 - + 950 Qt::Horizontal 75 true <html><head/><body><p><span style=" font-weight:400;">* \brief Select as least one Absorber. It's not possible to select more absorbers then wavelengths.</span></p></body></html> Chromophore selection <html><head/><body><p>* \brief One of the main absorbers in near infrared spectrum.</p></body></html> Oxyhemoglobin true true <html><head/><body><p>* \brief One of the main absorbers in near infrared spectrum.</p></body></html> Deoxygenated hemoglobin true true false <html><head/><body><p>* \brief One of the main absorbers in near infrared spectrum.</p></body></html> Melanin <html><head/><body><p>* \brief This endmember will be unmixed with 1 at all wavelgnths.</p></body></html> Static Endmember Qt::Horizontal 75 true <html><head/><body><p><span style=" font-weight:400;">* \brief One needs to choose an spectral unmixing algorithm.</span></p></body></html> Unmixing algorithm true MS Shell Dlg 2 <html><head/><body><p>* \brief For detailed information about the algorithms please have a look at the documentation.</p></body></html> false 21 2147483647 ==CHOSE ALGORITHM== ==QR decomposition== householderQr colPivHouseholderQr fullPivHouseholderQr ==LU decompositon fullPivLu ==Cholesky decompostion== ldlt llt .. ==Least squares== LS jacobiSvd NNLARS NNGoldfarb weighted ==Others== SimplexMax true 0 75 380 81 <html><head/><body><p>* \brief the weights are at the same order as the wavelength</p></body></html> false false Weights [%] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 + + + 19 + + 20 + + + 21 + + + + + 22 + + + + + 23 + + + + + 24 + + + + + 25 + + + + + 26 + + - 60 + 11 - 85 + 10 - 90 + 9 - 69 + 8 - 52 + 7 + + + + + 7 + + + + + 6 + + + + + 6 + + + + + 5 + + + + + 5 + + + + + 5 - + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 5 + + + + + 6 + + + + + 6 + + + + + 6 Qt::Horizontal 75 true Oxygen saturation <html><head/><body><p>* \brief calculates HbO2/(HbO2+Hb) if De- and oxyhemoglobin are selected.</p></body></html> calculate sO2 false 380 82 <html><head/><body><p>* \brief below threshold calculated sO2 value will set to zero</p></body></html> Threshold HbO2 Hb Sum SO2 % - 200 + - 100 + - 200 + - 50 + Qt::Horizontal 75 true Additional Settings <html><head/><body><p>* \brief This mode will give additional console outputs for debugging.</p></body></html> Verbose Mode (additional console outputs) false <html><head/><body><p>* \brief This checkbox will start Chrono and takes the time between clicking of the &quot;Perform spectral unmixing&quot; button until the GUI enables again.</p></body></html> Chrono <html><head/><body><p>* \brief Calculates the realtive error between unmixing result and the input image in the L2 norm.</p></body></html> Relative error image 307 70 <html><head/><body><p>* \brief below the threshold calculated relative error will set to zero</p></body></html> Threshold HbO2 Hb - 150 + - 200 + Do image processing Perform spectral unmixing Qt::Horizontal Qt::Vertical 17 54