diff --git a/Modules/SemanticRelations/include/mitkRelationStorage.h b/Modules/SemanticRelations/include/mitkRelationStorage.h index fc32e13c82..1ba900ea77 100644 --- a/Modules/SemanticRelations/include/mitkRelationStorage.h +++ b/Modules/SemanticRelations/include/mitkRelationStorage.h @@ -1,73 +1,81 @@ /*=================================================================== 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 MITKRELATIONSTORAGE_H #define MITKRELATIONSTORAGE_H +#include + // semantic relations module #include "mitkSemanticTypes.h" namespace mitk { namespace RelationStorage { - SemanticTypes::LesionVector GetAllLesionsOfCase(const SemanticTypes::CaseID& caseID); - SemanticTypes::Lesion GetRepresentedLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); - - SemanticTypes::IDVector GetAllSegmentationIDsOfCase(const SemanticTypes::CaseID& caseID); + MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllLesionsOfCase(const SemanticTypes::CaseID& caseID); + SemanticTypes::Lesion GetLesionOfSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); SemanticTypes::ControlPoint GetControlPointOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); - SemanticTypes::ControlPointVector GetAllControlPointsOfCase(const SemanticTypes::CaseID& caseID); + MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPointVector GetAllControlPointsOfCase(const SemanticTypes::CaseID& caseID); - SemanticTypes::ExaminationPeriodVector GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID& caseID); + MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ExaminationPeriodVector GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID& caseID); SemanticTypes::InformationType GetInformationTypeOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); - SemanticTypes::InformationTypeVector GetAllInformationTypesOfCase(const SemanticTypes::CaseID& caseID); + MITKSEMANTICRELATIONS_EXPORT SemanticTypes::InformationTypeVector GetAllInformationTypesOfCase(const SemanticTypes::CaseID& caseID); SemanticTypes::IDVector GetAllImageIDsOfCase(const SemanticTypes::CaseID& caseID); - std::vector GetAllCaseIDs(); + SemanticTypes::IDVector GetAllImageIDsOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); + SemanticTypes::IDVector GetAllImageIDsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType); + SemanticTypes::IDVector GetAllSegmentationIDsOfCase(const SemanticTypes::CaseID& caseID); + SemanticTypes::IDVector GetAllSegmentationIDsOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); + SemanticTypes::IDVector GetAllSegmentationIDsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); + + SemanticTypes::ID GetImageIDOfSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); + + MITKSEMANTICRELATIONS_EXPORT std::vector GetAllCaseIDs(); void AddCase(const SemanticTypes::CaseID& caseID); - void AddImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageNodeID); - void RemoveImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageNodeID); - void AddSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationNodeID, const SemanticTypes::ID& parentDataNodeID); - void RemoveSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationNodeID); + void AddImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); + void RemoveImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); + void AddSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID, const SemanticTypes::ID& parentID); + void RemoveSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); void AddLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); void OverwriteLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); void LinkSegmentationToLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID, const SemanticTypes::Lesion& lesion); void UnlinkSegmentationFromLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); void RemoveLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); void RemoveLesionClass(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& lesionClassID); void AddControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); - void LinkDataToControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& dataNodeID, const SemanticTypes::ControlPoint& controlPoint); - void UnlinkDataFromControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& dataNodeID); + void LinkImageToControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID, const SemanticTypes::ControlPoint& controlPoint); + void UnlinkImageFromControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); void RemoveControlPointFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); void AddExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod); - void AddControlPointToExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod examinationPeriod); - void RemoveControlPointFromExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod examinationPeriod); - void RemoveExaminationPeriodFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod examinationPeriod); + void AddControlPointToExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod& examinationPeriod); + void RemoveControlPointFromExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod& examinationPeriod); + void RemoveExaminationPeriodFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod); - void AddInformationTypeToImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID, const SemanticTypes::InformationType informationType); + void AddInformationTypeToImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID, const SemanticTypes::InformationType& informationType); void RemoveInformationTypeFromImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); - void RemoveInformationTypeFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType informationType); + void RemoveInformationTypeFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType); } // namespace RelationStorage } // namespace mitk #endif // MITKRELATIONSTORAGE_H diff --git a/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h b/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h index 857caff09e..2bedb6909c 100644 --- a/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h +++ b/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h @@ -1,278 +1,230 @@ /*=================================================================== 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 MITKSEMANTICRELATIONSINFERENCE_H #define MITKSEMANTICRELATIONSINFERENCE_H #include // semantic relations module #include "mitkSemanticTypes.h" // mitk core #include namespace mitk { /** * @brief The API provides functions to query image relations and instances * that are helpful during follow-up examination, like control-points (time period), * types of the images or lesions that may be visible on multiple images. * * The class is able to generate IDs from given data nodes using DICOM information. * These IDs are used to identify the corresponding instances of a specific case. * The case can also be directly identified by the given case ID. * * In order for most functions to work the case ID has to be used as a parameter. * If not, these functions do nothing. */ namespace SemanticRelationsInference { /************************************************************************/ /* functions to get instances / attributes */ /************************************************************************/ /** - * @brief Return a vector of all lesions that are currently available for the given case. - * The lesions may be marked by a segmentation or may be empty - with no connection to a specific image / segmentation of the case data. - * If no lesions are stored for the current case, an empty vector is returned. - * - * @param caseID The current case identifier is defined by the given string. - * @return A vector of lesions. - */ - MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllLesionsOfCase(const SemanticTypes::CaseID& caseID); - /** * @brief Return a vector of lesion classes that are currently available for the given case. * * @param caseID The current case identifier is defined by the given string. * @return A vector of lesion classes. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionClassVector GetAllLesionClassesOfCase(const SemanticTypes::CaseID& caseID); /** * @brief Return the lesion that is defined by the given segmentation data. * * @pre The given segmentation data node has to be valid (!nullptr). * @throw SemanticRelationException, if the given segmentation data node is invalid (==nullptr). * @pre The segmentation data node has to represent a lesion. If not, the retrieved lesion will be empty, which leads to an exception. * @throw SemanticRelationException, if the segmentation does not represent an existing lesion (this can be checked via 'IsRepresentingALesion'). * * @param segmentationNode The segmentation identifier is extracted from the given data node. * @return The represented lesion. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::Lesion GetRepresentedLesion(const DataNode* segmentationNode); /** - * @brief Returns the lesion that is defined by the segmentation identified by the segmentation ID. - * - * @throw SemanticRelationException, if the segmentation does not represent an existing lesion (this can be checked via 'IsRepresentingALesion'). - * - * @param caseID The current case identifier is defined by the given string. - * @param segmentationID The segmentation node identifier is defined by the given string. - * @return The represented lesion. - */ - MITKSEMANTICRELATIONS_EXPORT SemanticTypes::Lesion GetRepresentedLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); - /** * @brief Check if the given segmentation refers to an existing lesion instance. * This function can be used before calling 'GetRepresentedLesion' in order to avoid a possible exception. * * @param segmentationNode The segmentation identifier is extracted from the given data node. * @return True, if the segmentation refers to an existing lesion; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool IsRepresentingALesion(const DataNode* segmentationNode); /** * @brief Check if the segmentation identified by the given segmentation ID refers to an existing lesion instance. * This function can be used before calling 'GetRepresentedLesion' in order to avoid a possible exception. * * @param caseID The current case identifier is defined by the given string. * @param segmentationID The segmentation node identifier is defined by the given string. * @return True, if the segmentation refers to an existing lesion; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool IsRepresentingALesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID); /** * @brief Check if the given lesion is present on the segmentation identified by the given segmentation ID. * * @param caseID The current case identifier is defined by the given string. * @param lesion A Lesion with a UID that identifies the corresponding lesion instance. * @param segmentationID The segmentation node identifier is defined by the given string. * @return True, if the lesion is present on the segmentation identified by the given segmentation ID; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool IsLesionPresentOnSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ID& segmentationID); /** * @brief Check if the given data node exists in the relation storage. * The function receives the case- and the node-ID from the DICOM tags of the node itself. * It uses node predicates to decide if the node is an image or a segmentation node and searches * through the corresponding relations. * * @param dataNode A data node to check. * @return True, if the data node exists; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool InstanceExists(const DataNode* dataNode); /** * @brief Check if the given lesion instance exists. * This function can be used before calling 'GetAllSegmentationsOfLesion' in order to avoid a possible exception. * This function can be used before calling 'AddLesionInstance' in order to avoid a possible exception. * * @param caseID The current case identifier is defined by the given string. * @param lesion A Lesion with a UID that identifies the corresponding lesion instance. * @return True, if the lesion instance exists; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); /** * @brief Return a vector of all segmentation IDs that identify segmentations that define the given lesion. * These segmentations don't have to be linked to the same image. * If the lesion is not referred to by any segmentation, an empty vector is returned. * * @pre The UID of the lesion has to exist for a lesion instance. * @throw SemanticRelationException, if UID of the lesion does not exist for a lesion instance (this can be checked via 'InstanceExists'). * * @param caseID The current case identifier is defined by the given string. * @param lesion A Lesion with a UID that identifies the corresponding lesion instance. * @return A vector of IDs identifying segmentations that define the given lesion. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::IDVector GetAllSegmentationIDsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); /** - * @brief Return a vector of all control points that are valid for the given case. - * - * @param caseID The current case identifier is defined by the given string. - * @return A vector of control points. - */ - MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPointVector GetAllControlPointsOfCase(const SemanticTypes::CaseID& caseID); - /** * @brief Return the control point of a data node. * If the data node is not linked to a control point or the data node refers to a non-existing control point, * a control point with an empty UID is returned. * * @pre The given image data node has to be valid (!nullptr). * @throw SemanticRelationException, if the given image data node is invalid (==nullptr). * * @param dataNode The current case identifier is extracted from the given data node, which contains DICOM information about the case. * @return The control point of the given data node. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint GetControlPointOfImage(const DataNode* dataNode); /** - * @brief Return the control point of a data node identified by the image ID. - * If the data node is not linked to a control point or the data node refers to a non-existing control point, - * a control point with an empty UID is returned. - * - * @param caseID The current case identifier is defined by the given string. - * @param imageID The image node identifier is defined by the given string. - * @return The control point of the image node, defined by the image node ID. - */ - MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint GetControlPointOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); - /** - * @brief Return a vector of all image IDs that identify images that link to the given control point. - * If the control point is not referred to by any image, an empty vector is returned. - * - * @pre The UID of the control point has to exist for a control point instance. - * @throw SemanticRelationException, if the UID of the control point does not exist for a control point instance (this can be checked via 'InstanceExists'). - * - * @param caseID The current case identifier is defined by the given string. - * @param controlPoint A control point with a UID that identifies the corresponding control point instance. - * @return A vector of IDs identifying images that link to the given control point. - */ - MITKSEMANTICRELATIONS_EXPORT SemanticTypes::IDVector GetAllImageIDsOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); - /** * @brief Check if the given control point instance exists. * This function can be used before calling 'GetAllDataOfControlPoint' in order to avoid a possible exception. * This function can be used before adding, linking and unlinking control points to avoid a possible exception. * * @param caseID The current case identifier is defined by the given string. * @param controlPoint A control point with a UID that identifies the corresponding control point instance. * @return True, if the control point instance exists; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); /** * @brief Return a vector of all examination periods nodes that are valid for the given case. * * @param caseID The current case identifier is defined by the given string. * @return A vector of examination periods. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ExaminationPeriodVector GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID& caseID); /** * @brief Check if the given examination period instance exists. * This function can be used before calling 'AddExaminationPeriod' in order to avoid a possible exception. * * @param caseID The current case identifier is defined by the given string. * @param examinationPeriod An examination period with a UID that identifies the corresponding examination period instance. * @return True, if the examination period instance exists; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod); /** * @brief Return a vector of all information types that are valid for the given case. * * @param caseID The current case identifier is defined by the given string. * @return A vector of information types. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::InformationTypeVector GetAllInformationTypesOfCase(const SemanticTypes::CaseID& caseID); /** * @brief Return the information type of the given image. * If the image does not contain any information type, an empty information type is returned. * * @pre The given image data node has to be valid (!nullptr). * @throw SemanticRelationException, if the given image data node is invalid (==nullptr). * * @param imageNode The current case identifier is extracted from the given data node, which contains DICOM information about the case. * @return The information type of the given data node. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::InformationType GetInformationTypeOfImage(const DataNode* imageNode); /** * @brief Return the information type of the given image. * If the image does not contain any information type, an empty information type is returned. * * @param caseID The current case identifier is defined by the given string. * @param imageID The image node identifier is defined by the given string. * @return The information type of the image node, defined by the image node ID. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::InformationType GetInformationTypeOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID); /** * @brief Return a vector of all image IDs that identify images that are of the given information type. * If the information type is not used by any image, an empty vector is returned. * * @pre The information type has to exist. * @throw SemanticRelationException, if the information type does not exist (this can be checked via 'InstanceExists'). * * @param caseID The current case identifier is defined by the given string. * @param informationType An information type. * @return A vector of IDs identifying images that are of the given information type. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::IDVector GetAllImageIDsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType); /** * @brief Check if the given information type exists. * This function can be used before calling 'GetAllDataOfInformationType' in order to avoid a possible exception. * * @param caseID The current case identifier is defined by the given string. * @param informationType An information type. * @return True, if the information type exists; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType); /** * @brief Return a vector of all CaseIDs that are currently available. * * @return A vector of CaseIDs as strings. */ MITKSEMANTICRELATIONS_EXPORT std::vector GetAllCaseIDs(); /** * @brief Remove all control points from the storage that are not referenced by any image anymore. * This might happen if an image has been removed (and unlinked from the corresponding control point) * or if the user sets a new control point for an image manually in the GUI. * * @param caseID The current case identifier is defined by the given string. */ void ClearControlPoints(const SemanticTypes::CaseID& caseID); } // namespace SemanticRelationsInference } // namespace mitk #endif // MITKSEMANTICRELATIONSINFERENCE_H diff --git a/Modules/SemanticRelations/src/mitkRelationStorage.cpp b/Modules/SemanticRelations/src/mitkRelationStorage.cpp index 2a4327543a..3a9dd560e1 100644 --- a/Modules/SemanticRelations/src/mitkRelationStorage.cpp +++ b/Modules/SemanticRelations/src/mitkRelationStorage.cpp @@ -1,1294 +1,1498 @@ /*=================================================================== 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 "mitkRelationStorage.h" // semantic relations module #include "mitkDICOMHelper.h" // multi label module #include // mitk core #include #include // c++ #include #include namespace { mitk::PropertyList::Pointer GetStorageData(const mitk::SemanticTypes::CaseID& caseID) { // access the storage PERSISTENCE_GET_SERVICE_MACRO if (nullptr == persistenceService) { MITK_DEBUG << "Persistence service could not be loaded"; return nullptr; } // the property list is valid for a whole case and contains all the properties for the current case // the persistence service may create a new property list with the given ID, if no property list is found return persistenceService->GetPropertyList(const_cast(caseID)); } mitk::SemanticTypes::Lesion GenerateLesion(const mitk::SemanticTypes::CaseID& caseID, const mitk::SemanticTypes::ID& lesionID) { mitk::PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return mitk::SemanticTypes::Lesion(); } mitk::VectorProperty* lesionDataProperty = dynamic_cast*>(propertyList->GetProperty(lesionID)); if (nullptr == lesionDataProperty) { MITK_DEBUG << "Lesion " << lesionID << " not found. Lesion can not be retrieved."; return mitk::SemanticTypes::Lesion(); } std::vector lesionData = lesionDataProperty->GetValue(); // a lesion date has to have exactly two values (the name of the lesion and the UID of the lesion class) if (lesionData.size() != 2) { MITK_DEBUG << "Incorrect lesion data storage. Not two (2) strings of the lesion name and the lesion UID are stored."; return mitk::SemanticTypes::Lesion(); } // the lesion class ID is stored as the second property std::string lesionClassID = lesionData[1]; mitk::StringProperty* lesionClassProperty = dynamic_cast(propertyList->GetProperty(lesionClassID)); if (nullptr != lesionClassProperty) { mitk::SemanticTypes::LesionClass generatedLesionClass; generatedLesionClass.UID = lesionClassID; generatedLesionClass.classType = lesionClassProperty->GetValue(); mitk::SemanticTypes::Lesion generatedLesion; generatedLesion.UID = lesionID; generatedLesion.name = lesionData[0]; generatedLesion.lesionClass = generatedLesionClass; return generatedLesion; } MITK_DEBUG << "Incorrect lesion class storage. Lesion " << lesionID << " can not be retrieved."; return mitk::SemanticTypes::Lesion(); } mitk::SemanticTypes::ControlPoint GenerateControlpoint(const mitk::SemanticTypes::CaseID& caseID, const mitk::SemanticTypes::ID& controlPointUID) { mitk::PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return mitk::SemanticTypes::ControlPoint(); } // retrieve a vector property that contains the integer values of the date of a control point (0. year 1. month 2. day) mitk::VectorProperty* controlPointVectorProperty = dynamic_cast*>(propertyList->GetProperty(controlPointUID)); if (nullptr == controlPointVectorProperty) { MITK_DEBUG << "Could not find the control point " << controlPointUID << " in the storage."; return mitk::SemanticTypes::ControlPoint(); } - std::vector controlPointVectorValue = controlPointVectorProperty->GetValue(); + std::vector controlPointVectorPropertyValue = controlPointVectorProperty->GetValue(); // a control point has to have exactly three integer values (year, month and day) - if (controlPointVectorValue.size() != 3) + if (controlPointVectorPropertyValue.size() != 3) { MITK_DEBUG << "Incorrect control point storage. Not three (3) values of the date are stored."; return mitk::SemanticTypes::ControlPoint(); } // set the values of the control point mitk::SemanticTypes::ControlPoint generatedControlPoint; generatedControlPoint.UID = controlPointUID; - generatedControlPoint.date = boost::gregorian::date(controlPointVectorValue[0], - controlPointVectorValue[1], - controlPointVectorValue[2]); + generatedControlPoint.date = boost::gregorian::date(controlPointVectorPropertyValue[0], + controlPointVectorPropertyValue[1], + controlPointVectorPropertyValue[2]); return generatedControlPoint; } } mitk::SemanticTypes::LesionVector mitk::RelationStorage::GetAllLesionsOfCase(const SemanticTypes::CaseID& caseID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::LesionVector(); } // retrieve a vector property that contains the valid lesion-IDs for the current case - VectorProperty* vectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); - if (nullptr == vectorProperty) + VectorProperty* lesionsVectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); + if (nullptr == lesionsVectorProperty) { MITK_DEBUG << "Could not find any lesion in the storage."; return SemanticTypes::LesionVector(); } - std::vector vectorValue = vectorProperty->GetValue(); + std::vector lesionsVectorPropertyValue = lesionsVectorProperty->GetValue(); SemanticTypes::LesionVector allLesionsOfCase; - for (const auto& lesionID : vectorValue) + for (const auto& lesionID : lesionsVectorPropertyValue) { SemanticTypes::Lesion generatedLesion = GenerateLesion(caseID, lesionID); if (!generatedLesion.UID.empty()) { allLesionsOfCase.push_back(generatedLesion); } } return allLesionsOfCase; } -mitk::SemanticTypes::Lesion mitk::RelationStorage::GetRepresentedLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) +mitk::SemanticTypes::Lesion mitk::RelationStorage::GetLesionOfSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::Lesion(); } // retrieve a vector property that contains the referenced ID of a segmentation (0. image ID 1. lesion ID) VectorProperty* segmentationVectorProperty = dynamic_cast*>(propertyList->GetProperty(segmentationID)); if (nullptr == segmentationVectorProperty) { - MITK_DEBUG << "Could not find the segmentation node " << segmentationID << " in the storage."; + MITK_DEBUG << "Could not find the segmentation " << segmentationID << " in the storage."; return SemanticTypes::Lesion(); } - std::vector segmentationVectorValue = segmentationVectorProperty->GetValue(); + std::vector segmentationVectorPropertyValue = segmentationVectorProperty->GetValue(); // the lesion ID of a segmentation is the second value in the vector - if (segmentationVectorValue.size() != 2) + if (segmentationVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect segmentation storage. Not two (2) IDs stored."; return SemanticTypes::Lesion(); } - std::string lesionID = segmentationVectorValue[1]; + std::string lesionID = segmentationVectorPropertyValue[1]; if (lesionID.empty()) { // segmentation does not refer to any lesion; return empty lesion return SemanticTypes::Lesion(); } return GenerateLesion(caseID, lesionID); } -mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllSegmentationIDsOfCase(const SemanticTypes::CaseID& caseID) -{ - PropertyList::Pointer propertyList = GetStorageData(caseID); - if (nullptr == propertyList) - { - MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; - return SemanticTypes::IDVector(); - } - // retrieve a vector property that contains the valid segmentation-IDs for the current case - VectorProperty* allSegmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); - if (nullptr == allSegmentationsVectorProperty) - { - MITK_DEBUG << "Could not find any segmentation in the storage."; - return SemanticTypes::IDVector(); - } - - return allSegmentationsVectorProperty->GetValue(); -} - mitk::SemanticTypes::ControlPoint mitk::RelationStorage::GetControlPointOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::ControlPoint(); } // retrieve a vector property that contains the information type and the referenced ID of a control point (0. information type 1. control point ID) - VectorProperty* dataNodeVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); - if (nullptr == dataNodeVectorProperty) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) { - MITK_DEBUG << "Could not find the data node " << imageID << " in the storage."; + MITK_DEBUG << "Could not find the image " << imageID << " in the storage."; return SemanticTypes::ControlPoint(); } - std::vector dataNodeVectorValue = dataNodeVectorProperty->GetValue(); + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); SemanticTypes::ControlPoint controlPoint; - // an image node has to have exactly two values (the information type and the ID of the control point) - if (dataNodeVectorValue.size() != 2) + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return SemanticTypes::ControlPoint(); } - // the second value of the data node vector is the ID of the referenced control point - std::string controlPointID = dataNodeVectorValue[1]; + // the second value of the image vector is the ID of the referenced control point + std::string controlPointID = imageVectorPropertyValue[1]; // retrieve a vector property that contains the integer values of the date of a control point (0. year 1. month 2. day) VectorProperty* controlPointVectorProperty = dynamic_cast*>(propertyList->GetProperty(controlPointID)); if (nullptr == controlPointVectorProperty) { MITK_DEBUG << "Could not find the control point " << controlPointID << " in the storage."; return SemanticTypes::ControlPoint(); } - std::vector controlPointVectorValue = controlPointVectorProperty->GetValue(); + std::vector controlPointVectorPropertyValue = controlPointVectorProperty->GetValue(); // a control point has to have exactly three integer values (year, month and day) - if (controlPointVectorValue.size() != 3) + if (controlPointVectorPropertyValue.size() != 3) { MITK_DEBUG << "Incorrect control point storage. Not three (3) values of the date are stored."; return SemanticTypes::ControlPoint(); } // set the values of the control point controlPoint.UID = controlPointID; - controlPoint.date = boost::gregorian::date(controlPointVectorValue[0], - controlPointVectorValue[1], - controlPointVectorValue[2]); + controlPoint.date = boost::gregorian::date(controlPointVectorPropertyValue[0], + controlPointVectorPropertyValue[1], + controlPointVectorPropertyValue[2]); return controlPoint; } mitk::SemanticTypes::ControlPointVector mitk::RelationStorage::GetAllControlPointsOfCase(const SemanticTypes::CaseID& caseID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::ControlPointVector(); } // retrieve a vector property that contains the valid control point-IDs for the current case - VectorProperty* vectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); - if (nullptr == vectorProperty) + VectorProperty* controlPointsVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); + if (nullptr == controlPointsVectorProperty) { MITK_DEBUG << "Could not find any control points in the storage."; return SemanticTypes::ControlPointVector(); } - std::vector vectorValue = vectorProperty->GetValue(); + std::vector controlPointsVectorPropertyValue = controlPointsVectorProperty->GetValue(); SemanticTypes::ControlPointVector allControlPointsOfCase; - for (const auto& controlPointUID : vectorValue) + for (const auto& controlPointUID : controlPointsVectorPropertyValue) { SemanticTypes::ControlPoint generatedControlPoint = GenerateControlpoint(caseID, controlPointUID); if (!generatedControlPoint.UID.empty()) { allControlPointsOfCase.push_back(generatedControlPoint); } } return allControlPointsOfCase; } mitk::SemanticTypes::ExaminationPeriodVector mitk::RelationStorage::GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID& caseID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::ExaminationPeriodVector(); } // retrieve a vector property that contains the valid examination period UIDs for the current case - VectorProperty::Pointer vectorProperty = dynamic_cast*>(propertyList->GetProperty("examinationperiods")); - if (nullptr == vectorProperty) + VectorProperty::Pointer examinationPeriodsVectorProperty = dynamic_cast*>(propertyList->GetProperty("examinationperiods")); + if (nullptr == examinationPeriodsVectorProperty) { MITK_DEBUG << "Could not find any examination periods in the storage."; return SemanticTypes::ExaminationPeriodVector(); } - std::vector vectorValue = vectorProperty->GetValue(); + std::vector examinationPeriodsVectorPropertyValue = examinationPeriodsVectorProperty->GetValue(); SemanticTypes::ExaminationPeriodVector allExaminationPeriods; - for (const auto& examinationPeriodID : vectorValue) + for (const auto& examinationPeriodID : examinationPeriodsVectorPropertyValue) { // retrieve a vector property that contains the represented control point-IDs VectorProperty::Pointer examinationPeriodVectorProperty = dynamic_cast*>(propertyList->GetProperty(examinationPeriodID)); if (nullptr == examinationPeriodVectorProperty) { MITK_DEBUG << "Could not find the examination period " << examinationPeriodID << " in the storage."; continue; } - std::vector examinationPeriodVectorValue = examinationPeriodVectorProperty->GetValue(); + std::vector examinationPeriodVectorPropertyValue = examinationPeriodVectorProperty->GetValue(); // an examination period has an arbitrary number of vector values (name and control point UIDs) (at least one for the name) - if (examinationPeriodVectorValue.empty()) + if (examinationPeriodVectorPropertyValue.empty()) { MITK_DEBUG << "Incorrect examination period storage. At least one (1) value for the examination period name has to be stored."; continue; } else { // set the values of the name and the control points SemanticTypes::ExaminationPeriod generatedExaminationPeriod; generatedExaminationPeriod.UID = examinationPeriodID; - generatedExaminationPeriod.name = examinationPeriodVectorValue[0]; - for (int i = 1; i < examinationPeriodVectorValue.size(); ++i) + generatedExaminationPeriod.name = examinationPeriodVectorPropertyValue[0]; + for (int i = 1; i < examinationPeriodVectorPropertyValue.size(); ++i) { - generatedExaminationPeriod.controlPointUIDs.push_back(examinationPeriodVectorValue[i]); + generatedExaminationPeriod.controlPointUIDs.push_back(examinationPeriodVectorPropertyValue[i]); } allExaminationPeriods.push_back(generatedExaminationPeriod); } } return allExaminationPeriods; } mitk::SemanticTypes::InformationType mitk::RelationStorage::GetInformationTypeOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::InformationType(); } - // retrieve a vector property that contains the information type and the referenced ID of an image data node (0. information type 1. control point ID) - VectorProperty* dataNodeVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); - if (nullptr == dataNodeVectorProperty) + // retrieve a vector property that contains the information type and the referenced ID of an image (0. information type 1. control point ID) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) { MITK_DEBUG << "Could not find the image " << imageID << " in the storage."; return SemanticTypes::InformationType(); } - std::vector dataNodeVectorValue = dataNodeVectorProperty->GetValue(); - // an image node has to have exactly two values (the information type and the ID of the control point) - if (dataNodeVectorValue.size() != 2) + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return SemanticTypes::InformationType(); } - // the first value of the data node vector is the information type - return dataNodeVectorValue[0]; + // the first value of the image vector is the information type + return imageVectorPropertyValue[0]; } mitk::SemanticTypes::InformationTypeVector mitk::RelationStorage::GetAllInformationTypesOfCase(const SemanticTypes::CaseID& caseID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return SemanticTypes::InformationTypeVector(); } // retrieve a vector property that contains the valid information types of the current case - VectorProperty* informationTypeVectorProperty = dynamic_cast*>(propertyList->GetProperty("informationtypes")); - if (nullptr == informationTypeVectorProperty) + VectorProperty* informationTypesVectorProperty = dynamic_cast*>(propertyList->GetProperty("informationtypes")); + if (nullptr == informationTypesVectorProperty) { MITK_DEBUG << "Could not find any information types in the storage."; return SemanticTypes::InformationTypeVector(); } - return informationTypeVectorProperty->GetValue(); + return informationTypesVectorProperty->GetValue(); } mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllImageIDsOfCase(const SemanticTypes::CaseID& caseID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; - return SemanticTypes::InformationTypeVector(); + return SemanticTypes::IDVector(); } // retrieve a vector property that contains the valid image-IDs of the current case - VectorProperty* allImagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); - if (nullptr == allImagesVectorProperty) + VectorProperty* imagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); + if (nullptr == imagesVectorProperty) { MITK_DEBUG << "Could not find any image in the storage."; - return SemanticTypes::InformationTypeVector(); + return SemanticTypes::IDVector(); + } + + return imagesVectorProperty->GetValue(); +} + +mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllImageIDsOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) +{ + PropertyList::Pointer propertyList = GetStorageData(caseID); + if (nullptr == propertyList) + { + MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; + return SemanticTypes::IDVector(); + } + // retrieve a vector property that contains the valid image-IDs of the current case + VectorProperty* imagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); + if (nullptr == imagesVectorProperty) + { + MITK_DEBUG << "Could not find any image in the storage."; + return SemanticTypes::IDVector(); + } + + mitk::SemanticTypes::IDVector allImageIDsOfControlPoint; + std::vector imagesVectorPropertyValue = imagesVectorProperty->GetValue(); + for (const auto& imageID : imagesVectorPropertyValue) + { + // retrieve a vector property that contains the referenced ID of an image (0. information type 1. control point ID) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) + { + continue; + } + + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) + { + continue; + } + + // the second value of the image vector is the ID of the referenced control point + if (imageVectorPropertyValue[1] == controlPoint.UID) + { + allImageIDsOfControlPoint.push_back(imageID); + } + } + + return allImageIDsOfControlPoint; +} + +mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllImageIDsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) +{ + PropertyList::Pointer propertyList = GetStorageData(caseID); + if (nullptr == propertyList) + { + MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; + return SemanticTypes::IDVector(); + } + // retrieve a vector property that contains the valid image-IDs of the current case + VectorProperty* imagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); + if (nullptr == imagesVectorProperty) + { + MITK_DEBUG << "Could not find any image in the storage."; + return SemanticTypes::IDVector(); + } + + mitk::SemanticTypes::IDVector allImageIDsOfInformationType; + std::vector imagesVectorPropertyValue = imagesVectorProperty->GetValue(); + for (const auto& imageID : imagesVectorPropertyValue) + { + // retrieve a vector property that contains the referenced ID of an image (0. information type 1. control point ID) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) + { + continue; + } + + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) + { + continue; + } + + // the first value of the image vector is the ID of the referenced information type + if (imageVectorPropertyValue[0] == informationType) + { + allImageIDsOfInformationType.push_back(imageID); + } + } + + return allImageIDsOfInformationType; +} + +mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllSegmentationIDsOfCase(const SemanticTypes::CaseID& caseID) +{ + PropertyList::Pointer propertyList = GetStorageData(caseID); + if (nullptr == propertyList) + { + MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; + return SemanticTypes::IDVector(); + } + // retrieve a vector property that contains the valid segmentation-IDs for the current case + VectorProperty* segmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); + if (nullptr == segmentationsVectorProperty) + { + MITK_DEBUG << "Could not find any segmentation in the storage."; + return SemanticTypes::IDVector(); + } + + return segmentationsVectorProperty->GetValue(); +} + +mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllSegmentationIDsOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) +{ + PropertyList::Pointer propertyList = GetStorageData(caseID); + if (nullptr == propertyList) + { + MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; + return SemanticTypes::IDVector(); + } + // retrieve a vector property that contains the valid segmentation-IDs for the current case + VectorProperty* segmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); + if (nullptr == segmentationsVectorProperty) + { + MITK_DEBUG << "Could not find any segmentation in the storage."; + return SemanticTypes::IDVector(); + } + + mitk::SemanticTypes::IDVector allSegmentationIDsOfImage; + std::vector segmentationsVectorPropertyValue = segmentationsVectorProperty->GetValue(); + for (const auto& segmentationID : segmentationsVectorPropertyValue) + { + // retrieve a vector property that contains the referenced ID of a segmentation (0. image ID 1. lesion ID) + VectorProperty* segmentationVectorProperty = dynamic_cast*>(propertyList->GetProperty(segmentationID)); + if (nullptr == segmentationVectorProperty) + { + continue; + } + + std::vector segmentationVectorPropertyValue = segmentationVectorProperty->GetValue(); + // a segmentation has to have exactly two values (the ID of the referenced image and the ID of the referenced lesion) + if (segmentationVectorPropertyValue.size() != 2) + { + continue; + } + + // the first value of the segmentation vector is the ID of the referenced image + if (segmentationVectorPropertyValue[0] == imageID) + { + allSegmentationIDsOfImage.push_back(imageID); + } + } + + return allSegmentationIDsOfImage; +} + +mitk::SemanticTypes::IDVector mitk::RelationStorage::GetAllSegmentationIDsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) +{ + PropertyList::Pointer propertyList = GetStorageData(caseID); + if (nullptr == propertyList) + { + MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; + return SemanticTypes::IDVector(); + } + // retrieve a vector property that contains the valid segmentation-IDs for the current case + VectorProperty* segmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); + if (nullptr == segmentationsVectorProperty) + { + MITK_DEBUG << "Could not find any segmentation in the storage."; + return SemanticTypes::IDVector(); } - return allImagesVectorProperty->GetValue(); + mitk::SemanticTypes::IDVector allSegmentationIDsOfLesion; + std::vector segmentationsVectorPropertyValue = segmentationsVectorProperty->GetValue(); + for (const auto& segmentationID : segmentationsVectorPropertyValue) + { + // retrieve a vector property that contains the referenced ID of a segmentation (0. image ID 1. lesion ID) + VectorProperty* segmentationVectorProperty = dynamic_cast*>(propertyList->GetProperty(segmentationID)); + if (nullptr == segmentationVectorProperty) + { + continue; + } + + std::vector segmentationVectorPropertyValue = segmentationVectorProperty->GetValue(); + // a segmentation has to have exactly two values (the ID of the referenced image and the ID of the referenced lesion) + if (segmentationVectorPropertyValue.size() != 2) + { + continue; + } + + // the second value of the segmentation vector is the ID of the referenced lesion + if (segmentationVectorPropertyValue[1] == lesion.UID) + { + allSegmentationIDsOfLesion.push_back(segmentationID); + } + } + + return allSegmentationIDsOfLesion; +} + +mitk::SemanticTypes::ID mitk::RelationStorage::GetImageIDOfSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) +{ + PropertyList::Pointer propertyList = GetStorageData(caseID); + if (nullptr == propertyList) + { + MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; + return SemanticTypes::ID(); + } + + // retrieve a vector property that contains the referenced ID of a segmentation (0. image ID 1. lesion ID) + VectorProperty* segmentationVectorProperty = dynamic_cast*>(propertyList->GetProperty(segmentationID)); + if (nullptr == segmentationVectorProperty) + { + MITK_DEBUG << "Could not find the segmentation " << segmentationID << " in the storage."; + return SemanticTypes::ID(); + } + + std::vector segmentationVectorPropertyValue = segmentationVectorProperty->GetValue(); + // the lesion ID of a segmentation is the second value in the vector + if (segmentationVectorPropertyValue.size() != 2) + { + MITK_DEBUG << "Incorrect segmentation storage. Not two (2) IDs stored."; + return SemanticTypes::ID(); + } + + return segmentationVectorPropertyValue[0]; } std::vector mitk::RelationStorage::GetAllCaseIDs() { PERSISTENCE_GET_SERVICE_MACRO if (nullptr == persistenceService) { MITK_DEBUG << "Persistence service could not be loaded"; return std::vector(); } // the property list is valid for a certain scenario and contains all the case IDs of the radiological user's MITK session std::string listIdentifier = "caseIDs"; PropertyList::Pointer propertyList = persistenceService->GetPropertyList(listIdentifier); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << listIdentifier << " for the current MITK workbench / session."; return std::vector(); } // retrieve a vector property that contains all case IDs VectorProperty* caseIDsVectorProperty = dynamic_cast*>(propertyList->GetProperty(listIdentifier)); if (nullptr == caseIDsVectorProperty) { MITK_DEBUG << "Could not find the property " << listIdentifier << " for the " << listIdentifier << " property list."; return std::vector(); } return caseIDsVectorProperty->GetValue(); } void mitk::RelationStorage::AddCase(const SemanticTypes::CaseID& caseID) { PERSISTENCE_GET_SERVICE_MACRO if (nullptr == persistenceService) { MITK_DEBUG << "Persistence service could not be loaded"; return; } // the property list is valid for a certain scenario and contains all the case IDs of the radiological user's MITK session std::string listIdentifier = "caseIDs"; PropertyList::Pointer propertyList = persistenceService->GetPropertyList(listIdentifier); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << listIdentifier << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains all case IDs VectorProperty::Pointer caseIDsVectorProperty = dynamic_cast*>(propertyList->GetProperty(listIdentifier)); - std::vector caseIDsVectorValue; + std::vector caseIDsVectorPropertyValue; if (nullptr == caseIDsVectorProperty) { caseIDsVectorProperty = VectorProperty::New(); } else { - caseIDsVectorValue = caseIDsVectorProperty->GetValue(); + caseIDsVectorPropertyValue = caseIDsVectorProperty->GetValue(); } - auto existingCase = std::find(caseIDsVectorValue.begin(), caseIDsVectorValue.end(), caseID); - if (existingCase != caseIDsVectorValue.end()) + auto existingCase = std::find(caseIDsVectorPropertyValue.begin(), caseIDsVectorPropertyValue.end(), caseID); + if (existingCase != caseIDsVectorPropertyValue.end()) { return; } // add case to the "caseIDs" property list - caseIDsVectorValue.push_back(caseID); - caseIDsVectorProperty->SetValue(caseIDsVectorValue); + caseIDsVectorPropertyValue.push_back(caseID); + caseIDsVectorProperty->SetValue(caseIDsVectorPropertyValue); propertyList->SetProperty(listIdentifier, caseIDsVectorProperty); } -void mitk::RelationStorage::AddImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageNodeID) +void mitk::RelationStorage::AddImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid image-IDs for the current case - VectorProperty::Pointer allImagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); - std::vector allImagesIDs; - if (nullptr == allImagesVectorProperty) + VectorProperty::Pointer imagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); + std::vector imagesVectorPropertyValue; + if (nullptr == imagesVectorProperty) { - allImagesVectorProperty = VectorProperty::New(); + imagesVectorProperty = VectorProperty::New(); } else { - allImagesIDs = allImagesVectorProperty->GetValue(); + imagesVectorPropertyValue = imagesVectorProperty->GetValue(); } - auto existingImage = std::find(allImagesIDs.begin(), allImagesIDs.end(), imageNodeID); - if (existingImage != allImagesIDs.end()) + auto existingImage = std::find(imagesVectorPropertyValue.begin(), imagesVectorPropertyValue.end(), imageID); + if (existingImage != imagesVectorPropertyValue.end()) { return; } // add image to the "images" property list - allImagesIDs.push_back(imageNodeID); - allImagesVectorProperty->SetValue(allImagesIDs); - propertyList->SetProperty("images", allImagesVectorProperty); + imagesVectorPropertyValue.push_back(imageID); + imagesVectorProperty->SetValue(imagesVectorPropertyValue); + propertyList->SetProperty("images", imagesVectorProperty); // add the image itself - VectorProperty::Pointer imageNodeVectorProperty = VectorProperty::New(); - // an image node has to have exactly two values (the information type and the ID of the control point) - std::vector imageNodeVectorValue(2); - imageNodeVectorProperty->SetValue(imageNodeVectorValue); - propertyList->SetProperty(imageNodeID, imageNodeVectorProperty); + VectorProperty::Pointer imageVectorProperty = VectorProperty::New(); + // an image has to have exactly two values (the information type and the ID of the control point) + std::vector imageVectorPropertyValue(2); + imageVectorProperty->SetValue(imageVectorPropertyValue); + propertyList->SetProperty(imageID, imageVectorProperty); } -void mitk::RelationStorage::RemoveImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageNodeID) +void mitk::RelationStorage::RemoveImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid image-IDs for the current case - VectorProperty::Pointer allImagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); - if (nullptr == allImagesVectorProperty) + VectorProperty::Pointer imagesVectorProperty = dynamic_cast*>(propertyList->GetProperty("images")); + if (nullptr == imagesVectorProperty) { MITK_DEBUG << "Could not find any images in the storage."; return; } // remove the image reference from the list of all images of the current case - std::vector allImagesIDs = allImagesVectorProperty->GetValue(); - allImagesIDs.erase(std::remove(allImagesIDs.begin(), allImagesIDs.end(), imageNodeID), allImagesIDs.end()); - if (allImagesIDs.empty()) + std::vector imagesVectorPropertyValue = imagesVectorProperty->GetValue(); + imagesVectorPropertyValue.erase(std::remove(imagesVectorPropertyValue.begin(), imagesVectorPropertyValue.end(), imageID), imagesVectorPropertyValue.end()); + if (imagesVectorPropertyValue.empty()) { // no more images stored -> remove the images property list propertyList->DeleteProperty("images"); } else { // or store the modified vector value - allImagesVectorProperty->SetValue(allImagesIDs); + imagesVectorProperty->SetValue(imagesVectorPropertyValue); } // remove the image instance itself - propertyList->DeleteProperty(imageNodeID); + propertyList->DeleteProperty(imageID); } -void mitk::RelationStorage::AddSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationNodeID, const SemanticTypes::ID& parentNodeID) +void mitk::RelationStorage::AddSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID, const SemanticTypes::ID& parentID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid segmentation-IDs for the current case - VectorProperty::Pointer allSegmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); - std::vector allSegmentationsIDs; - if (nullptr == allSegmentationsVectorProperty) + VectorProperty::Pointer segmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); + std::vector segmentationsVectorPropertyValue; + if (nullptr == segmentationsVectorProperty) { - allSegmentationsVectorProperty = VectorProperty::New(); + segmentationsVectorProperty = VectorProperty::New(); } else { - allSegmentationsIDs = allSegmentationsVectorProperty->GetValue(); + segmentationsVectorPropertyValue = segmentationsVectorProperty->GetValue(); } - auto existingImage = std::find(allSegmentationsIDs.begin(), allSegmentationsIDs.end(), segmentationNodeID); - if (existingImage != allSegmentationsIDs.end()) + auto existingImage = std::find(segmentationsVectorPropertyValue.begin(), segmentationsVectorPropertyValue.end(), segmentationID); + if (existingImage != segmentationsVectorPropertyValue.end()) { return; } // add segmentation to the "segmentations" property list - allSegmentationsIDs.push_back(segmentationNodeID); - allSegmentationsVectorProperty->SetValue(allSegmentationsIDs); - propertyList->SetProperty("segmentations", allSegmentationsVectorProperty); + segmentationsVectorPropertyValue.push_back(segmentationID); + segmentationsVectorProperty->SetValue(segmentationsVectorPropertyValue); + propertyList->SetProperty("segmentations", segmentationsVectorProperty); // add the segmentation itself - VectorProperty::Pointer segmentationNodeVectorProperty = VectorProperty::New(); - // a segmentation node has to have exactly two values (the ID of the referenced image and the ID of the referenced lesion) - std::vector segmentationNodeVectorValue(2); - segmentationNodeVectorValue[0] = parentNodeID; - segmentationNodeVectorProperty->SetValue(segmentationNodeVectorValue); - propertyList->SetProperty(segmentationNodeID, segmentationNodeVectorProperty); + VectorProperty::Pointer segmentationVectorProperty = VectorProperty::New(); + // a segmentation has to have exactly two values (the ID of the referenced image and the ID of the referenced lesion) + std::vector segmentationVectorPropertyValue(2); + segmentationVectorPropertyValue[0] = parentID; + segmentationVectorProperty->SetValue(segmentationVectorPropertyValue); + propertyList->SetProperty(segmentationID, segmentationVectorProperty); } -void mitk::RelationStorage::RemoveSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationNodeID) +void mitk::RelationStorage::RemoveSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid segmentation-IDs for the current case - VectorProperty::Pointer allSegmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); - if (nullptr == allSegmentationsVectorProperty) + VectorProperty::Pointer segmentationsVectorProperty = dynamic_cast*>(propertyList->GetProperty("segmentations")); + if (nullptr == segmentationsVectorProperty) { MITK_DEBUG << "Could not find any segmentation in the storage."; return; } // remove the lesion reference from the list of all lesions of the current case - std::vector allSegmentationsIDs = allSegmentationsVectorProperty->GetValue(); - allSegmentationsIDs.erase(std::remove(allSegmentationsIDs.begin(), allSegmentationsIDs.end(), segmentationNodeID), allSegmentationsIDs.end()); - if (allSegmentationsIDs.empty()) + std::vector segmentationsVectorPropertyValue = segmentationsVectorProperty->GetValue(); + segmentationsVectorPropertyValue.erase(std::remove(segmentationsVectorPropertyValue.begin(), segmentationsVectorPropertyValue.end(), segmentationID), segmentationsVectorPropertyValue.end()); + if (segmentationsVectorPropertyValue.empty()) { // no more segmentations stored -> remove the segmentations property list propertyList->DeleteProperty("segmentations"); } else { // or store the modified vector value - allSegmentationsVectorProperty->SetValue(allSegmentationsIDs); + segmentationsVectorProperty->SetValue(segmentationsVectorPropertyValue); } // remove the lesion instance itself - propertyList->DeleteProperty(segmentationNodeID); + propertyList->DeleteProperty(segmentationID); } void mitk::RelationStorage::AddLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid lesion-IDs for the current case VectorProperty::Pointer lesionsVectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); - std::vector lesionsVectorValue; + std::vector lesionsVectorPropertyValue; if (nullptr == lesionsVectorProperty) { lesionsVectorProperty = VectorProperty::New(); } else { - lesionsVectorValue = lesionsVectorProperty->GetValue(); + lesionsVectorPropertyValue = lesionsVectorProperty->GetValue(); } - const auto& existingIndex = std::find(lesionsVectorValue.begin(), lesionsVectorValue.end(), lesion.UID); - if (existingIndex != lesionsVectorValue.end()) + const auto& existingIndex = std::find(lesionsVectorPropertyValue.begin(), lesionsVectorPropertyValue.end(), lesion.UID); + if (existingIndex != lesionsVectorPropertyValue.end()) { return; } // add the new lesion id from the given lesion to the vector of all current lesion IDs - lesionsVectorValue.push_back(lesion.UID); + lesionsVectorPropertyValue.push_back(lesion.UID); // overwrite the current vector property with the new, extended string vector - lesionsVectorProperty->SetValue(lesionsVectorValue); + lesionsVectorProperty->SetValue(lesionsVectorPropertyValue); propertyList->SetProperty("lesions", lesionsVectorProperty); // add the lesion with the lesion UID as the key and the lesion information as value std::vector lesionData; lesionData.push_back(lesion.name); lesionData.push_back(lesion.lesionClass.UID); VectorProperty::Pointer newLesionVectorProperty = VectorProperty::New(); newLesionVectorProperty->SetValue(lesionData); propertyList->SetProperty(lesion.UID, newLesionVectorProperty); // add the lesion class with the lesion class UID as key and the class type as value std::string lesionClassType = lesion.lesionClass.classType; propertyList->SetStringProperty(lesion.lesionClass.UID.c_str(), lesionClassType.c_str()); } void mitk::RelationStorage::OverwriteLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid lesion-IDs for the current case VectorProperty* lesionVectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); if (nullptr == lesionVectorProperty) { MITK_DEBUG << "Could not find any lesion in the storage."; return; } - std::vector lesionVectorValue = lesionVectorProperty->GetValue(); - const auto existingLesion = std::find(lesionVectorValue.begin(), lesionVectorValue.end(), lesion.UID); - if (existingLesion != lesionVectorValue.end()) + std::vector lesionVectorPropertyValue = lesionVectorProperty->GetValue(); + const auto existingLesion = std::find(lesionVectorPropertyValue.begin(), lesionVectorPropertyValue.end(), lesion.UID); + if (existingLesion != lesionVectorPropertyValue.end()) { // overwrite the referenced lesion class UID with the new, given lesion class data std::vector lesionData; lesionData.push_back(lesion.name); lesionData.push_back(lesion.lesionClass.UID); VectorProperty::Pointer newLesionVectorProperty = VectorProperty::New(); newLesionVectorProperty->SetValue(lesionData); propertyList->SetProperty(lesion.UID, newLesionVectorProperty); // overwrite the lesion class with the lesion class UID as key and the new, given class type as value std::string lesionClassType = lesion.lesionClass.classType; propertyList->SetStringProperty(lesion.lesionClass.UID.c_str(), lesionClassType.c_str()); } else { MITK_DEBUG << "Could not find lesion " << lesion.UID << " in the storage. Cannot overwrite the lesion."; } } void mitk::RelationStorage::LinkSegmentationToLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID, const SemanticTypes::Lesion& lesion) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid lesion-IDs for the current case VectorProperty* lesionVectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); if (nullptr == lesionVectorProperty) { - MITK_DEBUG << "Could not find any lesion property in the storage."; + MITK_DEBUG << "Could not find any lesion in the storage."; return; } - std::vector lesionVectorValue = lesionVectorProperty->GetValue(); - const auto existingLesion = std::find(lesionVectorValue.begin(), lesionVectorValue.end(), lesion.UID); - if (existingLesion != lesionVectorValue.end()) + std::vector lesionVectorPropertyValue = lesionVectorProperty->GetValue(); + const auto existingLesion = std::find(lesionVectorPropertyValue.begin(), lesionVectorPropertyValue.end(), lesion.UID); + if (existingLesion != lesionVectorPropertyValue.end()) { // set / overwrite the lesion reference of the given segmentation // retrieve a vector property that contains the referenced ID of a segmentation (0. image ID 1. lesion ID) VectorProperty* segmentationVectorProperty = dynamic_cast*>(propertyList->GetProperty(segmentationID)); if (nullptr == segmentationVectorProperty) { - MITK_DEBUG << "Could not find the segmentation node " << segmentationID << " in the storage. Cannot link segmentation to lesion."; + MITK_DEBUG << "Could not find the segmentation " << segmentationID << " in the storage. Cannot link segmentation to lesion."; return; } - std::vector segmentationVectorValue = segmentationVectorProperty->GetValue(); - if (segmentationVectorValue.size() != 2) + std::vector segmentationVectorPropertyValue = segmentationVectorProperty->GetValue(); + if (segmentationVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect segmentation storage. Not two (2) IDs stored."; return; } // the lesion ID of a segmentation is the second value in the vector - segmentationVectorValue[1] = lesion.UID; - segmentationVectorProperty->SetValue(segmentationVectorValue); + segmentationVectorPropertyValue[1] = lesion.UID; + segmentationVectorProperty->SetValue(segmentationVectorPropertyValue); return; } MITK_DEBUG << "Could not find lesion " << lesion.UID << " in the storage. Cannot link segmentation to lesion."; } void mitk::RelationStorage::UnlinkSegmentationFromLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the referenced ID of a segmentation (0. image ID 1. lesion ID) VectorProperty* segmentationVectorProperty = dynamic_cast*>(propertyList->GetProperty(segmentationID)); if (nullptr == segmentationVectorProperty) { - MITK_DEBUG << "Could not find the segmentation node " << segmentationID << " in the storage. Cannot unlink lesion from segmentation."; + MITK_DEBUG << "Could not find the segmentation " << segmentationID << " in the storage. Cannot unlink lesion from segmentation."; return; } - std::vector segmentationVectorValue = segmentationVectorProperty->GetValue(); + std::vector segmentationVectorPropertyValue = segmentationVectorProperty->GetValue(); // a segmentation has to have exactly two values (the ID of the linked image and the ID of the lesion) - if (segmentationVectorValue.size() != 2) + if (segmentationVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return; } - // the second value of the data node vector is the ID of the referenced lesion + // the second value of the segmentation vector is the ID of the referenced lesion // set the lesion reference to an empty string for removal - segmentationVectorValue[1] = ""; - segmentationVectorProperty->SetValue(segmentationVectorValue); + segmentationVectorPropertyValue[1] = ""; + segmentationVectorProperty->SetValue(segmentationVectorPropertyValue); } void mitk::RelationStorage::RemoveLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid lesions of the current case VectorProperty* lesionVectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); if (nullptr == lesionVectorProperty) { - MITK_DEBUG << "Could not find any lesion property in the storage."; + MITK_DEBUG << "Could not find any lesion in the storage."; return; } // remove the lesion reference from the list of all lesions of the current case - std::vector lesionVectorValue = lesionVectorProperty->GetValue(); - lesionVectorValue.erase(std::remove(lesionVectorValue.begin(), lesionVectorValue.end(), lesion.UID), lesionVectorValue.end()); - if (lesionVectorValue.empty()) + std::vector lesionsVectorPropertyValue = lesionVectorProperty->GetValue(); + lesionsVectorPropertyValue.erase(std::remove(lesionsVectorPropertyValue.begin(), lesionsVectorPropertyValue.end(), lesion.UID), lesionsVectorPropertyValue.end()); + if (lesionsVectorPropertyValue.empty()) { // no more lesions stored -> remove the lesions property list propertyList->DeleteProperty("lesions"); } else { // or store the modified vector value - lesionVectorProperty->SetValue(lesionVectorValue); + lesionVectorProperty->SetValue(lesionsVectorPropertyValue); } // remove the lesion instance itself // the lesion data is stored under the lesion ID VectorProperty* lesionDataProperty = dynamic_cast*>(propertyList->GetProperty(lesion.UID)); if (nullptr == lesionDataProperty) { MITK_DEBUG << "Lesion " << lesion.UID << " not found (already removed?). Cannot remove the lesion."; return; } std::vector lesionData = lesionDataProperty->GetValue(); // a lesion date has to have exactly two values (the name of the lesion and the UID of the lesion class) if (lesionData.size() != 2) { MITK_DEBUG << "Incorrect lesion data storage. Not two (2) strings of the lesion UID and the lesion name are stored."; } else { std::string lesionClassID = lesionData[1]; RemoveLesionClass(caseID, lesionClassID); } propertyList->DeleteProperty(lesion.UID); } void mitk::RelationStorage::RemoveLesionClass(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& lesionClassID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the lesion class StringProperty* lesionClassProperty = dynamic_cast(propertyList->GetProperty(lesionClassID)); if (nullptr == lesionClassProperty) { MITK_DEBUG << "Lesion class " << lesionClassID << " not found (already removed?). Cannot remove the lesion class."; return; } // retrieve a vector property that contains the valid lesions of the current case VectorProperty* lesionVectorProperty = dynamic_cast*>(propertyList->GetProperty("lesions")); if (nullptr == lesionVectorProperty) { return; } // check if the lesion class ID is referenced by any other lesion - std::vector lesionVectorValue = lesionVectorProperty->GetValue(); - const auto existingLesionClass = std::find_if(lesionVectorValue.begin(), lesionVectorValue.end(), + std::vector lesionsVectorPropertyValue = lesionVectorProperty->GetValue(); + const auto existingLesionClass = std::find_if(lesionsVectorPropertyValue.begin(), lesionsVectorPropertyValue.end(), [&propertyList, &lesionClassID](const std::string& lesionID) { VectorProperty* lesionDataProperty = dynamic_cast*>(propertyList->GetProperty(lesionID)); if (nullptr == lesionDataProperty) { return false; } std::vector lesionData = lesionDataProperty->GetValue(); // a lesion date has to have exactly two values (the name of the lesion and the UID of the lesion class) if (lesionData.size() != 2) { return false; } return lesionData[1] == lesionClassID; }); - if (existingLesionClass == lesionVectorValue.end()) + if (existingLesionClass == lesionsVectorPropertyValue.end()) { // lesion class ID not referenced; remove lesion class propertyList->DeleteProperty(lesionClassID); } } void mitk::RelationStorage::AddControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid controlPoint UIDs for the current case - VectorProperty::Pointer controlPointVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); - std::vector controlPointVectorValue; - if (nullptr == controlPointVectorProperty) + VectorProperty::Pointer controlPointsVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); + std::vector controlPointsVectorPropertyValue; + if (nullptr == controlPointsVectorProperty) { - controlPointVectorProperty = VectorProperty::New(); + controlPointsVectorProperty = VectorProperty::New(); } else { - controlPointVectorValue = controlPointVectorProperty->GetValue(); + controlPointsVectorPropertyValue = controlPointsVectorProperty->GetValue(); } - const auto existingControlPoint = std::find(controlPointVectorValue.begin(), controlPointVectorValue.end(), controlPoint.UID); - if (existingControlPoint != controlPointVectorValue.end()) + const auto existingControlPoint = std::find(controlPointsVectorPropertyValue.begin(), controlPointsVectorPropertyValue.end(), controlPoint.UID); + if (existingControlPoint != controlPointsVectorPropertyValue.end()) { return; } // add the new control point UID from the given control point to the vector of all current control point UIDs - controlPointVectorValue.push_back(controlPoint.UID); + controlPointsVectorPropertyValue.push_back(controlPoint.UID); // overwrite the current vector property with the new, extended string vector - controlPointVectorProperty->SetValue(controlPointVectorValue); - propertyList->SetProperty("controlpoints", controlPointVectorProperty); + controlPointsVectorProperty->SetValue(controlPointsVectorPropertyValue); + propertyList->SetProperty("controlpoints", controlPointsVectorProperty); // store the control point values (the three integer values of a date) std::vector controlPointDate; controlPointDate.push_back(controlPoint.date.year()); controlPointDate.push_back(controlPoint.date.month()); controlPointDate.push_back(controlPoint.date.day()); VectorProperty::Pointer newControlPointVectorProperty = VectorProperty::New(); newControlPointVectorProperty->SetValue(controlPointDate); propertyList->SetProperty(controlPoint.UID, newControlPointVectorProperty); } -void mitk::RelationStorage::LinkDataToControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& dataNodeID, const SemanticTypes::ControlPoint& controlPoint) +void mitk::RelationStorage::LinkImageToControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID, const SemanticTypes::ControlPoint& controlPoint) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid controlPoint UIDs for the current case - VectorProperty* controlPointVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); - if (nullptr == controlPointVectorProperty) + VectorProperty* controlPointsVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); + if (nullptr == controlPointsVectorProperty) { - MITK_DEBUG << "Could not find any control point property in the storage."; + MITK_DEBUG << "Could not find any control point in the storage."; return; } - std::vector controlPointVectorValue = controlPointVectorProperty->GetValue(); - const auto existingControlPoint = std::find(controlPointVectorValue.begin(), controlPointVectorValue.end(), controlPoint.UID); - if (existingControlPoint != controlPointVectorValue.end()) + std::vector controlPointsVectorPropertyValue = controlPointsVectorProperty->GetValue(); + const auto existingControlPoint = std::find(controlPointsVectorPropertyValue.begin(), controlPointsVectorPropertyValue.end(), controlPoint.UID); + if (existingControlPoint != controlPointsVectorPropertyValue.end()) { // set / overwrite the control point reference of the given data - // retrieve a vector property that contains the referenced ID of a data node (0. information type 1. control point ID) - VectorProperty* dataNodeVectorProperty = dynamic_cast*>(propertyList->GetProperty(dataNodeID)); - if (nullptr == dataNodeVectorProperty) + // retrieve a vector property that contains the referenced ID of a image (0. information type 1. control point ID) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) { - MITK_DEBUG << "Could not find the data node " << dataNodeID << " in the storage. Cannot link data to control point."; + MITK_DEBUG << "Could not find the image " << imageID << " in the storage. Cannot link data to control point."; return; } - std::vector dataNodeVectorValue = dataNodeVectorProperty->GetValue(); - // an image node has to have exactly two values (the information type and the ID of the control point) - if (dataNodeVectorValue.size() != 2) + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return; } - // the second value of the data node vector is the ID of the referenced control point - dataNodeVectorValue[1] = controlPoint.UID; - dataNodeVectorProperty->SetValue(dataNodeVectorValue); + // the second value of the image vector is the ID of the referenced control point + imageVectorPropertyValue[1] = controlPoint.UID; + imageVectorProperty->SetValue(imageVectorPropertyValue); return; } MITK_DEBUG << "Could not find control point " << controlPoint.UID << " in the storage. Cannot link data to control point."; } -void mitk::RelationStorage::UnlinkDataFromControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& dataNodeID) +void mitk::RelationStorage::UnlinkImageFromControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the referenced ID of a date (0. information type 1. control point ID) - VectorProperty* dataNodeVectorProperty = dynamic_cast*>(propertyList->GetProperty(dataNodeID)); - if (nullptr == dataNodeVectorProperty) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) { - MITK_DEBUG << "Could not find the date " << dataNodeID << " in the storage. Cannot unlink control point from date."; + MITK_DEBUG << "Could not find the date " << imageID << " in the storage. Cannot unlink control point from date."; return; } - std::vector dataNodeVectorValue = dataNodeVectorProperty->GetValue(); - // a data node has to have exactly two values (the information type and the ID of the control point) - if (dataNodeVectorValue.size() != 2) + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return; } - // the second value of the data node vector is the ID of the referenced control point + // the second value of the image vector is the ID of the referenced control point // set the control point reference to an empty string for removal - dataNodeVectorValue[1] = ""; - dataNodeVectorProperty->SetValue(dataNodeVectorValue); + imageVectorPropertyValue[1] = ""; + imageVectorProperty->SetValue(imageVectorPropertyValue); } void mitk::RelationStorage::RemoveControlPointFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid controlPoint UIDs for the current case - VectorProperty* allControlPointsVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); - if (nullptr == allControlPointsVectorProperty) + VectorProperty* controlPointsVectorProperty = dynamic_cast*>(propertyList->GetProperty("controlpoints")); + if (nullptr == controlPointsVectorProperty) { - MITK_DEBUG << "Could not find any control point property in the storage."; + MITK_DEBUG << "Could not find any control point in the storage."; return; } // remove the control point reference from the list of all control points of the current case - std::vector currentControlPointVectorValue = allControlPointsVectorProperty->GetValue(); - currentControlPointVectorValue.erase(std::remove(currentControlPointVectorValue.begin(), currentControlPointVectorValue.end(), controlPoint.UID), currentControlPointVectorValue.end()); - allControlPointsVectorProperty->SetValue(currentControlPointVectorValue); + std::vector controlPointsVectorPropertyValue = controlPointsVectorProperty->GetValue(); + controlPointsVectorPropertyValue.erase(std::remove(controlPointsVectorPropertyValue.begin(), controlPointsVectorPropertyValue.end(), controlPoint.UID), controlPointsVectorPropertyValue.end()); + controlPointsVectorProperty->SetValue(controlPointsVectorPropertyValue); // remove the control point instance itself propertyList->DeleteProperty(controlPoint.UID); } void mitk::RelationStorage::AddExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid examination period UIDs for the current case - VectorProperty::Pointer vectorProperty = dynamic_cast*>(propertyList->GetProperty("examinationperiods")); - std::vector examinationPeriodsVectorValue; - if (nullptr == vectorProperty) + VectorProperty::Pointer examinationPeriodsVectorProperty = dynamic_cast*>(propertyList->GetProperty("examinationperiods")); + std::vector examinationPeriodsVectorPropertyValue; + if (nullptr == examinationPeriodsVectorProperty) { - vectorProperty = VectorProperty::New(); + examinationPeriodsVectorProperty = VectorProperty::New(); } else { - examinationPeriodsVectorValue = vectorProperty->GetValue(); + examinationPeriodsVectorPropertyValue = examinationPeriodsVectorProperty->GetValue(); } - const auto& existingIndex = std::find(examinationPeriodsVectorValue.begin(), examinationPeriodsVectorValue.end(), examinationPeriod.UID); - if (existingIndex != examinationPeriodsVectorValue.end()) + const auto& existingIndex = std::find(examinationPeriodsVectorPropertyValue.begin(), examinationPeriodsVectorPropertyValue.end(), examinationPeriod.UID); + if (existingIndex != examinationPeriodsVectorPropertyValue.end()) { return; } // add the new examination period id from the given examination period to the vector of all current examination period UIDs - examinationPeriodsVectorValue.push_back(examinationPeriod.UID); + examinationPeriodsVectorPropertyValue.push_back(examinationPeriod.UID); // overwrite the current vector property with the new, extended string vector - vectorProperty->SetValue(examinationPeriodsVectorValue); - propertyList->SetProperty("examinationperiods", vectorProperty); + examinationPeriodsVectorProperty->SetValue(examinationPeriodsVectorPropertyValue); + propertyList->SetProperty("examinationperiods", examinationPeriodsVectorProperty); // add the examination period with the UID as the key and the name as as the vector value std::vector examinationPeriodData; examinationPeriodData.push_back(examinationPeriod.name); VectorProperty::Pointer newExaminationPeriodVectorProperty = VectorProperty::New(); newExaminationPeriodVectorProperty->SetValue(examinationPeriodData); propertyList->SetProperty(examinationPeriod.UID, newExaminationPeriodVectorProperty); } -void mitk::RelationStorage::AddControlPointToExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod examinationPeriod) +void mitk::RelationStorage::AddControlPointToExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod& examinationPeriod) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the represented control point UIDs of the given examination period VectorProperty* controlPointUIDsVectorProperty = dynamic_cast*>(propertyList->GetProperty(examinationPeriod.UID)); if (nullptr == controlPointUIDsVectorProperty) { MITK_DEBUG << "Could not find the examination period " << examinationPeriod.UID << " in the storage. Cannot add the control point to the examination period."; return; } - std::vector controlPointUIDsVectorValue = controlPointUIDsVectorProperty->GetValue(); + std::vector controlPointUIDsVectorPropertyValue = controlPointUIDsVectorProperty->GetValue(); // store the control point UID - controlPointUIDsVectorValue.push_back(controlPoint.UID); + controlPointUIDsVectorPropertyValue.push_back(controlPoint.UID); // sort the vector according to the date of the control points referenced by the UIDs auto lambda = [&caseID](const SemanticTypes::ID& leftControlPointUID, const SemanticTypes::ID& rightControlPointUID) { const auto& leftControlPoint = GenerateControlpoint(caseID, leftControlPointUID); const auto& rightControlPoint = GenerateControlpoint(caseID, rightControlPointUID); return leftControlPoint.date <= rightControlPoint.date; }; - std::sort(controlPointUIDsVectorValue.begin(), controlPointUIDsVectorValue.end(), lambda); + std::sort(controlPointUIDsVectorPropertyValue.begin(), controlPointUIDsVectorPropertyValue.end(), lambda); // store the modified and sorted control point UID vector of this examination period - controlPointUIDsVectorProperty->SetValue(controlPointUIDsVectorValue); + controlPointUIDsVectorProperty->SetValue(controlPointUIDsVectorPropertyValue); } -void mitk::RelationStorage::RemoveControlPointFromExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod examinationPeriod) +void mitk::RelationStorage::RemoveControlPointFromExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod& examinationPeriod) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the represented control point UIDs of the given examination period VectorProperty* controlPointUIDsVectorProperty = dynamic_cast*>(propertyList->GetProperty(examinationPeriod.UID)); if (nullptr == controlPointUIDsVectorProperty) { MITK_DEBUG << "Could not find examination period " << examinationPeriod.UID << " in the storage. Cannot add the control point to the examination period."; return; } - std::vector controlPointUIDsVectorValue = controlPointUIDsVectorProperty->GetValue(); + std::vector controlPointUIDsVectorPropertyValue = controlPointUIDsVectorProperty->GetValue(); // an examination period has an arbitrary number of vector values (name and control point UIDs) (at least one for the name) - if (controlPointUIDsVectorValue.size() < 2) + if (controlPointUIDsVectorPropertyValue.size() < 2) { MITK_DEBUG << "Incorrect examination period storage. At least one (1) control point ID has to be stored."; return; } else { - controlPointUIDsVectorValue.erase(std::remove(controlPointUIDsVectorValue.begin(), controlPointUIDsVectorValue.end(), controlPoint.UID), controlPointUIDsVectorValue.end()); - if (controlPointUIDsVectorValue.size() < 2) + controlPointUIDsVectorPropertyValue.erase(std::remove(controlPointUIDsVectorPropertyValue.begin(), controlPointUIDsVectorPropertyValue.end(), controlPoint.UID), controlPointUIDsVectorPropertyValue.end()); + if (controlPointUIDsVectorPropertyValue.size() < 2) { RemoveExaminationPeriodFromCase(caseID, examinationPeriod); } else { // store the modified vector value - controlPointUIDsVectorProperty->SetValue(controlPointUIDsVectorValue); + controlPointUIDsVectorProperty->SetValue(controlPointUIDsVectorPropertyValue); } } } -void mitk::RelationStorage::RemoveExaminationPeriodFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod examinationPeriod) +void mitk::RelationStorage::RemoveExaminationPeriodFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid examination period UIDs for the current case - VectorProperty::Pointer vectorProperty = dynamic_cast*>(propertyList->GetProperty("examinationperiods")); - if (nullptr == vectorProperty) + VectorProperty::Pointer examinationPeriodsVectorProperty = dynamic_cast*>(propertyList->GetProperty("examinationperiods")); + if (nullptr == examinationPeriodsVectorProperty) { MITK_DEBUG << "Could not find any examination periods in the storage."; return; } - std::vector examinationPeriodVectorValue = vectorProperty->GetValue(); - examinationPeriodVectorValue.erase(std::remove(examinationPeriodVectorValue.begin(), examinationPeriodVectorValue.end(), examinationPeriod.UID), examinationPeriodVectorValue.end()); - if (examinationPeriodVectorValue.empty()) + std::vector examinationPeriodsVectorPropertyValue = examinationPeriodsVectorProperty->GetValue(); + examinationPeriodsVectorPropertyValue.erase(std::remove(examinationPeriodsVectorPropertyValue.begin(), examinationPeriodsVectorPropertyValue.end(), examinationPeriod.UID), examinationPeriodsVectorPropertyValue.end()); + if (examinationPeriodsVectorPropertyValue.empty()) { // no more examination periods stored -> remove the examination period property list propertyList->DeleteProperty("examinationperiods"); } else { // or store the modified vector value - vectorProperty->SetValue(examinationPeriodVectorValue); + examinationPeriodsVectorProperty->SetValue(examinationPeriodsVectorPropertyValue); } } -void mitk::RelationStorage::AddInformationTypeToImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID, const SemanticTypes::InformationType informationType) +void mitk::RelationStorage::AddInformationTypeToImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID, const SemanticTypes::InformationType& informationType) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid information types of the current case - VectorProperty::Pointer informationTypeVectorProperty = dynamic_cast*>(propertyList->GetProperty("informationtypes")); - std::vector informationTypeVectorValue; - if (nullptr == informationTypeVectorProperty) + VectorProperty::Pointer informationTypesVectorProperty = dynamic_cast*>(propertyList->GetProperty("informationtypes")); + std::vector informationTypesVectorPropertyValue; + if (nullptr == informationTypesVectorProperty) { - informationTypeVectorProperty = VectorProperty::New(); + informationTypesVectorProperty = VectorProperty::New(); } else { - informationTypeVectorValue = informationTypeVectorProperty->GetValue(); + informationTypesVectorPropertyValue = informationTypesVectorProperty->GetValue(); } - const auto existingInformationType = std::find(informationTypeVectorValue.begin(), informationTypeVectorValue.end(), informationType); - if (existingInformationType == informationTypeVectorValue.end()) + const auto existingInformationType = std::find(informationTypesVectorPropertyValue.begin(), informationTypesVectorPropertyValue.end(), informationType); + if (existingInformationType == informationTypesVectorPropertyValue.end()) { // at first: add the information type to the storage - informationTypeVectorValue.push_back(informationType); - informationTypeVectorProperty->SetValue(informationTypeVectorValue); - propertyList->SetProperty("informationtypes", informationTypeVectorProperty); + informationTypesVectorPropertyValue.push_back(informationType); + informationTypesVectorProperty->SetValue(informationTypesVectorPropertyValue); + propertyList->SetProperty("informationtypes", informationTypesVectorProperty); } // set / overwrite the information type of the given data // retrieve a vector property that contains the referenced ID of an image (0. information type 1. control point ID) - VectorProperty* imageNodeVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); - if (nullptr == imageNodeVectorProperty) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) { MITK_DEBUG << "Could not find the image " << imageID << " in the storage. Cannot add information type to image."; return; } - std::vector imageNodeVectorValue = imageNodeVectorProperty->GetValue(); - // an image node has to have exactly two values (the information type and the ID of the control point) - if (imageNodeVectorValue.size() != 2) + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return; } - // the first value of the data node vector is the information type - imageNodeVectorValue[0] = informationType; - imageNodeVectorProperty->SetValue(imageNodeVectorValue); + // the first value of the image vector is the information type + imageVectorPropertyValue[0] = informationType; + imageVectorProperty->SetValue(imageVectorPropertyValue); } void mitk::RelationStorage::RemoveInformationTypeFromImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the referenced ID of an image (0. information type 1. control point ID) - VectorProperty* imageNodeVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); - if (nullptr == imageNodeVectorProperty) + VectorProperty* imageVectorProperty = dynamic_cast*>(propertyList->GetProperty(imageID)); + if (nullptr == imageVectorProperty) { MITK_DEBUG << "Could not find the image " << imageID << " in the storage. Cannot remove information type from image."; return; } - std::vector imageNodeVectorValue = imageNodeVectorProperty->GetValue(); - // an image node has to have exactly two values (the information type and the ID of the control point) - if (imageNodeVectorValue.size() != 2) + std::vector imageVectorPropertyValue = imageVectorProperty->GetValue(); + // an image has to have exactly two values (the information type and the ID of the control point) + if (imageVectorPropertyValue.size() != 2) { MITK_DEBUG << "Incorrect data storage. Not two (2) values stored."; return; } - // the first value of the data node vector is the information type + // the first value of the image vector is the information type // set the information type to an empty string for removal - imageNodeVectorValue[0] = ""; - imageNodeVectorProperty->SetValue(imageNodeVectorValue); + imageVectorPropertyValue[0] = ""; + imageVectorProperty->SetValue(imageVectorPropertyValue); } -void mitk::RelationStorage::RemoveInformationTypeFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType informationType) +void mitk::RelationStorage::RemoveInformationTypeFromCase(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) { PropertyList::Pointer propertyList = GetStorageData(caseID); if (nullptr == propertyList) { MITK_DEBUG << "Could not find the property list " << caseID << " for the current MITK workbench / session."; return; } // retrieve a vector property that contains the valid information types of the current case - VectorProperty* informationTypeVectorProperty = dynamic_cast*>(propertyList->GetProperty("informationtypes")); - if (nullptr == informationTypeVectorProperty) + VectorProperty* informationTypesVectorProperty = dynamic_cast*>(propertyList->GetProperty("informationtypes")); + if (nullptr == informationTypesVectorProperty) { - MITK_DEBUG << "Could not find any information type property in the storage."; + MITK_DEBUG << "Could not find any information type in the storage."; return; } - std::vector informationTypeVectorValue = informationTypeVectorProperty->GetValue(); - informationTypeVectorValue.erase(std::remove(informationTypeVectorValue.begin(), informationTypeVectorValue.end(), informationType), informationTypeVectorValue.end()); - if (informationTypeVectorValue.empty()) + std::vector informationTypesVectorPropertyValue = informationTypesVectorProperty->GetValue(); + informationTypesVectorPropertyValue.erase(std::remove(informationTypesVectorPropertyValue.begin(), informationTypesVectorPropertyValue.end(), informationType), informationTypesVectorPropertyValue.end()); + if (informationTypesVectorPropertyValue.empty()) { // no more information types stored -> remove the information types property list propertyList->DeleteProperty("informationtypes"); } else { // or store the modified vector value - informationTypeVectorProperty->SetValue(informationTypeVectorValue); + informationTypesVectorProperty->SetValue(informationTypesVectorPropertyValue); } } diff --git a/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp b/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp index 9f3bdf1d59..f124b56c0e 100644 --- a/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp +++ b/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp @@ -1,394 +1,322 @@ /*=================================================================== 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 "mitkSemanticRelationsInference.h" // semantic relations module #include "mitkControlPointManager.h" #include "mitkDICOMHelper.h" #include "mitkNodePredicates.h" #include "mitkRelationStorage.h" #include "mitkSemanticRelationException.h" /************************************************************************/ /* functions to get instances / attributes */ /************************************************************************/ -mitk::SemanticTypes::LesionVector mitk::SemanticRelationsInference::GetAllLesionsOfCase(const SemanticTypes::CaseID& caseID) -{ - return RelationStorage::GetAllLesionsOfCase(caseID); -} - mitk::SemanticTypes::LesionClassVector mitk::SemanticRelationsInference::GetAllLesionClassesOfCase(const SemanticTypes::CaseID& caseID) { - SemanticTypes::LesionVector allLesionsOfCase = GetAllLesionsOfCase(caseID); + SemanticTypes::LesionVector allLesionsOfCase = RelationStorage::GetAllLesionsOfCase(caseID); SemanticTypes::LesionClassVector allLesionClassesOfCase; for (const auto& lesion : allLesionsOfCase) { allLesionClassesOfCase.push_back(lesion.lesionClass); } // remove duplicate entries auto lessThan = [](const SemanticTypes::LesionClass& lesionClassLeft, const SemanticTypes::LesionClass& lesionClassRight) { return lesionClassLeft.UID < lesionClassRight.UID; }; auto equal = [](const SemanticTypes::LesionClass& lesionClassLeft, const SemanticTypes::LesionClass& lesionClassRight) { return lesionClassLeft.UID == lesionClassRight.UID; }; std::sort(allLesionClassesOfCase.begin(), allLesionClassesOfCase.end(), lessThan); allLesionClassesOfCase.erase(std::unique(allLesionClassesOfCase.begin(), allLesionClassesOfCase.end(), equal), allLesionClassesOfCase.end()); return allLesionClassesOfCase; } mitk::SemanticTypes::Lesion mitk::SemanticRelationsInference::GetRepresentedLesion(const DataNode* segmentationNode) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(segmentationNode); SemanticTypes::ID segmentationID = GetIDFromDataNode(segmentationNode); - SemanticTypes::Lesion representedLesion = GetRepresentedLesion(caseID, segmentationID); - - if (representedLesion.UID.empty()) - { - mitkThrowException(SemanticRelationException) << "Could not find a represented lesion instance for the given segmentation node " << segmentationNode->GetName(); - } - else - { - return representedLesion; - } -} - -mitk::SemanticTypes::Lesion mitk::SemanticRelationsInference::GetRepresentedLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) -{ - SemanticTypes::Lesion representedLesion = RelationStorage::GetRepresentedLesion(caseID, segmentationID); - - if (representedLesion.UID.empty()) - { - mitkThrowException(SemanticRelationException) << "Could not find a represented lesion instance for the given segmentation node ID " << segmentationID; - } - else - { - return representedLesion; - } + return RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); } bool mitk::SemanticRelationsInference::IsRepresentingALesion(const DataNode* segmentationNode) { try { SemanticTypes::Lesion representedLesion = GetRepresentedLesion(segmentationNode); - return true; + if (representedLesion.UID.empty()) + { + return false; + } } catch (const Exception&) { return false; } + + return true; } bool mitk::SemanticRelationsInference::IsRepresentingALesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) { - try - { - SemanticTypes::Lesion representedLesion = GetRepresentedLesion(caseID, segmentationID); - return true; - } - catch (const Exception&) + SemanticTypes::Lesion representedLesion = RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); + if (representedLesion.UID.empty()) { return false; } + + return true; } bool mitk::SemanticRelationsInference::IsLesionPresentOnSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ID& segmentationID) { - try - { - const auto representedLesion = GetRepresentedLesion(caseID, segmentationID); - return lesion.UID == representedLesion.UID; - } - catch (const SemanticRelationException&) - { - return false; - } + const auto representedLesion = RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); + return lesion.UID == representedLesion.UID; } bool mitk::SemanticRelationsInference::InstanceExists(const DataNode* dataNode) { try { SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(dataNode); SemanticTypes::ID dataNodeID = GetIDFromDataNode(dataNode); if (NodePredicates::GetImagePredicate()->CheckNode(dataNode)) { std::vector allImageIDsOfCase = RelationStorage::GetAllImageIDsOfCase(caseID); return std::find(allImageIDsOfCase.begin(), allImageIDsOfCase.end(), dataNodeID) != allImageIDsOfCase.end(); } else if (NodePredicates::GetSegmentationPredicate()->CheckNode(dataNode)) { std::vector allSegmentationIDsOfCase = RelationStorage::GetAllSegmentationIDsOfCase(caseID); return std::find(allSegmentationIDsOfCase.begin(), allSegmentationIDsOfCase.end(), dataNodeID) != allSegmentationIDsOfCase.end(); } else { return false; } } catch (const SemanticRelationException&) { return false; } } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { - SemanticTypes::LesionVector allLesions = GetAllLesionsOfCase(caseID); + SemanticTypes::LesionVector allLesions = RelationStorage::GetAllLesionsOfCase(caseID); // filter all lesions: check for equality with the given lesion using a lambda function auto lambda = [&lesion](const SemanticTypes::Lesion& currentLesion) { return currentLesion.UID == lesion.UID; }; const auto existingLesion = std::find_if(allLesions.begin(), allLesions.end(), lambda); if (existingLesion != allLesions.end()) { return true; } else { return false; } } mitk::SemanticTypes::IDVector mitk::SemanticRelationsInference::GetAllSegmentationIDsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { if (InstanceExists(caseID, lesion)) { // lesion exists, retrieve all case segmentations from the storage SemanticTypes::IDVector allSegmentationIDs = RelationStorage::GetAllSegmentationIDsOfCase(caseID); // filter all segmentationIDs: check for semantic relation with the given lesion using a lambda function auto lambda = [&lesion, caseID](const SemanticTypes::ID& segmentationID) { - try - { - SemanticTypes::Lesion representedLesion = GetRepresentedLesion(caseID, segmentationID); - return lesion.UID != representedLesion.UID; - } - catch (const SemanticRelationException&) - { - return true; - } + SemanticTypes::Lesion representedLesion = RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); + return lesion.UID != representedLesion.UID; }; allSegmentationIDs.erase(std::remove_if(allSegmentationIDs.begin(), allSegmentationIDs.end(), lambda), allSegmentationIDs.end()); return allSegmentationIDs; } else { mitkThrowException(SemanticRelationException) << "Could not find an existing lesion instance for the given caseID " << caseID << " and lesion " << lesion.UID << "."; } } -mitk::SemanticTypes::ControlPointVector mitk::SemanticRelationsInference::GetAllControlPointsOfCase(const SemanticTypes::CaseID& caseID) -{ - return RelationStorage::GetAllControlPointsOfCase(caseID); -} - mitk::SemanticTypes::ControlPoint mitk::SemanticRelationsInference::GetControlPointOfImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); SemanticTypes::ID dataNodeID = GetIDFromDataNode(imageNode); - return GetControlPointOfImage(caseID, dataNodeID); -} - -mitk::SemanticTypes::ControlPoint mitk::SemanticRelationsInference::GetControlPointOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) -{ - return RelationStorage::GetControlPointOfImage(caseID, imageID); -} - -mitk::SemanticTypes::IDVector mitk::SemanticRelationsInference::GetAllImageIDsOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) -{ - if (InstanceExists(caseID, controlPoint)) - { - // control point exists, retrieve all imageIDs from the storage - SemanticTypes::IDVector allImageIDs = RelationStorage::GetAllImageIDsOfCase(caseID); - - // filter all imageIDs to remove the ones with a different control point using a lambda function - auto lambda = [&controlPoint, &caseID](const SemanticTypes::ID& imageID) - { - return controlPoint.UID != RelationStorage::GetControlPointOfImage(caseID, imageID).UID; - }; - - allImageIDs.erase(std::remove_if(allImageIDs.begin(), allImageIDs.end(), lambda), allImageIDs.end()); - - return allImageIDs; - } - else - { - mitkThrowException(SemanticRelationException) << "Could not find an existing control point instance for the given caseID " << caseID << " and control point " << controlPoint.UID << "."; - } + return RelationStorage::GetControlPointOfImage(caseID, dataNodeID); } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) { - SemanticTypes::ControlPointVector allControlPoints = GetAllControlPointsOfCase(caseID); + SemanticTypes::ControlPointVector allControlPoints = RelationStorage::GetAllControlPointsOfCase(caseID); // filter all control points: check for equality with the given control point using a lambda function auto lambda = [&controlPoint](const SemanticTypes::ControlPoint& currentControlPoint) { return currentControlPoint.UID == controlPoint.UID; }; const auto existingControlPoint = std::find_if(allControlPoints.begin(), allControlPoints.end(), lambda); if (existingControlPoint != allControlPoints.end()) { return true; } else { return false; } } mitk::SemanticTypes::ExaminationPeriodVector mitk::SemanticRelationsInference::GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID& caseID) { return RelationStorage::GetAllExaminationPeriodsOfCase(caseID); } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod) { SemanticTypes::ExaminationPeriodVector allExaminationPeriods = GetAllExaminationPeriodsOfCase(caseID); // filter all examination periods: check for equality with the given examination period using a lambda function auto lambda = [&examinationPeriod](const SemanticTypes::ExaminationPeriod& currentExaminationPeriod) { return currentExaminationPeriod.UID == examinationPeriod.UID; }; const auto existingExaminationPeriod = std::find_if(allExaminationPeriods.begin(), allExaminationPeriods.end(), lambda); if (existingExaminationPeriod != allExaminationPeriods.end()) { return true; } else { return false; } } mitk::SemanticTypes::InformationTypeVector mitk::SemanticRelationsInference::GetAllInformationTypesOfCase(const SemanticTypes::CaseID& caseID) { return RelationStorage::GetAllInformationTypesOfCase(caseID); } mitk::SemanticTypes::InformationType mitk::SemanticRelationsInference::GetInformationTypeOfImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid image data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); SemanticTypes::ID imageID = GetIDFromDataNode(imageNode); return GetInformationTypeOfImage(caseID, imageID); } mitk::SemanticTypes::InformationType mitk::SemanticRelationsInference::GetInformationTypeOfImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& imageID) { return RelationStorage::GetInformationTypeOfImage(caseID, imageID); } mitk::SemanticTypes::IDVector mitk::SemanticRelationsInference::GetAllImageIDsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) { if (InstanceExists(caseID, informationType)) { // information type exists, retrieve all imageIDs from the storage SemanticTypes::IDVector allImageIDs = RelationStorage::GetAllImageIDsOfCase(caseID); // filter all images to remove the ones with a different information type using a lambda function auto lambda = [&informationType, caseID](const SemanticTypes::ID& imageID) { return informationType != RelationStorage::GetInformationTypeOfImage(caseID, imageID); }; allImageIDs.erase(std::remove_if(allImageIDs.begin(), allImageIDs.end(), lambda), allImageIDs.end()); return allImageIDs; } else { mitkThrowException(SemanticRelationException) << "Could not find an existing information type for the given caseID " << caseID << " and information type " << informationType; } } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) { SemanticTypes::InformationTypeVector allInformationTypes = GetAllInformationTypesOfCase(caseID); // filter all information types: check for equality with the given information type using a lambda function auto lambda = [&informationType](const SemanticTypes::InformationType& currentInformationType) { return currentInformationType == informationType; }; const auto existingInformationType = std::find_if(allInformationTypes.begin(), allInformationTypes.end(), lambda); if (existingInformationType != allInformationTypes.end()) { return true; } else { return false; } } std::vector mitk::SemanticRelationsInference::GetAllCaseIDs() { return RelationStorage::GetAllCaseIDs(); } void mitk::SemanticRelationsInference::ClearControlPoints(const SemanticTypes::CaseID& caseID) { - SemanticTypes::ControlPointVector allControlPointsOfCase = GetAllControlPointsOfCase(caseID); + SemanticTypes::ControlPointVector allControlPointsOfCase = RelationStorage::GetAllControlPointsOfCase(caseID); std::vector allImageIDsVectorValue = RelationStorage::GetAllImageIDsOfCase(caseID); SemanticTypes::ControlPointVector referencedControlPoints; for (const auto& imageID : allImageIDsVectorValue) { - auto controlPointOfImage = GetControlPointOfImage(caseID, imageID); + auto controlPointOfImage = RelationStorage::GetControlPointOfImage(caseID, imageID); referencedControlPoints.push_back(controlPointOfImage); } std::sort(allControlPointsOfCase.begin(), allControlPointsOfCase.end()); std::sort(referencedControlPoints.begin(), referencedControlPoints.end()); SemanticTypes::ControlPointVector nonReferencedControlPoints; std::set_difference(allControlPointsOfCase.begin(), allControlPointsOfCase.end(), referencedControlPoints.begin(), referencedControlPoints.end(), std::inserter(nonReferencedControlPoints, nonReferencedControlPoints.begin())); auto allExaminationPeriods = GetAllExaminationPeriodsOfCase(caseID); for (const auto& controlPoint : nonReferencedControlPoints) { const auto& examinationPeriod = FindExaminationPeriod(controlPoint, allExaminationPeriods); RelationStorage::RemoveControlPointFromExaminationPeriod(caseID, controlPoint, examinationPeriod); RelationStorage::RemoveControlPointFromCase(caseID, controlPoint); } } diff --git a/Modules/SemanticRelations/src/mitkSemanticRelationsIntegration.cpp b/Modules/SemanticRelations/src/mitkSemanticRelationsIntegration.cpp index 24cd6c93c3..deee49a3ab 100644 --- a/Modules/SemanticRelations/src/mitkSemanticRelationsIntegration.cpp +++ b/Modules/SemanticRelations/src/mitkSemanticRelationsIntegration.cpp @@ -1,446 +1,446 @@ /*=================================================================== 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 "mitkSemanticRelationsIntegration.h" // semantic relations module #include "mitkControlPointManager.h" #include "mitkDICOMHelper.h" #include "mitkNodePredicates.h" #include "mitkRelationStorage.h" #include "mitkSemanticRelationException.h" #include "mitkSemanticRelationsInference.h" #include "mitkUIDGeneratorBoost.h" // multi label module #include // c++ #include #include std::vector mitk::SemanticRelationsIntegration::m_ObserverVector; void mitk::SemanticRelationsIntegration::AddObserver(ISemanticRelationsObserver* observer) { std::vector::iterator existingObserver = std::find(m_ObserverVector.begin(), m_ObserverVector.end(), observer); if (existingObserver != m_ObserverVector.end()) { // no need to add the already existing observer return; } m_ObserverVector.push_back(observer); } void mitk::SemanticRelationsIntegration::RemoveObserver(ISemanticRelationsObserver* observer) { m_ObserverVector.erase(std::remove(m_ObserverVector.begin(), m_ObserverVector.end(), observer), m_ObserverVector.end()); } /************************************************************************/ /* functions to add / remove instances / attributes */ /************************************************************************/ void mitk::SemanticRelationsIntegration::AddImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } // continue with a valid data node SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); SemanticTypes::ID nodeID = GetIDFromDataNode(imageNode); RelationStorage::AddCase(caseID); RelationStorage::AddImage(caseID, nodeID); SemanticTypes::InformationType informationType = GetDICOMModalityFromDataNode(imageNode); AddInformationTypeToImage(imageNode, informationType); // set the correct control point for this image SemanticTypes::ControlPoint controlPoint = GenerateControlPoint(imageNode); SetControlPointOfData(imageNode, controlPoint); } void mitk::SemanticRelationsIntegration::RemoveImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } // continue with a valid data node SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); SemanticTypes::ID nodeID = GetIDFromDataNode(imageNode); RemoveInformationTypeFromImage(imageNode); UnlinkImageFromControlPoint(imageNode); RelationStorage::RemoveImage(caseID, nodeID); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::AddLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { if (SemanticRelationsInference::InstanceExists(caseID, lesion)) { mitkThrowException(SemanticRelationException) << "The lesion " << lesion.UID << " to add already exists for the given case."; } else { RelationStorage::AddLesion(caseID, lesion); NotifyObserver(caseID); } } void mitk::SemanticRelationsIntegration::OverwriteLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { if (SemanticRelationsInference::InstanceExists(caseID, lesion)) { RelationStorage::OverwriteLesion(caseID, lesion); NotifyObserver(caseID); } else { mitkThrowException(SemanticRelationException) << "The lesion " << lesion.UID << " to overwrite does not exist for the given case."; } } void mitk::SemanticRelationsIntegration::AddLesionAndLinkSegmentation(const DataNode* segmentationNode, const SemanticTypes::Lesion& lesion) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(segmentationNode); AddLesion(caseID, lesion); LinkSegmentationToLesion(segmentationNode, lesion); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::RemoveLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { if (SemanticRelationsInference::InstanceExists(caseID, lesion)) { SemanticTypes::IDVector allSegmentationIDsOfLesion = SemanticRelationsInference::GetAllSegmentationIDsOfLesion(caseID, lesion); if (allSegmentationIDsOfLesion.empty()) { // no more segmentations are linked to the specific lesion // the lesion can be removed from the storage RelationStorage::RemoveLesion(caseID, lesion); NotifyObserver(caseID); } else { mitkThrowException(SemanticRelationException) << "The lesion " << lesion.UID << " to remove is still referred to by a segmentation node. Lesion will not be removed."; } } else { mitkThrowException(SemanticRelationException) << "The lesion " << lesion.UID << " to remove does not exist for the given case."; } } void mitk::SemanticRelationsIntegration::AddSegmentation(const DataNode* segmentationNode, const DataNode* parentNode) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } if (nullptr == parentNode) { mitkThrowException(SemanticRelationException) << "Not a valid parent data node."; } // continue with a valid data node SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(segmentationNode); SemanticTypes::ID segmentationNodeID = GetIDFromDataNode(segmentationNode); SemanticTypes::ID parentNodeID = GetIDFromDataNode(parentNode); RelationStorage::AddSegmentation(caseID, segmentationNodeID, parentNodeID); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::LinkSegmentationToLesion(const DataNode* segmentationNode, const SemanticTypes::Lesion& lesion) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(segmentationNode); if (SemanticRelationsInference::InstanceExists(caseID, lesion)) { SemanticTypes::ID segmentationID = GetIDFromDataNode(segmentationNode); RelationStorage::LinkSegmentationToLesion(caseID, segmentationID, lesion); NotifyObserver(caseID); } else { mitkThrowException(SemanticRelationException) << "The lesion " << lesion.UID << " to link does not exist for the given case."; } } void mitk::SemanticRelationsIntegration::UnlinkSegmentationFromLesion(const DataNode* segmentationNode) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(segmentationNode); SemanticTypes::ID segmentationID = GetIDFromDataNode(segmentationNode); RelationStorage::UnlinkSegmentationFromLesion(caseID, segmentationID); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::RemoveSegmentation(const DataNode* segmentationNode) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } // continue with a valid data node SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(segmentationNode); SemanticTypes::ID segmentationNodeID = GetIDFromDataNode(segmentationNode); RelationStorage::RemoveSegmentation(caseID, segmentationNodeID); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::SetControlPointOfData(const DataNode* dataNode, const SemanticTypes::ControlPoint& controlPoint) { if (nullptr == dataNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(dataNode); SemanticTypes::ControlPointVector allControlPoints = RelationStorage::GetAllControlPointsOfCase(caseID); // need to check if an already existing control point fits/contains the user control point SemanticTypes::ControlPoint existingControlPoint = FindExistingControlPoint(controlPoint, allControlPoints); if (!existingControlPoint.UID.empty()) { try { // found an already existing control point LinkDataToControlPoint(dataNode, existingControlPoint, false); } catch (const SemanticRelationException&) { mitkThrowException(SemanticRelationException) << "The data can not be linked. Inconsistency in the semantic relations storage assumed."; } } else { try { AddControlPointAndLinkData(dataNode, controlPoint, false); // added a new control point // find closest control point to add the new control point to the correct examination period SemanticTypes::ControlPoint closestControlPoint = FindClosestControlPoint(controlPoint, allControlPoints); SemanticTypes::ExaminationPeriodVector allExaminationPeriods = RelationStorage::GetAllExaminationPeriodsOfCase(caseID); SemanticTypes::ExaminationPeriod examinationPeriod = FindExaminationPeriod(closestControlPoint, allExaminationPeriods); if (examinationPeriod.UID.empty()) { // no closest control point (exceed threshold) or no examination period found // create a new examination period for this control point and add it to the storage examinationPeriod.UID = UIDGeneratorBoost::GenerateUID(); examinationPeriod.name = "New examination period " + std::to_string(allExaminationPeriods.size()); AddExaminationPeriod(caseID, examinationPeriod); } // add the control point to the (newly created or found / close) examination period AddControlPointToExaminationPeriod(caseID, controlPoint, examinationPeriod); } catch (const SemanticRelationException&) { mitkThrowException(SemanticRelationException) << "The data can not be linked. Inconsistency in the semantic relations storage assumed."; } } ClearControlPoints(caseID); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::AddControlPointAndLinkData(const DataNode* dataNode, const SemanticTypes::ControlPoint& controlPoint, bool checkConsistence) { if (nullptr == dataNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(dataNode); if (SemanticRelationsInference::InstanceExists(caseID, controlPoint)) { mitkThrowException(SemanticRelationException) << "The control point " << controlPoint.UID << " to add already exists for the given case. \n Use 'LinkDataToControlPoint' instead."; } RelationStorage::AddControlPoint(caseID, controlPoint); LinkDataToControlPoint(dataNode, controlPoint, checkConsistence); } void mitk::SemanticRelationsIntegration::LinkDataToControlPoint(const DataNode* dataNode, const SemanticTypes::ControlPoint& controlPoint, bool checkConsistence) { if (nullptr == dataNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(dataNode); if (SemanticRelationsInference::InstanceExists(caseID, controlPoint)) { SemanticTypes::ID dataID = GetIDFromDataNode(dataNode); - RelationStorage::LinkDataToControlPoint(caseID, dataID, controlPoint); + RelationStorage::LinkImageToControlPoint(caseID, dataID, controlPoint); } else { mitkThrowException(SemanticRelationException) << "The control point " << controlPoint.UID << " to link does not exist for the given case."; } } void mitk::SemanticRelationsIntegration::UnlinkImageFromControlPoint(const DataNode* dataNode) { if (nullptr == dataNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(dataNode); SemanticTypes::ID dataID = GetIDFromDataNode(dataNode); SemanticTypes::ControlPoint controlPoint = RelationStorage::GetControlPointOfImage(caseID, dataID); - RelationStorage::UnlinkDataFromControlPoint(caseID, dataID); + RelationStorage::UnlinkImageFromControlPoint(caseID, dataID); ClearControlPoints(caseID); } void mitk::SemanticRelationsIntegration::AddExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod) { if (SemanticRelationsInference::InstanceExists(caseID, examinationPeriod)) { mitkThrowException(SemanticRelationException) << "The examination period " << examinationPeriod.UID << " to add already exists for the given case."; } else { RelationStorage::AddExaminationPeriod(caseID, examinationPeriod); } } void mitk::SemanticRelationsIntegration::AddControlPointToExaminationPeriod(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::ExaminationPeriod& examinationPeriod) { if (!SemanticRelationsInference::InstanceExists(caseID, controlPoint)) { mitkThrowException(SemanticRelationException) << "The control point " << controlPoint.UID << " to add does not exist for the given case."; } if (!SemanticRelationsInference::InstanceExists(caseID, examinationPeriod)) { mitkThrowException(SemanticRelationException) << "The examination period " << examinationPeriod.UID << " does not exist for the given case. \n Use 'AddExaminationPeriod' before."; } RelationStorage::AddControlPointToExaminationPeriod(caseID, controlPoint, examinationPeriod); } void mitk::SemanticRelationsIntegration::SetInformationType(const DataNode* imageNode, const SemanticTypes::InformationType& informationType) { RemoveInformationTypeFromImage(imageNode); AddInformationTypeToImage(imageNode, informationType); SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); NotifyObserver(caseID); } void mitk::SemanticRelationsIntegration::AddInformationTypeToImage(const DataNode* imageNode, const SemanticTypes::InformationType& informationType) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid image data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); SemanticTypes::ID imageID = GetIDFromDataNode(imageNode); RelationStorage::AddInformationTypeToImage(caseID, imageID, informationType); } void mitk::SemanticRelationsIntegration::RemoveInformationTypeFromImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid image data node."; } SemanticTypes::CaseID caseID = GetCaseIDFromDataNode(imageNode); SemanticTypes::ID imageID = GetIDFromDataNode(imageNode); SemanticTypes::InformationType originalInformationType = RelationStorage::GetInformationTypeOfImage(caseID, imageID); RelationStorage::RemoveInformationTypeFromImage(caseID, imageID); // check for further references to the removed information type std::vector allImageIDsVectorValue = RelationStorage::GetAllImageIDsOfCase(caseID); for (const auto& otherImageID : allImageIDsVectorValue) { SemanticTypes::InformationType otherInformationType = RelationStorage::GetInformationTypeOfImage(caseID, otherImageID); if (otherInformationType == originalInformationType) { // found the information type in another image -> cannot remove the information type from the case return; } } // given information type was not referred by any other image of the case -> the information type can be removed from the case RelationStorage::RemoveInformationTypeFromCase(caseID, originalInformationType); } /************************************************************************/ /* private functions */ /************************************************************************/ void mitk::SemanticRelationsIntegration::NotifyObserver(const SemanticTypes::CaseID& caseID) const { for (auto& observer : m_ObserverVector) { observer->Update(caseID); } } void mitk::SemanticRelationsIntegration::ClearControlPoints(const SemanticTypes::CaseID& caseID) { SemanticTypes::ControlPointVector allControlPointsOfCase = RelationStorage::GetAllControlPointsOfCase(caseID); std::vector allImageIDsVectorValue = RelationStorage::GetAllImageIDsOfCase(caseID); SemanticTypes::ControlPointVector referencedControlPoints; for (const auto& imageID : allImageIDsVectorValue) { auto controlPointOfImage = RelationStorage::GetControlPointOfImage(caseID, imageID); referencedControlPoints.push_back(controlPointOfImage); } std::sort(allControlPointsOfCase.begin(), allControlPointsOfCase.end()); std::sort(referencedControlPoints.begin(), referencedControlPoints.end()); SemanticTypes::ControlPointVector nonReferencedControlPoints; std::set_difference(allControlPointsOfCase.begin(), allControlPointsOfCase.end(), referencedControlPoints.begin(), referencedControlPoints.end(), std::inserter(nonReferencedControlPoints, nonReferencedControlPoints.begin())); auto allExaminationPeriods = RelationStorage::GetAllExaminationPeriodsOfCase(caseID); for (const auto& controlPoint : nonReferencedControlPoints) { const auto& examinationPeriod = FindExaminationPeriod(controlPoint, allExaminationPeriods); RelationStorage::RemoveControlPointFromExaminationPeriod(caseID, controlPoint, examinationPeriod); RelationStorage::RemoveControlPointFromCase(caseID, controlPoint); } }