diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp index a4425ccfd1..8ece2a3416 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.cpp @@ -1,214 +1,208 @@ /*=================================================================== 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" QmitkImageStatisticsTableModel::QmitkImageStatisticsTableModel(QObject *parent) : QAbstractTableModel(parent) {} 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) { - int count = 0; - - for (const auto& node : m_ImageNodes) - { - auto image = node->GetData(); - if (image) - { - count += static_cast(image->GetTimeSteps()); - } - - } - return count; + return static_cast(m_TimeStepResolvedImageNodes.size()); } else { mitkThrow() << "View mode ImageXMask is not implemented yet"; } } -const mitk::ImageStatisticsContainer::StatisticsObject* QmitkImageStatisticsTableModel::GetRelevantStatsticObjectByIndex(const QModelIndex &index) const +std::pair QmitkImageStatisticsTableModel::GetRelevantStatsticsByIndex(const QModelIndex &index) const { + auto result = std::make_pair(nullptr, 0); + if (m_ViewMode == ViewMode::imageXStatistic) { - //pick right image - int offset = 0; - const mitk::BaseData* selectedImage = nullptr; - - for (const auto& node : m_ImageNodes) + if (index.column() < static_cast(m_TimeStepResolvedImageNodes.size())) { - selectedImage = node->GetData(); - int timeStepCount = 0; - if (selectedImage) - { - timeStepCount = static_cast(selectedImage->GetTimeSteps()); - } + auto selectedImage = m_TimeStepResolvedImageNodes.at(static_cast(index.column())); - if (offset + timeStepCount <= index.column()) + //get the right statistic + auto rule = mitk::StatisticsToImageRelationRule::New(); + for (mitk::ImageStatisticsContainer::ConstPointer container : m_Statistics) { - offset += timeStepCount; - } - else - { - auto timeStepIndex = index.column() - offset; - - //get the right statistic - auto rule = mitk::StatisticsToImageRelationRule::New(); - for (const auto& container : m_Statistics) + if (rule->HasRelation(container, selectedImage.first) >= mitk::PropertyRelationRuleBase::RelationType::Connected_Data) { - if (rule->HasRelation(container, selectedImage) >= mitk::PropertyRelationRuleBase::RelationType::Connected_Data) - { - return &(container->GetStatisticsForTimeStep(timeStepIndex)); - } + return std::make_pair(container, selectedImage.second); } - }; + } } - - return nullptr; } 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 statsObj = GetRelevantStatsticObjectByIndex(index); + auto containerInfo = GetRelevantStatsticsByIndex(index); - if (statsObj && index.row() < rowCount(QModelIndex())) + 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)) + if (statsObj.HasStatistic(statisticKey)) { - ss << statsObj->GetValueNonConverted(statisticKey); + ss << statsObj.GetValueNonConverted(statisticKey); } else { ss << "N/A"; } - std::string statisticsValue = ss.str(); - result = QVariant(QString::fromStdString(statisticsValue)); + result = QVariant(QString::fromStdString(ss.str())); } else if (Qt::UserRole == role) { result = QVariant(index.row()); } } } return result; } 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_ImageNodes.empty()) { + if (!m_TimeStepResolvedImageNodes.empty()) { if (m_ViewMode == ViewMode::imageXStatistic) { - std::string maskName; + std::stringstream ss; + auto imageInfo = m_TimeStepResolvedImageNodes[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()) { - maskName = " / " + m_MaskNodes.at(section)->GetName(); + ss << " / " << m_MaskNodes.at(section)->GetName(); } - return QVariant((m_ImageNodes.at(section)->GetName() + maskName + std::to_string(section)).c_str()); + 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::SetStatistics(StatisticsContainerVector statistics) { emit beginResetModel(); m_Statistics = statistics; m_StatisticNames = mitk::GetAllStatisticNames(statistics); emit endResetModel(); } 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; emit endResetModel(); } void QmitkImageStatisticsTableModel::SetMaskNodes(const std::vector& nodes) { emit beginResetModel(); m_MaskNodes = nodes; 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(); } diff --git a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h index e593eb84ac..7b1438d1a7 100644 --- a/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h +++ b/Modules/ImageStatisticsUI/Qmitk/QmitkImageStatisticsTableModel.h @@ -1,70 +1,80 @@ /*=================================================================== 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 //MITK #include #include "mitkImageStatisticsContainer.h" #include "mitkDataNode.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 QAbstractTableModel { Q_OBJECT public: enum class ViewMode { imageXStatistic, imageXMask }; using StatisticsContainerVector = std::vector; QmitkImageStatisticsTableModel(QObject *parent = nullptr); virtual ~QmitkImageStatisticsTableModel() {}; void SetStatistics(StatisticsContainerVector statistics); 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; private: - const mitk::ImageStatisticsContainer::StatisticsObject* GetRelevantStatsticObjectByIndex(const QModelIndex &index) const; + /* 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; std::vector m_StatisticNames; ViewMode m_ViewMode = ViewMode::imageXStatistic; }; #endif // mitkQmitkImageStatisticsTableModel_h 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 849ebb56fd..d2cc6fc09f 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.cpp @@ -1,424 +1,424 @@ /*=================================================================== 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 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); m_statisticsManager = mitk::ImageStatisticsContainerManager::New(); m_statisticsManager->SetDataStorage(this->GetDataStorage().GetPointer()); PrepareDataStorageComboBoxes(); 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 = m_statisticsManager->GetImageStatistics(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::FillStatisticsWidget(mitk::ImageStatisticsContainer::ConstPointer statistics) +void QmitkImageStatisticsReloadedView::FillStatisticsWidget(std::vector statistics) { m_Controls.widget_statistics->Reset(); m_Controls.widget_statistics->SetStatistics(statistics); m_Controls.widget_statistics->SetImageNodes({ m_selectedImageNode }); if (m_selectedMaskNode) { m_Controls.widget_statistics->SetMaskNodes({ m_selectedMaskNode }); } m_Controls.widget_statistics->setEnabled(true); } 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) { auto isPlanarFigurePredicate = mitk::GetImageStatisticsPlanarFigurePredicate(); auto isMaskPredicate = mitk::GetImageStatisticsMaskPredicate(); auto hasSameGeometry = mitk::NodePredicateGeometry::New(selectedImageNode->GetData()->GetGeometry()); hasSameGeometry->SetCheckPrecision(1e-10); auto isMaskWithGeometryPredicate = mitk::NodePredicateAnd::New(isMaskPredicate, hasSameGeometry); auto isMaskOrPlanarFigureWithGeometryPredicate = mitk::NodePredicateOr::New(isPlanarFigurePredicate, isMaskWithGeometryPredicate); m_Controls.maskImageSelector->SetPredicate(isMaskOrPlanarFigureWithGeometryPredicate); m_Controls.maskImageSelector->SetZeroEntryText(""); CalculateOrGetStatistics(); } } void QmitkImageStatisticsReloadedView::OnMaskSelectorChanged() { CalculateOrGetStatistics(); } void QmitkImageStatisticsReloadedView::CalculateOrGetStatistics() { if (this->m_selectedPlanarFigure) { this->m_selectedPlanarFigure->RemoveObserver(this->m_PlanarFigureObserverTag); this->m_selectedPlanarFigure = nullptr; } m_selectedImageNode = m_Controls.imageSelector->GetSelectedNode(); m_selectedMaskNode = m_Controls.maskImageSelector->GetSelectedNode(); m_Controls.groupBox_intensityProfile->setVisible(false); 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()); } } if (mask) { auto imageStatistics = m_statisticsManager->GetImageStatistics(image, mask.GetPointer()); bool imageStatisticsOlderThanInputs = false; if (imageStatistics && (imageStatistics->GetMTime() < image->GetMTime() || imageStatistics->GetMTime() < mask->GetMTime())) { imageStatisticsOlderThanInputs = true; } //compute statistics with given mask if (!imageStatistics || imageStatisticsOlderThanInputs || m_ForceRecompute) { CalculateStatistics(image, mask.GetPointer()); } //statistics already computed else { this->FillStatisticsWidget({ imageStatistics }); if (imageStatistics->TimeStepExists(0)) { this->FillHistogramWidget({ imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer() }, { m_selectedImageNode->GetName() }); } } } 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()) { //compute line profile and display statistics for voxels on line 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()); } auto imageStatistics = m_statisticsManager->GetImageStatistics(image, maskPlanarFigure.GetPointer()); bool imageStatisticsOlderThanInputs = false; if (imageStatistics && (imageStatistics->GetMTime() < image->GetMTime() || imageStatistics->GetMTime() < maskPlanarFigure->GetMTime())) { imageStatisticsOlderThanInputs = true; } //for all planar figures: compute statistics with planarFigure as mask if (!imageStatistics || imageStatisticsOlderThanInputs || m_ForceRecompute) { CalculateStatistics(image, nullptr, maskPlanarFigure.GetPointer()); } //statistics already computed else { this->FillStatisticsWidget({ imageStatistics }); if (maskPlanarFigure->IsClosed()) { if (imageStatistics->TimeStepExists(0)) { this->FillHistogramWidget({ imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer() }, { m_selectedImageNode->GetName() }); } } } } else { auto imageStatistics = m_statisticsManager->GetImageStatistics(image); bool imageStatisticsOlderThanInputs = false; if (imageStatistics && (imageStatistics->GetMTime() < image->GetMTime())) { imageStatisticsOlderThanInputs = true; } //compute statistics with image only if (!imageStatistics || imageStatisticsOlderThanInputs || m_ForceRecompute) { CalculateStatistics(image); } //statistics already computed else { this->FillStatisticsWidget({ imageStatistics }); if (imageStatistics->TimeStepExists(0)) { this->FillHistogramWidget({ imageStatistics->GetStatisticsForTimeStep(0).m_Histogram.GetPointer() }, { m_selectedImageNode->GetName() }); } } } } else { ResetGUI(); } m_ForceRecompute = false; } 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); m_statisticsManager->SetRules(m_statisticContainerRules); - this->FillStatisticsWidget(statistic); + this->FillStatisticsWidget({ statistic }); 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.widget_statistics->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() { m_selectedImageNode = m_Controls.imageSelector->GetSelectedNode(); if (m_selectedImageNode) { CalculateOrGetStatistics(); } else { ResetGUI(); } } 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 index 190a11dd4c..1030ce11ce 100644 --- a/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.h +++ b/Plugins/org.mitk.gui.qt.measurementtoolbox/src/internal/QmitkImageStatisticsReloadedView.h @@ -1,113 +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 QmitkImageStatisticsReloadedView_H__INCLUDED #define QmitkImageStatisticsReloadedView_H__INCLUDED #include "ui_QmitkImageStatisticsReloadedViewControls.h" // Qmitk includes #include #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 FillStatisticsWidget(mitk::ImageStatisticsContainer::ConstPointer statistics); + void FillStatisticsWidget(std::vector statistics); void FillHistogramWidget(const std::vector& histogram, const std::vector& dataLabels); QmitkChartWidget::ChartStyle 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 ResetGUI(); 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; std::vector m_statisticContainerRules; mitk::PlanarFigure::Pointer m_selectedPlanarFigure=nullptr; mitk::ImageStatisticsContainerManager::Pointer m_statisticsManager; long m_PlanarFigureObserverTag; bool m_ForceRecompute = false; }; #endif // QmitkImageStatisticsView_H__INCLUDED