diff --git a/Modules/SemanticRelations/files.cmake b/Modules/SemanticRelations/files.cmake index b5e1bddd7a..9b653f4f14 100644 --- a/Modules/SemanticRelations/files.cmake +++ b/Modules/SemanticRelations/files.cmake @@ -1,14 +1,15 @@ 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/mitkLesionManager.h b/Modules/SemanticRelations/include/mitkLesionManager.h index 790382bc0e..3192999b87 100644 --- a/Modules/SemanticRelations/include/mitkLesionManager.h +++ b/Modules/SemanticRelations/include/mitkLesionManager.h @@ -1,78 +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 MITKLESIONMANAGER_H #define MITKLESIONMANAGER_H #include // semantic relations module #include "mitkSemanticTypes.h" #include "mitkLesionData.h" // mitk core -#include +#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 { typedef std::vector LesionClassVector; /** * @brief Generate a new lesion and lesion class with UIDs and the given string as lesion class type. * * @param lesionClassType The lesion class type as string. Default parameter is "". */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::Lesion GenerateNewLesion(const std::string& lesionClassType = ""); /** * @brief Generate a new lesion class with UID and the given string as lesion class type. * * @param lesionClassType The lesion class type as string. Default parameter is "". */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionClass GenerateNewLesionClass(const std::string& lesionClassType = ""); /** * @brief Find and return a whole lesion including its lesion class given a specific lesion UID. * * @param lesionUID The lesion UID as string. * @param allLesions All currently known lesions of a specific case. * * @return The lesion with its UID and the lesion class. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::Lesion GetLesionByUID(const SemanticTypes::ID& lesionUID, const std::vector& allLesions); /** * @brief Find and return the whole lesion class including its UID given a specific lesion class type. * * @param lesionClassType The lesion class type as string. * @param allLesionClasses All currently known lesion classes of a specific case. * * @return The lesion class with its UID and the class type. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionClass FindExistingLesionClass(const std::string& lesionClassType, const std::vector& allLesionClasses); /** * @brief Generate and store additional lesion data such as lesion presence and lesion volume for each control point. * * @param lesionData The lesion data that holds the lesion and will hold the additional lesion data. * @param caseID The current case ID. */ - MITKSEMANTICRELATIONS_EXPORT void GenerateAdditionalLesionData(LesionData& lesionData, const SemanticTypes::CaseID& caseID); + MITKSEMANTICRELATIONS_EXPORT void GenerateAdditionalLesionData(DataStorage* dataStorage, LesionData& lesionData, const SemanticTypes::CaseID& caseID); } // namespace mitk #endif // MITKLESIONMANAGER_H diff --git a/Modules/SemanticRelations/include/mitkStatisticsCalculator.h b/Modules/SemanticRelations/include/mitkStatisticsCalculator.h new file mode 100644 index 0000000000..7dedd1926d --- /dev/null +++ b/Modules/SemanticRelations/include/mitkStatisticsCalculator.h @@ -0,0 +1,59 @@ +/*=================================================================== + +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/mitkLesionManager.cpp b/Modules/SemanticRelations/src/mitkLesionManager.cpp index a9e83d88e2..d0d922a644 100644 --- a/Modules/SemanticRelations/src/mitkLesionManager.cpp +++ b/Modules/SemanticRelations/src/mitkLesionManager.cpp @@ -1,123 +1,128 @@ /*=================================================================== 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 "mitkLesionManager.h" #include "mitkSemanticRelationException.h" +#include "mitkSemanticRelationsDataStorageAccess.h" #include "mitkSemanticRelationsInference.h" #include "mitkRelationStorage.h" +#include "mitkStatisticsCalculator.h" #include "mitkUIDGeneratorBoost.h" -double GetLesionVolume(const mitk::SemanticTypes::CaseID& caseID, const mitk::SemanticTypes::Lesion& lesion, const mitk::SemanticTypes::ControlPoint& controlPoint); - mitk::SemanticTypes::Lesion mitk::GenerateNewLesion(const std::string& lesionClassType/* = ""*/) { SemanticTypes::Lesion lesion; lesion.UID = mitk::UIDGeneratorBoost::GenerateUID(); lesion.name = "New lesion"; lesion.lesionClass = GenerateNewLesionClass(lesionClassType); return lesion; } mitk::SemanticTypes::LesionClass mitk::GenerateNewLesionClass(const std::string& lesionClassType/* = ""*/) { SemanticTypes::LesionClass lesionClass; lesionClass.UID = mitk::UIDGeneratorBoost::GenerateUID(); lesionClass.classType = lesionClassType; return lesionClass; } mitk::SemanticTypes::Lesion mitk::GetLesionByUID(const SemanticTypes::ID& lesionUID, const std::vector& allLesions) { auto lambda = [&lesionUID](const SemanticTypes::Lesion& currentLesion) { return currentLesion.UID == lesionUID; }; const auto existingLesion = std::find_if(allLesions.begin(), allLesions.end(), lambda); SemanticTypes::Lesion lesion; if (existingLesion != allLesions.end()) { lesion = *existingLesion; } return lesion; } mitk::SemanticTypes::LesionClass mitk::FindExistingLesionClass(const std::string& lesionClassType, const std::vector& allLesionClasses) { auto lambda = [&lesionClassType](const SemanticTypes::LesionClass& currentLesionClass) { return currentLesionClass.classType == lesionClassType; }; const auto existingLesionClass = std::find_if(allLesionClasses.begin(), allLesionClasses.end(), lambda); SemanticTypes::LesionClass lesionClass; if (existingLesionClass != allLesionClasses.end()) { lesionClass = *existingLesionClass; } return lesionClass; } -void mitk::GenerateAdditionalLesionData(LesionData& lesionData, const SemanticTypes::CaseID& caseID) +void mitk::GenerateAdditionalLesionData(DataStorage* dataStorage, LesionData& lesionData, const SemanticTypes::CaseID& caseID) { std::vector lesionPresence; std::vector lesionVolume; SemanticTypes::Lesion lesion = lesionData.GetLesion(); bool presence = false; double volume = 0.0; SemanticTypes::ControlPointVector controlPoints = RelationStorage::GetAllControlPointsOfCase(caseID); // sort the vector of control points for the timeline std::sort(controlPoints.begin(), controlPoints.end()); - for (const auto& controlPoint : controlPoints) + SemanticTypes::InformationTypeVector informationTypes = mitk::RelationStorage::GetAllInformationTypesOfCase(caseID); + for (const auto& informationType : informationTypes) { - try - { - presence = SemanticRelationsInference::IsLesionPresentAtControlPoint(caseID, lesion, controlPoint); - } - catch (SemanticRelationException& e) + + for (const auto& controlPoint : controlPoints) { - mitkReThrow(e) << "Cannot determine the lesion presence for generating additional lesion data."; + try + { + presence = SemanticRelationsInference::IsLesionPresentAtControlPoint(caseID, lesion, controlPoint); + } + catch (SemanticRelationException&) + { + presence = false; + } + + SemanticRelationsDataStorageAccess semanticRelationsDataStorageAccess(dataStorage); + mitk::DataNode::Pointer specificSegmentation; + try + { + specificSegmentation = semanticRelationsDataStorageAccess.GetSpecificSegmentation(caseID, controlPoint, informationType, lesion); + // compute mask volume of the specific segmentation + mitk::StatisticsCalculator statisticsCalculator; + volume = statisticsCalculator.GetSegmentationMaskVolume(specificSegmentation); + } + catch (SemanticRelationException&) + { + volume = 0.0; + } + + lesionPresence.push_back(presence); + lesionVolume.push_back(volume); } - - lesionPresence.push_back(presence); - volume = GetLesionVolume(caseID, lesion, controlPoint); - lesionVolume.push_back(volume); } lesionData.SetLesionPresence(lesionPresence); lesionData.SetLesionVolume(lesionVolume); } - -double GetLesionVolume(const mitk::SemanticTypes::CaseID& caseID, const mitk::SemanticTypes::Lesion& lesion, const mitk::SemanticTypes::ControlPoint& controlPoint) -{ - bool presence = mitk::SemanticRelationsInference::IsLesionPresentAtControlPoint(caseID, lesion, controlPoint); - if (presence) - { - return 1.0; - } - else - { - return 0.0; - } -} diff --git a/Modules/SemanticRelations/src/mitkStatisticsCalculator.cpp b/Modules/SemanticRelations/src/mitkStatisticsCalculator.cpp new file mode 100644 index 0000000000..b3368e00bf --- /dev/null +++ b/Modules/SemanticRelations/src/mitkStatisticsCalculator.cpp @@ -0,0 +1,61 @@ +/*=================================================================== + +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; +}