diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationRunnable.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationRunnable.cpp new file mode 100644 index 0000000000..19beeb26ae --- /dev/null +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationRunnable.cpp @@ -0,0 +1,225 @@ +/*=================================================================== + +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 "QmitkImageStatisticsCalculationRunnable.h" + +#include "mitkImageStatisticsCalculator.h" +#include +#include +#include + +QmitkImageStatisticsCalculationRunnable::QmitkImageStatisticsCalculationRunnable() + : QRunnable() + , m_StatisticsImage(nullptr) + , m_BinaryMask(nullptr) + , m_PlanarFigureMask(nullptr) + , m_IgnoreZeros(false) + , m_HistogramNBins(100) + , m_CalculationSuccessful(false) +{ +} + +QmitkImageStatisticsCalculationRunnable::~QmitkImageStatisticsCalculationRunnable() +{ +} + +void QmitkImageStatisticsCalculationRunnable::Initialize(const mitk::Image *image, + const mitk::Image *binaryImage, + const mitk::PlanarFigure *planarFig) +{ + this->m_StatisticsImage = image; + this->m_BinaryMask = binaryImage; + this->m_PlanarFigureMask = planarFig; +} + +mitk::ImageStatisticsContainer* QmitkImageStatisticsCalculationRunnable::GetStatisticsData() const +{ + return this->m_StatisticsContainer.GetPointer(); +} + +const mitk::Image* QmitkImageStatisticsCalculationRunnable::GetStatisticsImage() const +{ + return this->m_StatisticsImage.GetPointer(); +} + +const mitk::Image* QmitkImageStatisticsCalculationRunnable::GetMaskImage() const +{ + return this->m_BinaryMask.GetPointer(); +} + +const mitk::PlanarFigure* QmitkImageStatisticsCalculationRunnable::GetPlanarFigure() const +{ + return this->m_PlanarFigureMask.GetPointer(); +} + +void QmitkImageStatisticsCalculationRunnable::SetIgnoreZeroValueVoxel(bool _arg) +{ + this->m_IgnoreZeros = _arg; +} + +bool QmitkImageStatisticsCalculationRunnable::GetIgnoreZeroValueVoxel() const +{ + return this->m_IgnoreZeros; +} + +void QmitkImageStatisticsCalculationRunnable::SetHistogramNBins(unsigned int nbins) +{ + this->m_HistogramNBins = nbins; +} + +unsigned int QmitkImageStatisticsCalculationRunnable::GetHistogramNBins() const +{ + return this->m_HistogramNBins; +} + +std::string QmitkImageStatisticsCalculationRunnable::GetLastErrorMessage() const +{ + return m_message; +} + +const QmitkImageStatisticsCalculationRunnable::HistogramType* +QmitkImageStatisticsCalculationRunnable::GetTimeStepHistogram(unsigned int t) const +{ + if (t >= this->m_HistogramVector.size()) + return nullptr; + + return this->m_HistogramVector.at(t).GetPointer(); +} + +bool QmitkImageStatisticsCalculationRunnable::GetStatisticsUpdateSuccessFlag() const +{ + return m_CalculationSuccessful; +} + +void QmitkImageStatisticsCalculationRunnable::run() +{ + bool statisticCalculationSuccessful = true; + mitk::ImageStatisticsCalculator::Pointer calculator = mitk::ImageStatisticsCalculator::New(); + + if (this->m_StatisticsImage.IsNotNull()) + { + calculator->SetInputImage(m_StatisticsImage); + } + else + { + statisticCalculationSuccessful = false; + } + + // Bug 13416 : The ImageStatistics::SetImageMask() method can throw exceptions, i.e. when the dimensionality + // of the masked and input image differ, we need to catch them and mark the calculation as failed + // the same holds for the ::SetPlanarFigure() + try + { + if (this->m_BinaryMask.IsNotNull()) + { + mitk::ImageMaskGenerator::Pointer imgMask = mitk::ImageMaskGenerator::New(); + imgMask->SetImageMask(m_BinaryMask->Clone()); + calculator->SetMask(imgMask.GetPointer()); + } + if (this->m_PlanarFigureMask.IsNotNull()) + { + mitk::PlanarFigureMaskGenerator::Pointer pfMaskGen = mitk::PlanarFigureMaskGenerator::New(); + pfMaskGen->SetInputImage(m_StatisticsImage); + pfMaskGen->SetPlanarFigure(m_PlanarFigureMask->Clone()); + calculator->SetMask(pfMaskGen.GetPointer()); + } + } + catch (const mitk::Exception& e) + { + MITK_ERROR << "MITK Exception: " << e.what(); + m_message = e.what(); + statisticCalculationSuccessful = false; + } + catch (const itk::ExceptionObject& e) + { + MITK_ERROR << "ITK Exception:" << e.what(); + m_message = e.what(); + statisticCalculationSuccessful = false; + } + catch (const std::runtime_error &e) + { + MITK_ERROR << "Runtime Exception: " << e.what(); + m_message = e.what(); + statisticCalculationSuccessful = false; + } + catch (const std::exception &e) + { + MITK_ERROR << "Standard Exception: " << e.what(); + m_message = e.what(); + statisticCalculationSuccessful = false; + } + + if (this->m_IgnoreZeros) + { + mitk::IgnorePixelMaskGenerator::Pointer ignorePixelValueMaskGen = mitk::IgnorePixelMaskGenerator::New(); + ignorePixelValueMaskGen->SetIgnoredPixelValue(0); + ignorePixelValueMaskGen->SetInputImage(m_StatisticsImage); + calculator->SetSecondaryMask(ignorePixelValueMaskGen.GetPointer()); + } + else + { + calculator->SetSecondaryMask(nullptr); + } + + calculator->SetNBinsForHistogramStatistics(m_HistogramNBins); + + try + { + calculator->GetStatistics(); + } + catch (mitk::Exception& e) + { + m_message = e.GetDescription(); + MITK_ERROR << "MITK Exception: " << e.what(); + statisticCalculationSuccessful = false; + } + catch (const std::runtime_error &e) + { + m_message = "Failure: " + std::string(e.what()); + MITK_ERROR << "Runtime Exception: " << e.what(); + statisticCalculationSuccessful = false; + } + catch (const std::exception &e) + { + m_message = "Failure: " + std::string(e.what()); + MITK_ERROR << "Standard Exception: " << e.what(); + statisticCalculationSuccessful = false; + } + + this->m_CalculationSuccessful = statisticCalculationSuccessful; + + if (statisticCalculationSuccessful) + { + m_StatisticsContainer = calculator->GetStatistics(); + this->m_HistogramVector.clear(); + + for (unsigned int i = 0; i < m_StatisticsImage->GetTimeSteps(); i++) + { + HistogramType::ConstPointer tempHistogram; + try { + if (calculator->GetStatistics()->TimeStepExists(i)) + { + tempHistogram = calculator->GetStatistics()->GetStatisticsForTimeStep(i).m_Histogram; + this->m_HistogramVector.push_back(tempHistogram); + } + } + catch (mitk::Exception&) { + MITK_WARN << ":-("; + } + + } + } +} diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationRunnable.h b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationRunnable.h new file mode 100644 index 0000000000..72711d8bee --- /dev/null +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationRunnable.h @@ -0,0 +1,102 @@ +/*=================================================================== + +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. + +===================================================================*/ +#ifndef QMITKIMAGESTATISTICSCALCULATIONRUNNABLE_H_INCLUDED +#define QMITKIMAGESTATISTICSCALCULATIONRUNNABLE_H_INCLUDED + +//QT headers +#include +#include + + +//mitk headers +#include "mitkImage.h" +#include "mitkPlanarFigure.h" +#include "mitkImageStatisticsContainer.h" +#include + +// itk headers +#ifndef __itkHistogram_h +#include +#endif + + +/** /brief This class is executed as background thread for image statistics calculation. + * Documentation: This class is derived from QThread and is intended to be used by QmitkImageStatisticsView + to run the image statistics calculation in a background thread keeping the gui usable. + */ + +class MITKIMAGESTATISTICSUI_EXPORT QmitkImageStatisticsCalculationRunnable : public QRunnable +{ + +public: + + typedef itk::Statistics::Histogram HistogramType; + + /*! + /brief standard constructor. */ + QmitkImageStatisticsCalculationRunnable(); + /*! + /brief standard destructor. */ + ~QmitkImageStatisticsCalculationRunnable(); + + /*! + /brief Initializes the object with necessary data. */ + void Initialize(const mitk::Image* image, const mitk::Image* binaryImage, const mitk::PlanarFigure* planarFig); + /*! + /brief returns the calculated image statistics. */ + mitk::ImageStatisticsContainer* GetStatisticsData() const; + + const mitk::Image* GetStatisticsImage() const; + const mitk::Image* GetMaskImage() const; + const mitk::PlanarFigure* GetPlanarFigure() const; + + /*! + /brief Set flag to ignore zero valued voxels */ + void SetIgnoreZeroValueVoxel(bool _arg); + /*! + /brief Get status of zero value voxel ignoring. */ + bool GetIgnoreZeroValueVoxel() const; + /*! + /brief Set bin size for histogram resolution.*/ + void SetHistogramNBins(unsigned int nbins); + /*! + /brief Get bin size for histogram resolution.*/ + unsigned int GetHistogramNBins() const; + /*! + /brief Returns the histogram of the currently selected time step. */ + const HistogramType* GetTimeStepHistogram(unsigned int t = 0) const; + + /*! + /brief Returns a flag the indicates if the statistics are updated successfully */ + bool GetStatisticsUpdateSuccessFlag() const; + /*! + /brief Method called once the thread is executed. */ + void run() override; + + std::string GetLastErrorMessage() const; + +private: + mitk::Image::ConstPointer m_StatisticsImage; ///< member variable holds the input image for which the statistics need to be calculated. + mitk::Image::ConstPointer m_BinaryMask; ///< member variable holds the binary mask image for segmentation image statistics calculation. + mitk::PlanarFigure::ConstPointer m_PlanarFigureMask; ///< member variable holds the planar figure for segmentation image statistics calculation. + mitk::ImageStatisticsContainer::Pointer m_StatisticsContainer; + bool m_IgnoreZeros; ///< member variable holds flag to indicate if zero valued voxel should be suppressed + unsigned int m_HistogramNBins; ///< member variable holds the bin size for histogram resolution. + bool m_CalculationSuccessful; ///< flag set if statistics calculation was successful + std::vector m_HistogramVector; ///< member holds the histograms of all time steps. + std::string m_message; +}; +#endif // QMITKIMAGESTATISTICSCALCULATIONRUNNABLE_H_INCLUDED