diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.cpp index 3cc5603737..99f1cd0747 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.cpp +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.cpp @@ -1,246 +1,235 @@ /*=================================================================== 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 "QmitkImageStatisticsCalculationJob.h" #include "mitkImageStatisticsCalculator.h" #include #include #include QmitkImageStatisticsCalculationJob::QmitkImageStatisticsCalculationJob() : QThread() , m_StatisticsImage(nullptr) , m_BinaryMask(nullptr) , m_PlanarFigureMask(nullptr) - , m_TimeStep(0) , m_IgnoreZeros(false) , m_HistogramNBins(100) , m_StatisticChanged(false) , m_CalculationSuccessful(false) { } QmitkImageStatisticsCalculationJob::~QmitkImageStatisticsCalculationJob() { } void QmitkImageStatisticsCalculationJob::Initialize( mitk::Image::ConstPointer image, mitk::Image::ConstPointer binaryImage, mitk::PlanarFigure::ConstPointer planarFig ) { // reset old values if( this->m_StatisticsImage.IsNotNull() ) this->m_StatisticsImage = nullptr; if( this->m_BinaryMask.IsNotNull() ) this->m_BinaryMask = nullptr; if( this->m_PlanarFigureMask.IsNotNull()) this->m_PlanarFigureMask = nullptr; // set new values if passed in if(image.IsNotNull()) this->m_StatisticsImage = image; if(binaryImage.IsNotNull()) this->m_BinaryMask = binaryImage; if(planarFig.IsNotNull()) this->m_PlanarFigureMask = planarFig; } -void QmitkImageStatisticsCalculationJob::SetTimeStep( int times ) -{ - this->m_TimeStep = times; -} - -int QmitkImageStatisticsCalculationJob::GetTimeStep() const -{ - return this->m_TimeStep; -} - mitk::ImageStatisticsContainer::ConstPointer QmitkImageStatisticsCalculationJob::GetStatisticsData() const { mitk::ImageStatisticsContainer::ConstPointer constContainer = this->m_StatisticsContainer.GetPointer(); return constContainer; } mitk::Image::ConstPointer QmitkImageStatisticsCalculationJob::GetStatisticsImage() const { return this->m_StatisticsImage; } mitk::Image::ConstPointer QmitkImageStatisticsCalculationJob::GetMaskImage() const { return this->m_BinaryMask; } mitk::PlanarFigure::ConstPointer QmitkImageStatisticsCalculationJob::GetPlanarFigure() const { return this->m_PlanarFigureMask; } void QmitkImageStatisticsCalculationJob::SetIgnoreZeroValueVoxel(bool _arg) { this->m_IgnoreZeros = _arg; } bool QmitkImageStatisticsCalculationJob::GetIgnoreZeroValueVoxel() const { return this->m_IgnoreZeros; } void QmitkImageStatisticsCalculationJob::SetHistogramNBins(unsigned int nbins) { this->m_HistogramNBins = nbins; } unsigned int QmitkImageStatisticsCalculationJob::GetHistogramNBins() const { return this->m_HistogramNBins; } std::string QmitkImageStatisticsCalculationJob::GetLastErrorMessage() const { return m_message; } QmitkImageStatisticsCalculationJob::HistogramType::ConstPointer QmitkImageStatisticsCalculationJob::GetTimeStepHistogram(unsigned int t) const { if (t >= this->m_HistogramVector.size()) return nullptr; return this->m_HistogramVector[t]; } bool QmitkImageStatisticsCalculationJob::GetStatisticsChangedFlag() const { return m_StatisticChanged; } bool QmitkImageStatisticsCalculationJob::GetStatisticsUpdateSuccessFlag() const { return m_CalculationSuccessful; } void QmitkImageStatisticsCalculationJob::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; } bool statisticChanged = 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_StatisticChanged = statisticChanged; this->m_CalculationSuccessful = statisticCalculationSuccessful; if(statisticCalculationSuccessful) { m_StatisticsContainer = calculator->GetStatistics(); this->m_HistogramVector.clear(); for (unsigned int i = 0; i < m_StatisticsImage->GetTimeSteps(); i++) { this->m_HistogramVector.push_back(calculator->GetStatistics()->GetStatisticsForTimeStep(i).m_Histogram); } } } diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.h b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.h index 66769171b1..8589a97b5d 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.h +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsCalculationJob.h @@ -1,116 +1,107 @@ /*=================================================================== 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 QMITKIMAGESTATISTICSCALCULATIONTHREAD_H_INCLUDED #define QMITKIMAGESTATISTICSCALCULATIONTHREAD_H_INCLUDED //QT headers #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 keepung the gui usable. */ class MITKIMAGESTATISTICSUI_EXPORT QmitkImageStatisticsCalculationJob : public QThread { Q_OBJECT public: typedef itk::Statistics::Histogram HistogramType; /*! /brief standard constructor. */ QmitkImageStatisticsCalculationJob(); /*! /brief standard destructor. */ ~QmitkImageStatisticsCalculationJob(); /*! /brief Initializes the object with necessary data. */ void Initialize( mitk::Image::ConstPointer image, mitk::Image::ConstPointer binaryImage, mitk::PlanarFigure::ConstPointer planarFig ); /*! /brief returns the calculated image statistics. */ mitk::ImageStatisticsContainer::ConstPointer GetStatisticsData() const; mitk::Image::ConstPointer GetStatisticsImage() const; mitk::Image::ConstPointer GetMaskImage() const; mitk::PlanarFigure::ConstPointer GetPlanarFigure() const; - //T25568: can be removed when deprecated image statistics plugin is removed - /*! - /brief Set the time step of the image you want to process. */ - void SetTimeStep( int times ); - /*! - /brief Get the time step of the image you want to process. */ - int GetTimeStep() 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. */ HistogramType::ConstPointer GetTimeStepHistogram(unsigned int t = 0) const; /*! /brief Returns a flag indicating if the statistics have changed during calculation */ bool GetStatisticsChangedFlag() 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: //member declaration 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; - //T25568: can be removed when deprecated image statistics plugin is removed - int m_TimeStep; ///< member variable holds the time step for statistics calculation 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_StatisticChanged; ///< flag set if statistics have changed 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 // QMITKIMAGESTATISTICSCALCULATIONTHREAD_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/files.cmake b/Plugins/org.mitk.gui.qt.measurementtoolbox/files.cmake index c6751d8b7a..5292027335 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/files.cmake +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/files.cmake @@ -1,56 +1,53 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES QmitkMeasurementView.cpp QmitkImageStatisticsView.cpp - QmitkImageStatisticsReloadedView.cpp mitkPluginActivator.cpp ) set(UI_FILES - src/internal/QmitkImageStatisticsReloadedViewControls.ui src/internal/QmitkImageStatisticsViewControls.ui ) set(MOC_H_FILES src/internal/QmitkMeasurementView.h src/internal/QmitkImageStatisticsView.h - src/internal/QmitkImageStatisticsReloadedView.h src/internal/mitkPluginActivator.h ) set(CACHED_RESOURCE_FILES resources/angle.png resources/arrow.png resources/circle.png resources/four-point-angle.png resources/lena.xpm resources/line.png resources/measurement.svg resources/path.png resources/polygon.png resources/rectangle.png resources/stats.png resources/text.png resources/bar-chart.svg resources/bar-chart2.svg plugin.xml ) set(QRC_FILES resources/measurement.qrc resources/QmitkImageStatisticsView.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/plugin.xml b/Plugins/org.mitk.gui.qt.measurementtoolbox/plugin.xml index 2e69a3ef29..1241a6fdc5 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/plugin.xml +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/plugin.xml @@ -1,53 +1,42 @@ Measure distance and areas in the image - - - - DEPRECATED: Calculate the statistic of image regions - - - - Calculate the statistic of image regions - + diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp deleted file mode 100644 index 75f797b850..0000000000 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp +++ /dev/null @@ -1,511 +0,0 @@ -/*=================================================================== - -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 "QmitkImageStatisticsReloadedView.h" - -#include - -// berry includes -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mitkImageStatisticsContainerManager.h" -#include - -const std::string QmitkImageStatisticsReloadedView::VIEW_ID = "org.mitk.views.imagestatisticsReloaded"; - -QmitkImageStatisticsReloadedView::QmitkImageStatisticsReloadedView(QObject * /*parent*/, const char * /*name*/) -{ - this->m_CalculationThread = new QmitkImageStatisticsCalculationJob(); -} - -QmitkImageStatisticsReloadedView::~QmitkImageStatisticsReloadedView() -{ - if (m_selectedPlanarFigure) - m_selectedPlanarFigure->RemoveObserver(m_PlanarFigureObserverTag); -} - -void QmitkImageStatisticsReloadedView::CreateQtPartControl(QWidget *parent) -{ - m_Controls.setupUi(parent); - m_Controls.widget_histogram->SetTheme(this->GetColorTheme()); - m_Controls.widget_intensityProfile->SetTheme(this->GetColorTheme()); - m_Controls.groupBox_histogram->setVisible(true); - m_Controls.groupBox_intensityProfile->setVisible(false); - m_Controls.label_currentlyComputingStatistics->setVisible(false); - m_Controls.sliderWidget_histogram->setPrefix("Time: "); - m_Controls.sliderWidget_histogram->setDecimals(0); - m_Controls.sliderWidget_histogram->setVisible(false); - ResetGUI(); - - PrepareDataStorageComboBoxes(); - m_Controls.widget_statistics->SetDataStorage(this->GetDataStorage()); - CreateConnections(); -} - -void QmitkImageStatisticsReloadedView::CreateConnections() -{ - connect(this->m_CalculationThread, - &QmitkImageStatisticsCalculationJob::finished, - this, - &QmitkImageStatisticsReloadedView::OnStatisticsCalculationEnds, - Qt::QueuedConnection); - connect(this->m_Controls.checkBox_ignoreZero, - &QCheckBox::stateChanged, - this, - &QmitkImageStatisticsReloadedView::OnCheckBoxIgnoreZeroStateChanged); - connect(this->m_Controls.sliderWidget_histogram, - &ctkSliderWidget::valueChanged, - this, - &QmitkImageStatisticsReloadedView::OnSliderWidgetHistogramChanged); - connect(this->m_Controls.imageSelector, - static_cast(&QComboBox::currentIndexChanged), - this, - &QmitkImageStatisticsReloadedView::OnImageSelectorChanged); - connect(this->m_Controls.maskImageSelector, - static_cast(&QComboBox::currentIndexChanged), - this, - &QmitkImageStatisticsReloadedView::OnMaskSelectorChanged); -} - -void QmitkImageStatisticsReloadedView::OnCheckBoxIgnoreZeroStateChanged(int state) -{ - m_ForceRecompute = true; - if (state != Qt::Unchecked) - { - this->m_CalculationThread->SetIgnoreZeroValueVoxel(true); - } - else - { - this->m_CalculationThread->SetIgnoreZeroValueVoxel(false); - } - CalculateOrGetStatistics(); -} - -void QmitkImageStatisticsReloadedView::OnSliderWidgetHistogramChanged(double value) -{ - unsigned int timeStep = static_cast(value); - auto mask = m_selectedMaskNode ? m_selectedMaskNode->GetData() : nullptr; - auto imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics( - this->GetDataStorage(), m_selectedImageNode->GetData(), mask); - HistogramType::ConstPointer histogram = imageStatistics->GetStatisticsForTimeStep(timeStep).m_Histogram; - - if (histogram.IsNotNull() && this->m_CalculationThread->GetStatisticsUpdateSuccessFlag()) - { - this->FillHistogramWidget({histogram}, {m_selectedImageNode->GetName()}); - } -} - -void QmitkImageStatisticsReloadedView::PartClosed(const berry::IWorkbenchPartReference::Pointer &) {} - -void QmitkImageStatisticsReloadedView::FillHistogramWidget(const std::vector &histogram, - const std::vector &dataLabels) -{ - m_Controls.groupBox_histogram->setVisible(true); - m_Controls.widget_histogram->SetTheme(this->GetColorTheme()); - m_Controls.widget_histogram->Reset(); - m_Controls.widget_histogram->SetHistogram(histogram.front(), dataLabels.front()); - connect(m_Controls.widget_histogram, - &QmitkHistogramVisualizationWidget::RequestHistogramUpdate, - this, - &QmitkImageStatisticsReloadedView::OnRequestHistogramUpdate); -} - -QmitkChartWidget::ColorTheme QmitkImageStatisticsReloadedView::GetColorTheme() const -{ - ctkPluginContext *context = berry::WorkbenchPlugin::GetDefault()->GetPluginContext(); - ctkServiceReference styleManagerRef = context->getServiceReference(); - if (styleManagerRef) - { - auto styleManager = context->getService(styleManagerRef); - if (styleManager->GetStyle().name == "Dark") - { - return QmitkChartWidget::ColorTheme::darkstyle; - } - else - { - return QmitkChartWidget::ColorTheme::lightstyle; - } - } - return QmitkChartWidget::ColorTheme::darkstyle; -} - -void QmitkImageStatisticsReloadedView::OnImageSelectorChanged() -{ - auto selectedImageNode = m_Controls.imageSelector->GetSelectedNode(); - if (selectedImageNode != m_selectedImageNode) - { - m_selectedImageNode = selectedImageNode; - if (m_selectedImageNode.IsNotNull()) - { - ResetGUIDefault(); - - auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate(); - auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate(); - auto hasSameGeometry = mitk::NodePredicateGeometry::New(m_selectedImageNode->GetData()->GetGeometry()); - hasSameGeometry->SetCheckPrecision(1e-10); - auto isMaskWithGeometryPredicate = mitk::NodePredicateAnd::New(isMaskPredicate, hasSameGeometry); - auto isMaskOrPlanarFigureWithGeometryPredicate = - mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskWithGeometryPredicate); - // prevent triggering of computation as the predicate triggers a signalChanged event - m_Controls.maskImageSelector->disconnect(); - m_Controls.maskImageSelector->SetPredicate(isMaskOrPlanarFigureWithGeometryPredicate); - // reset mask to - m_Controls.maskImageSelector->SetZeroEntryText(""); - m_Controls.checkBox_ignoreZero->setEnabled(true); - m_selectedMaskNode = nullptr; - m_Controls.widget_statistics->SetMaskNodes({}); - CalculateOrGetStatistics(); - m_Controls.widget_statistics->SetImageNodes({m_selectedImageNode.GetPointer()}); - connect(this->m_Controls.maskImageSelector, - static_cast(&QComboBox::currentIndexChanged), - this, - &QmitkImageStatisticsReloadedView::OnMaskSelectorChanged); - } - else - { - m_Controls.widget_statistics->SetImageNodes({}); - m_Controls.widget_statistics->SetMaskNodes({}); - m_Controls.widget_statistics->Reset(); - m_Controls.widget_histogram->Reset(); - ResetGUI(); - } - } -} - -void QmitkImageStatisticsReloadedView::OnMaskSelectorChanged() -{ - auto selectedMaskNode = m_Controls.maskImageSelector->GetSelectedNode(); - if (selectedMaskNode != m_selectedMaskNode) - { - m_selectedMaskNode = selectedMaskNode; - if (m_selectedMaskNode.IsNotNull()) - { - m_Controls.widget_statistics->SetMaskNodes({m_selectedMaskNode.GetPointer()}); - } - else - { - m_Controls.widget_statistics->SetMaskNodes({}); - } - CalculateOrGetStatistics(); - } -} - -void QmitkImageStatisticsReloadedView::CalculateOrGetStatistics() -{ - if (this->m_selectedPlanarFigure) - { - this->m_selectedPlanarFigure->RemoveObserver(this->m_PlanarFigureObserverTag); - this->m_selectedPlanarFigure = nullptr; - } - - m_Controls.groupBox_intensityProfile->setVisible(false); - m_Controls.widget_statistics->setEnabled(m_selectedImageNode.IsNotNull()); - - if (m_selectedImageNode != nullptr) - { - auto image = dynamic_cast(m_selectedImageNode->GetData()); - mitk::Image::Pointer mask = nullptr; - mitk::PlanarFigure::Pointer maskPlanarFigure = nullptr; - - if (image->GetDimension() == 4) - { - m_Controls.sliderWidget_histogram->setVisible(true); - unsigned int maxTimestep = image->GetTimeSteps(); - m_Controls.sliderWidget_histogram->setMaximum(maxTimestep - 1); - } - else - { - m_Controls.sliderWidget_histogram->setVisible(false); - } - - if (m_selectedMaskNode != nullptr) - { - mask = dynamic_cast(m_selectedMaskNode->GetData()); - if (mask == nullptr) - { - maskPlanarFigure = dynamic_cast(m_selectedMaskNode->GetData()); - } - } - - mitk::ImageStatisticsContainer::ConstPointer imageStatistics; - if (mask) - { - imageStatistics = - mitk::ImageStatisticsContainerManager::GetImageStatistics(this->GetDataStorage(), image, mask.GetPointer()); - } - else if (maskPlanarFigure) - { - m_selectedPlanarFigure = maskPlanarFigure; - ITKCommandType::Pointer changeListener = ITKCommandType::New(); - changeListener->SetCallbackFunction(this, &QmitkImageStatisticsReloadedView::CalculateOrGetStatistics); - this->m_PlanarFigureObserverTag = - m_selectedPlanarFigure->AddObserver(mitk::EndInteractionPlanarFigureEvent(), changeListener); - if (!maskPlanarFigure->IsClosed()) - { - ComputeAndDisplayIntensityProfile(image, maskPlanarFigure); - } - imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics( - this->GetDataStorage(), image, maskPlanarFigure.GetPointer()); - } - else - { - imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics(this->GetDataStorage(), image); - } - - - - bool imageStatisticsOlderThanInputs = false; - if (imageStatistics && - (imageStatistics->GetMTime() < image->GetMTime() || (mask && imageStatistics->GetMTime() < mask->GetMTime()) || - (maskPlanarFigure && imageStatistics->GetMTime() < maskPlanarFigure->GetMTime()))) - { - imageStatisticsOlderThanInputs = true; - } - - if (imageStatistics) - { - // triggers recomputation when switched between images and the newest one has not 100 bins (default) - auto calculatedBins = imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer()->Size(); - if (calculatedBins != 100) - { - OnRequestHistogramUpdate(m_Controls.widget_histogram->GetBins()); - } - } - - //statistics need to be computed - if (!imageStatistics || imageStatisticsOlderThanInputs || m_ForceRecompute) { - CalculateStatistics(image, mask.GetPointer(), maskPlanarFigure.GetPointer()); - } - // statistics already computed - else - { - // Not an open planar figure: show histogram (intensity profile already shown) - if (!(maskPlanarFigure && !maskPlanarFigure->IsClosed())) - { - if (imageStatistics->TimeStepExists(0)) - { - auto histogram = imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer(); - std::string imageNodeName = m_selectedImageNode->GetName(); - this->FillHistogramWidget({histogram}, {imageNodeName}); - } - } - } - } - else - { - ResetGUI(); - } - m_ForceRecompute = false; -} - -void QmitkImageStatisticsReloadedView::ComputeAndDisplayIntensityProfile(mitk::Image *image, - mitk::PlanarFigure::Pointer maskPlanarFigure) -{ - auto intensityProfile = mitk::ComputeIntensityProfile(image, maskPlanarFigure); - // Don't show histogram for intensity profiles - m_Controls.groupBox_histogram->setVisible(false); - m_Controls.groupBox_intensityProfile->setVisible(true); - m_Controls.widget_intensityProfile->Reset(); - m_Controls.widget_intensityProfile->SetIntensityProfile(intensityProfile.GetPointer(), - "Intensity Profile of " + m_selectedImageNode->GetName()); -} - -void QmitkImageStatisticsReloadedView::ResetGUI() -{ - m_Controls.widget_statistics->Reset(); - m_Controls.widget_statistics->setEnabled(false); m_Controls.widget_histogram->Reset(); - m_Controls.widget_histogram->setEnabled(false); - m_Controls.checkBox_ignoreZero->setEnabled(false); -} - -void QmitkImageStatisticsReloadedView::ResetGUIDefault() -{ - MITK_INFO << "reset GUI"; - m_Controls.widget_histogram->ResetDefault(); - m_Controls.checkBox_ignoreZero->setChecked(false); -} - -void QmitkImageStatisticsReloadedView::OnStatisticsCalculationEnds() -{ - mitk::StatusBar::GetInstance()->Clear(); - - if (this->m_CalculationThread->GetStatisticsUpdateSuccessFlag()) - { - auto statistic = m_CalculationThread->GetStatisticsData(); - auto image = m_CalculationThread->GetStatisticsImage(); - mitk::BaseData::ConstPointer mask = nullptr; - auto statisticNonConst = statistic->Clone(); - auto imageRule = mitk::StatisticsToImageRelationRule::New(); - imageRule->Connect(statisticNonConst.GetPointer(), image); - - if (m_CalculationThread->GetMaskImage()) - { - auto maskRule = mitk::StatisticsToMaskRelationRule::New(); - mask = m_CalculationThread->GetMaskImage(); - maskRule->Connect(statisticNonConst.GetPointer(), mask); - } - else if (m_CalculationThread->GetPlanarFigure()) - { - auto planarFigureRule = mitk::StatisticsToMaskRelationRule::New(); - mask = m_CalculationThread->GetPlanarFigure(); - planarFigureRule->Connect(statisticNonConst.GetPointer(), mask); - } - - auto imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics( - this->GetDataStorage(), image, mask); - - //if statistics base data already exist: add to existing node - if (imageStatistics) - { - auto allDataNodes = this->GetDataStorage()->GetAll()->CastToSTLConstContainer(); - for (auto node : allDataNodes) - { - auto nodeData = node->GetData(); - if (nodeData && nodeData->GetUID() ==imageStatistics->GetUID()) - { - node->SetData(statisticNonConst); - } - } - } - //statistics base data does not exist: add new node - else - { - auto statisticsNodeName = m_selectedImageNode->GetName(); - if (m_selectedMaskNode) - { - statisticsNodeName += "_" + m_selectedMaskNode->GetName(); - } - statisticsNodeName += "_statistics"; - auto statisticsNode = mitk::CreateImageStatisticsNode(statisticNonConst, statisticsNodeName); - this->GetDataStorage()->Add(statisticsNode); - } - - if (!m_selectedPlanarFigure || m_selectedPlanarFigure->IsClosed()) - { - this->FillHistogramWidget({m_CalculationThread->GetTimeStepHistogram()}, {m_selectedImageNode->GetName()}); - } - } - else - { - mitk::StatusBar::GetInstance()->DisplayErrorText(m_CalculationThread->GetLastErrorMessage().c_str()); - m_Controls.widget_histogram->setEnabled(false); - } - m_Controls.label_currentlyComputingStatistics->setVisible(false); -} - -void QmitkImageStatisticsReloadedView::OnRequestHistogramUpdate(unsigned int nBins) -{ - m_CalculationThread->SetHistogramNBins(nBins); - m_CalculationThread->start(); -} - -void QmitkImageStatisticsReloadedView::CalculateStatistics(mitk::Image::ConstPointer image, - mitk::Image::ConstPointer mask, - mitk::PlanarFigure::ConstPointer maskPlanarFigure) -{ - this->m_StatisticsUpdatePending = true; - auto renderPart = this->GetRenderWindowPart(); - unsigned int timeStep = renderPart->GetTimeNavigationController()->GetTime()->GetPos(); - this->m_CalculationThread->Initialize(image, mask, maskPlanarFigure); - this->m_CalculationThread->SetTimeStep(timeStep); - - try - { - // Compute statistics - this->m_CalculationThread->start(); - m_Controls.label_currentlyComputingStatistics->setVisible(true); - } - catch (const mitk::Exception &e) - { - mitk::StatusBar::GetInstance()->DisplayErrorText(e.GetDescription()); - this->m_StatisticsUpdatePending = false; - m_Controls.label_currentlyComputingStatistics->setVisible(false); - } - catch (const std::runtime_error &e) - { - mitk::StatusBar::GetInstance()->DisplayErrorText(e.what()); - this->m_StatisticsUpdatePending = false; - m_Controls.label_currentlyComputingStatistics->setVisible(false); - } - catch (const std::exception &e) - { - mitk::StatusBar::GetInstance()->DisplayErrorText(e.what()); - this->m_StatisticsUpdatePending = false; - m_Controls.label_currentlyComputingStatistics->setVisible(false); - } -} - -void QmitkImageStatisticsReloadedView::OnSelectionChanged(berry::IWorkbenchPart::Pointer part, - const QList &nodes) -{ - Q_UNUSED(part); - Q_UNUSED(nodes); -} - -void QmitkImageStatisticsReloadedView::PrepareDataStorageComboBoxes() -{ - auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate(); - auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate(); - auto isImagePredicate = mitk::GetImageStatisticsImagePredicate(); - auto isMaskOrPlanarFigurePredicate = mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskPredicate); - - m_Controls.imageSelector->SetDataStorage(GetDataStorage()); - m_Controls.imageSelector->SetPredicate(isImagePredicate); - - m_Controls.maskImageSelector->SetDataStorage(GetDataStorage()); - - m_Controls.maskImageSelector->SetPredicate(isMaskOrPlanarFigurePredicate); - m_Controls.maskImageSelector->SetZeroEntryText(""); -} - -void QmitkImageStatisticsReloadedView::Activated() {} - -void QmitkImageStatisticsReloadedView::Deactivated() {} - -void QmitkImageStatisticsReloadedView::Visible() -{ - connect(this->m_Controls.imageSelector, - static_cast(&QComboBox::currentIndexChanged), - this, - &QmitkImageStatisticsReloadedView::OnImageSelectorChanged); - connect(this->m_Controls.maskImageSelector, - static_cast(&QComboBox::currentIndexChanged), - this, - &QmitkImageStatisticsReloadedView::OnMaskSelectorChanged); - OnImageSelectorChanged(); - OnMaskSelectorChanged(); -} - -void QmitkImageStatisticsReloadedView::Hidden() -{ - m_Controls.imageSelector->disconnect(); - m_Controls.maskImageSelector->disconnect(); -} - -void QmitkImageStatisticsReloadedView::SetFocus() {} diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.h b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.h deleted file mode 100644 index df952f210d..0000000000 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.h +++ /dev/null @@ -1,112 +0,0 @@ -/*=================================================================== - -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 QmitkImageStatisticsReloadedView_H__INCLUDED -#define QmitkImageStatisticsReloadedView_H__INCLUDED - -#include "ui_QmitkImageStatisticsReloadedViewControls.h" - -// Qmitk includes -#include -#include -#include - -#include -#include -#include - -/*! -\brief QmitkImageStatisticsView is a bundle that allows statistics calculation from images. Three modes -are supported: 1. Statistics of one image, 2. Statistics of an image and a segmentation, 3. Statistics -of an image and a Planar Figure. The statistics calculation is realized in a separate thread to keep the -gui accessible during calculation. - -\ingroup Plugins/org.mitk.gui.qt.measurementtoolbox -*/ -class QmitkImageStatisticsReloadedView : public QmitkAbstractView, public mitk::ILifecycleAwarePart, public berry::IPartListener -{ - Q_OBJECT - -public: - using HistogramType = mitk::ImageStatisticsContainer::HistogramType; - - /*! - \brief default constructor */ - QmitkImageStatisticsReloadedView(QObject *parent = nullptr, const char *name = nullptr); - /*! - \brief default destructor */ - virtual ~QmitkImageStatisticsReloadedView(); - /*! - \brief method for creating the widget containing the application controls, like sliders, buttons etc. */ - virtual void CreateQtPartControl(QWidget *parent) override; - /*! - \brief method for creating the connections of main and control widget */ - virtual void CreateConnections(); - /*! - \brief Is called from the selection mechanism once the data manager selection has changed*/ - void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList &selectedNodes) override; - - void PrepareDataStorageComboBoxes(); - - static const std::string VIEW_ID; - - void FillHistogramWidget(const std::vector& histogram, const std::vector& dataLabels); - QmitkChartWidget::ColorTheme GetColorTheme() const; -protected: - virtual void Activated() override; - virtual void Deactivated() override; - virtual void Visible() override; - virtual void Hidden() override; - - virtual void SetFocus() override; - - /** \brief Is called right before the view closes (before the destructor) */ - virtual void PartClosed(const berry::IWorkbenchPartReference::Pointer&) override; - - /** \brief Required for berry::IPartListener */ - virtual Events::Types GetPartEventTypes() const override { return Events::CLOSED; } - - void OnImageSelectorChanged(); - void OnMaskSelectorChanged(); - - void CalculateOrGetStatistics(); - - void ComputeAndDisplayIntensityProfile(mitk::Image * image, mitk::PlanarFigure::Pointer maskPlanarFigure); - - void ResetGUI(); - void ResetGUIDefault(); - - void OnStatisticsCalculationEnds(); - void OnRequestHistogramUpdate(unsigned int nBins); - void OnCheckBoxIgnoreZeroStateChanged(int state); - void OnSliderWidgetHistogramChanged(double value); - - void CalculateStatistics(mitk::Image::ConstPointer image, mitk::Image::ConstPointer mask=nullptr, mitk::PlanarFigure::ConstPointer maskPlanarFigure = nullptr); - - // member variables - Ui::QmitkImageStatisticsReloadedViewControls m_Controls; - -private: - typedef itk::SimpleMemberCommand< QmitkImageStatisticsReloadedView > ITKCommandType; - QmitkImageStatisticsCalculationJob * m_CalculationThread = nullptr; - bool m_StatisticsUpdatePending=false; - mitk::DataNode::ConstPointer m_selectedImageNode = nullptr, m_selectedMaskNode = nullptr; - - mitk::PlanarFigure::Pointer m_selectedPlanarFigure=nullptr; - long m_PlanarFigureObserverTag; - bool m_ForceRecompute = false; -}; -#endif // QmitkImageStatisticsView_H__INCLUDED diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedViewControls.ui b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedViewControls.ui deleted file mode 100644 index dfd1df3073..0000000000 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedViewControls.ui +++ /dev/null @@ -1,469 +0,0 @@ - - - QmitkImageStatisticsReloadedViewControls - - - true - - - - 0 - 0 - 419 - 1016 - - - - Form - - - - - - QLayout::SetMinimumSize - - - 4 - - - - - - 0 - 0 - - - - false - - - - - - - - - - - - 255 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - - - 255 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - Calculating statistics... - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - - Mask image: - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - - Image: - - - - - - - - 0 - 0 - - - - false - - - - - - - Ignore zero-valued voxels - - - - - - - - - - 0 - 200 - - - - Statistics - - - - 3 - - - 3 - - - 3 - - - 3 - - - - - - - - - - 255 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - - - 255 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - - - - - - - - - - 0 - 200 - - - - Histogram - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - - 0 - 200 - - - - Intensity Profile - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - QmitkDataStorageComboBox - QComboBox -
QmitkDataStorageComboBox.h
-
- - QmitkHistogramVisualizationWidget - QWidget -
QmitkHistogramVisualizationWidget.h
- 1 -
- - QmitkImageStatisticsWidget - QWidget -
QmitkImageStatisticsWidget.h
- 1 -
- - QmitkDataStorageComboBoxWithSelectNone - QComboBox -
QmitkDataStorageComboBoxWithSelectNone.h
-
- - QmitkIntensityProfileVisualizationWidget - QWidget -
QmitkIntensityProfileVisualizationWidget.h
- 1 -
- - ctkSliderWidget - QWidget -
ctkSliderWidget.h
- 1 -
-
- - -
diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp index 31aabd3b2c..9d90a7ad54 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.cpp @@ -1,1298 +1,508 @@ /*=================================================================== 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 "QmitkImageStatisticsView.h" -// Qt includes -#include -#include -#include +#include // berry includes -#include +#include +#include -// mitk includes -#include -#include -#include -#include -#include #include -#include -#include -#include - -// itk includes -#include "itksys/SystemTools.hxx" -#include "itkImageRegionConstIteratorWithIndex.h" - -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -//blueberry includes -#include -#include +#include "mitkImageStatisticsContainerManager.h" +#include const std::string QmitkImageStatisticsView::VIEW_ID = "org.mitk.views.imagestatistics"; -const int QmitkImageStatisticsView::STAT_TABLE_BASE_HEIGHT = 180; -QmitkImageStatisticsView::QmitkImageStatisticsView(QObject* /*parent*/, const char* /*name*/) - : m_Controls(nullptr), - m_SelectedImage(nullptr), - m_SelectedImageMask(nullptr), - m_SelectedPlanarFigure(nullptr), - m_ImageObserverTag(-1), - m_ImageMaskObserverTag(-1), - m_PlanarFigureObserverTag(-1), - m_TimeObserverTag(-1), - m_CurrentStatisticsValid(false), - m_StatisticsUpdatePending(false), - m_DataNodeSelectionChanged(false), - m_Visible(false) +QmitkImageStatisticsView::QmitkImageStatisticsView(QObject * /*parent*/, const char * /*name*/) { - this->m_CalculationThread = new QmitkImageStatisticsCalculationJob; + this->m_CalculationThread = new QmitkImageStatisticsCalculationJob(); } QmitkImageStatisticsView::~QmitkImageStatisticsView() { - if (m_SelectedImage != nullptr) - m_SelectedImage->RemoveObserver(m_ImageObserverTag); - if (m_SelectedImageMask != nullptr) - m_SelectedImageMask->RemoveObserver(m_ImageMaskObserverTag); - if (m_SelectedPlanarFigure != nullptr) - m_SelectedPlanarFigure->RemoveObserver(m_PlanarFigureObserverTag); - - while (this->m_CalculationThread->isRunning()) // wait until thread has finished - { - itksys::SystemTools::Delay(100); - } - delete this->m_CalculationThread; + if (m_selectedPlanarFigure) + m_selectedPlanarFigure->RemoveObserver(m_PlanarFigureObserverTag); } - void QmitkImageStatisticsView::CreateQtPartControl(QWidget *parent) { - if (m_Controls == nullptr) - { - m_Controls = new Ui::QmitkImageStatisticsViewControls; - m_Controls->setupUi(parent); - CreateConnections(); + m_Controls.setupUi(parent); + m_Controls.widget_histogram->SetTheme(this->GetColorTheme()); + m_Controls.widget_intensityProfile->SetTheme(this->GetColorTheme()); + m_Controls.groupBox_histogram->setVisible(true); + m_Controls.groupBox_intensityProfile->setVisible(false); + m_Controls.label_currentlyComputingStatistics->setVisible(false); + m_Controls.sliderWidget_histogram->setPrefix("Time: "); + m_Controls.sliderWidget_histogram->setDecimals(0); + m_Controls.sliderWidget_histogram->setVisible(false); + ResetGUI(); - m_Controls->m_ErrorMessageLabel->hide(); - m_Controls->m_StatisticsWidgetStack->setCurrentIndex(0); - m_Controls->m_BinSizeFrame->setEnabled(false); - } + PrepareDataStorageComboBoxes(); + m_Controls.widget_statistics->SetDataStorage(this->GetDataStorage()); + CreateConnections(); } -void QmitkImageStatisticsView::OnPageSuccessfullyLoaded() +void QmitkImageStatisticsView::CreateConnections() { - berry::IPreferencesService* prefService = berry::WorkbenchPlugin::GetDefault()->GetPreferencesService(); - m_StylePref = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE); - - QString styleName = m_StylePref->Get(berry::QtPreferences::QT_STYLE_NAME, ""); - - if (styleName == ":/org.blueberry.ui.qt/darkstyle.qss") - { - this->m_Controls->m_JSHistogram->SetTheme(QmitkChartWidget::ColorTheme::darkstyle); + connect(this->m_CalculationThread, + &QmitkImageStatisticsCalculationJob::finished, + this, + &QmitkImageStatisticsView::OnStatisticsCalculationEnds, + Qt::QueuedConnection); + connect(this->m_Controls.checkBox_ignoreZero, + &QCheckBox::stateChanged, + this, + &QmitkImageStatisticsView::OnCheckBoxIgnoreZeroStateChanged); + connect(this->m_Controls.sliderWidget_histogram, + &ctkSliderWidget::valueChanged, + this, + &QmitkImageStatisticsView::OnSliderWidgetHistogramChanged); + connect(this->m_Controls.imageSelector, + static_cast(&QComboBox::currentIndexChanged), + this, + &QmitkImageStatisticsView::OnImageSelectorChanged); + connect(this->m_Controls.maskImageSelector, + static_cast(&QComboBox::currentIndexChanged), + this, + &QmitkImageStatisticsView::OnMaskSelectorChanged); +} + +void QmitkImageStatisticsView::OnCheckBoxIgnoreZeroStateChanged(int state) +{ + m_ForceRecompute = true; + if (state != Qt::Unchecked) + { + this->m_CalculationThread->SetIgnoreZeroValueVoxel(true); } else { - this->m_Controls->m_JSHistogram->SetTheme(QmitkChartWidget::ColorTheme::lightstyle); + this->m_CalculationThread->SetIgnoreZeroValueVoxel(false); } + CalculateOrGetStatistics(); } -void QmitkImageStatisticsView::CreateConnections() +void QmitkImageStatisticsView::OnSliderWidgetHistogramChanged(double value) { - if (m_Controls) - { - connect((QObject*)(this->m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()), (QObject*)this, SLOT(OnClipboardHistogramButtonClicked())); - connect((QObject*)(this->m_Controls->m_ButtonCopyStatisticsToClipboard), SIGNAL(clicked()), (QObject*)this, SLOT(OnClipboardStatisticsButtonClicked())); - connect((QObject*)(this->m_Controls->m_IgnoreZerosCheckbox), SIGNAL(clicked()), (QObject*)this, SLOT(OnIgnoreZerosCheckboxClicked())); - connect((QObject*)this->m_CalculationThread, SIGNAL(finished()), this, SLOT(OnThreadedStatisticsCalculationEnds()), Qt::QueuedConnection); - connect((QObject*)this, SIGNAL(StatisticsUpdate()), this, SLOT(RequestStatisticsUpdate()), Qt::QueuedConnection); - connect((QObject*)this->m_Controls->m_StatisticsTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(JumpToCoordinates(int, int))); - connect((QObject*)(this->m_Controls->m_barRadioButton), SIGNAL(clicked()), (QObject*)(this), SLOT(OnBarRadioButtonSelected())); - connect((QObject*)(this->m_Controls->m_lineRadioButton), SIGNAL(clicked()), (QObject*)(this), SLOT(OnLineRadioButtonSelected())); - connect((QObject*)(this->m_Controls->m_HistogramNBinsSpinbox), SIGNAL(editingFinished()), this, SLOT(OnHistogramNBinsCheckBoxValueChanged())); - connect((QObject*)(this->m_Controls->m_UseDefaultNBinsCheckBox), SIGNAL(clicked()), (QObject*)this, SLOT(OnDefaultNBinsSpinBoxChanged())); - connect((QObject*)(this->m_Controls->m_ShowSubchartCheckBox), SIGNAL(clicked()), (QObject*)this, SLOT(OnShowSubchartBoxChanged())); - connect((QObject*)(this->m_Controls->m_JSHistogram), SIGNAL(PageSuccessfullyLoaded()), (QObject*)this, SLOT(OnPageSuccessfullyLoaded())); - } -} + unsigned int timeStep = static_cast(value); + auto mask = m_selectedMaskNode ? m_selectedMaskNode->GetData() : nullptr; + auto imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics( + this->GetDataStorage(), m_selectedImageNode->GetData(), mask); + HistogramType::ConstPointer histogram = imageStatistics->GetStatisticsForTimeStep(timeStep).m_Histogram; -void QmitkImageStatisticsView::OnDefaultNBinsSpinBoxChanged() -{ - if (this->m_Controls->m_UseDefaultNBinsCheckBox->isChecked()) { - m_Controls->m_HistogramNBinsSpinbox->setValue(100); - this->m_CalculationThread->SetHistogramNBins(m_Controls->m_HistogramNBinsSpinbox->value()); - m_HistogramNBins = m_Controls->m_HistogramNBinsSpinbox->value(); + if (histogram.IsNotNull() && this->m_CalculationThread->GetStatisticsUpdateSuccessFlag()) + { + this->FillHistogramWidget({histogram}, {m_selectedImageNode->GetName()}); } - m_Controls->m_BinSizeFrame->setEnabled(!m_Controls->m_UseDefaultNBinsCheckBox->isChecked()); - - this->UpdateStatistics(); - -} - -void QmitkImageStatisticsView::OnShowSubchartBoxChanged() -{ - bool showSubchart = this->m_Controls->m_ShowSubchartCheckBox->isChecked(); - this->m_Controls->m_JSHistogram->SetShowSubchart(showSubchart); - this->m_Controls->m_JSHistogram->Reload(); -} - - -void QmitkImageStatisticsView::OnBarRadioButtonSelected() -{ - this->m_Controls->m_JSHistogram->SetChartTypeForAllDataAndReload(QmitkChartWidget::ChartType::bar); } -void QmitkImageStatisticsView::OnLineRadioButtonSelected() -{ - this->m_Controls->m_JSHistogram->SetChartTypeForAllDataAndReload(QmitkChartWidget::ChartType::line); -} +void QmitkImageStatisticsView::PartClosed(const berry::IWorkbenchPartReference::Pointer &) {} -void QmitkImageStatisticsView::PartClosed(const berry::IWorkbenchPartReference::Pointer&) +void QmitkImageStatisticsView::FillHistogramWidget(const std::vector &histogram, + const std::vector &dataLabels) { + m_Controls.groupBox_histogram->setVisible(true); + m_Controls.widget_histogram->SetTheme(this->GetColorTheme()); + m_Controls.widget_histogram->Reset(); + m_Controls.widget_histogram->SetHistogram(histogram.front(), dataLabels.front()); + connect(m_Controls.widget_histogram, + &QmitkHistogramVisualizationWidget::RequestHistogramUpdate, + this, + &QmitkImageStatisticsView::OnRequestHistogramUpdate); } -void QmitkImageStatisticsView::OnTimeChanged(const itk::EventObject& e) +QmitkChartWidget::ColorTheme QmitkImageStatisticsView::GetColorTheme() const { - if (this->m_SelectedDataNodes.isEmpty() || this->m_SelectedImage == nullptr) - return; - - const mitk::SliceNavigationController::GeometryTimeEvent* timeEvent = - dynamic_cast(&e); - assert(timeEvent != nullptr); - int timestep = timeEvent->GetPos(); - - if (this->m_SelectedImage->GetTimeSteps() > 1) + ctkPluginContext *context = berry::WorkbenchPlugin::GetDefault()->GetPluginContext(); + ctkServiceReference styleManagerRef = context->getServiceReference(); + if (styleManagerRef) { - for (int x = 0; x < this->m_Controls->m_StatisticsTable->columnCount(); x++) + auto styleManager = context->getService(styleManagerRef); + if (styleManager->GetStyle().name == "Dark") { - for (int y = 0; y < this->m_Controls->m_StatisticsTable->rowCount(); y++) - { - QTableWidgetItem* item = this->m_Controls->m_StatisticsTable->item(y, x); - if (item == nullptr) - break; - - if (x == timestep) - { - item->setBackgroundColor(Qt::yellow); - } - else - { - if (y % 2 == 0) - item->setBackground(this->m_Controls->m_StatisticsTable->palette().base()); - else - item->setBackground(this->m_Controls->m_StatisticsTable->palette().alternateBase()); - } - } + return QmitkChartWidget::ColorTheme::darkstyle; } - - this->m_Controls->m_StatisticsTable->viewport()->update(); - } - - if ((this->m_SelectedImage->GetTimeSteps() == 1 && timestep == 0) || - this->m_SelectedImage->GetTimeSteps() > 1) - { - m_Controls->m_JSHistogram->Clear(); - QmitkImageStatisticsCalculationJob::HistogramType::ConstPointer histogram = - (QmitkImageStatisticsCalculationJob::HistogramType::ConstPointer)this->m_CalculationThread->GetTimeStepHistogram(timestep); - - if (histogram.IsNotNull()) + else { - bool statisticsUpdateSuccessful = this->m_CalculationThread->GetStatisticsUpdateSuccessFlag(); - - if (statisticsUpdateSuccessful) - { - - auto imageNameLabel = m_Controls->m_SelectedFeatureImageLabel->text().toStdString(); - this->m_Controls->m_JSHistogram->AddData2D(ConvertHistogramToMap(histogram), imageNameLabel); - if (this->m_Controls->m_lineRadioButton->isChecked()) - { - this->m_Controls->m_JSHistogram->SetChartType(imageNameLabel, QmitkChartWidget::ChartType::line); - } - else - { - this->m_Controls->m_JSHistogram->SetChartType(imageNameLabel, QmitkChartWidget::ChartType::bar); - } - this->m_Controls->m_JSHistogram->SetXAxisLabel("Grey value"); - this->m_Controls->m_JSHistogram->SetYAxisLabel("Frequency"); - this->m_Controls->m_JSHistogram->Show(this->m_Controls->m_ShowSubchartCheckBox->isChecked()); - } + return QmitkChartWidget::ColorTheme::lightstyle; } } + return QmitkChartWidget::ColorTheme::darkstyle; } -void QmitkImageStatisticsView::JumpToCoordinates(int row, int col) -{ - if (m_SelectedDataNodes.isEmpty()) - { - MITK_WARN("QmitkImageStatisticsView") << "No data node selected for statistics calculation."; - return; - } - - mitk::Point3D world; - if (row == 5 && !m_WorldMinList.empty()) - world = m_WorldMinList[col]; - else if (row == 4 && !m_WorldMaxList.empty()) - world = m_WorldMaxList[col]; - else - return; - - mitk::IRenderWindowPart* part = this->GetRenderWindowPart(); - if (part) - { - part->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SelectSliceByPoint(world); - part->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SelectSliceByPoint(world); - part->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SelectSliceByPoint(world); - - mitk::SliceNavigationController::GeometryTimeEvent timeEvent(this->m_SelectedImage->GetTimeGeometry(), col); - part->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetGeometryTime(timeEvent); - } -} - -void QmitkImageStatisticsView::OnIgnoreZerosCheckboxClicked() -{ - emit StatisticsUpdate(); -} - -void QmitkImageStatisticsView::OnClipboardHistogramButtonClicked() +void QmitkImageStatisticsView::OnImageSelectorChanged() { - if (!m_CurrentStatisticsValid) + auto selectedImageNode = m_Controls.imageSelector->GetSelectedNode(); + if (selectedImageNode != m_selectedImageNode) { - QApplication::clipboard()->clear(); - } - - if (m_SelectedPlanarFigure == nullptr) - { - const unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos(); - - typedef mitk::ImageStatisticsCalculator::HistogramType HistogramType; - const HistogramType *histogram = this->m_CalculationThread->GetTimeStepHistogram(t).GetPointer(); - - QString clipboard("Measurement \t Frequency\n"); - for (HistogramType::ConstIterator it = histogram->Begin(); - it != histogram->End(); - ++it) + m_selectedImageNode = selectedImageNode; + if (m_selectedImageNode.IsNotNull()) { - clipboard = clipboard.append("%L1 \t %L2\n") - .arg(it.GetMeasurementVector()[0], 0, 'f', 2) - .arg(it.GetFrequency()); - } + ResetGUIDefault(); - QApplication::clipboard()->setText( - clipboard, QClipboard::Clipboard); - } - //If a (non-closed) PlanarFigure is selected, display a line profile widget - else if (m_SelectedPlanarFigure != nullptr) - { - QString clipboard("Pixel \t Intensity\n"); - for (unsigned int i = 0; i < m_IntensityProfileList.size(); i++) + auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate(); + auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate(); + auto hasSameGeometry = mitk::NodePredicateGeometry::New(m_selectedImageNode->GetData()->GetGeometry()); + hasSameGeometry->SetCheckPrecision(1e-10); + auto isMaskWithGeometryPredicate = mitk::NodePredicateAnd::New(isMaskPredicate, hasSameGeometry); + auto isMaskOrPlanarFigureWithGeometryPredicate = + mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskWithGeometryPredicate); + // prevent triggering of computation as the predicate triggers a signalChanged event + m_Controls.maskImageSelector->disconnect(); + m_Controls.maskImageSelector->SetPredicate(isMaskOrPlanarFigureWithGeometryPredicate); + // reset mask to + m_Controls.maskImageSelector->SetZeroEntryText(""); + m_Controls.checkBox_ignoreZero->setEnabled(true); + m_selectedMaskNode = nullptr; + m_Controls.widget_statistics->SetMaskNodes({}); + CalculateOrGetStatistics(); + m_Controls.widget_statistics->SetImageNodes({m_selectedImageNode.GetPointer()}); + connect(this->m_Controls.maskImageSelector, + static_cast(&QComboBox::currentIndexChanged), + this, + &QmitkImageStatisticsView::OnMaskSelectorChanged); + } + else { - clipboard = - clipboard.append("%L1 \t %L2\n").arg(QString::number(i)).arg(QString::number(m_IntensityProfileList.at(i))); + m_Controls.widget_statistics->SetImageNodes({}); + m_Controls.widget_statistics->SetMaskNodes({}); + m_Controls.widget_statistics->Reset(); + m_Controls.widget_histogram->Reset(); + ResetGUI(); } - QApplication::clipboard()->setText(clipboard, QClipboard::Clipboard); } } -void QmitkImageStatisticsView::OnClipboardStatisticsButtonClicked() +void QmitkImageStatisticsView::OnMaskSelectorChanged() { - QLocale tempLocal; - QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); - if (m_CurrentStatisticsValid && !(m_SelectedPlanarFigure != nullptr)) + auto selectedMaskNode = m_Controls.maskImageSelector->GetSelectedNode(); + if (selectedMaskNode != m_selectedMaskNode) { - const auto &statistics = - this->m_CalculationThread->GetStatisticsData(); - - // Set time borders for for loop ;) - unsigned int startT, endT; - if (this->m_Controls->m_CheckBox4dCompleteTable->checkState() == Qt::CheckState::Unchecked) + m_selectedMaskNode = selectedMaskNode; + if (m_selectedMaskNode.IsNotNull()) { - startT = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()-> - GetPos(); - endT = startT + 1; + m_Controls.widget_statistics->SetMaskNodes({m_selectedMaskNode.GetPointer()}); } else { - startT = 0; - endT = statistics->GetNumberOfTimeSteps(); - } - QVector< QVector > statisticsTable; - QStringList headline{ "Timestep", "Mean", "Median", "StdDev", "RMS", "Max", "Min", "NumberOfVoxels", "Skewness", "Kurtosis", "Uniformity", "Entropy", "MPP", "UPP", "V [mm³]" }; - - for (int i = 0; i < headline.size(); i++) - { - QVector row; - row.append(headline.at(i)); - statisticsTable.append(row); - } - - // Fill Table - for (unsigned int t = startT; t < endT; t++) - { - // Copy statistics to clipboard ("%Ln" will use the default locale for - // number formatting) - QStringList value; - value << QString::number(t) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::MEAN())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::MEDIAN())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::STANDARDDEVIATION())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::RMS())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::MAXIMUM())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::MINIMUM())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::NUMBEROFVOXELS())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::SKEWNESS())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::KURTOSIS())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::UNIFORMITY())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::ENTROPY())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::MPP())) - << QString::number(statistics->GetStatisticsForTimeStep(t).GetValueConverted(mitk::ImageStatisticsConstants::UPP())) - << QString::number(m_Controls->m_StatisticsTable->item(7, 0)->data(Qt::DisplayRole).toDouble()); - - for (int z = 0; z < value.size(); z++) - { - statisticsTable[z].append(value.at(z)); - } + m_Controls.widget_statistics->SetMaskNodes({}); } - - // Create output string - QString clipboard; - for (int i = 0; i < statisticsTable.size(); i++) - { - for (int t = 0; t < statisticsTable.at(i).size(); t++) - { - clipboard.append(statisticsTable.at(i).at(t)); - clipboard.append("\t"); - } - clipboard.append("\n"); - } - QApplication::clipboard()->setText(clipboard, QClipboard::Clipboard); - } - else - { - QApplication::clipboard()->clear(); + CalculateOrGetStatistics(); } - QLocale::setDefault(tempLocal); } -void QmitkImageStatisticsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, - const QList &nodes) +void QmitkImageStatisticsView::CalculateOrGetStatistics() { - if (this->m_Visible) - { - this->SelectionChanged(nodes); - } - else + if (this->m_selectedPlanarFigure) { - this->m_DataNodeSelectionChanged = true; + this->m_selectedPlanarFigure->RemoveObserver(this->m_PlanarFigureObserverTag); + this->m_selectedPlanarFigure = nullptr; } -} - -void QmitkImageStatisticsView::SelectionChanged(const QList &selectedNodes) -{ - m_Controls->m_JSHistogram->Clear(); - if (this->m_StatisticsUpdatePending) - { - this->m_DataNodeSelectionChanged = true; - return; // not ready for new data now! - } + m_Controls.groupBox_intensityProfile->setVisible(false); + m_Controls.widget_statistics->setEnabled(m_selectedImageNode.IsNotNull()); - if (selectedNodes.size() == this->m_SelectedDataNodes.size()) + if (m_selectedImageNode != nullptr) { - int i = 0; - for (; i < selectedNodes.size(); ++i) - { - if (selectedNodes.at(i) != this->m_SelectedDataNodes.at(i)) - { - break; - } - } - // node selection did not change - if (i == selectedNodes.size()) return; - } - - //reset the feature image and image mask field - m_Controls->m_SelectedFeatureImageLabel->setText("None"); - m_Controls->m_SelectedMaskLabel->setText("None"); + auto image = dynamic_cast(m_selectedImageNode->GetData()); + mitk::Image::Pointer mask = nullptr; + mitk::PlanarFigure::Pointer maskPlanarFigure = nullptr; - this->ReinitData(); - if (selectedNodes.isEmpty()) - { - DisableHistogramGUIElements(); - } - else - { - EnableHistogramGUIElements(); - ResetHistogramGUIElementsToDefault(); - } - if (selectedNodes.size() == 1 || selectedNodes.size() == 2) - { - bool isBinary = false; - selectedNodes.value(0)->GetBoolProperty("binary", isBinary); - mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); - isBinary |= isLabelSet->CheckNode(selectedNodes.value(0)); - if (isBinary) + if (image->GetDimension() == 4) { - EnableHistogramGUIElements(); - m_Controls->m_InfoLabel->setText(""); + m_Controls.sliderWidget_histogram->setVisible(true); + unsigned int maxTimestep = image->GetTimeSteps(); + m_Controls.sliderWidget_histogram->setMaximum(maxTimestep - 1); } - for (int i = 0; i < selectedNodes.size(); ++i) + else { - this->m_SelectedDataNodes.push_back(selectedNodes.at(i)); + m_Controls.sliderWidget_histogram->setVisible(false); } - this->m_DataNodeSelectionChanged = false; - this->m_Controls->m_ErrorMessageLabel->setText(""); - this->m_Controls->m_ErrorMessageLabel->hide(); - emit StatisticsUpdate(); - } - else - { - this->m_DataNodeSelectionChanged = false; - } -} - -void QmitkImageStatisticsView::DisableHistogramGUIElements() -{ - m_Controls->m_InfoLabel->setText(""); - m_Controls->groupBox_histogram->setEnabled(false); - m_Controls->groupBox_statistics->setEnabled(false); -} - -void QmitkImageStatisticsView::ResetHistogramGUIElementsToDefault() -{ - m_Controls->m_barRadioButton->setChecked(true); - m_Controls->m_HistogramNBinsSpinbox->setValue(100); - m_HistogramNBins = m_Controls->m_HistogramNBinsSpinbox->value(); - m_Controls->m_UseDefaultNBinsCheckBox->setChecked(true); - m_Controls->m_ShowSubchartCheckBox->setChecked(true); - m_Controls->m_BinSizeFrame->setEnabled(false); - m_Controls->m_barRadioButton->setEnabled(true); - m_Controls->m_lineRadioButton->setEnabled(true); - m_Controls->m_HistogramNBinsSpinbox->setEnabled(true); - this->m_CalculationThread->SetHistogramNBins(m_Controls->m_HistogramNBinsSpinbox->value()); -} -void QmitkImageStatisticsView::EnableHistogramGUIElements() -{ - m_Controls->groupBox_histogram->setEnabled(true); - m_Controls->groupBox_plot->setEnabled(true); - m_Controls->groupBox_statistics->setEnabled(true); -} - -void QmitkImageStatisticsView::ReinitData() -{ - while (this->m_CalculationThread->isRunning()) // wait until thread has finished - { - itksys::SystemTools::Delay(100); - } - - if (this->m_SelectedImage != nullptr) - { - this->m_SelectedImage->RemoveObserver(this->m_ImageObserverTag); - this->m_SelectedImage = nullptr; - } - if (this->m_SelectedImageMask != nullptr) - { - this->m_SelectedImageMask->RemoveObserver(this->m_ImageMaskObserverTag); - this->m_SelectedImageMask = nullptr; - } - if (this->m_SelectedPlanarFigure != nullptr) - { - this->m_SelectedPlanarFigure->RemoveObserver(this->m_PlanarFigureObserverTag); - this->m_SelectedPlanarFigure = nullptr; - } - this->m_SelectedDataNodes.clear(); - this->m_StatisticsUpdatePending = false; - - m_Controls->m_ErrorMessageLabel->setText(""); - m_Controls->m_ErrorMessageLabel->hide(); - this->InvalidateStatisticsTableView(); - m_Controls->m_StatisticsWidgetStack->setCurrentIndex(0); -} - -void QmitkImageStatisticsView::OnThreadedStatisticsCalculationEnds() -{ - m_Controls->m_ErrorMessageLabel->setText(""); - m_Controls->m_ErrorMessageLabel->hide(); - this->WriteStatisticsToGUI(); -} - -void QmitkImageStatisticsView::UpdateStatistics() -{ - mitk::IRenderWindowPart* renderPart = this->GetRenderWindowPart(); - if (renderPart == nullptr) - { - this->m_StatisticsUpdatePending = false; - return; - } - m_WorldMinList.clear(); - m_WorldMaxList.clear(); - - // classify selected nodes - mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image"); - mitk::NodePredicateDataType::Pointer isLabelSet = mitk::NodePredicateDataType::New("LabelSetImage"); - mitk::NodePredicateOr::Pointer imagePredicate = mitk::NodePredicateOr::New(isImage, isLabelSet); - - std::string maskName; - std::string maskType; - std::string featureImageName; - unsigned int maskDimension = 0; - - // reset data from last run - ITKCommandType::Pointer changeListener = ITKCommandType::New(); - changeListener->SetCallbackFunction(this, &QmitkImageStatisticsView::SelectedDataModified); - - mitk::DataNode::Pointer planarFigureNode; - for (int i = 0; i < this->m_SelectedDataNodes.size(); ++i) - { - mitk::PlanarFigure::Pointer planarFig = dynamic_cast(this->m_SelectedDataNodes.at(i)->GetData()); - if (imagePredicate->CheckNode(this->m_SelectedDataNodes.at(i))) + if (m_selectedMaskNode != nullptr) { - bool isMask = false; - this->m_SelectedDataNodes.at(i)->GetPropertyValue("binary", isMask); - isMask |= isLabelSet->CheckNode(this->m_SelectedDataNodes.at(i)); - - if (this->m_SelectedImageMask == nullptr && isMask) - { - this->m_SelectedImageMask = dynamic_cast(this->m_SelectedDataNodes.at(i)->GetData()); - this->m_ImageMaskObserverTag = this->m_SelectedImageMask->AddObserver(itk::ModifiedEvent(), changeListener); - - maskName = this->m_SelectedDataNodes.at(i)->GetName(); - maskType = m_SelectedImageMask->GetNameOfClass(); - maskDimension = 3; - } - else if (!isMask) + mask = dynamic_cast(m_selectedMaskNode->GetData()); + if (mask == nullptr) { - if (this->m_SelectedImage == nullptr) - { - this->m_SelectedImage = static_cast(this->m_SelectedDataNodes.at(i)->GetData()); - this->m_ImageObserverTag = this->m_SelectedImage->AddObserver(itk::ModifiedEvent(), changeListener); - } - featureImageName = this->m_SelectedDataNodes.at(i)->GetName(); + maskPlanarFigure = dynamic_cast(m_selectedMaskNode->GetData()); } } - else if (planarFig.IsNotNull()) - { - if (this->m_SelectedPlanarFigure == nullptr) - { - this->m_SelectedPlanarFigure = planarFig; - this->m_PlanarFigureObserverTag = - this->m_SelectedPlanarFigure->AddObserver(mitk::EndInteractionPlanarFigureEvent(), changeListener); - maskName = this->m_SelectedDataNodes.at(i)->GetName(); - maskType = this->m_SelectedPlanarFigure->GetNameOfClass(); - maskDimension = 2; - planarFigureNode = m_SelectedDataNodes.at(i); - } - } - else + + mitk::ImageStatisticsContainer::ConstPointer imageStatistics; + if (mask) { - m_Controls->m_ErrorMessageLabel->setText("Invalid data node type!"); - m_Controls->m_ErrorMessageLabel->show(); + imageStatistics = + mitk::ImageStatisticsContainerManager::GetImageStatistics(this->GetDataStorage(), image, mask.GetPointer()); } - } - - if (maskName == "") - { - maskName = "None"; - maskType = ""; - maskDimension = 0; - } - - if (featureImageName == "") - { - featureImageName = "None"; - } - - if (m_SelectedPlanarFigure != nullptr && m_SelectedImage == nullptr) - { - mitk::DataStorage::SetOfObjects::ConstPointer parentSet = this->GetDataStorage()->GetSources(planarFigureNode); - for (unsigned int i = 0; i < parentSet->Size(); i++) + else if (maskPlanarFigure) { - mitk::DataNode::Pointer node = parentSet->ElementAt(i); - if (imagePredicate->CheckNode(node)) + m_selectedPlanarFigure = maskPlanarFigure; + ITKCommandType::Pointer changeListener = ITKCommandType::New(); + changeListener->SetCallbackFunction(this, &QmitkImageStatisticsView::CalculateOrGetStatistics); + this->m_PlanarFigureObserverTag = + m_selectedPlanarFigure->AddObserver(mitk::EndInteractionPlanarFigureEvent(), changeListener); + if (!maskPlanarFigure->IsClosed()) { - bool isMask = false; - node->GetPropertyValue("binary", isMask); - isMask |= isLabelSet->CheckNode(node); - - if (!isMask) - { - if (this->m_SelectedImage == nullptr) - { - this->m_SelectedImage = static_cast(node->GetData()); - this->m_ImageObserverTag = this->m_SelectedImage->AddObserver(itk::ModifiedEvent(), changeListener); - } - } + ComputeAndDisplayIntensityProfile(image, maskPlanarFigure); } + imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics( + this->GetDataStorage(), image, maskPlanarFigure.GetPointer()); } - } - - unsigned int timeStep = renderPart->GetTimeNavigationController()->GetTime()->GetPos(); - - if (m_SelectedImage != nullptr && m_SelectedImage->IsInitialized()) - { - // Check if a the selected image is a multi-channel image. If yes, statistics - // cannot be calculated currently. - if (m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1) + else { - m_Controls->m_ErrorMessageLabel->setText("Multi-component images not supported."); - m_Controls->m_ErrorMessageLabel->show(); - - this->InvalidateStatisticsTableView(); - m_Controls->m_StatisticsWidgetStack->setCurrentIndex(0); - m_CurrentStatisticsValid = false; - this->m_StatisticsUpdatePending = false; - this->DisableHistogramGUIElements(); - m_Controls->m_InfoLabel->setText(""); - return; + imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics(this->GetDataStorage(), image); } - std::stringstream maskLabel; - maskLabel << maskName; - if (maskDimension > 0) - { - maskLabel << " [" << maskDimension << "D " << maskType << "]"; - } - m_Controls->m_SelectedMaskLabel->setText(maskLabel.str().c_str()); - m_Controls->m_SelectedFeatureImageLabel->setText(featureImageName.c_str()); + - // check time step validity - if (m_SelectedImage->GetDimension() <= 3 && timeStep > m_SelectedImage->GetDimension(3) - 1) + bool imageStatisticsOlderThanInputs = false; + if (imageStatistics && + (imageStatistics->GetMTime() < image->GetMTime() || (mask && imageStatistics->GetMTime() < mask->GetMTime()) || + (maskPlanarFigure && imageStatistics->GetMTime() < maskPlanarFigure->GetMTime()))) { - timeStep = m_SelectedImage->GetDimension(3) - 1; + imageStatisticsOlderThanInputs = true; } - // Add the used mask time step to the mask label so the user knows which mask time step was used - // if the image time step is bigger than the total number of mask time steps (see - // ImageStatisticsCalculator::ExtractImageAndMask) - if (m_SelectedImageMask != nullptr) + if (imageStatistics) { - unsigned int maskTimeStep = timeStep; - - if (maskTimeStep >= m_SelectedImageMask->GetTimeSteps()) + // triggers recomputation when switched between images and the newest one has not 100 bins (default) + auto calculatedBins = imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer()->Size(); + if (calculatedBins != 100) { - maskTimeStep = m_SelectedImageMask->GetTimeSteps() - 1; + OnRequestHistogramUpdate(m_Controls.widget_histogram->GetBins()); } - - m_Controls->m_SelectedMaskLabel->setText(m_Controls->m_SelectedMaskLabel->text() + - QString(" (t=") + - QString::number(maskTimeStep) + - QString(")")); } - // check if the segmentation mask is empty - if (m_SelectedImageMask != nullptr) + //statistics need to be computed + if (!imageStatistics || imageStatisticsOlderThanInputs || m_ForceRecompute) { + CalculateStatistics(image, mask.GetPointer(), maskPlanarFigure.GetPointer()); + } + // statistics already computed + else { - auto maskStatistics = m_SelectedImageMask->GetStatistics(); - mitk::ScalarType maskMaxValue = maskStatistics->GetScalarValueMax(0); - if (m_SelectedImageMask->GetDimension() == 4) { - for (unsigned int curTimestep = 1; curTimestep < m_SelectedImageMask->GetTimeSteps(); curTimestep++) { - maskMaxValue = std::max(maskStatistics->GetScalarValueMax(curTimestep), maskMaxValue); - } - } - - bool segmentationIsEmpty = maskMaxValue == 0; - - if (segmentationIsEmpty) + // Not an open planar figure: show histogram (intensity profile already shown) + if (!(maskPlanarFigure && !maskPlanarFigure->IsClosed())) { - m_Controls->m_ErrorMessageLabel->setText("Empty segmentation mask selected..."); - m_Controls->m_ErrorMessageLabel->show(); - this->m_StatisticsUpdatePending = false; - return; + if (imageStatistics->TimeStepExists(0)) + { + auto histogram = imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer(); + std::string imageNodeName = m_selectedImageNode->GetName(); + this->FillHistogramWidget({histogram}, {imageNodeName}); + } } } - - //// initialize thread and trigger it - this->m_CalculationThread->SetIgnoreZeroValueVoxel(m_Controls->m_IgnoreZerosCheckbox->isChecked()); - this->m_CalculationThread->Initialize(m_SelectedImage, m_SelectedImageMask, m_SelectedPlanarFigure); - this->m_CalculationThread->SetTimeStep(timeStep); - - m_Controls->m_ErrorMessageLabel->setText("Calculating statistics..."); - m_Controls->m_ErrorMessageLabel->show(); - - try - { - // Compute statistics - this->m_CalculationThread->start(); - } - catch (const mitk::Exception& e) - { - m_Controls->m_ErrorMessageLabel->setText("" + QString(e.GetDescription()) + ""); - m_Controls->m_ErrorMessageLabel->show(); - this->m_StatisticsUpdatePending = false; - } - catch (const std::runtime_error &e) - { - // In case of exception, print error message on GUI - m_Controls->m_ErrorMessageLabel->setText("" + QString(e.what()) + ""); - m_Controls->m_ErrorMessageLabel->show(); - this->m_StatisticsUpdatePending = false; - } - catch (const std::exception &e) - { - MITK_ERROR << "Caught exception: " << e.what(); - - // In case of exception, print error message on GUI - m_Controls->m_ErrorMessageLabel->setText("" + QString(e.what()) + ""); - m_Controls->m_ErrorMessageLabel->show(); - this->m_StatisticsUpdatePending = false; - } } else { - this->m_StatisticsUpdatePending = false; - } -} - -void QmitkImageStatisticsView::SelectedDataModified() -{ - if (!m_StatisticsUpdatePending) - { - emit StatisticsUpdate(); + ResetGUI(); } + m_ForceRecompute = false; } -void QmitkImageStatisticsView::NodeRemoved(const mitk::DataNode *node) +void QmitkImageStatisticsView::ComputeAndDisplayIntensityProfile(mitk::Image *image, + mitk::PlanarFigure::Pointer maskPlanarFigure) { - while (this->m_CalculationThread->isRunning()) // wait until thread has finished - { - itksys::SystemTools::Delay(100); - } - - if (node->GetData() == m_SelectedImage) - { - m_SelectedImage = nullptr; - } + auto intensityProfile = mitk::ComputeIntensityProfile(image, maskPlanarFigure); + // Don't show histogram for intensity profiles + m_Controls.groupBox_histogram->setVisible(false); + m_Controls.groupBox_intensityProfile->setVisible(true); + m_Controls.widget_intensityProfile->Reset(); + m_Controls.widget_intensityProfile->SetIntensityProfile(intensityProfile.GetPointer(), + "Intensity Profile of " + m_selectedImageNode->GetName()); } -void QmitkImageStatisticsView::RequestStatisticsUpdate() +void QmitkImageStatisticsView::ResetGUI() { - if (!m_StatisticsUpdatePending) - { - if (this->m_DataNodeSelectionChanged) - { - this->SelectionChanged(this->GetCurrentSelection()); - } - else - { - this->m_StatisticsUpdatePending = true; - this->UpdateStatistics(); - } - } - if (this->GetRenderWindowPart()) - this->GetRenderWindowPart()->RequestUpdate(); + m_Controls.widget_statistics->Reset(); + m_Controls.widget_statistics->setEnabled(false); m_Controls.widget_histogram->Reset(); + m_Controls.widget_histogram->setEnabled(false); + m_Controls.checkBox_ignoreZero->setEnabled(false); } -void QmitkImageStatisticsView::OnHistogramNBinsCheckBoxValueChanged() +void QmitkImageStatisticsView::ResetGUIDefault() { - if (static_cast(m_Controls->m_HistogramNBinsSpinbox->value()) != m_HistogramNBins) - { - m_HistogramNBins = m_Controls->m_HistogramNBinsSpinbox->value(); - this->m_CalculationThread->SetHistogramNBins(m_Controls->m_HistogramNBinsSpinbox->value()); - this->UpdateStatistics(); - } + MITK_INFO << "reset GUI"; + m_Controls.widget_histogram->ResetDefault(); + m_Controls.checkBox_ignoreZero->setChecked(false); } -void QmitkImageStatisticsView::WriteStatisticsToGUI() +void QmitkImageStatisticsView::OnStatisticsCalculationEnds() { - m_Controls->m_JSHistogram->Clear(); - m_IntensityProfileList.clear(); - - //Disconnect OnLineRadioButtonSelected() to prevent reloading chart when radiobutton is checked programmatically - disconnect((QObject*)(this->m_Controls->m_JSHistogram), SIGNAL(PageSuccessfullyLoaded()), 0, 0); - connect((QObject*)(this->m_Controls->m_JSHistogram), SIGNAL(PageSuccessfullyLoaded()), (QObject*)this, SLOT(OnPageSuccessfullyLoaded())); - m_Controls->m_InfoLabel->setText(""); - - if (m_DataNodeSelectionChanged) - { - this->m_StatisticsUpdatePending = false; - this->RequestStatisticsUpdate(); - return; // stop visualization of results and calculate statistics of new selection - } + mitk::StatusBar::GetInstance()->Clear(); if (this->m_CalculationThread->GetStatisticsUpdateSuccessFlag()) { - if (this->m_CalculationThread->GetStatisticsChangedFlag()) + auto statistic = m_CalculationThread->GetStatisticsData(); + auto image = m_CalculationThread->GetStatisticsImage(); + mitk::BaseData::ConstPointer mask = nullptr; + auto statisticNonConst = statistic->Clone(); + auto imageRule = mitk::StatisticsToImageRelationRule::New(); + imageRule->Connect(statisticNonConst.GetPointer(), image); + + if (m_CalculationThread->GetMaskImage()) { - // Do not show any error messages - m_Controls->m_ErrorMessageLabel->hide(); - m_CurrentStatisticsValid = true; + auto maskRule = mitk::StatisticsToMaskRelationRule::New(); + mask = m_CalculationThread->GetMaskImage(); + maskRule->Connect(statisticNonConst.GetPointer(), mask); + } + else if (m_CalculationThread->GetPlanarFigure()) + { + auto planarFigureRule = mitk::StatisticsToMaskRelationRule::New(); + mask = m_CalculationThread->GetPlanarFigure(); + planarFigureRule->Connect(statisticNonConst.GetPointer(), mask); } - if (m_SelectedImage != nullptr) { - //all statistics are now computed also on planar figures (lines, paths...)! - // If a (non-closed) PlanarFigure is selected, display a line profile widget - if (m_SelectedPlanarFigure != nullptr && !m_SelectedPlanarFigure->IsClosed()) { - - // check whether PlanarFigure is initialized - const mitk::PlaneGeometry *planarFigurePlaneGeometry = m_SelectedPlanarFigure->GetPlaneGeometry(); - - if (planarFigurePlaneGeometry != nullptr) - { - unsigned int timeStep = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()->GetPos(); - - mitk::Image::Pointer image; - - if (this->m_CalculationThread->GetStatisticsImage()->GetDimension() == 4) - { - mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); - timeSelector->SetInput(this->m_CalculationThread->GetStatisticsImage()); - timeSelector->SetTimeNr(timeStep); - timeSelector->Update(); - - image = timeSelector->GetOutput(); - } - else - { - image = this->m_CalculationThread->GetStatisticsImage()->Clone(); - } - - mitk::IntensityProfile::ConstPointer intensityProfile = (mitk::IntensityProfile::ConstPointer)mitk::ComputeIntensityProfile(image, m_SelectedPlanarFigure); - - m_IntensityProfileList = ConvertIntensityProfileToVector(intensityProfile); - auto lineDataLabel = "Intensity profile " + m_Controls->m_SelectedMaskLabel->text().toStdString(); - m_Controls->m_JSHistogram->SetChartType(lineDataLabel, QmitkChartWidget::ChartType::line); - m_Controls->m_JSHistogram->AddData1D(m_IntensityProfileList, lineDataLabel); - m_Controls->m_JSHistogram->SetXAxisLabel("Distance"); - m_Controls->m_JSHistogram->SetYAxisLabel("Intensity"); - m_Controls->m_JSHistogram->Show(m_Controls->m_ShowSubchartCheckBox->isChecked()); - - m_Controls->m_lineRadioButton->setChecked(true); - m_Controls->m_lineRadioButton->setEnabled(false); - m_Controls->m_barRadioButton->setEnabled(false); - m_Controls->m_HistogramNBinsSpinbox->setEnabled(false); - m_Controls->m_BinSizeFrame->setEnabled(false); - m_Controls->m_UseDefaultNBinsCheckBox->setEnabled(false); - - //Reconnect OnLineRadioButtonSelected() - connect((QObject*)(this->m_Controls->m_JSHistogram), SIGNAL(PageSuccessfullyLoaded()), (QObject*)this, SLOT(OnLineRadioButtonSelected())); - auto statisticsContainer = this->m_CalculationThread->GetStatisticsData(); - //only one entry (current timestep) - this->FillLinearProfileStatisticsTableView(statisticsContainer, this->m_CalculationThread->GetStatisticsImage()); + auto imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics( + this->GetDataStorage(), image, mask); - QString message("Only linegraph available for an intensity profile!"); - if (this->m_CalculationThread->GetStatisticsImage()->GetDimension() == 4) { - message += "Only current timestep displayed!"; - } - message += ""; - m_Controls->m_InfoLabel->setText(message); - m_CurrentStatisticsValid = true; - } - else + //if statistics base data already exist: add to existing node + if (imageStatistics) + { + auto allDataNodes = this->GetDataStorage()->GetAll()->CastToSTLConstContainer(); + for (auto node : allDataNodes) + { + auto nodeData = node->GetData(); + if (nodeData && nodeData->GetUID() ==imageStatistics->GetUID()) { - // Clear statistics, histogram, and GUI - this->InvalidateStatisticsTableView(); - m_Controls->m_StatisticsWidgetStack->setCurrentIndex(0); - m_CurrentStatisticsValid = false; - m_Controls->m_ErrorMessageLabel->hide(); - m_Controls->m_SelectedMaskLabel->setText("None"); - this->m_StatisticsUpdatePending = false; - m_Controls->m_InfoLabel->setText(""); - return; + node->SetData(statisticNonConst); } } - else + } + //statistics base data does not exist: add new node + else + { + auto statisticsNodeName = m_selectedImageNode->GetName(); + if (m_selectedMaskNode) { - m_Controls->m_StatisticsWidgetStack->setCurrentIndex(0); - - auto histogram = this->m_CalculationThread->GetTimeStepHistogram(this->m_CalculationThread->GetTimeStep()).GetPointer(); - - auto imageLabelName = m_Controls->m_SelectedFeatureImageLabel->text().toStdString(); - m_Controls->m_JSHistogram->AddData2D(ConvertHistogramToMap(histogram), imageLabelName); - m_Controls->m_JSHistogram->SetChartType(imageLabelName, QmitkChartWidget::ChartType::bar); - this->m_Controls->m_JSHistogram->SetXAxisLabel("Gray value"); - this->m_Controls->m_JSHistogram->SetYAxisLabel("Frequency"); - m_Controls->m_UseDefaultNBinsCheckBox->setEnabled(true); - m_Controls->m_JSHistogram->Show(this->m_Controls->m_ShowSubchartCheckBox->isChecked()); - this->FillStatisticsTableView(this->m_CalculationThread->GetStatisticsData(), this->m_CalculationThread->GetStatisticsImage()); - - auto aStatistic = this->m_CalculationThread->GetStatisticsData(); - auto statisticsNode = mitk::DataNode::New(); - statisticsNode->SetName(m_Controls->m_SelectedFeatureImageLabel->text().toStdString()); - statisticsNode->SetData(aStatistic->Clone()); - statisticsNode->SetProperty("helper object", mitk::BoolProperty::New(true)); - this->GetDataStorage()->Add(statisticsNode); - + statisticsNodeName += "_" + m_selectedMaskNode->GetName(); } - m_CurrentStatisticsValid = true; + statisticsNodeName += "_statistics"; + auto statisticsNode = mitk::CreateImageStatisticsNode(statisticNonConst, statisticsNodeName); + this->GetDataStorage()->Add(statisticsNode); } - } - else - { - m_Controls->m_SelectedMaskLabel->setText("None"); - m_Controls->m_ErrorMessageLabel->setText(m_CalculationThread->GetLastErrorMessage().c_str()); - m_Controls->m_ErrorMessageLabel->show(); - - // Clear statistics and histogram - this->InvalidateStatisticsTableView(); - m_Controls->m_StatisticsWidgetStack->setCurrentIndex(0); - m_CurrentStatisticsValid = false; - - } - berry::IPreferencesService* prefService = berry::WorkbenchPlugin::GetDefault()->GetPreferencesService(); - m_StylePref = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE); - - this->m_StatisticsUpdatePending = false; -} - -void QmitkImageStatisticsView::FillStatisticsTableView( - mitk::ImageStatisticsContainer::ConstPointer statistics, - const mitk::Image *image) -{ - this->m_Controls->m_StatisticsTable->setColumnCount(image->GetTimeSteps()); - this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(image->GetTimeSteps() > 1); - // Set Checkbox for complete copy of statistic table - if (image->GetTimeSteps() > 1) - { - this->m_Controls->m_CheckBox4dCompleteTable->setEnabled(true); - } - else - { - this->m_Controls->m_CheckBox4dCompleteTable->setEnabled(false); - this->m_Controls->m_CheckBox4dCompleteTable->setChecked(false); - } - - - for (unsigned int t = 0; t < image->GetTimeSteps(); t++) - { - this->m_Controls->m_StatisticsTable->setHorizontalHeaderItem(t, - new QTableWidgetItem(QString::number(t))); - - auto minIndex = statistics->GetStatisticsForTimeStep(t).GetValueConverted( - mitk::ImageStatisticsConstants::MINIMUMPOSITION()); - auto maxIndex = statistics->GetStatisticsForTimeStep(t).GetValueConverted( - mitk::ImageStatisticsConstants::MAXIMUMPOSITION()); - - if (maxIndex.size() == 3) + if (!m_selectedPlanarFigure || m_selectedPlanarFigure->IsClosed()) { - - mitk::Point3D index, max, min; - index[0] = maxIndex[0]; - index[1] = maxIndex[1]; - index[2] = maxIndex[2]; - m_SelectedImage->GetGeometry()->IndexToWorld(index, max); - this->m_WorldMaxList.push_back(max); - index[0] = minIndex[0]; - index[1] = minIndex[1]; - index[2] = minIndex[2]; - m_SelectedImage->GetGeometry()->IndexToWorld(index, min); - this->m_WorldMinList.push_back(min); - } - - auto statisticsVector = AssembleStatisticsIntoVector(statistics, image); - - unsigned int count = 0; - for (const auto& entry : statisticsVector) { - auto item = new QTableWidgetItem(entry); - this->m_Controls->m_StatisticsTable->setItem(count, t, item); - count++; + this->FillHistogramWidget({m_CalculationThread->GetTimeStepHistogram()}, {m_selectedImageNode->GetName()}); } - - } - - - this->m_Controls->m_StatisticsTable->resizeColumnsToContents(); - int height = STAT_TABLE_BASE_HEIGHT; - - if (this->m_Controls->m_StatisticsTable->horizontalHeader()->isVisible()) - height += this->m_Controls->m_StatisticsTable->horizontalHeader()->height(); - - if (this->m_Controls->m_StatisticsTable->horizontalScrollBar()->isVisible()) - height += this->m_Controls->m_StatisticsTable->horizontalScrollBar()->height(); - - this->m_Controls->m_StatisticsTable->setMinimumHeight(height); - - // make sure the current timestep's column is highlighted (and the correct histogram is displayed) - unsigned int t = this->GetRenderWindowPart()->GetTimeNavigationController()->GetTime()-> - GetPos(); - mitk::SliceNavigationController::GeometryTimeEvent timeEvent(this->m_SelectedImage->GetTimeGeometry(), - t); - this->OnTimeChanged(timeEvent); - - t = std::min(image->GetTimeSteps() - 1, t); - - // See bug 18340 - /*QString hotspotMean; hotspotMean.append(QString("%1").arg(s[t].GetHotspotStatistics().GetMean(), 0, 'f', decimals)); - hotspotMean += " ("; - for (int i=0; im_Controls->m_StatisticsTable->setItem( 7, t, new QTableWidgetItem( hotspotMean ) ); - - QString hotspotMax; hotspotMax.append(QString("%1").arg(s[t].GetHotspotStatistics().GetMax(), 0, 'f', decimals)); - hotspotMax += " ("; - for (int i=0; im_Controls->m_StatisticsTable->setItem( 8, t, new QTableWidgetItem( hotspotMax ) ); - - QString hotspotMin; hotspotMin.append(QString("%1").arg(s[t].GetHotspotStatistics().GetMin(), 0, 'f', decimals)); - hotspotMin += " ("; - for (int i=0; iDisplayErrorText(m_CalculationThread->GetLastErrorMessage().c_str()); + m_Controls.widget_histogram->setEnabled(false); } - hotspotMin += ")"; - - this->m_Controls->m_StatisticsTable->setItem( 9, t, new QTableWidgetItem( hotspotMin ) );*/ + m_Controls.label_currentlyComputingStatistics->setVisible(false); } -std::vector QmitkImageStatisticsView::AssembleStatisticsIntoVector(mitk::ImageStatisticsContainer::ConstPointer statistics, mitk::Image::ConstPointer image, bool noVolumeDefined) const +void QmitkImageStatisticsView::OnRequestHistogramUpdate(unsigned int nBins) { - std::vector result; - - unsigned int decimals = 2; - - //statistics of higher order should have 5 decimal places because they used to be very small - unsigned int decimalsHigherOrderStatistics = 5; - - if (image->GetPixelType().GetComponentType() == itk::ImageIOBase::DOUBLE || image->GetPixelType().GetComponentType() == itk::ImageIOBase::FLOAT) - { - decimals = 5; - } - auto statistic = statistics->GetStatisticsForTimeStep(0); - result.push_back(GetFormattedString( - statistic.GetValueConverted(mitk::ImageStatisticsConstants::MEAN()), decimals)); - result.push_back(GetFormattedString( - statistic.GetValueConverted(mitk::ImageStatisticsConstants::MEDIAN()), decimals)); - result.push_back(GetFormattedString( - statistic.GetValueConverted(mitk::ImageStatisticsConstants::STANDARDDEVIATION()), decimals)); - result.push_back(GetFormattedString( - statistic.GetValueConverted(mitk::ImageStatisticsConstants::RMS()), decimals)); - result.push_back(GetFormattedString( - statistic.GetValueConverted(mitk::ImageStatisticsConstants::MAXIMUM()), decimals) + - " " + GetFormattedIndex(statistic.GetValueConverted(mitk::ImageStatisticsConstants::MAXIMUMPOSITION()))); - result.push_back(GetFormattedString( - statistic.GetValueConverted(mitk::ImageStatisticsConstants::MINIMUM()), decimals) + - " " + GetFormattedIndex(statistic.GetValueConverted(mitk::ImageStatisticsConstants::MINIMUMPOSITION()))); - - auto numberVoxels = statistic.GetValueConverted(mitk::ImageStatisticsConstants::NUMBEROFVOXELS()); - //to prevent large negative values of empty image statistics - if (numberVoxels != std::numeric_limits::min()) { - result.push_back(GetFormattedString(numberVoxels, 0)); - - const mitk::BaseGeometry *geometry = image->GetGeometry(); - if (geometry != NULL && !noVolumeDefined) - { - const mitk::Vector3D &spacing = image->GetGeometry()->GetSpacing(); - double volume = spacing[0] * spacing[1] * spacing[2] * static_cast(numberVoxels); - result.push_back(GetFormattedString(volume, decimals)); - } - else { - result.push_back("NA"); - } - } - else { - result.push_back("NA"); - result.push_back("NA"); - } - - result.push_back( - GetFormattedString(statistic.GetValueConverted(mitk::ImageStatisticsConstants::SKEWNESS()), decimalsHigherOrderStatistics)); - result.push_back( - GetFormattedString(statistic.GetValueConverted(mitk::ImageStatisticsConstants::KURTOSIS()), decimalsHigherOrderStatistics)); - result.push_back( - GetFormattedString(statistic.GetValueConverted(mitk::ImageStatisticsConstants::UNIFORMITY()), decimalsHigherOrderStatistics)); - result.push_back( - GetFormattedString(statistic.GetValueConverted(mitk::ImageStatisticsConstants::ENTROPY()), decimalsHigherOrderStatistics)); - result.push_back( - GetFormattedString(statistic.GetValueConverted(mitk::ImageStatisticsConstants::MPP()), decimals)); - result.push_back( - GetFormattedString(statistic.GetValueConverted(mitk::ImageStatisticsConstants::UPP()), decimalsHigherOrderStatistics)); - - return result; + m_CalculationThread->SetHistogramNBins(nBins); + m_CalculationThread->start(); } -void QmitkImageStatisticsView::FillLinearProfileStatisticsTableView(mitk::ImageStatisticsContainer::ConstPointer statistics, - const mitk::Image *image) +void QmitkImageStatisticsView::CalculateStatistics(mitk::Image::ConstPointer image, + mitk::Image::ConstPointer mask, + mitk::PlanarFigure::ConstPointer maskPlanarFigure) { - this->m_Controls->m_StatisticsTable->setColumnCount(1); - this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(false); + this->m_StatisticsUpdatePending = true; + this->m_CalculationThread->Initialize(image, mask, maskPlanarFigure); - m_PlanarFigureStatistics = this->AssembleStatisticsIntoVector(statistics, image, true); - - for (unsigned int i = 0; i < m_PlanarFigureStatistics.size(); i++) + try { - this->m_Controls->m_StatisticsTable->setItem(i, 0, new QTableWidgetItem(m_PlanarFigureStatistics[i])); + // Compute statistics + this->m_CalculationThread->start(); + m_Controls.label_currentlyComputingStatistics->setVisible(true); } - - this->m_Controls->m_StatisticsTable->resizeColumnsToContents(); - int height = STAT_TABLE_BASE_HEIGHT; - - if (this->m_Controls->m_StatisticsTable->horizontalHeader()->isVisible()) - height += this->m_Controls->m_StatisticsTable->horizontalHeader()->height(); - - if (this->m_Controls->m_StatisticsTable->horizontalScrollBar()->isVisible()) - height += this->m_Controls->m_StatisticsTable->horizontalScrollBar()->height(); - - this->m_Controls->m_StatisticsTable->setMinimumHeight(height); -} - -void QmitkImageStatisticsView::InvalidateStatisticsTableView() -{ - this->m_Controls->m_StatisticsTable->horizontalHeader()->setVisible(false); - this->m_Controls->m_StatisticsTable->setColumnCount(1); - - for (int i = 0; i < this->m_Controls->m_StatisticsTable->rowCount(); ++i) + catch (const mitk::Exception &e) { - { - this->m_Controls->m_StatisticsTable->setItem(i, 0, new QTableWidgetItem("NA")); - } - } - - this->m_Controls->m_StatisticsTable->setMinimumHeight(STAT_TABLE_BASE_HEIGHT); -} - -void QmitkImageStatisticsView::Activated() -{ -} - -void QmitkImageStatisticsView::Deactivated() -{ -} - -void QmitkImageStatisticsView::Visible() -{ - m_Visible = true; - - mitk::IRenderWindowPart* renderWindow = GetRenderWindowPart(); - - if (renderWindow) - { - itk::ReceptorMemberCommand::Pointer cmdTimeEvent = - itk::ReceptorMemberCommand::New(); - cmdTimeEvent->SetCallbackFunction(this, &QmitkImageStatisticsView::OnTimeChanged); - - // It is sufficient to add the observer to the axial render window since the GeometryTimeEvent - // is always triggered by all views. - m_TimeObserverTag = renderWindow->GetQmitkRenderWindow("axial")-> - GetSliceNavigationController()-> - AddObserver(mitk::SliceNavigationController::GeometryTimeEvent(nullptr, 0), cmdTimeEvent); + mitk::StatusBar::GetInstance()->DisplayErrorText(e.GetDescription()); + this->m_StatisticsUpdatePending = false; + m_Controls.label_currentlyComputingStatistics->setVisible(false); } - - if (m_DataNodeSelectionChanged) + catch (const std::runtime_error &e) { - if (this->IsCurrentSelectionValid()) - { - this->SelectionChanged(this->GetCurrentSelection()); - } - else - { - this->SelectionChanged(this->GetDataManagerSelection()); - } - m_DataNodeSelectionChanged = false; + mitk::StatusBar::GetInstance()->DisplayErrorText(e.what()); + this->m_StatisticsUpdatePending = false; + m_Controls.label_currentlyComputingStatistics->setVisible(false); } -} - -void QmitkImageStatisticsView::Hidden() -{ - m_Visible = false; - - // The slice navigation controller observer is removed here instead of in the destructor. - // If it was called in the destructor, the application would freeze because the view's - // destructor gets called after the render windows have been destructed. - if (m_TimeObserverTag != 0) + catch (const std::exception &e) { - mitk::IRenderWindowPart* renderWindow = GetRenderWindowPart(); - - if (renderWindow) - { - renderWindow->GetQmitkRenderWindow("axial")->GetSliceNavigationController()-> - RemoveObserver(m_TimeObserverTag); - } - m_TimeObserverTag = 0; + mitk::StatusBar::GetInstance()->DisplayErrorText(e.what()); + this->m_StatisticsUpdatePending = false; + m_Controls.label_currentlyComputingStatistics->setVisible(false); } } -void QmitkImageStatisticsView::SetFocus() +void QmitkImageStatisticsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer part, + const QList &nodes) { + Q_UNUSED(part); + Q_UNUSED(nodes); } -std::map QmitkImageStatisticsView::ConvertHistogramToMap(itk::Statistics::Histogram::ConstPointer histogram) const +void QmitkImageStatisticsView::PrepareDataStorageComboBoxes() { - std::map histogramMap; + auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate(); + auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate(); + auto isImagePredicate = mitk::GetImageStatisticsImagePredicate(); + auto isMaskOrPlanarFigurePredicate = mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskPredicate); - auto endIt = histogram->End(); - auto it = histogram->Begin(); + m_Controls.imageSelector->SetDataStorage(GetDataStorage()); + m_Controls.imageSelector->SetPredicate(isImagePredicate); - // generating Lists of measurement and frequencies - for (; it != endIt; ++it) - { - double frequency = it.GetFrequency(); - double measurement = it.GetMeasurementVector()[0]; - histogramMap.emplace(measurement, frequency); - } + m_Controls.maskImageSelector->SetDataStorage(GetDataStorage()); - return histogramMap; + m_Controls.maskImageSelector->SetPredicate(isMaskOrPlanarFigurePredicate); + m_Controls.maskImageSelector->SetZeroEntryText(""); } -std::vector QmitkImageStatisticsView::ConvertIntensityProfileToVector(mitk::IntensityProfile::ConstPointer intensityProfile) const -{ - std::vector intensityProfileList; - auto end = intensityProfile->End(); +void QmitkImageStatisticsView::Activated() {} - for (auto it = intensityProfile->Begin(); it != end; ++it) - { - intensityProfileList.push_back(it.GetMeasurementVector()[0]); - } - return intensityProfileList; -} +void QmitkImageStatisticsView::Deactivated() {} -QString QmitkImageStatisticsView::GetFormattedString(double value, unsigned int decimals) const +void QmitkImageStatisticsView::Visible() { - typedef mitk::ImageStatisticsContainer::RealType RealType; - RealType maxVal = std::numeric_limits::max(); - - if (value == maxVal) - { - return QString("NA"); - } - else - { - return QString("%1").arg(value, 0, 'f', decimals); - } + connect(this->m_Controls.imageSelector, + static_cast(&QComboBox::currentIndexChanged), + this, + &QmitkImageStatisticsView::OnImageSelectorChanged); + connect(this->m_Controls.maskImageSelector, + static_cast(&QComboBox::currentIndexChanged), + this, + &QmitkImageStatisticsView::OnMaskSelectorChanged); + OnImageSelectorChanged(); + OnMaskSelectorChanged(); } -QString QmitkImageStatisticsView::GetFormattedIndex(const vnl_vector& vector) const +void QmitkImageStatisticsView::Hidden() { - if (vector.empty()) { - return QString(); - } - QString formattedIndex("("); - for (const auto& entry : vector) - { - formattedIndex += QString::number(entry); - formattedIndex += ","; - } - formattedIndex.chop(1); - formattedIndex += ")"; - return formattedIndex; + m_Controls.imageSelector->disconnect(); + m_Controls.maskImageSelector->disconnect(); } + +void QmitkImageStatisticsView::SetFocus() {} diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.h b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.h index e49ee842d2..6390f25e7f 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.h +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsView.h @@ -1,191 +1,112 @@ /*=================================================================== 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 QmitkImageStatisticsView_H__INCLUDED #define QmitkImageStatisticsView_H__INCLUDED #include "ui_QmitkImageStatisticsViewControls.h" // Qmitk includes #include -#include #include -#include +#include -// mitk includes #include -#include -#include - -#include +#include +#include /*! \brief QmitkImageStatisticsView is a bundle that allows statistics calculation from images. Three modes are supported: 1. Statistics of one image, 2. Statistics of an image and a segmentation, 3. Statistics of an image and a Planar Figure. The statistics calculation is realized in a separate thread to keep the gui accessible during calculation. \ingroup Plugins/org.mitk.gui.qt.measurementtoolbox */ class QmitkImageStatisticsView : public QmitkAbstractView, public mitk::ILifecycleAwarePart, public berry::IPartListener { Q_OBJECT -private: - /*! - \ Convenient typedefs */ - typedef QList SelectedDataNodeVectorType; - typedef itk::SimpleMemberCommand< QmitkImageStatisticsView > ITKCommandType; - - std::map ConvertHistogramToMap(itk::Statistics::Histogram::ConstPointer histogram) const; - std::vector ConvertIntensityProfileToVector(mitk::IntensityProfile::ConstPointer intensityProfile) const; - std::vector AssembleStatisticsIntoVector(mitk::ImageStatisticsContainer::ConstPointer statistics, mitk::Image::ConstPointer image, bool noVolumeDefined=false) const; - - QString GetFormattedIndex(const vnl_vector& vector) const; - QString GetFormattedString(double value, unsigned int decimals) const; public: + using HistogramType = mitk::ImageStatisticsContainer::HistogramType; /*! \brief default constructor */ QmitkImageStatisticsView(QObject *parent = nullptr, const char *name = nullptr); /*! \brief default destructor */ virtual ~QmitkImageStatisticsView(); /*! \brief method for creating the widget containing the application controls, like sliders, buttons etc. */ virtual void CreateQtPartControl(QWidget *parent) override; /*! \brief method for creating the connections of main and control widget */ virtual void CreateConnections(); /*! \brief Is called from the selection mechanism once the data manager selection has changed*/ void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList &selectedNodes) override; - static const std::string VIEW_ID; - static const int STAT_TABLE_BASE_HEIGHT; - - public slots: - /** \brief Called when the statistics update is finished, sets the results to GUI.*/ - void OnThreadedStatisticsCalculationEnds(); - - /** \brief Update bin size for histogram resolution. */ - void OnHistogramNBinsCheckBoxValueChanged(); - - protected slots: - /** \brief Saves the histogram to the clipboard */ - void OnClipboardHistogramButtonClicked(); - /** \brief Saves the statistics to the clipboard */ - void OnClipboardStatisticsButtonClicked(); - /** \brief Indicates if zeros should be excluded from statistics calculation */ - void OnIgnoreZerosCheckboxClicked(); - /** \brief Checks if update is possible and calls StatisticsUpdate() possible */ - void RequestStatisticsUpdate(); - /** \brief Jump to coordinates stored in the double clicked cell */ - void JumpToCoordinates(int row, int col); - /** \brief Toogle GUI elements if histogram default bin size checkbox value changed. */ - void OnDefaultNBinsSpinBoxChanged(); - - void OnShowSubchartBoxChanged(); - - void OnBarRadioButtonSelected(); + void PrepareDataStorageComboBoxes(); - void OnLineRadioButtonSelected(); - - void OnPageSuccessfullyLoaded(); - -signals: - /** \brief Method to set the data to the member and start the threaded statistics update */ - void StatisticsUpdate(); + static const std::string VIEW_ID; + void FillHistogramWidget(const std::vector& histogram, const std::vector& dataLabels); + QmitkChartWidget::ColorTheme GetColorTheme() const; protected: - /** \brief Writes the calculated statistics to the GUI */ - void FillStatisticsTableView(mitk::ImageStatisticsContainer::ConstPointer statistics, - const mitk::Image *image); - - void FillLinearProfileStatisticsTableView(mitk::ImageStatisticsContainer::ConstPointer statistics, const mitk::Image *image); - - /** \brief Removes statistics from the GUI */ - void InvalidateStatisticsTableView(); - - /** \brief Recalculate statistics for currently selected image and mask and - * update the GUI. */ - void UpdateStatistics(); - virtual void Activated() override; virtual void Deactivated() override; virtual void Visible() override; virtual void Hidden() override; virtual void SetFocus() override; - /** \brief Method called when itkModifiedEvent is called by selected data. */ - void SelectedDataModified(); - /** \brief Method called when the data manager selection changes */ - void SelectionChanged(const QList &selectedNodes); - - void DisableHistogramGUIElements(); - - void ResetHistogramGUIElementsToDefault(); - - void EnableHistogramGUIElements(); - - /** \brief Method called to remove old selection when a new selection is present */ - void ReinitData(); - /** \brief writes the statistics to the gui*/ - void WriteStatisticsToGUI(); - - void NodeRemoved(const mitk::DataNode *node) override; - /** \brief Is called right before the view closes (before the destructor) */ virtual void PartClosed(const berry::IWorkbenchPartReference::Pointer&) override; - /** \brief Is called from the image navigator once the time step has changed */ - void OnTimeChanged(const itk::EventObject&); + /** \brief Required for berry::IPartListener */ virtual Events::Types GetPartEventTypes() const override { return Events::CLOSED; } - // member variables - Ui::QmitkImageStatisticsViewControls *m_Controls; - // if you have a planar figure selected, the statistics values will be saved in this one. - std::vector m_PlanarFigureStatistics; - QmitkImageStatisticsCalculationJob* m_CalculationThread; - - // Image and mask data - mitk::Image* m_SelectedImage; - mitk::Image* m_SelectedImageMask; - mitk::PlanarFigure* m_SelectedPlanarFigure; - - // observer tags - long m_ImageObserverTag; - long m_ImageMaskObserverTag; - long m_PlanarFigureObserverTag; - long m_TimeObserverTag; + void OnImageSelectorChanged(); + void OnMaskSelectorChanged(); + + void CalculateOrGetStatistics(); + + void ComputeAndDisplayIntensityProfile(mitk::Image * image, mitk::PlanarFigure::Pointer maskPlanarFigure); - SelectedDataNodeVectorType m_SelectedDataNodes; + void ResetGUI(); + void ResetGUIDefault(); - bool m_CurrentStatisticsValid; - bool m_StatisticsUpdatePending; - bool m_DataNodeSelectionChanged; - bool m_Visible; + void OnStatisticsCalculationEnds(); + void OnRequestHistogramUpdate(unsigned int nBins); + void OnCheckBoxIgnoreZeroStateChanged(int state); + void OnSliderWidgetHistogramChanged(double value); - unsigned int m_HistogramNBins; + void CalculateStatistics(mitk::Image::ConstPointer image, mitk::Image::ConstPointer mask=nullptr, mitk::PlanarFigure::ConstPointer maskPlanarFigure = nullptr); + + // member variables + Ui::QmitkImageStatisticsViewControls m_Controls; - std::vector m_WorldMinList; - std::vector m_WorldMaxList; +private: + typedef itk::SimpleMemberCommand< QmitkImageStatisticsView > ITKCommandType; + QmitkImageStatisticsCalculationJob * m_CalculationThread = nullptr; + bool m_StatisticsUpdatePending=false; + mitk::DataNode::ConstPointer m_selectedImageNode = nullptr, m_selectedMaskNode = nullptr; - std::vector m_IntensityProfileList; - berry::IPreferences::Pointer m_StylePref; + mitk::PlanarFigure::Pointer m_selectedPlanarFigure=nullptr; + long m_PlanarFigureObserverTag; + bool m_ForceRecompute = false; }; #endif // QmitkImageStatisticsView_H__INCLUDED diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsViewControls.ui b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsViewControls.ui index d0171ca775..82459f65dd 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsViewControls.ui +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsViewControls.ui @@ -1,747 +1,469 @@ QmitkImageStatisticsViewControls true 0 0 - 548 - 812 + 419 + 1016 Form - - - - - - - - 255 - 0 - 4 - - - - - - - 255 - 0 - 4 - - - - - - - 255 - 0 - 4 - - - - - - - - - 255 - 0 - 4 - - - - - - - 255 - 0 - 4 - - - - - - - 255 - 0 - 4 - - - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - - - 120 - 120 - 120 - - - - - + + + QLayout::SetMinimumSize - - This plugin is deprecated. Consider using the new image statistics plugin (icon with star). + + 4 - - - - - - + + - + 0 0 - - Qt::LeftToRight - - - Feature Image: + + false - - - - - 0 - 0 - + + + + + + + + + 255 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + - None + Calculating statistics... - + 0 0 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + - Mask: + Mask image: - - + + - + 0 0 - - None + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + - - -1 + + Image: - - + + - + 0 0 - - color: rgb(255, 0, 0); + + false + + + + - Error Message - - - Qt::AutoText - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Ignore zero-valued voxels - - - - Ignore zero-valued voxels - - - - - false + + + 0 + 200 + Statistics - 9 + 3 + + + 3 - 9 + 3 - 9 + 3 - - - - 100 - 180 - - - - - 16777215 - 16777215 - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - - - true + + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + - - QAbstractItemView::NoEditTriggers - - - true - - - true - - - Qt::DotLine - - - false - - - 14 - - - 1 - - - false - - - false - - - 80 - - - true - - - 80 - - - false - - - true - - - true - - - false - - - 25 - - - 25 - - - false - - - false - - - - Mean - - - - - Median - - - - - StdDev - - - - - RMS - - - - - Max - - - - - Min - - - - - N - - - - - V (mm³) - - - - - Skewness - - - - - Kurtosis - - - - - Uniformity - - - - - Entropy - - - - - MPP - - - - - UPP - - - - - 0 - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Copy to Clipboard - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - false - - - copy complete table - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - false - - 400 - 450 + 0 + 200 Histogram - - false - - - - - - false - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Plot - - - - - - - - - 0 - 0 - - - - - - - Barchart - - - true - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Linegraph - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Show Subchart - - - true - - - - - - - Use default #bins - - - true - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 60 - 0 - - - - - 100 - 16777215 - - - - # bins: - - - - - - - false - - - Press enter to recalculate statistics with new bin size. - - - 1 - - - 10000 - - - 100 - - - - - - - - - + - - - - 0 - 0 - - - - 0 - - - - - 0 - 0 - - - - + - - - - - + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + 0 + 200 + + + + Intensity Profile + + - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Copy to Clipboard - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + Qt::Vertical 20 40 - QmitkChartWidget + QmitkImageStatisticsWidget + QWidget +
QmitkImageStatisticsWidget.h
+ 1 +
+ + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+ + QmitkHistogramVisualizationWidget + QWidget +
QmitkHistogramVisualizationWidget.h
+ 1 +
+ + QmitkDataStorageComboBoxWithSelectNone + QComboBox +
QmitkDataStorageComboBoxWithSelectNone.h
+
+ + QmitkIntensityProfileVisualizationWidget + QWidget +
QmitkIntensityProfileVisualizationWidget.h
+ 1 +
+ + ctkSliderWidget QWidget -
QmitkChartWidget.h
+
ctkSliderWidget.h
+ 1
diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp index 259a13aeeb..a48d1c5ae9 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/mitkPluginActivator.cpp @@ -1,41 +1,39 @@ /*=================================================================== 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 "mitkPluginActivator.h" #include "QmitkMeasurementView.h" #include "QmitkImageStatisticsView.h" -#include "QmitkImageStatisticsReloadedView.h" ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; ctkPluginContext* mitk::PluginActivator::GetContext() { return m_Context; } void mitk::PluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkMeasurementView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkImageStatisticsView, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkImageStatisticsReloadedView, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) m_Context = nullptr; }