diff --git a/Modules/SemanticRelations/include/mitkSemanticRelationsDataStorageAccess.h b/Modules/SemanticRelations/include/mitkSemanticRelationsDataStorageAccess.h index 07b2854aaf..4aaec86e9c 100644 --- a/Modules/SemanticRelations/include/mitkSemanticRelationsDataStorageAccess.h +++ b/Modules/SemanticRelations/include/mitkSemanticRelationsDataStorageAccess.h @@ -1,140 +1,158 @@ /*=================================================================== 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 MITKSEMANTICRELATIONSDATASTORAGEACCESS_H #define MITKSEMANTICRELATIONSDATASTORAGEACCESS_H #include // semantic relations module #include "mitkSemanticTypes.h" // mitk core #include #include namespace mitk { /** * @brief The API provides functions to query and manipulate 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. */ class MITKSEMANTICRELATIONS_EXPORT SemanticRelationsDataStorageAccess { public: using DataNodeVector = std::vector; SemanticRelationsDataStorageAccess(DataStorage* dataStorage); - ~SemanticRelationsDataStorageAccess(); /************************************************************************/ /* functions to get instances / attributes */ /************************************************************************/ /** * @brief Return a vector of all segmentations that are currently available for the given case. * The segmentations may be connected / not connected to a lesion of the case. * If no segmentations are stored for the current case, an empty vector is returned. * * @pre The data storage member has to be valid (!nullptr). * @throw SemanticRelationException, if the data storage member is invalid (==nullptr). * * @param caseID The current case identifier is defined by the given string. * @return A vector of data nodes representing segmentations. */ DataNodeVector GetAllSegmentationsOfCase(const SemanticTypes::CaseID& caseID) const; /** * @brief Return a vector of all 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 data storage member has to be valid (!nullptr). * @throw SemanticRelationException, if the data storage member is invalid (==nullptr). * @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. + * @param lesion A lesion with a UID that identifies the corresponding lesion instance. * @return A vector of data nodes representing segmentations that define the given lesion. */ DataNodeVector GetAllSegmentationsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) const; /** * @brief Return a vector of all images that are currently available for the given case. * * @pre The data storage member has to be valid (!nullptr). * @throw SemanticRelationException, if the data storage member is invalid (==nullptr). * * @param caseID The current case identifier is defined by the given string. * @return A vector of data nodes representing images. */ DataNodeVector GetAllImagesOfCase(const SemanticTypes::CaseID& caseID) const; /** * @brief Return a vector of all images that are connected to those segmentations that are linked to the given lesion. * 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. + * @param lesion A lesion with a UID that identifies the corresponding lesion instance. * @return A vector of data nodes representing images on which the lesions are visible. */ DataNodeVector GetAllImagesOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) const; /** * @brief Return a vector of all image nodes that are defined with the given information type and with the given control point. * * @pre The UID of the control point has to exist for a control point instance. * The information type has to exist for the given case (and is therefore used by at least one data node). * @throw SemanticRelationException, if the UID of the control point does not exist for a control point instance (this can be checked via 'InstanceExists') or * if the information type is not used by any data node (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. * @param informationType An information type that identifies the corresponding information type instance. * @return A vector of image nodes that are defined with the given information type with the given control point. */ DataNodeVector GetAllSpecificImages(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::InformationType& informationType) const; /** * @brief Return a vector of all segmentation nodes that are defined with the given information type and with the given control point. * The function uses the 'GetAllSpecificImages'-function to retrieve the specific images and then searches for the derived nodes (segmentation child nodes). * * @pre The UID of the control point has to exist for a control point instance. * The information type has to exist for the given case (and is therefore used by at least one data node). * @throw SemanticRelationException, if the UID of the control point does not exist for a control point instance (this can be checked via 'InstanceExists') or * if the information type is not used by any data node (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. * @param informationType An information type that identifies the corresponding information type instance. * @return A vector of segmentation nodes that are defined with the given information type with the given control point. */ DataNodeVector GetAllSpecificSegmentations(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::InformationType& informationType) const; + /** + * @brief Return the single segmentation node that is defined with the given information type, the given control point and is representing the given lesion. + * The function uses the 'GetAllSpecificSegmentations'-function to retrieve the specific segmentations and then checks for the represented lesion. + * + * @pre The UID of the control point has to exist for a control point instance. + * The information type has to exist for the given case (and is therefore used by at least one data node). + * The lesion has to exist for the given case. + * @throw SemanticRelationException, if the UID of the control point does not exist for a control point instance (this can be checked via 'InstanceExists') or + * if the information type is not used by any data node (this can be checked via 'InstanceExists') or + * if the lesion does not exist for the given case (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. + * @param informationType An information type that identifies the corresponding information type instance. + * @param lesion A lesion with a UID that identifies the corresponding lesion instance. + * @return A single segmentation node that is defined with the given information type, the given control point and is representing the given lesion. + */ + DataNode::Pointer GetSpecificSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, + const SemanticTypes::InformationType& informationType, const SemanticTypes::Lesion& lesion) const; private: WeakPointer m_DataStorage; }; } // namespace mitk #endif // MITKSEMANTICRELATIONSDATASTORAGEACCESS_H diff --git a/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h b/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h index fa9faeda4d..a323f62748 100644 --- a/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h +++ b/Modules/SemanticRelations/include/mitkSemanticRelationsInference.h @@ -1,292 +1,315 @@ /*=================================================================== 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 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. * * @pre The given segmentation data node has to be valid (!nullptr). * @throw SemanticRelationException, if the given segmentation 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 GetLesionOfSegmentation(const DataNode* segmentationNode); /** * @brief Returns a vector of all lesions that are currently available for the current case and are connected to the given image (via a segmentation). * If no lesions are stored for the current case, an empty vector is returned. If no segmentations are * connected with the image node, no lesions for the specific image will be found and an empty vector 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 A vector of lesions. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllLesionsOfImage(const DataNode* imageNode); /** * @brief Returns a vector of all lesions that are valid for the given case, given a specific control point. * * @param caseID The current case identifier is defined by the given string. * @param controlPoint A specific control point which has to be available at a returned (found) lesion: * Only those lesions are returned for which the image of the associated segmentation is linked to the given control point. * If the control point instance does not exist, an empty vector is returned. - * @return A vector of control points. + * @return A vector of lesions. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllLesionsOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); /** + * @brief Returns a vector of all lesions that are valid for the given case, given a specific information type. + * + * @param caseID The current case identifier is defined by the given string. + * @param informationType A specific information type which has to be available at a returned (found) lesion: + * Only those lesions are returned for which the image of the associated segmentation is of the given information type. + * If the information type instance does not exist, an empty vector is returned. + * @return A vector of lesions. + */ + MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllLesionsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType); + /** + * @brief Returns a vector of all lesions that are valid for the given case, given a specific control point and a specific information type. + * + * @param caseID The current case identifier is defined by the given string. + * @param controlPoint A specific control point which has to be available at a returned (found) lesion: + * Only those lesions are returned for which the image of the associated segmentation is linked to the given control point. + * If the control point instance does not exist, an empty vector is returned. + * @param informationType A specific information type which has to be available at a returned (found) lesion: + * Only those lesions are returned for which the image of the associated segmentation is of the given information type. + * If the information type instance does not exist, an empty vector is returned. + * @return A vector of lesions. + */ + MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllSpecificLesions(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::InformationType& informationType); + /** * @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 given data node. * 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. * * @param lesion A lesion with a UID that identifies the corresponding lesion instance. * @param dataNode A data node to check. * @return True, if the lesion is present on the data node; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool IsLesionPresent(const SemanticTypes::Lesion& lesion, const DataNode* dataNode); /** * @brief Check if the given lesion is related to the image identified by the given image ID. * Each lesion is represented by a segmentation which is connected to its parent image. * * @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 imageID The image node identifier is defined by the given string. * @return True, if the lesion is related to image identified by the given image ID; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool IsLesionPresentOnImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ID& imageID); /** * @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 lesion is present at the given control point. * * @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 controlPoint A control point with a UID that identifies the corresponding control point instance. * @return True, if the lesion is present at the given control point; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool IsLesionPresentAtControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ControlPoint& controlPoint); /** * @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 '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 image IDs that identify images that are related to the given lesion. * Each lesion is represented by a segmentation which is connected to its parent image. * If the lesion is not represented 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 images that identify images that are related to the given lesion. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::IDVector GetAllImageIDsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); /** * @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 a vector of all control points that are valid for the given case, given a specific lesion * * @param caseID The current case identifier is defined by the given string. * @param lesion A specific lesion which has to be available at a returned (found) control point: * Only those control points are returned for which an associated data has a segmentation that references the given lesion. * If the lesion does not exists, an empty vector is returned. * @return A vector of control points. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPointVector GetAllControlPointsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion); /** * @brief Return a vector of all control points that are valid for the given case, given a specific information type. * * @param caseID The current case identifier is defined by the given string. * @param informationType A specific information type which has to be available at a returned (found) control point: * Only those control points are returned for which an associated data has the given information type. * If the information type instance does not exists, an empty vector is returned. * @return A vector of control points. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPointVector GetAllControlPointsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType); /** * @brief Check if the given control point instance exists. * 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 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 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 a vector of all information types that are valid for the given case, given a specific control point. * * @param caseID The current case identifier is defined by the given string. * @param controlPoint A specific control point which has to be available at a returned (found) information type: * Only those information types are returned for which an associated data is linked to the given control point. * If the control point instance does not exist, an empty vector is returned. * @return A vector of information types. */ MITKSEMANTICRELATIONS_EXPORT SemanticTypes::InformationTypeVector GetAllInformationTypesOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint); /** * @brief Check if the given information type exists. * * @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 Determine if the given information type contains images, which are connected to segmentations that represent the given lesion. * If the lesion or the information type are not correctly stored, the function returns false. * * @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 informationType An information type that identifies the corresponding information type instance. * * @return True, if the given information type contains data that is related to the given lesion; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool SpecificImageExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::InformationType& informationType); /** * @brief Determine if the given control point contains images, which are connected to segmentations that represent the given lesion. * If the lesion or the control point are not correctly stored, the function returns false. * * @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 controlPoint A control point with a UID that identifies the corresponding control point instance. * * @return True, if the given control point contains data that is related to the given lesion; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool SpecificImageExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ControlPoint& controlPoint); /** * @brief Determine if the given control point contains images, which refer to the given information type. * If the information type or the control point are not correctly stored, the function returns false. * * @param caseID The current case identifier is defined by the given string. * @param informationType An information type that identifies the corresponding information type instance. * @param controlPoint A control point with a UID that identifies the corresponding control point instance. * * @return True, if the given control point contains data that is related to the given information type; false otherwise. */ MITKSEMANTICRELATIONS_EXPORT bool SpecificImageExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType, const SemanticTypes::ControlPoint& controlPoint); } // namespace SemanticRelationsInference } // namespace mitk #endif // MITKSEMANTICRELATIONSINFERENCE_H diff --git a/Modules/SemanticRelations/src/mitkSemanticRelationsDataStorageAccess.cpp b/Modules/SemanticRelations/src/mitkSemanticRelationsDataStorageAccess.cpp index e020f5706b..25fd91513c 100644 --- a/Modules/SemanticRelations/src/mitkSemanticRelationsDataStorageAccess.cpp +++ b/Modules/SemanticRelations/src/mitkSemanticRelationsDataStorageAccess.cpp @@ -1,236 +1,272 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSemanticRelationsDataStorageAccess.h" // semantic relations module #include "mitkControlPointManager.h" #include "mitkDICOMHelper.h" #include "mitkNodePredicates.h" #include "mitkRelationStorage.h" #include "mitkSemanticRelationException.h" #include "mitkSemanticRelationsInference.h" // c++ #include #include mitk::SemanticRelationsDataStorageAccess::SemanticRelationsDataStorageAccess(DataStorage* dataStorage) : m_DataStorage(dataStorage) { // nothing here } -mitk::SemanticRelationsDataStorageAccess::~SemanticRelationsDataStorageAccess() -{ - // nothing here -} - /************************************************************************/ /* functions to get instances / attributes */ /************************************************************************/ mitk::SemanticRelationsDataStorageAccess::DataNodeVector mitk::SemanticRelationsDataStorageAccess::GetAllSegmentationsOfCase(const SemanticTypes::CaseID& caseID) const { if (m_DataStorage.IsExpired()) { mitkThrowException(SemanticRelationException) << "Not a valid data storage."; } std::vector allSegmentationIDsOfCase = RelationStorage::GetAllSegmentationIDsOfCase(caseID); std::vector allSegmentationsOfCase; // get all segmentation nodes of the current data storage // only those nodes are respected, that are currently held in the data storage DataStorage::SetOfObjects::ConstPointer segmentationNodes = m_DataStorage.Lock()->GetSubset(NodePredicates::GetSegmentationPredicate()); for (auto it = segmentationNodes->Begin(); it != segmentationNodes->End(); ++it) { DataNode* segmentationNode = it->Value(); std::string caseID; std::string segmentationID; try { // find the corresponding segmentation node for the given segmentation ID caseID = GetCaseIDFromDataNode(segmentationNode); segmentationID = GetIDFromDataNode(segmentationNode); } catch (SemanticRelationException&) { // found a segmentation node that is not stored in the semantic relations // this segmentation node does not have any DICOM information --> exception thrown // continue with the next segmentation to compare IDs continue; } if (caseID == caseID && (std::find(allSegmentationIDsOfCase.begin(), allSegmentationIDsOfCase.end(), segmentationID) != allSegmentationIDsOfCase.end())) { // found current image node in the storage, add it to the return vector allSegmentationsOfCase.push_back(segmentationNode); } } return allSegmentationsOfCase; } mitk::SemanticRelationsDataStorageAccess::DataNodeVector mitk::SemanticRelationsDataStorageAccess::GetAllSegmentationsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) const { if (SemanticRelationsInference::InstanceExists(caseID, lesion)) { // lesion exists, retrieve all case segmentations from the storage DataNodeVector allSegmentationsOfLesion = GetAllSegmentationsOfCase(caseID); // filter all segmentations: check for semantic relation with the given lesion using a lambda function auto lambda = [&lesion, this](DataNode::Pointer segmentation) { try { SemanticTypes::Lesion representedLesion = SemanticRelationsInference::GetLesionOfSegmentation(segmentation); return lesion.UID != representedLesion.UID; } catch (const SemanticRelationException&) { return true; } }; allSegmentationsOfLesion.erase(std::remove_if(allSegmentationsOfLesion.begin(), allSegmentationsOfLesion.end(), lambda), allSegmentationsOfLesion.end()); return allSegmentationsOfLesion; } else { mitkThrowException(SemanticRelationException) << "Could not find an existing lesion instance for the given caseID " << caseID << " and lesion " << lesion.UID << "."; } } mitk::SemanticRelationsDataStorageAccess::DataNodeVector mitk::SemanticRelationsDataStorageAccess::GetAllImagesOfCase(const SemanticTypes::CaseID& caseID) const { if (m_DataStorage.IsExpired()) { mitkThrowException(SemanticRelationException) << "Not a valid data storage."; } std::vector allImageIDsOfCase = RelationStorage::GetAllImageIDsOfCase(caseID); std::vector allImagesOfCase; // get all image nodes of the current data storage // only those nodes are respected, that are currently held in the data storage DataStorage::SetOfObjects::ConstPointer imageNodes = m_DataStorage.Lock()->GetSubset(NodePredicates::GetImagePredicate()); for (auto it = imageNodes->Begin(); it != imageNodes->End(); ++it) { DataNode* imageNode = it->Value(); std::string caseID; std::string imageID; try { // find the corresponding image node for the given segmentation ID caseID = GetCaseIDFromDataNode(imageNode); imageID = GetIDFromDataNode(imageNode); } catch (SemanticRelationException&) { // found an image node that is not stored in the semantic relations // this image node does not have any DICOM information --> exception thrown // continue with the next image to compare IDs continue; } if (caseID == caseID && (std::find(allImageIDsOfCase.begin(), allImageIDsOfCase.end(), imageID) != allImageIDsOfCase.end())) { // found current image node in the storage, add it to the return vector allImagesOfCase.push_back(imageNode); } } return allImagesOfCase; } mitk::SemanticRelationsDataStorageAccess::DataNodeVector mitk::SemanticRelationsDataStorageAccess::GetAllImagesOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) const { if (m_DataStorage.IsExpired()) { mitkThrowException(SemanticRelationException) << "Not a valid data storage."; } DataNodeVector allImagesOfLesion; // 1. get all segmentations that define the lesion // 2. retrieve the parent node (source) of the found segmentation node DataNodeVector allSegmentationsOfLesion = GetAllSegmentationsOfLesion(caseID, lesion); for (const auto& segmentationNode : allSegmentationsOfLesion) { // get parent node of the current segmentation node with the node predicate DataStorage::SetOfObjects::ConstPointer parentNodes = m_DataStorage.Lock()->GetSources(segmentationNode, NodePredicates::GetImagePredicate(), false); for (auto it = parentNodes->Begin(); it != parentNodes->End(); ++it) { DataNode::Pointer dataNode = it->Value(); allImagesOfLesion.push_back(it->Value()); } } std::sort(allImagesOfLesion.begin(), allImagesOfLesion.end()); allImagesOfLesion.erase(std::unique(allImagesOfLesion.begin(), allImagesOfLesion.end()), allImagesOfLesion.end()); return allImagesOfLesion; } mitk::SemanticRelationsDataStorageAccess::DataNodeVector mitk::SemanticRelationsDataStorageAccess::GetAllSpecificImages(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::InformationType& informationType) const { if (SemanticRelationsInference::InstanceExists(caseID, controlPoint)) { if (SemanticRelationsInference::InstanceExists(caseID, informationType)) { // control point exists, information type exists, retrieve all images from the storage DataNodeVector allImagesOfCase = GetAllImagesOfCase(caseID); // filter all images to remove the ones with a different control point and information type using a lambda function auto lambda = [&controlPoint, &informationType, this](DataNode::Pointer imageNode) { return (informationType != SemanticRelationsInference::GetInformationTypeOfImage(imageNode)) || (controlPoint.date != SemanticRelationsInference::GetControlPointOfImage(imageNode).date); }; allImagesOfCase.erase(std::remove_if(allImagesOfCase.begin(), allImagesOfCase.end(), lambda), allImagesOfCase.end()); return allImagesOfCase; } else { mitkThrowException(SemanticRelationException) << "Could not find an existing information type for the given caseID " << caseID << " and information type " << informationType; } } else { mitkThrowException(SemanticRelationException) << "Could not find an existing control point for the given caseID " << caseID << " and control point " << controlPoint.UID; } } mitk::SemanticRelationsDataStorageAccess::DataNodeVector mitk::SemanticRelationsDataStorageAccess::GetAllSpecificSegmentations(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::InformationType& informationType) const { if (m_DataStorage.IsExpired()) { mitkThrow() << "Not a valid data storage."; } - DataNodeVector allSpecificImages = GetAllSpecificImages(caseID, controlPoint, informationType); + DataNodeVector allSpecificImages; + try + { + allSpecificImages = GetAllSpecificImages(caseID, controlPoint, informationType); + + } + catch (SemanticRelationException& e) + { + mitkReThrow(e) << "Cannot get the specific segmentation"; + } + DataNodeVector allSpecificSegmentations; for (const auto& imageNode : allSpecificImages) { DataStorage::SetOfObjects::ConstPointer segmentationNodes = m_DataStorage.Lock()->GetDerivations(imageNode, NodePredicates::GetSegmentationPredicate(), false); for (auto it = segmentationNodes->Begin(); it != segmentationNodes->End(); ++it) { allSpecificSegmentations.push_back(it->Value()); } } return allSpecificSegmentations; } + +mitk::DataNode::Pointer mitk::SemanticRelationsDataStorageAccess::GetSpecificSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, + const SemanticTypes::InformationType& informationType, const SemanticTypes::Lesion& lesion) const +{ + if (m_DataStorage.IsExpired()) + { + mitkThrow() << "Not a valid data storage."; + } + + DataNodeVector allSpecificSegmentations; + try + { + allSpecificSegmentations = GetAllSpecificSegmentations(caseID, controlPoint, informationType); + + } + catch (SemanticRelationException& e) + { + mitkReThrow(e) << "Cannot get the specific segmentation"; + } + + for (const auto& segmentationNode : allSpecificSegmentations) + { + SemanticTypes::Lesion representedLesion = SemanticRelationsInference::GetLesionOfSegmentation(segmentationNode); + if (representedLesion.UID == lesion.UID) + { + return segmentationNode; + } + } + + return mitk::DataNode::Pointer(); +} diff --git a/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp b/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp index 21dfdb3301..ad1ca571a5 100644 --- a/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp +++ b/Modules/SemanticRelations/src/mitkSemanticRelationsInference.cpp @@ -1,528 +1,570 @@ /*=================================================================== 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::LesionClassVector mitk::SemanticRelationsInference::GetAllLesionClassesOfCase(const SemanticTypes::CaseID& 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::GetLesionOfSegmentation(const DataNode* segmentationNode) { if (nullptr == segmentationNode) { mitkThrowException(SemanticRelationException) << "Not a valid segmentation data node."; } SemanticTypes::CaseID caseID = ""; SemanticTypes::ID segmentationID = ""; try { caseID = GetCaseIDFromDataNode(segmentationNode); segmentationID = GetIDFromDataNode(segmentationNode); } catch (SemanticRelationException& e) { mitkReThrow(e) << "Cannot get the lesion of the given segmentation data node."; } return RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); } mitk::SemanticTypes::LesionVector mitk::SemanticRelationsInference::GetAllLesionsOfImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid image data node."; } SemanticTypes::CaseID caseID = ""; SemanticTypes::ID imageID = ""; try { caseID = GetCaseIDFromDataNode(imageNode); imageID = GetIDFromDataNode(imageNode); } catch (SemanticRelationException& e) { mitkReThrow(e) << "Cannot get all lesions of the given image data node."; } SemanticTypes::LesionVector allLesionsOfImage; // 1. get all segmentations that are connected to the given image // 2. get the lesion of each segmentation // 3. guarantee uniqueness of lesions SemanticTypes::IDVector allSegmentationIDsOfImage = RelationStorage::GetAllSegmentationIDsOfImage(caseID, imageID); for (const auto& segmentationID : allSegmentationIDsOfImage) { // get represented lesion of the current segmentation SemanticTypes::Lesion representedLesion = RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); if (!representedLesion.UID.empty()) { allLesionsOfImage.push_back(representedLesion); } } // remove duplicate entries auto lessThan = [](const SemanticTypes::Lesion& lesionLeft, const SemanticTypes::Lesion& lesionRight) { return lesionLeft.UID < lesionRight.UID; }; auto equal = [](const SemanticTypes::Lesion& lesionLeft, const SemanticTypes::Lesion& lesionRight) { return lesionLeft.UID == lesionRight.UID; }; std::sort(allLesionsOfImage.begin(), allLesionsOfImage.end(), lessThan); allLesionsOfImage.erase(std::unique(allLesionsOfImage.begin(), allLesionsOfImage.end(), equal), allLesionsOfImage.end()); return allLesionsOfImage; } mitk::SemanticTypes::LesionVector mitk::SemanticRelationsInference::GetAllLesionsOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) { SemanticTypes::LesionVector allLesions = RelationStorage::GetAllLesionsOfCase(caseID); // filter the lesions: use only those, where the associated data is connected to image data that refers to the given control point using a lambda function auto lambda = [&caseID, &controlPoint](const SemanticTypes::Lesion& lesion) { return !SpecificImageExists(caseID, lesion, controlPoint); }; allLesions.erase(std::remove_if(allLesions.begin(), allLesions.end(), lambda), allLesions.end()); return allLesions; } +mitk::SemanticTypes::LesionVector mitk::SemanticRelationsInference::GetAllLesionsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) +{ + SemanticTypes::LesionVector allLesions = RelationStorage::GetAllLesionsOfCase(caseID); + + // filter the lesions: use only those, where the associated data is connected to image data that refers to the given information type using a lambda function + auto lambda = [&caseID, &informationType](const SemanticTypes::Lesion& lesion) + { + return !SpecificImageExists(caseID, lesion, informationType); + }; + + allLesions.erase(std::remove_if(allLesions.begin(), allLesions.end(), lambda), allLesions.end()); + + return allLesions; +} + +mitk::SemanticTypes::LesionVector mitk::SemanticRelationsInference::GetAllSpecificLesions(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint, const SemanticTypes::InformationType& informationType) +{ + auto allLesionsOfControlPoint = GetAllLesionsOfControlPoint(caseID, controlPoint); + auto allLesionsOfInformationType = GetAllLesionsOfInformationType(caseID, informationType); + SemanticTypes::LesionVector allLesionsIntersection; + + auto lessThan = [](const SemanticTypes::Lesion& lesionLeft, const SemanticTypes::Lesion& lesionRight) + { + return lesionLeft.UID < lesionRight.UID; + }; + + auto equal = [](const SemanticTypes::Lesion& lesionLeft, const SemanticTypes::Lesion& lesionRight) + { + return lesionLeft.UID == lesionRight.UID; + }; + + std::sort(allLesionsOfControlPoint.begin(), allLesionsOfControlPoint.end(), lessThan); + std::sort(allLesionsOfInformationType.begin(), allLesionsOfInformationType.end(), lessThan); + SemanticTypes::IDVector allImageIDsIntersection; + // set_intersection removes duplicated nodes + std::set_intersection(allLesionsOfControlPoint.begin(), allLesionsOfControlPoint.end(), + allLesionsOfInformationType.begin(), allLesionsOfInformationType.end(), + std::back_inserter(allLesionsIntersection), equal); + + return allLesionsIntersection; +} + bool mitk::SemanticRelationsInference::IsRepresentingALesion(const DataNode* segmentationNode) { SemanticTypes::Lesion representedLesion; try { representedLesion = GetLesionOfSegmentation(segmentationNode); } catch (const SemanticRelationException&) { return false; } return !representedLesion.UID.empty(); } bool mitk::SemanticRelationsInference::IsRepresentingALesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::ID& segmentationID) { SemanticTypes::Lesion representedLesion = RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); return !representedLesion.UID.empty(); } bool mitk::SemanticRelationsInference::IsLesionPresent(const SemanticTypes::Lesion& lesion, const DataNode* dataNode) { SemanticTypes::CaseID caseID = ""; SemanticTypes::ID dataNodeID = ""; try { caseID = GetCaseIDFromDataNode(dataNode); dataNodeID = GetIDFromDataNode(dataNode); } catch (const SemanticRelationException&) { return false; } if (NodePredicates::GetImagePredicate()->CheckNode(dataNode)) { return IsLesionPresentOnImage(caseID, lesion, dataNodeID); } if (NodePredicates::GetSegmentationPredicate()->CheckNode(dataNode)) { return IsLesionPresentOnSegmentation(caseID, lesion, dataNodeID); } return false; } bool mitk::SemanticRelationsInference::IsLesionPresentOnImage(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ID& imageID) { SemanticTypes::IDVector allImageIDsOfLesion; try { allImageIDsOfLesion = GetAllImageIDsOfLesion(caseID, lesion); } catch (SemanticRelationException& e) { mitkReThrow(e) << "Cannot get all image IDs of the given lesion to determine the lesion presence."; } for (const auto& imageIDOfLesion : allImageIDsOfLesion) { if (imageIDOfLesion == imageID) { return true; } } return false; } bool mitk::SemanticRelationsInference::IsLesionPresentOnSegmentation(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ID& segmentationID) { const auto representedLesion = RelationStorage::GetLesionOfSegmentation(caseID, segmentationID); return lesion.UID == representedLesion.UID; } bool mitk::SemanticRelationsInference::IsLesionPresentAtControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ControlPoint& controlPoint) { SemanticTypes::IDVector allImageIDsOfLesion; try { allImageIDsOfLesion = GetAllImageIDsOfLesion(caseID, lesion); } catch (SemanticRelationException& e) { mitkReThrow(e) << "Cannot get all image IDs of the given lesion to determine the lesion presence."; } for (const auto& imageIDOfLesion : allImageIDsOfLesion) { auto imageControlPoint = mitk::RelationStorage::GetControlPointOfImage(caseID, imageIDOfLesion); if (imageControlPoint.date == controlPoint.date) { return true; } } return false; } bool mitk::SemanticRelationsInference::InstanceExists(const DataNode* dataNode) { SemanticTypes::CaseID caseID = ""; SemanticTypes::ID dataNodeID = ""; try { caseID = GetCaseIDFromDataNode(dataNode); dataNodeID = GetIDFromDataNode(dataNode); } catch (const SemanticRelationException&) { return false; } if (NodePredicates::GetImagePredicate()->CheckNode(dataNode)) { std::vector allImageIDsOfCase = RelationStorage::GetAllImageIDsOfCase(caseID); return std::find(allImageIDsOfCase.begin(), allImageIDsOfCase.end(), dataNodeID) != allImageIDsOfCase.end(); } if (NodePredicates::GetSegmentationPredicate()->CheckNode(dataNode)) { std::vector allSegmentationIDsOfCase = RelationStorage::GetAllSegmentationIDsOfCase(caseID); return std::find(allSegmentationIDsOfCase.begin(), allSegmentationIDsOfCase.end(), dataNodeID) != allSegmentationIDsOfCase.end(); } return false; } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { 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); return existingLesion != allLesions.end(); } mitk::SemanticTypes::IDVector mitk::SemanticRelationsInference::GetAllImageIDsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { if (!InstanceExists(caseID, lesion)) { mitkThrowException(SemanticRelationException) << "Could not find an existing lesion instance for the given caseID " << caseID << " and lesion " << lesion.UID << "."; } SemanticTypes::IDVector allImageIDsOfLesion; // 1. get all segmentations that define the lesion // 2. get the parentID (imageID) of each segmentation // 3. guarantee uniqueness of image IDs SemanticTypes::IDVector allSegmentationIDsOfLesion = RelationStorage::GetAllSegmentationIDsOfLesion(caseID, lesion); for (const auto& segmentationID : allSegmentationIDsOfLesion) { // get parent ID of the current segmentation ID SemanticTypes::ID imageID = RelationStorage::GetImageIDOfSegmentation(caseID, segmentationID); if(!imageID.empty()) { allImageIDsOfLesion.push_back(imageID); } } std::sort(allImageIDsOfLesion.begin(), allImageIDsOfLesion.end()); allImageIDsOfLesion.erase(std::unique(allImageIDsOfLesion.begin(), allImageIDsOfLesion.end()), allImageIDsOfLesion.end()); return allImageIDsOfLesion; } mitk::SemanticTypes::ControlPoint mitk::SemanticRelationsInference::GetControlPointOfImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid data node."; } SemanticTypes::CaseID caseID = ""; SemanticTypes::ID imageID = ""; try { caseID = GetCaseIDFromDataNode(imageNode); imageID = GetIDFromDataNode(imageNode); } catch (SemanticRelationException& e) { mitkReThrow(e) << "Cannot get the control point of the given image data node."; } return RelationStorage::GetControlPointOfImage(caseID, imageID); } mitk::SemanticTypes::ControlPointVector mitk::SemanticRelationsInference::GetAllControlPointsOfLesion(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion) { SemanticTypes::ControlPointVector allControlPoints = RelationStorage::GetAllControlPointsOfCase(caseID); // filter the control points: use only those, where the associated image data has a segmentation that refers to the given lesion using a lambda function auto lambda = [&caseID, &lesion](const SemanticTypes::ControlPoint& controlPoint) { return !SpecificImageExists(caseID, lesion, controlPoint); }; allControlPoints.erase(std::remove_if(allControlPoints.begin(), allControlPoints.end(), lambda), allControlPoints.end()); return allControlPoints; } mitk::SemanticTypes::ControlPointVector mitk::SemanticRelationsInference::GetAllControlPointsOfInformationType(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) { SemanticTypes::ControlPointVector allControlPoints = RelationStorage::GetAllControlPointsOfCase(caseID); // filter the control points: use only those, where the associated image data refers to the given information type using a lambda function auto lambda = [&caseID, &informationType](const SemanticTypes::ControlPoint& controlPoint) { return !SpecificImageExists(caseID, informationType, controlPoint); }; allControlPoints.erase(std::remove_if(allControlPoints.begin(), allControlPoints.end(), lambda), allControlPoints.end()); return allControlPoints; } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) { 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; } } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::ExaminationPeriod& examinationPeriod) { SemanticTypes::ExaminationPeriodVector allExaminationPeriods = RelationStorage::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::InformationType mitk::SemanticRelationsInference::GetInformationTypeOfImage(const DataNode* imageNode) { if (nullptr == imageNode) { mitkThrowException(SemanticRelationException) << "Not a valid image data node."; } SemanticTypes::CaseID caseID = ""; SemanticTypes::ID imageID = ""; try { caseID = GetCaseIDFromDataNode(imageNode); imageID = GetIDFromDataNode(imageNode); } catch (SemanticRelationException& e) { mitkReThrow(e) << "Cannot get the information type of the given image data node."; } return RelationStorage::GetInformationTypeOfImage(caseID, imageID); } mitk::SemanticTypes::InformationTypeVector mitk::SemanticRelationsInference::GetAllInformationTypesOfControlPoint(const SemanticTypes::CaseID& caseID, const SemanticTypes::ControlPoint& controlPoint) { SemanticTypes::InformationTypeVector allInformationTypes = RelationStorage::GetAllInformationTypesOfCase(caseID); // filter the information types: use only those, where the associated data refers to the given control point using a lambda function auto lambda = [&caseID, &controlPoint](const SemanticTypes::InformationType& informationType) { return !SpecificImageExists(caseID, informationType, controlPoint); }; allInformationTypes.erase(std::remove_if(allInformationTypes.begin(), allInformationTypes.end(), lambda), allInformationTypes.end()); return allInformationTypes; } bool mitk::SemanticRelationsInference::InstanceExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType) { SemanticTypes::InformationTypeVector allInformationTypes = RelationStorage::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; } } bool mitk::SemanticRelationsInference::SpecificImageExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::InformationType& informationType) { SemanticTypes::IDVector allImageIDsOfLesion; try { allImageIDsOfLesion = GetAllImageIDsOfLesion(caseID, lesion); } catch (const SemanticRelationException&) { return false; } SemanticTypes::IDVector allImageIDsOfInformationType = RelationStorage::GetAllImageIDsOfInformationType(caseID, informationType); std::sort(allImageIDsOfLesion.begin(), allImageIDsOfLesion.end()); std::sort(allImageIDsOfInformationType.begin(), allImageIDsOfInformationType.end()); SemanticTypes::IDVector allImageIDsIntersection; // set_intersection removes duplicated nodes, since 'GetAllImageIDsOfInformationType' only contains at most one of each node std::set_intersection(allImageIDsOfLesion.begin(), allImageIDsOfLesion.end(), allImageIDsOfInformationType.begin(), allImageIDsOfInformationType.end(), std::back_inserter(allImageIDsIntersection)); // if the vector of intersecting image IDs is empty, the information type does not contain the lesion return !allImageIDsIntersection.empty(); } bool mitk::SemanticRelationsInference::SpecificImageExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::Lesion& lesion, const SemanticTypes::ControlPoint& controlPoint) { SemanticTypes::IDVector allImageIDsOfLesion; try { allImageIDsOfLesion = GetAllImageIDsOfLesion(caseID, lesion); } catch (const SemanticRelationException&) { return false; } SemanticTypes::IDVector allImageIDsOfControlPoint = RelationStorage::GetAllImageIDsOfControlPoint(caseID, controlPoint); std::sort(allImageIDsOfLesion.begin(), allImageIDsOfLesion.end()); std::sort(allImageIDsOfControlPoint.begin(), allImageIDsOfControlPoint.end()); SemanticTypes::IDVector allImageIDsIntersection; // set_intersection removes duplicated nodes, since 'GetAllImageIDsOfControlPoint' only contains at most one of each node std::set_intersection(allImageIDsOfLesion.begin(), allImageIDsOfLesion.end(), allImageIDsOfControlPoint.begin(), allImageIDsOfControlPoint.end(), std::back_inserter(allImageIDsIntersection)); // if the vector of intersecting image IDs is empty, the control point does not contain the lesion return !allImageIDsIntersection.empty(); } bool mitk::SemanticRelationsInference::SpecificImageExists(const SemanticTypes::CaseID& caseID, const SemanticTypes::InformationType& informationType, const SemanticTypes::ControlPoint& controlPoint) { SemanticTypes::IDVector allImageIDsOfInformationType = RelationStorage::GetAllImageIDsOfInformationType(caseID, informationType); SemanticTypes::IDVector allImageIDsOfControlPoint = RelationStorage::GetAllImageIDsOfControlPoint(caseID, controlPoint); std::sort(allImageIDsOfInformationType.begin(), allImageIDsOfInformationType.end()); std::sort(allImageIDsOfControlPoint.begin(), allImageIDsOfControlPoint.end()); SemanticTypes::IDVector allImageIDsIntersection; // set_intersection removes duplicated nodes std::set_intersection(allImageIDsOfInformationType.begin(), allImageIDsOfInformationType.end(), allImageIDsOfControlPoint.begin(), allImageIDsOfControlPoint.end(), std::back_inserter(allImageIDsIntersection)); // if the vector of intersecting image IDs is empty no image exists for the given information type and control point return !allImageIDsIntersection.empty(); }