diff --git a/Modules/SemanticRelations/CMakeLists.txt b/Modules/SemanticRelations/CMakeLists.txt index 72db95214f..aa6819b240 100644 --- a/Modules/SemanticRelations/CMakeLists.txt +++ b/Modules/SemanticRelations/CMakeLists.txt @@ -1,7 +1,7 @@ MITK_CREATE_MODULE( - DEPENDS MitkSceneSerializationBase MitkDICOMReader MitkMultilabel MitkPersistence + DEPENDS MitkSceneSerializationBase MitkDICOMReader MitkMultilabel MitkPersistence MitkImageStatisticsUI ) if(BUILD_TESTING) ADD_SUBDIRECTORY(Test) endif(BUILD_TESTING) diff --git a/Modules/SemanticRelations/files.cmake b/Modules/SemanticRelations/files.cmake index 9b653f4f14..b5e1bddd7a 100644 --- a/Modules/SemanticRelations/files.cmake +++ b/Modules/SemanticRelations/files.cmake @@ -1,15 +1,14 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkControlPointManager.cpp mitkDICOMHelper.cpp mitkLesionData.cpp mitkLesionManager.cpp mitkNodePredicates.cpp mitkRelationStorage.cpp mitkSemanticRelationsDataStorageAccess.cpp mitkSemanticRelationsInference.cpp mitkSemanticRelationsIntegration.cpp - mitkStatisticsCalculator.cpp mitkUIDGeneratorBoost.cpp ) diff --git a/Modules/SemanticRelations/include/mitkStatisticsCalculator.h b/Modules/SemanticRelations/include/mitkStatisticsCalculator.h deleted file mode 100644 index 7dedd1926d..0000000000 --- a/Modules/SemanticRelations/include/mitkStatisticsCalculator.h +++ /dev/null @@ -1,59 +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 MITKSTATISTICSCALCULATOR_H -#define MITKSTATISTICSCALCULATOR_H - -#include - -// mitk core -#include -#include - -// itk -#include - -/* -* @brief Provides helper functions that are needed to work with lesions. -* -* These functions help to generate new lesions, check for existing lesions or provide functionality -* to find existing lesion class types. -*/ -namespace mitk -{ - class MITKSEMANTICRELATIONS_EXPORT StatisticsCalculator - { - - public: - - double GetSegmentationMaskVolume(mitk::DataNode::Pointer segmentationNode); - - private: - - template - void InternalGetSegmentationMaskVolume(typename itk::Image * segmentation); - - template - double GetVoxelVolume(typename itk::Image* image) const; - - Image::Pointer m_Segmentation; - double m_MaskVolume; - - }; - -} // namespace mitk - -#endif // MITKSTATISTICSCALCULATOR_H diff --git a/Modules/SemanticRelations/src/mitkStatisticsCalculator.cpp b/Modules/SemanticRelations/src/mitkStatisticsCalculator.cpp deleted file mode 100644 index b3368e00bf..0000000000 --- a/Modules/SemanticRelations/src/mitkStatisticsCalculator.cpp +++ /dev/null @@ -1,61 +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. - -===================================================================*/ - -// semantic relations module -#include "mitkStatisticsCalculator.h" - -// mitk core module -#include - -double mitk::StatisticsCalculator::GetSegmentationMaskVolume(mitk::DataNode::Pointer segmentationNode) -{ - m_MaskVolume = 0.0; - if (segmentationNode.IsNull()) - { - return m_MaskVolume; - } - - m_Segmentation = dynamic_cast(segmentationNode->GetData()); - if (nullptr == m_Segmentation) - { - return m_MaskVolume; - } - - AccessByItk(m_Segmentation, InternalGetSegmentationMaskVolume); - - return m_MaskVolume; -} - -template -void mitk::StatisticsCalculator::InternalGetSegmentationMaskVolume(typename itk::Image * segmentation) -{ - // simple statistics for the beginning - auto voxelVolume = GetVoxelVolume(segmentation); - auto numberOfPixels = m_Segmentation->GetLargestPossibleRegion().GetNumberOfPixels(); - m_MaskVolume = static_cast(numberOfPixels) * voxelVolume; -} - -template -double mitk::StatisticsCalculator::GetVoxelVolume(typename itk::Image * segmentation) const -{ - auto spacing = segmentation->GetSpacing(); - double voxelVolume = 1.0; - for (unsigned int i = 0; i < segmentation->GetImageDimension(); ++i) - { - voxelVolume *= spacing[i]; - } - return voxelVolume; -} diff --git a/Modules/SemanticRelationsUI/files.cmake b/Modules/SemanticRelationsUI/files.cmake index 9540adc6af..a10162f616 100644 --- a/Modules/SemanticRelationsUI/files.cmake +++ b/Modules/SemanticRelationsUI/files.cmake @@ -1,34 +1,36 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkModuleActivator.cpp QmitkAbstractSemanticRelationsStorageInspector.cpp QmitkAbstractSemanticRelationsStorageModel.cpp QmitkControlPointDialog.cpp QmitkLesionTextDialog.cpp QmitkLesionTreeItem.cpp QmitkLesionTreeModel.cpp QmitkPatientTableHeaderView.cpp QmitkPatientTableInspector.cpp QmitkPatientTableModel.cpp QmitkSemanticRelationsUIHelper.cpp + QmitkStatisticsCalculator.cpp QmitkStatisticsTreeModel.cpp QmitkTableItemThumbnailDelegate.cpp ) set(MOC_H_FILES include/QmitkAbstractSemanticRelationsStorageInspector.h include/QmitkAbstractSemanticRelationsStorageModel.h include/QmitkControlPointDialog.h include/QmitkLesionTextDialog.h include/QmitkLesionTreeModel.h include/QmitkPatientTableHeaderView.h include/QmitkPatientTableInspector.h include/QmitkPatientTableModel.h + include/QmitkStatisticsCalculator.h include/QmitkStatisticsTreeModel.h include/QmitkTableItemThumbnailDelegate.h ) set(UI_FILES src/QmitkPatientTableInspector.ui ) diff --git a/Modules/SemanticRelationsUI/include/QmitkStatisticsCalculator.h b/Modules/SemanticRelationsUI/include/QmitkStatisticsCalculator.h new file mode 100644 index 0000000000..47e08b453d --- /dev/null +++ b/Modules/SemanticRelationsUI/include/QmitkStatisticsCalculator.h @@ -0,0 +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. + +===================================================================*/ + +#ifndef QMITKSTATISTICSCALCULATOR_H +#define QMITKSTATISTICSCALCULATOR_H + +// mitk semantic relations UI +#include "MitkSemanticRelationsUIExports.h" + +// mitk semantic relations module +#include +#include + +// mitk core +#include +#include +#include + +// mitk image statistics ui module +#include + +// itk +#include + +/* +* @brief +*/ +class MITKSEMANTICRELATIONSUI_EXPORT QmitkStatisticsCalculator : public QObject +{ + Q_OBJECT + +public: + + QmitkStatisticsCalculator(); + ~QmitkStatisticsCalculator(); + + void SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } + /** + * @brief Compute and store lesion volume for all available control points and information types. + * + * @param lesionData The lesion data that holds the lesion and will hold the additional lesion data. + * @param caseID The current case ID. + */ + void ComputeLesionVolume(mitk::LesionData& lesionData, const mitk::SemanticTypes::CaseID& caseID); + +private: + + /** + * @brief + * + * + */ + double GetSegmentationMaskVolume(mitk::DataNode::Pointer imageNode, mitk::DataNode::Pointer segmentationNode); + + void OnStatisticsCalculationEnds(); + + QmitkImageStatisticsCalculationJob * m_CalculationJob; + mitk::WeakPointer m_DataStorage; + mitk::DataNode::Pointer m_ImageNode; + mitk::DataNode::Pointer m_SegmentationNode; + double m_MaskVolume; + +}; + +#endif // QMITKSTATISTICSCALCULATOR_H diff --git a/Modules/SemanticRelationsUI/include/QmitkStatisticsTreeModel.h b/Modules/SemanticRelationsUI/include/QmitkStatisticsTreeModel.h index cf09422fe5..c1cc85c3e0 100644 --- a/Modules/SemanticRelationsUI/include/QmitkStatisticsTreeModel.h +++ b/Modules/SemanticRelationsUI/include/QmitkStatisticsTreeModel.h @@ -1,81 +1,84 @@ /*=================================================================== 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 QMITKSTATISTICSTREEMODEL_H #define QMITKSTATISTICSTREEMODEL_H // mitk semantic relations UI #include "MitkSemanticRelationsUIExports.h" #include "QmitkAbstractSemanticRelationsStorageModel.h" #include "QmitkLesionTreeItem.h" +#include /* * @brief */ class MITKSEMANTICRELATIONSUI_EXPORT QmitkStatisticsTreeModel : public QmitkAbstractSemanticRelationsStorageModel { Q_OBJECT public: /** * @brief Initialize the root item of the model. The root item does not have a parent item. */ QmitkStatisticsTreeModel(QObject* parent = nullptr); ////////////////////////////////////////////////////////////////////////// // overridden virtual functions from QAbstractItemModel ////////////////////////////////////////////////////////////////////////// virtual QModelIndex index(int row, int column, const QModelIndex& itemIndex = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex& itemIndex) const override; virtual int rowCount(const QModelIndex& itemIndex = QModelIndex()) const override; virtual int columnCount(const QModelIndex& itemIndex = QModelIndex()) const override; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; ////////////////////////////////////////////////////////////////////////// // end override ////////////////////////////////////////////////////////////////////////// protected: - // the following functions have to be overridden but are not implemented in this model + virtual void DataStorageChanged() override; virtual void NodePredicateChanged() override { } - virtual void NodeAdded(const mitk::DataNode*) override { } - virtual void NodeChanged(const mitk::DataNode*) override { } - virtual void NodeRemoved(const mitk::DataNode*) override { } + virtual void NodeAdded(const mitk::DataNode*) override; + virtual void NodeChanged(const mitk::DataNode*) override; + virtual void NodeRemoved(const mitk::DataNode*) override; /** * @brief Overridden from 'QmitkAbstractSemanticRelationsStorageModel': This function retrieves all control points * of the current case and stores them to define the header of the tree. * Furthermore all lesions are retrieved and the lesion data is stored and show in the tree view. */ virtual void SetData() override; private: void SetLesionData(); void AddLesion(const mitk::SemanticTypes::Lesion& lesion); QmitkLesionTreeItem* GetItemByIndex(const QModelIndex& index) const; + std::unique_ptr m_StatisticsCalculator; + std::shared_ptr m_RootItem; mitk::SemanticTypes::ControlPointVector m_ControlPoints; mitk::SemanticTypes::InformationTypeVector m_InformationTypes; mitk::SemanticTypes::LesionVector m_CurrentLesions; }; #endif // QMITKSTATISTICSTREEMODEL_H diff --git a/Modules/SemanticRelationsUI/src/QmitkStatisticsCalculator.cpp b/Modules/SemanticRelationsUI/src/QmitkStatisticsCalculator.cpp new file mode 100644 index 0000000000..f646341ec6 --- /dev/null +++ b/Modules/SemanticRelationsUI/src/QmitkStatisticsCalculator.cpp @@ -0,0 +1,240 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// semantic relations UI module +#include "QmitkStatisticsCalculator.h" + +// semantic relations module +#include +#include +#include +#include +#include + +// mitk core module +#include + +// mitk image statistics module +#include +#include +#include +#include + +QmitkStatisticsCalculator::QmitkStatisticsCalculator() + : m_CalculationJob(nullptr) + , m_DataStorage(nullptr) + , m_MaskVolume(0.0) +{ + m_CalculationJob = new QmitkImageStatisticsCalculationJob(); + + connect(m_CalculationJob, &QmitkImageStatisticsCalculationJob::finished, this, + &QmitkStatisticsCalculator::OnStatisticsCalculationEnds, Qt::QueuedConnection); +} + +QmitkStatisticsCalculator::~QmitkStatisticsCalculator() +{ + if (!m_CalculationJob->isFinished()) + { + m_CalculationJob->terminate(); + m_CalculationJob->wait(); + } + m_CalculationJob->deleteLater(); +} + +void QmitkStatisticsCalculator::ComputeLesionVolume(mitk::LesionData& lesionData, const mitk::SemanticTypes::CaseID& caseID) +{ + if (m_DataStorage.IsExpired()) + { + return; + } + + auto dataStorage = m_DataStorage.Lock(); + + std::vector lesionVolume; + mitk::SemanticTypes::Lesion lesion = lesionData.GetLesion(); + double volume = 0.0; + + mitk::SemanticTypes::ControlPointVector controlPoints = mitk::RelationStorage::GetAllControlPointsOfCase(caseID); + // sort the vector of control points for the timeline + std::sort(controlPoints.begin(), controlPoints.end()); + mitk::SemanticTypes::InformationTypeVector informationTypes = mitk::RelationStorage::GetAllInformationTypesOfCase(caseID); + for (const auto& informationType : informationTypes) + { + for (const auto& controlPoint : controlPoints) + { + mitk::SemanticRelationsDataStorageAccess semanticRelationsDataStorageAccess(dataStorage); + mitk::DataNode::Pointer specificImage; + mitk::DataNode::Pointer specificSegmentation; + try + { + specificSegmentation = semanticRelationsDataStorageAccess.GetSpecificSegmentation(caseID, controlPoint, informationType, lesion); + if (nullptr == specificSegmentation) + { + volume = 0.0; + } + else + { + // get parent node of the specific segmentation node with the node predicate + auto parentNodes = dataStorage->GetSources(specificSegmentation, mitk::NodePredicates::GetImagePredicate(), false); + for (auto it = parentNodes->Begin(); it != parentNodes->End(); ++it) + { + specificImage = it->Value(); + } + + volume = GetSegmentationMaskVolume(specificImage, specificSegmentation); + } + } + catch (mitk::SemanticRelationException&) + { + volume = 0.0; + } + + lesionVolume.push_back(volume); + } + } + + lesionData.SetLesionVolume(lesionVolume); +} + +double QmitkStatisticsCalculator::GetSegmentationMaskVolume(mitk::DataNode::Pointer imageNode, mitk::DataNode::Pointer segmentationNode) +{ + m_MaskVolume = 0.0; + + if (m_DataStorage.IsExpired()) + { + return m_MaskVolume; + } + + auto dataStorage = m_DataStorage.Lock(); + + if (imageNode.IsNull() || segmentationNode.IsNull()) + { + return m_MaskVolume; + } + + m_ImageNode = imageNode; + m_SegmentationNode = segmentationNode; + + auto image = dynamic_cast(m_ImageNode->GetData()); + auto segmentation = dynamic_cast(m_SegmentationNode->GetData()); + if (nullptr == image || nullptr == segmentation) + { + return m_MaskVolume; + } + + // all nodes and images are valid, retrieve statistics + mitk::ImageStatisticsContainer::ConstPointer imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics(dataStorage, image, segmentation); + + bool imageStatisticsOlderThanInputs = false; + if (imageStatistics && (imageStatistics->GetMTime() < image->GetMTime() || (imageStatistics->GetMTime() < segmentation->GetMTime()))) + { + imageStatisticsOlderThanInputs = true; + } + // statistics need to be (re)computed + if (!imageStatistics || imageStatisticsOlderThanInputs) + { + m_CalculationJob->Initialize(image, segmentation, nullptr); + try + { + m_CalculationJob->start(); + return m_MaskVolume; + } + catch (const std::exception&) + { + return m_MaskVolume; + } + } + + // use a valid statistics object to get the volume of the image-segmentation pair + mitk::ImageStatisticsContainer::ImageStatisticsObject statisticsObject; + try + { + statisticsObject = imageStatistics->GetStatisticsForTimeStep(0); + } + catch (mitk::Exception&) + { + return m_MaskVolume; + } + try + { + if (statisticsObject.HasStatistic(mitk::ImageStatisticsConstants::VOLUME())) + { + auto valueVariant = statisticsObject.GetValueNonConverted(mitk::ImageStatisticsConstants::VOLUME()); + m_MaskVolume = boost::get(valueVariant); + } + } + catch (mitk::Exception&) + { + return m_MaskVolume; + } + + return m_MaskVolume; +} + +void QmitkStatisticsCalculator::OnStatisticsCalculationEnds() +{ + // taken from 'QmitkImageStatisticsView' (see measurementtoolbox plugin) + if (m_DataStorage.IsExpired()) + { + return; + } + + auto dataStorage = m_DataStorage.Lock(); + + if (m_CalculationJob->GetStatisticsUpdateSuccessFlag()) + { + auto statistic = m_CalculationJob->GetStatisticsData(); + auto image = m_CalculationJob->GetStatisticsImage(); + mitk::BaseData::ConstPointer mask = nullptr; + auto imageRule = mitk::StatisticsToImageRelationRule::New(); + imageRule->Connect(statistic, image); + + if (m_CalculationJob->GetMaskImage()) + { + auto maskRule = mitk::StatisticsToMaskRelationRule::New(); + mask = m_CalculationJob->GetMaskImage(); + maskRule->Connect(statistic, mask); + } + + auto imageStatistics = mitk::ImageStatisticsContainerManager::GetImageStatistics(dataStorage, image, mask); + + // if statistics base data already exist: add to existing node + if (nullptr != imageStatistics) + { + auto allDataNodes = dataStorage->GetAll()->CastToSTLConstContainer(); + for (auto node : allDataNodes) + { + auto nodeData = node->GetData(); + if (nullptr != nodeData && nodeData->GetUID() == imageStatistics->GetUID()) + { + node->SetData(statistic); + } + } + } + // statistics base data does not exist: add new node + else + { + auto statisticsNodeName = m_ImageNode->GetName(); + if (m_SegmentationNode) + { + statisticsNodeName += "_" + m_SegmentationNode->GetName(); + } + statisticsNodeName += "_statistics"; + auto statisticsNode = mitk::CreateImageStatisticsNode(statistic, statisticsNodeName); + dataStorage->Add(statisticsNode); + } + } +} diff --git a/Modules/SemanticRelationsUI/src/QmitkStatisticsTreeModel.cpp b/Modules/SemanticRelationsUI/src/QmitkStatisticsTreeModel.cpp index 3f17e7031c..7157668873 100644 --- a/Modules/SemanticRelationsUI/src/QmitkStatisticsTreeModel.cpp +++ b/Modules/SemanticRelationsUI/src/QmitkStatisticsTreeModel.cpp @@ -1,240 +1,272 @@ /*=================================================================== 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. ===================================================================*/ // semantic relations UI module #include "QmitkStatisticsTreeModel.h" // semantic relations module #include #include #include #include #include QmitkStatisticsTreeModel::QmitkStatisticsTreeModel(QObject* parent/* = nullptr*/) : QmitkAbstractSemanticRelationsStorageModel(parent) , m_RootItem(std::make_shared(mitk::LesionData())) { - // nothing here + m_StatisticsCalculator = std::make_unique(); } ////////////////////////////////////////////////////////////////////////// // overridden virtual functions from QAbstractItemModel ////////////////////////////////////////////////////////////////////////// QModelIndex QmitkStatisticsTreeModel::index(int row, int column, const QModelIndex& itemIndex) const { if (!hasIndex(row, column, itemIndex)) { return QModelIndex(); } auto childItem = GetItemByIndex(itemIndex)->GetChildInRow(row); if (nullptr == childItem) { return QModelIndex(); } return createIndex(row, column, childItem.get()); } QModelIndex QmitkStatisticsTreeModel::parent(const QModelIndex& itemIndex) const { if (!itemIndex.isValid()) { return QModelIndex(); } auto parentItemWeakPtr = GetItemByIndex(itemIndex)->GetParent(); if (parentItemWeakPtr.expired()) { return QModelIndex(); } auto parentItem = parentItemWeakPtr.lock(); if (parentItem == m_RootItem) { return QModelIndex(); } return createIndex(parentItem->GetRow(), 0, parentItem.get()); } int QmitkStatisticsTreeModel::rowCount(const QModelIndex& itemIndex/* = QModelIndex()*/) const { return GetItemByIndex(itemIndex)->ChildCount(); } int QmitkStatisticsTreeModel::columnCount(const QModelIndex&/* itemIndex = QModelIndex() */) const { if (0 == m_RootItem->ChildCount()) { // no lesion items stored, no need to display columns return 0; } return m_ControlPoints.size() + 1; } QVariant QmitkStatisticsTreeModel::data(const QModelIndex& index, int role) const { if (!index.isValid()) { return QVariant(); } if (index.column() < 0 || index.column() > static_cast(m_ControlPoints.size())) { return QVariant(); } QmitkLesionTreeItem* currentItem = GetItemByIndex(index); if (Qt::DisplayRole == role) { if (currentItem->GetParent().expired()) { return QVariant(); } auto parentItem = currentItem->GetParent().lock(); // parent exists and is the root item -> top level item if (m_RootItem == parentItem) { // display role fills the first columns with the lesion UID / name if (0 == index.column()) { std::string itemString = currentItem->GetData().GetLesionName(); if (itemString.empty()) { itemString = currentItem->GetData().GetLesionUID(); } return QString::fromStdString(itemString); } } // parent is not the root item -> volume item else { // display role fills the first columns with the information type if (0 == index.column()) { if (index.row() < static_cast(m_InformationTypes.size())) { return QString::fromStdString(m_InformationTypes.at(index.row())); } return "No information type"; } else { // display role fills other columns with the lesion volume info const auto lesionVolume = currentItem->GetData().GetLesionVolume(); if ((index.column() - 1) * index.row() < static_cast(lesionVolume.size())) { return QVariant(lesionVolume.at(index.row()*m_ControlPoints.size() + (index.column() - 1))); } return "No lesion volume"; } } } return QVariant(); } QVariant QmitkStatisticsTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { if (0 == m_RootItem->ChildCount()) { // no lesion items stored, no need to display the header return QVariant(); } if (Qt::Horizontal == orientation && Qt::DisplayRole == role) { if (0 == section) { return QVariant("Lesion"); } if (static_cast(m_ControlPoints.size()) >= section) { mitk::SemanticTypes::ControlPoint currentControlPoint = m_ControlPoints.at(section-1); return QVariant(QString::fromStdString(currentControlPoint.ToString())); } } return QVariant(); } +void QmitkStatisticsTreeModel::DataStorageChanged() +{ + if (!m_DataStorage.IsExpired()) + { + auto dataStorage = m_DataStorage.Lock(); + m_SemanticRelationsDataStorageAccess = std::make_unique(dataStorage); + m_StatisticsCalculator->SetDataStorage(dataStorage); + UpdateModelData(); + } +} + +void QmitkStatisticsTreeModel::NodeRemoved(const mitk::DataNode*) +{ + emit beginResetModel(); + UpdateModelData(); + emit endResetModel(); +} + +void QmitkStatisticsTreeModel::NodeAdded(const mitk::DataNode*) +{ + emit beginResetModel(); + UpdateModelData(); + emit endResetModel(); +} + +void QmitkStatisticsTreeModel::NodeChanged(const mitk::DataNode*) +{ + emit beginResetModel(); + UpdateModelData(); + emit endResetModel(); +} + void QmitkStatisticsTreeModel::SetData() { m_RootItem = std::make_shared(mitk::LesionData()); // get all control points of current case m_ControlPoints = mitk::RelationStorage::GetAllControlPointsOfCase(m_CaseID); // sort the vector of control points for the timeline std::sort(m_ControlPoints.begin(), m_ControlPoints.end()); // get all information types points of current case m_InformationTypes = mitk::RelationStorage::GetAllInformationTypesOfCase(m_CaseID); SetLesionData(); } void QmitkStatisticsTreeModel::SetLesionData() { m_CurrentLesions = mitk::RelationStorage::GetAllLesionsOfCase(m_CaseID); for (auto& lesion : m_CurrentLesions) { AddLesion(lesion); } } void QmitkStatisticsTreeModel::AddLesion(const mitk::SemanticTypes::Lesion& lesion) { if (m_DataStorage.IsExpired()) { return; } auto dataStorage = m_DataStorage.Lock(); // create new lesion tree item data and modify it according to the control point data mitk::LesionData lesionData(lesion); - mitk::GenerateAdditionalLesionData(dataStorage, lesionData, m_CaseID); + m_StatisticsCalculator->ComputeLesionVolume(lesionData, m_CaseID); // add the 1. level lesion item to the root item std::shared_ptr newLesionTreeItem = std::make_shared(lesionData); m_RootItem->AddChild(newLesionTreeItem); auto informationTypeSize = m_InformationTypes.size(); for (int i = 0; i < informationTypeSize; ++i) { std::shared_ptr volumeItem = std::make_shared(lesionData); newLesionTreeItem->AddChild(volumeItem); } } QmitkLesionTreeItem* QmitkStatisticsTreeModel::GetItemByIndex(const QModelIndex& index) const { if (index.isValid()) { auto item = static_cast(index.internalPointer()); if (nullptr != item) { return item; } } return m_RootItem.get(); }