Medical Imaging Interaction Toolkit  2018.4.99-1bab67a2
Medical Imaging Interaction Toolkit
QmitkLesionTreeModel.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 "QmitkLesionTreeModel.h"
15 
16 // semantic relations module
18 #include <mitkLesionManager.h>
19 #include <mitkNodePredicates.h>
22 #include <mitkRelationStorage.h>
23 
24 // qt
25 #include <QColor>
26 
27 QmitkLesionTreeModel::QmitkLesionTreeModel(QObject* parent/* = nullptr*/)
29  , m_LastSegmentation(nullptr)
30  , m_RootItem(std::make_shared<QmitkLesionTreeItem>(mitk::LesionData()))
31 {
32  // nothing here
33 }
34 
36 // overridden virtual functions from QAbstractItemModel
38 QModelIndex QmitkLesionTreeModel::index(int row, int column, const QModelIndex& itemIndex) const
39 {
40  if (!hasIndex(row, column, itemIndex))
41  {
42  return QModelIndex();
43  }
44 
45  auto childItem = GetItemByIndex(itemIndex)->GetChildInRow(row);
46  if (nullptr == childItem)
47  {
48  return QModelIndex();
49  }
50 
51  return createIndex(row, column, childItem.get());
52 }
53 
54 QModelIndex QmitkLesionTreeModel::parent(const QModelIndex& itemIndex) const
55 {
56  if (!itemIndex.isValid())
57  {
58  return QModelIndex();
59  }
60 
61  auto parentItem = GetItemByIndex(itemIndex)->GetParent();
62  if (parentItem.expired())
63  {
64  return QModelIndex();
65  }
66 
67  auto sharedParent = parentItem.lock();
68  if (sharedParent == m_RootItem)
69  {
70  return QModelIndex();
71  }
72 
73  return createIndex(sharedParent->GetRow(), 0, sharedParent.get());
74 }
75 
76 int QmitkLesionTreeModel::rowCount(const QModelIndex& itemIndex/* = QModelIndex()*/) const
77 {
78  return GetItemByIndex(itemIndex)->ChildCount();
79 }
80 
81 int QmitkLesionTreeModel::columnCount(const QModelIndex&/* itemIndex = QModelIndex() */) const
82 {
83  if (0 == m_RootItem->ChildCount())
84  {
85  // no lesion items stored, no need to display columns
86  return 0;
87  }
88 
89  return m_ControlPoints.size() + 1;
90 }
91 
92 QVariant QmitkLesionTreeModel::data(const QModelIndex& index, int role) const
93 {
94  if (!index.isValid())
95  {
96  return QVariant();
97  }
98 
99  if (index.column() < 0 || index.column() > static_cast<int>(m_ControlPoints.size()))
100  {
101  return QVariant();
102  }
103 
104  QmitkLesionTreeItem* currentItem = GetItemByIndex(index);
105  if (Qt::DisplayRole == role)
106  {
107  if (currentItem->GetParent().expired())
108  {
109  return QVariant();
110  }
111 
112  auto parentItem = currentItem->GetParent().lock();
113  // parent exists and is the root item -> 1. item of a lesion entry
114  if (m_RootItem == parentItem)
115  {
116  // display role fills the first columns with the lesion UID / name
117  if (0 == index.column())
118  {
119  std::string itemString = currentItem->GetData().GetLesionName();
120  if (itemString.empty())
121  {
122  itemString = currentItem->GetData().GetLesionUID();
123  }
124  return QString::fromStdString(itemString);
125  }
126  else
127  {
128  // display role fills other columns with the lesion presence info
129  const auto lesionPresence = currentItem->GetData().GetLesionPresence();
130  if (index.column() - 1 > static_cast<int>(lesionPresence.size()))
131  {
132  return "N/A";
133  }
134 
135  if (lesionPresence.at(index.column() - 1))
136  {
137  return QString::fromStdString("present");
138  }
139 
140  return QString::fromStdString("not present");
141  }
142  }
143  }
144 
145  if (Qt::BackgroundColorRole == role)
146  {
147  auto it = m_DataNodePresence.find(currentItem->GetData().GetLesion().UID);
148  if (it != m_DataNodePresence.end())
149  {
150  return it->second ? QVariant(QColor(Qt::darkGreen)) : QVariant(QColor(Qt::transparent));
151  }
152 
153  return QVariant(QColor(Qt::transparent));
154  }
155 
156  if (Qt::UserRole == role)
157  {
158  return QVariant::fromValue(currentItem);
159  }
160 
161  return QVariant();
162 }
163 
164 QVariant QmitkLesionTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
165 {
166  if (0 == m_RootItem->ChildCount())
167  {
168  // no lesion items stored, no need to display the header
169  return QVariant();
170  }
171 
172  if (Qt::Horizontal == orientation && Qt::DisplayRole == role)
173  {
174  if (0 == section)
175  {
176  return QVariant("Lesion");
177  }
178 
179  if (static_cast<int>(m_ControlPoints.size()) >= section)
180  {
181  mitk::SemanticTypes::ControlPoint currentControlPoint = m_ControlPoints.at(section-1);
182  return QVariant(QString::fromStdString(currentControlPoint.ToString()));
183  }
184  }
185 
186  return QVariant();
187 }
188 
190 {
191  return m_LastSegmentation;
192 }
193 
195 {
196  if (mitk::NodePredicates::GetSegmentationPredicate()->CheckNode(dataNode))
197  {
198  m_LastSegmentation = dataNode;
199  }
200 }
201 
203 {
204  m_RootItem = std::make_shared<QmitkLesionTreeItem>(mitk::LesionData());
205 
206  // get all control points of current case
208  // sort the vector of control points for the timeline
209  std::sort(m_ControlPoints.begin(), m_ControlPoints.end());
210 
211  SetLesionData();
212  SetSelectedDataNodesPresence();
213 }
214 
215 void QmitkLesionTreeModel::SetLesionData()
216 {
218  for (auto& lesion : m_CurrentLesions)
219  {
220  AddLesion(lesion);
221  }
222 }
223 
224 void QmitkLesionTreeModel::AddLesion(const mitk::SemanticTypes::Lesion& lesion)
225 {
226  if (m_DataStorage.IsExpired())
227  {
228  return;
229  }
230 
231  auto dataStorage = m_DataStorage.Lock();
232 
233  // create new lesion tree item data and modify it according to the control point data
234  mitk::LesionData lesionData(lesion);
236 
237  // add the top-level lesion item to the root item
238  std::shared_ptr<QmitkLesionTreeItem> newLesionTreeItem = std::make_shared<QmitkLesionTreeItem>(lesionData);
239  m_RootItem->AddChild(newLesionTreeItem);
240 }
241 
242 void QmitkLesionTreeModel::SetSelectedDataNodesPresence()
243 {
244  m_DataNodePresence.clear();
245  for (const auto& dataNode : m_SelectedDataNodes)
246  {
248  {
249  continue;
250  }
251 
252  for (const auto& lesion : m_CurrentLesions)
253  {
255  {
256  continue;
257  }
258  try
259  {
260  // set the lesion presence for the current node
261  bool dataNodePresence = mitk::SemanticRelationsInference::IsLesionPresent(lesion, dataNode);
262  SetDataNodePresenceOfLesion(&lesion, dataNodePresence);
263  }
264  catch (const mitk::SemanticRelationException&)
265  {
266  continue;
267  }
268  }
269  }
270 }
271 
272 void QmitkLesionTreeModel::SetDataNodePresenceOfLesion(const mitk::SemanticTypes::Lesion* lesion, bool dataNodePresence)
273 {
274  std::map<mitk::SemanticTypes::ID, bool>::iterator iter = m_DataNodePresence.find(lesion->UID);
275  if (iter != m_DataNodePresence.end())
276  {
277  // key already existing, overwrite already stored bool value
278  iter->second = dataNodePresence;
279  }
280  else
281  {
282  m_DataNodePresence.insert(std::make_pair(lesion->UID, dataNodePresence));
283  }
284 }
285 
286 QmitkLesionTreeItem* QmitkLesionTreeModel::GetItemByIndex(const QModelIndex& index) const
287 {
288  if (index.isValid())
289  {
290  auto item = static_cast<QmitkLesionTreeItem*>(index.internalPointer());
291  if (nullptr != item)
292  {
293  return item;
294  }
295  }
296 
297  return m_RootItem.get();
298 }
QmitkLesionTreeModel(QObject *parent=nullptr)
Initialize the root item of the model. The root item does not have a parent item. ...
int columnCount(const QModelIndex &itemIndex=QModelIndex()) const override
int rowCount(const QModelIndex &itemIndex=QModelIndex()) const override
MITKSEMANTICRELATIONS_EXPORT void ComputeLesionPresence(LesionData &lesionData, const SemanticTypes::CaseID &caseID)
Compute and store lesion presence for all available control points and information types...
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 ...
itk::SmartPointer< T > Lock() const
std::string GetLesionName() const
mitk::LesionData & GetData()
Return the item data, which contains ...
void NodeAdded(const mitk::DataNode *) override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
STL namespace.
DataCollection - Class to facilitate loading/accessing structured data.
QModelIndex index(int row, int column, const QModelIndex &itemIndex=QModelIndex()) const override
SemanticTypes::Lesion GetLesion() const
MITKSEMANTICRELATIONS_EXPORT NodePredicateAnd::Pointer GetSegmentationPredicate()
ChildPointer GetChildInRow(int row) const
Return the child of this item at a specific position.
ParentPointer GetParent() const
Return the parent item.
bool IsExpired() const noexcept
void SetData() override
Overridden from &#39;QmitkAbstractSemanticRelationsStorageModel&#39;: This function retrieves all control poi...
This class holds the data of each lesion in the lesion tree view. The data is the lesion itself with ...
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::LesionVector GetAllLesionsOfCase(const SemanticTypes::CaseID &caseID)
SemanticTypes::ID GetLesionUID() const
QModelIndex parent(const QModelIndex &itemIndex) const override
const mitk::DataNode * GetLastSegmentation() const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
const std::vector< bool > & GetLesionPresence() const
vcl_size_t ChildCount() const
Return the number of child items.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
mitk::WeakPointer< mitk::DataStorage > m_DataStorage
MITKSEMANTICRELATIONS_EXPORT SemanticTypes::ControlPointVector GetAllControlPointsOfCase(const SemanticTypes::CaseID &caseID)
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 ...