diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp index 641b9f87c4..702e46439c 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp @@ -1,323 +1,327 @@ /*=================================================================== 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 "QmitkImageStatisticsTableModel.h" + #include "mitkProportionalTimeGeometry.h" #include "mitkStatisticsToImageRelationRule.h" #include "mitkImageStatisticsContainerManager.h" #include "itkMutexLockHolder.h" -#include "itkSimpleFastMutexLock.h" QmitkImageStatisticsTableModel::QmitkImageStatisticsTableModel(QObject *parent) : QmitkAbstractDataStorageModel(parent) {} QmitkImageStatisticsTableModel ::~QmitkImageStatisticsTableModel() { // set data storage to nullptr so that the event listener gets removed this->SetDataStorage(nullptr); }; void QmitkImageStatisticsTableModel::DataStorageChanged() { emit beginResetModel(); UpdateByDataStorage(); emit endResetModel(); } void QmitkImageStatisticsTableModel::NodePredicateChanged() { emit beginResetModel(); UpdateByDataStorage(); emit endResetModel(); } int QmitkImageStatisticsTableModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return m_StatisticNames.size(); } int QmitkImageStatisticsTableModel::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; if (m_ViewMode == ViewMode::imageXStatistic) { return static_cast(m_TimeStepResolvedImageNodes.size()); } else { mitkThrow() << "View mode ImageXMask is not implemented yet"; } } std::pair QmitkImageStatisticsTableModel::GetRelevantStatsticsByIndex(const QModelIndex &index) const { auto result = std::make_pair(nullptr, 0); if (m_ViewMode == ViewMode::imageXStatistic) { if (index.column() < static_cast(m_TimeStepResolvedImageNodes.size())) { auto selectedImage = m_TimeStepResolvedImageNodes.at(static_cast(index.column())); //get the right statistic auto rule = mitk::StatisticsToImageRelationRule::New(); for (mitk::ImageStatisticsContainer::ConstPointer container : m_Statistics) { if (rule->HasRelation(container, selectedImage.first->GetData()) >= mitk::PropertyRelationRuleBase::RelationType::Connected_Data) { return std::make_pair(container, selectedImage.second); } } } } else { mitkThrow() << "View mode ImageXMask is not implemented yet"; } return result; } QVariant QmitkImageStatisticsTableModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); QVariant result; if (m_ViewMode == ViewMode::imageXStatistic) { auto containerInfo = GetRelevantStatsticsByIndex(index); if (containerInfo.first.IsNotNull() && index.row() < rowCount(QModelIndex())) { if (Qt::DisplayRole == role) { auto statsObj = containerInfo.first->GetStatisticsForTimeStep(containerInfo.second); auto statisticKey = m_StatisticNames.at(index.row()); std::stringstream ss; if (statsObj.HasStatistic(statisticKey)) { ss << statsObj.GetValueNonConverted(statisticKey); } else { ss << "N/A"; } result = QVariant(QString::fromStdString(ss.str())); } else if (Qt::UserRole == role) { result = QVariant(index.row()); } } } return result; } QModelIndex QmitkImageStatisticsTableModel::index(int row, int column, const QModelIndex &parent) const { bool hasIndex = this->hasIndex(row, column, parent); if (hasIndex) { return this->createIndex(row, column); } return QModelIndex(); } QModelIndex QmitkImageStatisticsTableModel::parent(const QModelIndex &/*child*/) const { return QModelIndex(); } Qt::ItemFlags QmitkImageStatisticsTableModel::flags(const QModelIndex &index) const { Qt::ItemFlags flags = QAbstractItemModel::flags(index); return flags; } QVariant QmitkImageStatisticsTableModel::headerData(int section, Qt::Orientation orientation, int role) const { if ((Qt::DisplayRole == role) && (Qt::Horizontal == orientation)) { if (!m_TimeStepResolvedImageNodes.empty()) { if (m_ViewMode == ViewMode::imageXStatistic) { std::stringstream ss; auto imageInfo = m_TimeStepResolvedImageNodes.at(section); ss << imageInfo.first->GetName(); if (imageInfo.first->GetData() && imageInfo.first->GetData()->GetTimeSteps() > 1) { ss << " #" << imageInfo.second; } if (!m_MaskNodes.empty() && m_MaskNodes.size() == m_ImageNodes.size()) { auto maskInfo = m_TimeStepResolvedMaskNodes.at(section); ss << " / " << maskInfo.first->GetName(); } return QVariant(ss.str().c_str()); } } } else if ((Qt::DisplayRole == role) && (Qt::Vertical == orientation)) { if (m_ViewMode == ViewMode::imageXStatistic) { return QVariant(m_StatisticNames.at(section).c_str()); } } return QVariant(); } void QmitkImageStatisticsTableModel::SetImageNodes(const std::vector& nodes) { std::vector > tempNodes; for (const auto& node: nodes) { auto data = node->GetData(); if (data) { auto timeSteps = data->GetTimeSteps(); for (unsigned int i = 0; i < timeSteps; i++) { tempNodes.push_back(std::make_pair(node, i)); } } } emit beginResetModel(); m_TimeStepResolvedImageNodes = std::move(tempNodes); m_ImageNodes = nodes; UpdateByDataStorage(); emit endResetModel(); } void QmitkImageStatisticsTableModel::SetMaskNodes(const std::vector& nodes) { std::vector> tempNodes; for (const auto &node : nodes) { auto data = node->GetData(); if (data) { auto timeSteps = data->GetTimeSteps(); //special case: apply one mask to each timestep of an 4D image if (timeSteps == 1 && m_TimeStepResolvedImageNodes.size() > 1) { timeSteps = m_TimeStepResolvedImageNodes.size(); } for (unsigned int i = 0; i < timeSteps; i++) { tempNodes.push_back(std::make_pair(node, i)); } } } emit beginResetModel(); m_TimeStepResolvedMaskNodes = std::move(tempNodes); m_MaskNodes = nodes; UpdateByDataStorage(); emit endResetModel(); } void QmitkImageStatisticsTableModel::SetViewMode(ViewMode m) { emit beginResetModel(); m_ViewMode = m; emit endResetModel(); } void QmitkImageStatisticsTableModel::Clear() { emit beginResetModel(); m_Statistics.clear(); m_ImageNodes.clear(); m_TimeStepResolvedImageNodes.clear(); m_MaskNodes.clear(); m_StatisticNames.clear(); emit endResetModel(); } void QmitkImageStatisticsTableModel::UpdateByDataStorage() { StatisticsContainerVector newStatistics; auto datamanager = m_DataStorage.Lock(); if (datamanager.IsNotNull()) { for (const auto& image : m_ImageNodes) { if (m_MaskNodes.empty()) { auto stats = mitk::ImageStatisticsContainerManager::GetImageStatistics(datamanager, image->GetData()); if (stats.IsNotNull()) { newStatistics.emplace_back(stats); } } else { for (const auto& mask : m_MaskNodes) { auto stats = mitk::ImageStatisticsContainerManager::GetImageStatistics(datamanager, image->GetData(), mask->GetData()); if (stats.IsNotNull()) { newStatistics.emplace_back(stats); } } } } + if (!newStatistics.empty()) + { + emit dataAvailable(); + } } { itk::MutexLockHolder locked(m_Mutex); m_Statistics = newStatistics; } m_StatisticNames = mitk::GetAllStatisticNames(m_Statistics); } void QmitkImageStatisticsTableModel::NodeRemoved(const mitk::DataNode *) { emit beginResetModel(); UpdateByDataStorage(); emit endResetModel(); } void QmitkImageStatisticsTableModel::NodeAdded(const mitk::DataNode *) { emit beginResetModel(); UpdateByDataStorage(); emit endResetModel(); } void QmitkImageStatisticsTableModel::NodeChanged(const mitk::DataNode *) { emit beginResetModel(); UpdateByDataStorage(); emit endResetModel(); } diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h index cd35e5798b..add0af5f48 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h @@ -1,112 +1,113 @@ /*=================================================================== 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 QmitkImageStatisticsTableModel_h #define QmitkImageStatisticsTableModel_h #include "itkSimpleFastMutexLock.h" #include "QmitkAbstractDataStorageModel.h" //MITK #include #include "mitkImageStatisticsContainer.h" -#include "mitkDataNode.h" -#include "mitkDataStorage.h" /*! \class QmitkImageStatisticsTableModel Model that takes a mitk::ImageStatisticsContainer and represents it as model in context of the QT view-model-concept. */ class MITKIMAGESTATISTICSUI_EXPORT QmitkImageStatisticsTableModel : public QmitkAbstractDataStorageModel { Q_OBJECT public: enum class ViewMode { imageXStatistic, imageXMask }; QmitkImageStatisticsTableModel(QObject *parent = nullptr); virtual ~QmitkImageStatisticsTableModel(); void SetImageNodes(const std::vector& nodes); void SetMaskNodes(const std::vector& nodes); void SetViewMode(ViewMode m); void Clear(); virtual Qt::ItemFlags flags(const QModelIndex &index) const override; virtual QVariant data(const QModelIndex &index, int role) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &child) const override; +signals: + void dataAvailable(); + protected: /* * @brief See 'QmitkAbstractDataStorageModel' */ void DataStorageChanged() override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodePredicateChanged() override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodeAdded(const mitk::DataNode *node) override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodeChanged(const mitk::DataNode *node) override; /* * @brief See 'QmitkAbstractDataStorageModel' */ void NodeRemoved(const mitk::DataNode *node) override; private: void UpdateByDataStorage(); using StatisticsContainerVector = std::vector; /* the function returns the statistic container and the time point indicated by the index. If the index is not valid result.first will point to a nullptr.*/ std::pair GetRelevantStatsticsByIndex(const QModelIndex &index) const; StatisticsContainerVector m_Statistics; /** Relevant images set by the user.*/ std::vector m_ImageNodes; /** Helper that is constructed when m_ImageNodes is set. It has the same order like m_ImageNodes, but each image is represented n times, while n is the number of time steps the respective image has. This structure makes the business logic to select the correct image given a QIndex much simpler and therfore easy to understand/maintaine. */ std::vector > m_TimeStepResolvedImageNodes; /** relevant masks set by the user.*/ std::vector m_MaskNodes; /** @sa m_TimeStepResolvedImageNodes */ std::vector> m_TimeStepResolvedMaskNodes; std::vector m_StatisticNames; ViewMode m_ViewMode = ViewMode::imageXStatistic; itk::SimpleFastMutexLock m_Mutex; }; #endif // mitkQmitkImageStatisticsTableModel_h diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.cpp index be83f69c06..931502fcd1 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.cpp +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.cpp @@ -1,72 +1,78 @@ /*=================================================================== 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 "QmitkImageStatisticsWidget.h" #include "QmitkTableModelToStringConverter.h" +#include "QmitkImageStatisticsTableModel.h" #include #include QmitkImageStatisticsWidget::QmitkImageStatisticsWidget(QWidget* parent) : QWidget(parent) { m_Controls.setupUi(this); m_imageStatisticsModel = new QmitkImageStatisticsTableModel(parent); - //temporarily disabled because 4D clipboard functionality is not implemented yet - m_Controls.checkBox4dCompleteTable->setVisible(false); CreateConnections(); m_ProxyModel = new QSortFilterProxyModel(this); m_Controls.tableViewStatistics->setModel(m_ProxyModel); m_ProxyModel->setSourceModel(m_imageStatisticsModel); + connect(m_imageStatisticsModel, &QmitkImageStatisticsTableModel::dataAvailable, this, &QmitkImageStatisticsWidget::OnDataAvailable); } void QmitkImageStatisticsWidget::SetDataStorage(mitk::DataStorage* newDataStorage) { m_imageStatisticsModel->SetDataStorage(newDataStorage); m_Controls.tableViewStatistics->resizeColumnsToContents(); // should call data in table model m_Controls.tableViewStatistics->resizeRowsToContents(); } void QmitkImageStatisticsWidget::SetImageNodes(const std::vector& nodes) { m_imageStatisticsModel->SetImageNodes(nodes); } void QmitkImageStatisticsWidget::SetMaskNodes(const std::vector& nodes) { m_imageStatisticsModel->SetMaskNodes(nodes); } void QmitkImageStatisticsWidget::Reset() { m_imageStatisticsModel->Clear(); + m_Controls.buttonCopyImageStatisticsToClipboard->setEnabled(false); } void QmitkImageStatisticsWidget::CreateConnections() { connect(m_Controls.buttonCopyImageStatisticsToClipboard, &QPushButton::clicked, this, &QmitkImageStatisticsWidget::OnClipboardButtonClicked); } +void QmitkImageStatisticsWidget::OnDataAvailable() +{ + m_Controls.buttonCopyImageStatisticsToClipboard->setEnabled(true); +} + void QmitkImageStatisticsWidget::OnClipboardButtonClicked() { QmitkTableModelToStringConverter converter; converter.SetTableModel(m_imageStatisticsModel); converter.SetIncludeHeaderData(true); converter.SetColumnDelimiter('\t'); QString clipboardAsString = converter.GetString(); QApplication::clipboard()->setText(clipboardAsString, QClipboard::Clipboard); } diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.h b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.h index bdd716c09b..94ed1387f8 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.h +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.h @@ -1,58 +1,57 @@ /*=================================================================== 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 QmitkImageStatisticsWidget_H__INCLUDED #define QmitkImageStatisticsWidget_H__INCLUDED -#include - #include #include -#include -class QSortFilterProxyModel; +#include +#include -//Qt -#include +class QSortFilterProxyModel; +class QmitkImageStatisticsTableModel; class MITKIMAGESTATISTICSUI_EXPORT QmitkImageStatisticsWidget : public QWidget { - Q_OBJECT + Q_OBJECT public: - QmitkImageStatisticsWidget(QWidget* parent = nullptr); + QmitkImageStatisticsWidget(QWidget *parent = nullptr); /**Documentation Set the data storage the model should fetch its statistic objects from. @pre data storage must be valid */ - void SetDataStorage(mitk::DataStorage* newDataStorage); + void SetDataStorage(mitk::DataStorage *newDataStorage); - void SetImageNodes(const std::vector& nodes); - void SetMaskNodes(const std::vector& nodes); + void SetImageNodes(const std::vector &nodes); + void SetMaskNodes(const std::vector &nodes); void Reset(); private: - void CreateConnections(); + void CreateConnections(); + void OnDataAvailable(); - /** \brief Saves the image statistics to the clipboard */ - void OnClipboardButtonClicked(); + /** \brief Saves the image statistics to the clipboard */ + void OnClipboardButtonClicked(); private: - Ui::QmitkImageStatisticsControls m_Controls; - QmitkImageStatisticsTableModel* m_imageStatisticsModel; - QSortFilterProxyModel* m_ProxyModel; + Ui::QmitkImageStatisticsControls m_Controls; + QmitkImageStatisticsTableModel *m_imageStatisticsModel; + QSortFilterProxyModel *m_ProxyModel; }; #endif // QmitkImageStatisticsWidget_H__INCLUDED diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.ui b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.ui index 2db3a52e73..7f0984bed8 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.ui +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsWidget.ui @@ -1,140 +1,114 @@ QmitkImageStatisticsControls 0 0 395 366 0 0 Form 2 2 2 2 0 0 0 150 QAbstractItemView::NoEditTriggers true false - + 0 0 0 0 0 false 0 0 Copy to Clipboard - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - false - - - copy complete table - - - Qt::Horizontal 40 20 diff --git a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp index 672bb2b976..995c3ce01e 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp @@ -1,414 +1,415 @@ /*=================================================================== 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 #include "mitkImageStatisticsContainerManager.h" 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); 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::ChartStyle 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::ChartStyle::darkstyle; } else { return QmitkChartWidget::ChartStyle::lightstyle; } } return QmitkChartWidget::ChartStyle::darkstyle; } void QmitkImageStatisticsReloadedView::OnImageSelectorChanged() { auto selectedImageNode = m_Controls.imageSelector->GetSelectedNode(); if (selectedImageNode != m_selectedImageNode) { m_selectedImageNode = selectedImageNode; if (m_selectedImageNode.IsNotNull()) { 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); m_Controls.maskImageSelector->SetZeroEntryText(""); 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->Reset(); } } } 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) { auto 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; } //statistics need to be computed if (!imageStatistics || imageStatisticsOlderThanInputs || m_ForceRecompute) { CalculateStatistics(image, mask.GetPointer(), maskPlanarFigure.GetPointer()); } //statistics already computed else { 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); } void QmitkImageStatisticsReloadedView::OnStatisticsCalculationEnds() { mitk::StatusBar::GetInstance()->Clear(); if (this->m_CalculationThread->GetStatisticsUpdateSuccessFlag()) { auto statistic = m_CalculationThread->GetStatisticsData(); mitk::PropertyRelations::RuleResultVectorType rulesForCurrentStatistic; auto statisticNonConst = statistic->Clone(); auto statisticsNodeName = m_selectedImageNode->GetName(); if (m_selectedMaskNode) { statisticsNodeName += "_" + m_selectedMaskNode->GetName(); } statisticsNodeName += "_statistics"; auto statisticsNode = mitk::CreateImageStatisticsNode(statisticNonConst, statisticsNodeName); auto imageRule = mitk::StatisticsToImageRelationRule::New(); imageRule->Connect(statisticNonConst.GetPointer(), m_CalculationThread->GetStatisticsImage().GetPointer()); rulesForCurrentStatistic.push_back(imageRule.GetPointer()); if (m_CalculationThread->GetMaskImage()) { auto maskRule = mitk::StatisticsToMaskRelationRule::New(); maskRule->Connect(statisticNonConst.GetPointer(), m_CalculationThread->GetMaskImage().GetPointer()); rulesForCurrentStatistic.push_back(maskRule.GetPointer()); } else if (m_CalculationThread->GetPlanarFigure()) { auto planarFigureRule = mitk::StatisticsToMaskRelationRule::New(); planarFigureRule->Connect(statisticNonConst.GetPointer(), m_CalculationThread->GetPlanarFigure().GetPointer()); rulesForCurrentStatistic.push_back(planarFigureRule.GetPointer()); } m_statisticContainerRules.push_back(rulesForCurrentStatistic); 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() { }