Medical Imaging Interaction Toolkit  2018.4.99-1640525a
Medical Imaging Interaction Toolkit
mitkControlPointManager.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 // semantic relations module
15 #include "mitkDICOMHelper.h"
16 #include "mitkRelationStorage.h"
18 #include "mitkUIDGeneratorBoost.h"
19 
20 // mitk core
21 #include <mitkPropertyNameHelper.h>
22 
24 {
25  SemanticTypes::ControlPoint controlPoint;
26  try
27  {
28  controlPoint = GetDICOMDateFromDataNode(datanode);
29  }
30  catch (SemanticRelationException& e)
31  {
32  mitkReThrow(e) << "Cannot generate a control point from the DICOM tag of the given data node.";
33  }
34 
35  controlPoint.UID = UIDGeneratorBoost::GenerateUID();
36  return controlPoint;
37 }
38 
40 {
41  auto lambda = [&controlPointUID](const SemanticTypes::ControlPoint& currentControlPoint)
42  {
43  return currentControlPoint.UID == controlPointUID;
44  };
45 
47  const auto existingControlPoint = std::find_if(allControlPoints.begin(), allControlPoints.end(), lambda);
48 
50  if (existingControlPoint != allControlPoints.end())
51  {
52  controlPoint = *existingControlPoint;
53  }
54 
55  return controlPoint;
56 }
57 
59 {
61  for (const auto& currentControlPoint : allControlPoints)
62  {
63  if (controlPoint.date == currentControlPoint.date)
64  {
65  return currentControlPoint;
66  }
67  }
68 
70 }
71 
73 {
75  if (allControlPoints.empty())
76  {
78  }
79 
80  // sort the vector of control points for easier lookup
81  std::sort(allControlPoints.begin(), allControlPoints.end());
82  // new control point does not match an existing control point
83  // check if the control point is close to an already existing control point
84  SemanticTypes::ControlPointVector::const_iterator it;
85  for (it = allControlPoints.begin(); it != allControlPoints.end(); ++it)
86  {
87  if (controlPoint.date < it->date)
88  {
89  break;
90  }
91  }
92 
93  SemanticTypes::ControlPoint nextControlPoint;
94  SemanticTypes::ControlPoint previousControlPoint;
95  if (it == allControlPoints.begin())
96  {
97  // new date is smaller ("older") than the smallest already existing control point
98  nextControlPoint = *it;
99  }
100  else if (it != allControlPoints.end())
101  {
102  // new date is greater ("newer") than an already existing control point,
103  // but smaller ("older") than another already existing control point
104  nextControlPoint = *it;
105  previousControlPoint = *(--it);
106  }
107  else
108  {
109  // new date is greater ("newer") than the greatest already existing control point
110  previousControlPoint = *(--it);
111  }
112 
113  // test distance to next and previous time period
114  double distanceToNextExaminationPeriod = nextControlPoint.DistanceInDays(controlPoint);
115  double distanceToPreviousExaminationPeriod = previousControlPoint.DistanceInDays(controlPoint);
116 
117  SemanticTypes::ControlPoint closestControlPoint;
118  int closestDistanceInDays = 0;
119  if (distanceToNextExaminationPeriod < distanceToPreviousExaminationPeriod)
120  {
121  // control point is closer to the next control point
122  closestControlPoint = nextControlPoint;
123  closestDistanceInDays = distanceToNextExaminationPeriod;
124  }
125  else
126  {
127  // control point is closer to the previous control point
128  closestControlPoint = previousControlPoint;
129  closestDistanceInDays = distanceToPreviousExaminationPeriod;
130  }
131 
132  int THRESHOLD_DISTANCE_IN_DAYS = 30;
133  if (closestDistanceInDays <= THRESHOLD_DISTANCE_IN_DAYS)
134  {
135  return closestControlPoint;
136  }
137 
139 }
140 
142 {
144  for (const auto& examinationPeriod : allExaminationPeriods)
145  {
146  for (const auto& UID : examinationPeriod.controlPointUIDs)
147  {
148  if (controlPoint.UID == UID)
149  {
150  return examinationPeriod;
151  }
152  }
153  }
154 
156 }
157 
159 {
160  SemanticTypes::ExaminationPeriod specificExaminationPeriod;
161  SemanticTypes::ControlPoint specificControlPoint;
162  // find the closest control point
163  SemanticTypes::ControlPoint existingControlPoint = FindExistingControlPoint(caseID, controlPoint);
164  if (!existingControlPoint.UID.empty())
165  {
166  specificControlPoint = existingControlPoint;
167  }
168  else
169  {
170  auto closestControlPoint = FindClosestControlPoint(caseID, controlPoint);
171  if (!closestControlPoint.UID.empty())
172  {
173  specificControlPoint = closestControlPoint;
174  }
175  }
176 
177  // find the containing examination period
178  return FindContainingExaminationPeriod(caseID, specificControlPoint);
179 }
180 
182 {
183  SemanticTypes::CaseID caseID = "";
184  SemanticTypes::ControlPoint controlPoint;
185  try
186  {
187  caseID = GetCaseIDFromDataNode(dataNode);
188  controlPoint = GetDICOMDateFromDataNode(dataNode);
189  }
190  catch (SemanticRelationException& e)
191  {
192  mitkReThrow(e) << "Cannot find an examination period.";
193  }
194 
195  return FindFittingExaminationPeriod(caseID, controlPoint);
196 }
197 
199 {
201  // sort the vector of control points for the timeline
202  std::sort(controlPoints.begin(), controlPoints.end());
203 
204  auto lambda = [&caseID](const SemanticTypes::ExaminationPeriod& leftExaminationPeriod, const SemanticTypes::ExaminationPeriod& rightExaminationPeriod)
205  {
206  if (leftExaminationPeriod.controlPointUIDs.empty())
207  {
208  return true;
209  }
210 
211  if (rightExaminationPeriod.controlPointUIDs.empty())
212  {
213  return false;
214  }
215  const auto leftUID = leftExaminationPeriod.controlPointUIDs.front();
216  const auto rightUID = rightExaminationPeriod.controlPointUIDs.front();
217  const auto& leftControlPoint = GetControlPointByUID(caseID, leftUID);
218  const auto& rightControlPoint = GetControlPointByUID(caseID, rightUID);
219 
220  return leftControlPoint.date < rightControlPoint.date;
221  };
222 
223  std::sort(allExaminationPeriods.begin(), allExaminationPeriods.end(), lambda);
224 }
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ExaminationPeriod FindFittingExaminationPeriod(const SemanticTypes::CaseID &caseID, const SemanticTypes::ControlPoint &controlPoint)
Return the examination period to which the given data node belongs. The control point is used to find...
#define mitkReThrow(mitkexception)
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint FindExistingControlPoint(const SemanticTypes::CaseID &caseID, const SemanticTypes::ControlPoint &controlPoint)
Returns an already existing control point from the given vector of control points. This existing control point has the the same date (year, month, day) as the given single control point. If no existing control point can be found an empty control point is returned.
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::CaseID GetCaseIDFromDataNode(const mitk::DataNode *dataNode)
std::vector< ControlPoint > ControlPointVector
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint FindClosestControlPoint(const SemanticTypes::CaseID &caseID, const SemanticTypes::ControlPoint &controlPoint)
Returns an already existing close control point from the given vector of control points. This closest control point has a date that is within a certain distance-in-days to the given control point. If no closest control point can be found within the distance threshold an empty control point is returned.
The concept of an examination period. An examination period holds a vector of control point UIDs...
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint GenerateControlPoint(const mitk::DataNode *datanode)
Provides helper functions that are needed to work with control points.
int DistanceInDays(const ControlPoint &other) const
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ExaminationPeriod FindContainingExaminationPeriod(const SemanticTypes::CaseID &caseID, const SemanticTypes::ControlPoint &controlPoint)
Returns the examination period to which the given control point belongs. Each examination point holds...
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ExaminationPeriodVector GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID &caseID)
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint GetDICOMDateFromDataNode(const mitk::DataNode *dataNode)
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPoint GetControlPointByUID(const SemanticTypes::CaseID &caseID, const SemanticTypes::ID &controlPointUID)
Find and return a whole control point including its date given a specific control point UID...
std::vector< ExaminationPeriod > ExaminationPeriodVector
MITKSEMANTICRELATIONS_EXPORT std::string GenerateUID()
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPointVector GetAllControlPointsOfCase(const SemanticTypes::CaseID &caseID)
MITKSEMANTICRELATIONS_EXPORT void SortAllExaminationPeriods(const SemanticTypes::CaseID &caseID, SemanticTypes::ExaminationPeriodVector &allExaminationPeriods)
Sort the given vector of examination periods. Each examination period has a vector of control point U...