Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
QmitkPatientTableModel.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 UI module
14 #include "QmitkPatientTableModel.h"
17 
18 // semantic relations module
20 #include <mitkNodePredicates.h>
23 #include <mitkRelationStorage.h>
24 
25 #include <QmitkCustomVariants.h>
26 #include <QmitkEnums.h>
27 
28 // qt
29 #include <QColor>
30 
31 // c++
32 #include <iostream>
33 #include <string>
34 
35 QmitkPatientTableModel::QmitkPatientTableModel(QObject* parent /*= nullptr*/)
37  , m_SelectedNodeType("Image")
38 {
39  m_HeaderModel = new QStandardItemModel(this);
40 }
41 
43 {
44  // nothing here
45 }
46 
47 QModelIndex QmitkPatientTableModel::index(int row, int column, const QModelIndex& parent/* = QModelIndex()*/) const
48 {
49  if (hasIndex(row, column, parent))
50  {
51  return createIndex(row, column);
52  }
53 
54  return QModelIndex();
55 }
56 
57 QModelIndex QmitkPatientTableModel::parent(const QModelIndex& /*child*/) const
58 {
59  return QModelIndex();
60 }
61 
62 int QmitkPatientTableModel::rowCount(const QModelIndex& parent/* = QModelIndex()*/) const
63 {
64  if (parent.isValid())
65  {
66  return 0;
67  }
68 
69  return m_InformationTypes.size();
70 }
71 
72 int QmitkPatientTableModel::columnCount(const QModelIndex& parent/* = QModelIndex()*/) const
73 {
74  if (parent.isValid())
75  {
76  return 0;
77  }
78 
79  return m_ExaminationPeriods.size();
80 }
81 
82 QVariant QmitkPatientTableModel::data(const QModelIndex& index, int role/* = Qt::DisplayRole*/) const
83 {
84  // special role for returning the horizontal header
86  {
87  return QVariant::fromValue<QStandardItemModel*>(m_HeaderModel);
88  }
89 
90  if (!index.isValid())
91  {
92  return QVariant();
93  }
94 
95  if (index.row() < 0 || index.row() >= static_cast<int>(m_InformationTypes.size())
96  || index.column() < 0 || index.column() >= static_cast<int>(m_ExaminationPeriods.size()))
97  {
98  return QVariant();
99  }
100 
101  mitk::DataNode* dataNode = GetCurrentDataNode(index);
102 
103  if (Qt::DecorationRole == role)
104  {
105  auto it = m_PixmapMap.find(dataNode);
106  if (it != m_PixmapMap.end())
107  {
108  return QVariant(it->second);
109  }
110 
111  auto emptyPixmap = QPixmap(120, 120);
112  emptyPixmap.fill(Qt::transparent);
113  return emptyPixmap;
114  }
115 
116  if (Qt::BackgroundColorRole == role)
117  {
118  auto it = m_LesionPresence.find(dataNode);
119  if (it != m_LesionPresence.end())
120  {
121  return it->second ? QVariant(QColor(Qt::darkGreen)) : QVariant(QColor(Qt::transparent));
122  }
123 
124  return QVariant(QColor(Qt::transparent));
125  }
126 
127  if (QmitkDataNodeRole == role)
128  {
129  return QVariant::fromValue<mitk::DataNode::Pointer>(mitk::DataNode::Pointer(dataNode));
130  }
131 
132  if (QmitkDataNodeRawPointerRole == role)
133  {
134  return QVariant::fromValue<mitk::DataNode*>(dataNode);
135  }
136 
137  return QVariant();
138 }
139 
140 QVariant QmitkPatientTableModel::headerData(int section, Qt::Orientation orientation, int role) const
141 {
142  if (Qt::Vertical == orientation && Qt::DisplayRole == role)
143  {
144  if (static_cast<int>(m_InformationTypes.size()) > section)
145  {
146  mitk::SemanticTypes::InformationType currentInformationType = m_InformationTypes.at(section);
147  return QVariant(QString::fromStdString(currentInformationType));
148  }
149  }
150 
151  return QVariant();
152 }
153 
154 Qt::ItemFlags QmitkPatientTableModel::flags(const QModelIndex& index) const
155 {
156  Qt::ItemFlags flags;
157  mitk::DataNode* dataNode = GetCurrentDataNode(index);
158  if (nullptr != dataNode)
159  {
160  flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
161  }
162 
163  return flags;
164 }
165 
166 void QmitkPatientTableModel::SetNodeType(const std::string& nodeType)
167 {
168  m_SelectedNodeType = nodeType;
169  UpdateModelData();
170 }
171 
173 {
174  UpdateModelData();
175 }
176 
178 {
179  // get all examination periods of current case
181 
182  // sort all examination periods for the timeline
183  mitk::SortAllExaminationPeriods(m_CaseID, m_ExaminationPeriods);
184 
185  // rename examination periods according to their new order
186  std::string examinationPeriodName = "Baseline";
187  for (size_t i = 0; i < m_ExaminationPeriods.size(); ++i)
188  {
189  auto& examinationPeriod = m_ExaminationPeriods.at(i);
190  examinationPeriod.name = examinationPeriodName;
192  examinationPeriodName = "Follow-up " + std::to_string(i);
193  }
194 
195  // get all information types points of current case
197 
198  if ("Image" == m_SelectedNodeType)
199  {
200  m_CurrentDataNodes = m_SemanticRelationsDataStorageAccess->GetAllImagesOfCase(m_CaseID);
201  }
202  else if ("Segmentation" == m_SelectedNodeType)
203  {
204  m_CurrentDataNodes = m_SemanticRelationsDataStorageAccess->GetAllSegmentationsOfCase(m_CaseID);
205  }
206 
207  SetHeaderModel();
208  SetPixmaps();
209  SetLesionPresences();
210 }
211 
212 void QmitkPatientTableModel::SetHeaderModel()
213 {
214  m_HeaderModel->clear();
215  QStandardItem* rootItem = new QStandardItem("Timeline");
216  QList<QStandardItem*> standardItems;
217 
218  for (const auto& examinationPeriod : m_ExaminationPeriods)
219  {
220  QStandardItem* examinationPeriodItem = new QStandardItem(QString::fromStdString(examinationPeriod.name));
221  standardItems.push_back(examinationPeriodItem);
222  rootItem->appendColumn(standardItems);
223  standardItems.clear();
224  }
225 
226  m_HeaderModel->setItem(0, 0, rootItem);
227 }
228 
229 void QmitkPatientTableModel::SetPixmaps()
230 {
231  m_PixmapMap.clear();
232  for (const auto& dataNode : m_CurrentDataNodes)
233  {
234  // set the pixmap for the current node
235  QPixmap pixmapFromImage = QmitkSemanticRelationsUIHelper::GetPixmapFromImageNode(dataNode);
236  SetPixmapOfNode(dataNode, &pixmapFromImage);
237  }
238 }
239 
240 void QmitkPatientTableModel::SetPixmapOfNode(const mitk::DataNode* dataNode, QPixmap* pixmapFromImage)
241 {
242  if (nullptr == dataNode)
243  {
244  return;
245  }
246 
247  std::map<mitk::DataNode::ConstPointer, QPixmap>::iterator iter = m_PixmapMap.find(dataNode);
248  if (iter != m_PixmapMap.end())
249  {
250  // key already existing
251  if (nullptr != pixmapFromImage)
252  {
253  // overwrite already stored pixmap
254  iter->second = pixmapFromImage->scaled(120, 120, Qt::IgnoreAspectRatio);
255  }
256  else
257  {
258  // remove key if no pixmap is given
259  m_PixmapMap.erase(iter);
260  }
261  }
262  else
263  {
264  m_PixmapMap.insert(std::make_pair(dataNode, pixmapFromImage->scaled(120, 120, Qt::IgnoreAspectRatio)));
265  }
266 }
267 
268 void QmitkPatientTableModel::SetLesionPresences()
269 {
270  m_LesionPresence.clear();
272  {
273  return;
274  }
275 
276  for (const auto& dataNode : m_CurrentDataNodes)
277  {
279  {
280  continue;
281  }
282 
283  // set the lesion presence for the current node
284  bool lesionPresence = mitk::SemanticRelationsInference::IsLesionPresent(m_Lesion, dataNode);
285  SetLesionPresenceOfNode(dataNode, lesionPresence);
286  }
287 }
288 
289 void QmitkPatientTableModel::SetLesionPresenceOfNode(const mitk::DataNode* dataNode, bool lesionPresence)
290 {
291  std::map<mitk::DataNode::ConstPointer, bool>::iterator iter = m_LesionPresence.find(dataNode);
292  if (iter != m_LesionPresence.end())
293  {
294  // key already existing, overwrite already stored bool value
295  iter->second = lesionPresence;
296  }
297  else
298  {
299  m_LesionPresence.insert(std::make_pair(dataNode, lesionPresence));
300  }
301 }
302 
303 mitk::DataNode* QmitkPatientTableModel::GetCurrentDataNode(const QModelIndex& index) const
304 {
305  if (!index.isValid())
306  {
307  return nullptr;
308  }
309 
310  auto examinationPeriod = m_ExaminationPeriods.at(index.column());
311  auto currentInformationType = m_InformationTypes.at(index.row());
312  auto controlPointsOfExaminationPeriod = examinationPeriod.controlPointUIDs;
313  for (const auto& controlPointUID : controlPointsOfExaminationPeriod)
314  {
315  auto currentControlPoint = mitk::GetControlPointByUID(m_CaseID, controlPointUID);
316  try
317  {
318  std::vector<mitk::DataNode::Pointer> filteredDataNodes;
319  if ("Image" == m_SelectedNodeType)
320  {
321  filteredDataNodes = m_SemanticRelationsDataStorageAccess->GetAllSpecificImages(m_CaseID, currentControlPoint, currentInformationType);
322  }
323  else if ("Segmentation" == m_SelectedNodeType)
324  {
325  filteredDataNodes = m_SemanticRelationsDataStorageAccess->GetAllSpecificSegmentations(m_CaseID, currentControlPoint, currentInformationType);
326  }
327 
328  if (filteredDataNodes.empty())
329  {
330  // try next control point
331  continue;
332  }
333  else
334  {
335  // found a specific image
336  return filteredDataNodes.front();
337  }
338  }
339  catch (const mitk::SemanticRelationException&)
340  {
341  return nullptr;
342  }
343  }
344  // could not find a specif image
345  return nullptr;
346 }
MITKSEMANTICRELATIONS_EXPORT bool IsLesionPresent(const SemanticTypes::Lesion &lesion, const DataNode *dataNode)
Check if the given lesion is present on the given data node. The function receives the case- and the ...
QmitkPatientTableModel(QObject *parent=nullptr)
int columnCount(const QModelIndex &parent=QModelIndex()) const override
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::InformationTypeVector GetAllInformationTypesOfCase(const SemanticTypes::CaseID &caseID)
void SetNodeType(const std::string &nodeType)
end override
itk::SmartPointer< Self > Pointer
Definition: mitkDataNode.h:71
MITKSEMANTICRELATIONS_EXPORT void RenameExaminationPeriod(const SemanticTypes::CaseID &caseID, const SemanticTypes::ExaminationPeriod &examinationPeriod)
std::unique_ptr< mitk::SemanticRelationsDataStorageAccess > m_SemanticRelationsDataStorageAccess
void SetData() override
Overridden from &#39;QmitkAbstractSemanticRelationsStorageModel&#39;: This function retrieves all control poi...
QModelIndex parent(const QModelIndex &child) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
MITKSEMANTICRELATIONSUI_EXPORT QPixmap GetPixmapFromImageNode(const mitk::DataNode *dataNode)
std::string InformationType
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ExaminationPeriodVector GetAllExaminationPeriodsOfCase(const SemanticTypes::CaseID &caseID)
Qt::ItemFlags flags(const QModelIndex &index) const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
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...
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
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...
MITKSEMANTICRELATIONS_EXPORT bool InstanceExists(const DataNode *dataNode)
Check if the given data node exists in the relation storage. The function receives the case- and the ...