Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkDataStorage.h
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 #ifndef MITKDATASTORAGE_H
14 #define MITKDATASTORAGE_H
15 
16 #include "itkObject.h"
17 #include "itkSimpleFastMutexLock.h"
18 #include "itkVectorContainer.h"
19 #include "mitkDataNode.h"
20 #include "mitkGeometry3D.h"
21 #include "mitkMessage.h"
22 #include <MitkCoreExports.h>
23 #include <map>
24 
25 namespace mitk
26 {
27  class NodePredicateBase;
28  class DataNode;
29  class BaseRenderer;
30 
31  //##Documentation
32  //## @brief Data management class that handles 'was created by' relations
33  //##
34  //## The DataStorage provides data storage and management functionality.
35  //## It handles a 'was created by' relation by associating each data object with a
36  //## set of source objects, that this object was created from.
37  //## Thus, nodes are stored in a noncyclical directed graph data structure.
38  //## If a new node is added to the DataStorage, AddNodeEvent is emitted.
39  //## If a node is removed, RemoveNodeEvent is emitted.
40  //##
41  //##
42  //## \ingroup DataStorage
43  class MITKCORE_EXPORT DataStorage : public itk::Object
44  {
45  public:
47 
48  //##Documentation
49  //## @brief A Container of objects that is used as a result set of GetSubset() query operations (Set of
50  //SmartPointers
51  // to DataNodes).
52  typedef itk::VectorContainer<unsigned int, DataNode::Pointer> SetOfObjects;
53 
54  //##Documentation
55  //## @brief Adds a DataNode containing a data object to its internal storage
56  //##
57  //## This Method adds a new data object to the DataStorage. The new object is
58  //## passed in the first parameter. The second parameter is a set
59  //## of source objects, that were used to create this object. The new object will have
60  //## a 'was created from' relation to its source objects.
61  //## the addition of a new object will fire the notification mechanism.
62  //## If the node parameter is nullptr or if the DataNode has already been added,
63  //## an exception will be thrown.
64  virtual void Add(DataNode *node, const DataStorage::SetOfObjects *parents = nullptr) = 0;
65 
66  //##Documentation
67  //## @brief Convenience method to add a node that has one parent
68  //##
69  void Add(DataNode *node, DataNode *parent);
70 
71  //##Documentation
72  //## @brief Removes node from the DataStorage
73  //##
74  virtual void Remove(const DataNode *node) = 0;
75 
76  //##Documentation
77  //## @brief Checks if a node exists in the DataStorage
78  //##
79  virtual bool Exists(const DataNode *node) const = 0;
80 
81  //##Documentation
82  //## @brief Removes a set of nodes from the DataStorage
83  //##
84  void Remove(const DataStorage::SetOfObjects *nodes);
85 
86  //##Documentation
87  //## @brief returns a set of data objects that meet the given condition(s)
88  //##
89  //## GetSubset returns a set of objects with a specific data type that meet the condition(s)
90  //## specified in the condition parameter. Conditions can be
91  //## - data type of the data object
92  //## - is source object of specific object (e.g. all source objects of node x)
93  //## - has property with specific value (e.g. OrganType is Liver)
94  //## - negation of any condition
95  //## - conjunction of a set of conditions
96  //## - disjunction of a set of conditions
97  //## Conditions are implemented as predicates using the Composite Design Pattern
98  //## (see definition of NodePredicateBase for details).
99  //## The method returns a set of SmartPointers to the DataNodes that fulfill the
100  //## conditions. A set of all objects can be retrieved with the GetAll() method;
101  SetOfObjects::ConstPointer GetSubset(const NodePredicateBase *condition) const;
102 
103  //##Documentation
104  //## @brief returns a set of source objects for a given node that meet the given condition(s).
105  //##
106  virtual SetOfObjects::ConstPointer GetSources(const DataNode *node,
107  const NodePredicateBase *condition = nullptr,
108  bool onlyDirectSources = true) const = 0;
109 
110  //##Documentation
111  //## @brief returns a set of derived objects for a given node.
112  //##
113  //## GetDerivations() returns a set of objects that are derived from the DataNode node.
114  //## This means, that node was used to create the returned objects. If the parameter
115  //## onlyDirectDerivations is set to true (default value), only objects that directly have
116  //## node as one of their source objects will be returned. Otherwise, objects that are
117  //## derived from derivations of node are returned too.
118  //## The derived objects can be filtered with a predicate object as described in the GetSubset()
119  //## method by providing a predicate as the condition parameter.
120  virtual SetOfObjects::ConstPointer GetDerivations(const DataNode *node,
121  const NodePredicateBase *condition = nullptr,
122  bool onlyDirectDerivations = true) const = 0;
123 
124  //##Documentation
125  //## @brief returns a set of all data objects that are stored in the data storage
126  //##
127  virtual SetOfObjects::ConstPointer GetAll() const = 0;
128 
129  //##Documentation
130  //## @brief Convenience method to get the first node that matches the predicate condition
131  //##
132  DataNode *GetNode(const NodePredicateBase *condition = nullptr) const;
133 
134  //##Documentation
135  //## @brief Convenience method to get the first node with a given name
136  //##
137  DataNode *GetNamedNode(const char *name) const;
138 
139  //##Documentation
140  //## @brief Convenience method to get the first node with a given name
141  //##
142  DataNode *GetNamedNode(const std::string name) const { return this->GetNamedNode(name.c_str()); }
143  //##Documentation
144  //## @brief Convenience method to get the first node with a given name that is derived from sourceNode
145  //##
146  DataNode *GetNamedDerivedNode(const char *name,
147  const DataNode *sourceNode,
148  bool onlyDirectDerivations = true) const;
149 
150  //##Documentation
151  //## @brief Convenience method to get the first data object of a given data type with a given name
152  //##
153  template <class DataType>
154  DataType *GetNamedObject(const char *name) const
155  {
156  if (name == nullptr)
157  return nullptr;
158  DataNode *n = this->GetNamedNode(name);
159  if (n == nullptr)
160  return nullptr;
161  else
162  return dynamic_cast<DataType *>(n->GetData());
163  }
164  //##Documentation
165  //## @brief Convenience method to get the first data object of a given data type with a given name
166  //##
167  template <class DataType>
168  DataType *GetNamedObject(const std::string name) const
169  {
170  return this->GetNamedObject<DataType>(name.c_str());
171  }
172 
173  //##Documentation
174  //## @brief Convenience method to get the first data object of a given data type with a given name that is derived
175  // from a specific node
176  //##
177  template <class DataType>
178  DataType *GetNamedDerivedObject(const char *name,
179  const DataNode *sourceNode,
180  bool onlyDirectDerivations = true) const
181  {
182  if (name == nullptr)
183  return nullptr;
184  DataNode *n = this->GetNamedDerivedNode(name, sourceNode, onlyDirectDerivations);
185  if (n == nullptr)
186  return nullptr;
187  else
188  return dynamic_cast<DataType *>(n->GetData());
189  }
190 
191  //##Documentation
192  //## @brief Returns a list of used grouptags
193  //##
194  const DataNode::GroupTagList GetGroupTags() const;
195 
196  /*ITK Mutex */
197  mutable itk::SimpleFastMutexLock m_MutexOne;
198 
199  /* Public Events */
201  //##Documentation
202  //## @brief AddEvent is emitted whenever a new node has been added to the DataStorage.
203  //##
204  //## Observers should register to this event by calling myDataStorage->AddNodeEvent.AddListener(myObject,
205  // MyObject::MyMethod).
206  //## After registering, myObject->MyMethod() will be called every time a new node has been added to the DataStorage.
207  //## Observers should unregister by calling myDataStorage->AddNodeEvent.RemoveListener(myObject,
208  //MyObject::MyMethod).
209  //## Note: AddEvents are _not_ emitted if a node is added to DataStorage by adding it to the the underlying
210  //DataTree!
211 
212  // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef
213  // for
214  // a Message1 object which is thread safe
215  DataStorageEvent AddNodeEvent;
216 
217  //##Documentation
218  //## @brief RemoveEvent is emitted directly before a node is removed from the DataStorage.
219  //##
220  //## Observers should register to this event by calling myDataStorage->RemoveNodeEvent.AddListener(myObject,
221  // MyObject::MyMethod).
222  //## After registering, myObject->MyMethod() will be called every time a new node has been added to the DataStorage.
223  //## Observers should unregister by calling myDataStorage->RemoveNodeEvent.RemoveListener(myObject,
224  // MyObject::MyMethod).
225  //## Note: RemoveEvents are also emitted if a node was removed from the DataStorage by deleting it from the
226  //underlying
227  // DataTree
228 
229  // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef
230  // for
231  // a Message1 object which is thread safe
232  DataStorageEvent RemoveNodeEvent;
233 
234  //##Documentation
235  //## @brief ChangedEvent is emitted directly after a node was changed.
236  //##
237  //## Observers should register to this event by calling myDataStorage->ChangedNodeEvent.AddListener(myObject,
238  // MyObject::MyMethod).
239  //## After registering, myObject->MyMethod() will be called every time a new node has been changed.
240  //## Observers should unregister by calling myDataStorage->ChangedNodeEvent.RemoveListener(myObject,
241  // MyObject::MyMethod).
242  //## Internally the DataStorage listens to itk::ModifiedEvents on the nodes and forwards them
243  //## to the listeners of this event.
244 
245  // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef
246  // for
247  // a Message1 object which is thread safe
248  DataStorageEvent ChangedNodeEvent;
249 
250  //##Documentation
251  //## @brief DeleteNodeEvent is emitted directly before a node is deleted.
252  //##
253  //## Observers should register to this event by calling myDataStorage->DeleteNodeEvent.AddListener(myObject,
254  // MyObject::MyMethod).
255  //## After registering, myObject->MyMethod() will be called when a node is deleted.
256  //## Observers should unregister by calling myDataStorage->DeleteNodeEvent.RemoveListener(myObject,
257  // MyObject::MyMethod).
258  //## Internally the DataStorage listens to itk::DeleteEvents on the nodes and forwards them
259  //## to the listeners of this event.
260 
261  // member variable is not needed to be locked in multi threaded scenarios since the DataStorageEvent is a typedef
262  // for
263  // a Message1 object which is thread safe
264  DataStorageEvent DeleteNodeEvent;
265 
266  DataStorageEvent InteractorChangedNodeEvent;
267 
268  //##Documentation
269  //## @brief Compute the axis-parallel bounding geometry of the input objects
270  //##
271  //## Throws std::invalid_argument exception if input is nullptr
272  //## @param input set of objects of the DataStorage to be included in the bounding geometry
273  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
274  //## and is set to @a false, the node is ignored for the bounding-box calculation.
275  //## @param renderer see @a boolPropertyKey
276  //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey
277  TimeGeometry::ConstPointer ComputeBoundingGeometry3D(const SetOfObjects *input,
278  const char *boolPropertyKey = nullptr,
279  const BaseRenderer *renderer = nullptr,
280  const char *boolPropertyKey2 = nullptr) const;
281 
282  //##Documentation
283  //## @brief Compute the axis-parallel bounding geometry of the data tree
284  //## (bounding box, minimal spacing of the considered nodes, live-span)
285  //##
286  //## it -> an iterator to a data tree structure
287  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
288  //## and is set to @a false, the node is ignored for the bounding-box calculation.
289  //## @param renderer see @a boolPropertyKey
290  //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey
291  TimeGeometry::ConstPointer ComputeBoundingGeometry3D(const char *boolPropertyKey = nullptr,
292  const BaseRenderer *renderer = nullptr,
293  const char *boolPropertyKey2 = nullptr) const;
294 
295  //##Documentation
296  //## @brief Compute the axis-parallel bounding geometry of all visible parts of the
297  //## data tree bounding box, minimal spacing of the considered nodes, live-span)
298  //##
299  //## Simply calls ComputeBoundingGeometry3D(it, "visible", renderer, boolPropertyKey).
300  //## it -> an iterator of a data tree structure
301  //## @param renderer the reference to the renderer
302  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
303  //## and is set to @a false, the node is ignored for the bounding-box calculation.
304  TimeGeometry::ConstPointer ComputeVisibleBoundingGeometry3D(const BaseRenderer *renderer = nullptr,
305  const char *boolPropertyKey = nullptr);
306 
307  //##Documentation
308  //## @brief Compute the bounding box of data tree structure
309  //## it -> an iterator to a data tree structure
310  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
311  //## and is set to @a false, the node is ignored for the bounding-box calculation.
312  //## @param renderer see @a boolPropertyKey
313  //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey
314  BoundingBox::Pointer ComputeBoundingBox(const char *boolPropertyKey = nullptr,
315  const BaseRenderer *renderer = nullptr,
316  const char *boolPropertyKey2 = nullptr);
317 
318  //##Documentation
319  //## \brief Compute the bounding box of all visible parts of the data tree structure, for general
320  //## rendering or renderer specific visibility property checking
321  //##
322  //## Simply calls ComputeBoundingBox(it, "visible", renderer, boolPropertyKey).
323  //## it -> an iterator of a data tree structure
324  //## @param renderer the reference to the renderer
325  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
326  //## and is set to @a false, the node is ignored for the bounding-box calculation.
327  BoundingBox::Pointer ComputeVisibleBoundingBox(const BaseRenderer *renderer = nullptr,
328  const char *boolPropertyKey = nullptr)
329  {
330  return ComputeBoundingBox("visible", renderer, boolPropertyKey);
331  }
332 
333  //##Documentation
334  //## @brief Compute the time-bounds of the contents of a data tree structure
335  //##
336  //## The methods returns only [-infinity, +infinity], if all data-objects have an infinite live-span. Otherwise,
337  //## all data-objects with infinite live-span are ignored.
338  //## it -> an iterator to a data tree structure
339  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
340  //## and is set to @a false, the node is ignored for the time-bounds calculation.
341  //## @param renderer see @a boolPropertyKey
342  //## @param boolPropertyKey2 a second condition that is applied additionally to @a boolPropertyKey
343  TimeBounds ComputeTimeBounds(const char *boolPropertyKey,
344  const BaseRenderer *renderer,
345  const char *boolPropertyKey2);
346 
347  //##Documentation
348  //## @brief Compute the time-bounds of all visible parts of the data tree structure, for general
349  //## rendering or renderer specific visibility property checking
350  //##
351  //## The methods returns only [-infinity, +infinity], if all data-objects have an infinite live-span. Otherwise,
352  //## all data-objects with infinite live-span are ignored.
353  //## Simply calls ComputeTimeBounds(it, "visible", renderer, boolPropertyKey).
354  //## @param it an iterator to a data tree structure
355  //## @param boolPropertyKey if a BoolProperty with this boolPropertyKey exists for a node (for @a renderer)
356  //## and is set to @a false, the node is ignored for the time-bounds calculation.
357  //## @param renderer see @a boolPropertyKey
358  TimeBounds ComputeTimeBounds(const BaseRenderer *renderer, const char *boolPropertyKey)
359  {
360  return ComputeTimeBounds("visible", renderer, boolPropertyKey);
361  }
362 
363  //##Documentation
364  //## @brief Defines whether or not NodeChangedEvent is invoked .
365  //##
366  //## This method can be used to set m_BlockNodeModifiedEvents.
367  //##
368  //## If this flag is true, NodeChangedEvent is not invoked when a
369  //## DataNode is modified. This might be undesired when setting
370  //## many properties on a datanode and you do not want anyone to
371  //## react.
372  void BlockNodeModifiedEvents(bool block);
373 
374  protected:
375  //##Documentation
376  //## @brief EmitAddNodeEvent emits the AddNodeEvent
377  //##
378  //## This method should be called by subclasses to emit the AddNodeEvent
379  void EmitAddNodeEvent(const DataNode *node);
380 
381  //##Documentation
382  //## @brief EmitRemoveNodeEvent emits the RemoveNodeEvent
383  //##
384  //## This method should be called by subclasses to emit the RemoveNodeEvent
385  void EmitRemoveNodeEvent(const DataNode *node);
386 
387  void OnNodeInteractorChanged(itk::Object *caller, const itk::EventObject &event);
388 
389  //##Documentation
390  //## @brief OnNodeModified listens to modified events of DataNodes.
391  //##
392  //## The node is hidden behind the caller parameter, which has to be casted first.
393  //## If the cast succeeds the ChangedNodeEvent is emitted with this node.
394  void OnNodeModifiedOrDeleted(const itk::Object *caller, const itk::EventObject &event);
395 
396  //##Documentation
397  //## @brief Adds a Modified-Listener to the given Node.
398  void AddListeners(const DataNode *_Node);
399 
400  //##Documentation
401  //## @brief Removes a Modified-Listener from the given Node.
402  void RemoveListeners(const DataNode *_Node);
403 
404  //##Documentation
405  //## @brief Saves Modified-Observer Tags for each node in order to remove the event listeners again.
406  std::map<const DataNode *, unsigned long> m_NodeModifiedObserverTags;
407 
408  std::map<const DataNode *, unsigned long> m_NodeInteractorChangedObserverTags;
409 
410  //##Documentation
411  //## @brief Saves Delete-Observer Tags for each node in order to remove the event listeners again.
412  std::map<const DataNode *, unsigned long> m_NodeDeleteObserverTags;
413 
414  //##Documentation
415  //## @brief If this class changes nodes itself, set this to TRUE in order
416  //## to suppress NodeChangedEvent to be emitted.
418 
419  //##Documentation
420  //## @brief Standard Constructor for ::New() instantiation
421  DataStorage();
422  //##Documentation
423  //## @brief Standard Destructor
424  ~DataStorage() override;
425 
426  //##Documentation
427  //## @brief Filters a SetOfObjects by the condition. If no condition is provided, the original set is returned
428  SetOfObjects::ConstPointer FilterSetOfObjects(const SetOfObjects *set, const NodePredicateBase *condition) const;
429 
430  //##Documentation
431  //## @brief Prints the contents of the DataStorage to os. Do not call directly, call ->Print() instead
432  void PrintSelf(std::ostream &os, itk::Indent indent) const override;
433  };
434 
435  //##Documentation
436  //## @brief returns the topmost visible node of a given list of nodes.
437  //## The function returns a node that is visible and has the highest layer of a set of given nodes.
438  //## The property list, which is used to find the visibility- and layer-property is is specified by the
439  //## given base renderer.
440  //##
441  MITKCORE_EXPORT DataNode::Pointer FindTopmostVisibleNode(const DataStorage::SetOfObjects::ConstPointer nodes,
442  const Point3D worldPosition,
443  const TimePointType timePoint,
444  const BaseRenderer* baseRender);
445 } // namespace mitk
446 
447 #endif // MITKDATASTORAGE_H
Message1< const DataNode * > DataStorageEvent
Data management class that handles &#39;was created by&#39; relations.
std::map< const DataNode *, unsigned long > m_NodeInteractorChangedObserverTags
#define MITKCORE_EXPORT
std::set< std::string > GroupTagList
Definition: mitkDataNode.h:71
itk::FixedArray< ScalarType, 2 > TimeBounds
Standard typedef for time-bounds.
DataType * GetNamedObject(const char *name) const
Convenience method to get the first data object of a given data type with a given name...
itk::SimpleFastMutexLock m_MutexOne
std::map< const DataNode *, unsigned long > m_NodeDeleteObserverTags
Saves Delete-Observer Tags for each node in order to remove the event listeners again.
DataNode * GetNamedNode(const std::string name) const
Convenience method to get the first node with a given name.
Organizes the rendering process.
DataStorageEvent DeleteNodeEvent
DeleteNodeEvent is emitted directly before a node is deleted.
DataCollection - Class to facilitate loading/accessing structured data.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
TimeBounds ComputeTimeBounds(const BaseRenderer *renderer, const char *boolPropertyKey)
Compute the time-bounds of all visible parts of the data tree structure, for general rendering or ren...
#define mitkClassMacroItkParent(className, SuperClassName)
Definition: mitkCommon.h:49
DataStorageEvent AddNodeEvent
AddEvent is emitted whenever a new node has been added to the DataStorage.
mitk::ScalarType TimePointType
std::map< const DataNode *, unsigned long > m_NodeModifiedObserverTags
Saves Modified-Observer Tags for each node in order to remove the event listeners again...
itk::VectorContainer< unsigned int, DataNode::Pointer > SetOfObjects
A Container of objects that is used as a result set of GetSubset() query operations (Set of...
BoundingBox::Pointer ComputeVisibleBoundingBox(const BaseRenderer *renderer=nullptr, const char *boolPropertyKey=nullptr)
Compute the bounding box of all visible parts of the data tree structure, for general rendering or re...
DataStorageEvent RemoveNodeEvent
RemoveEvent is emitted directly before a node is removed from the DataStorage.
DataType * GetNamedObject(const std::string name) const
Convenience method to get the first data object of a given data type with a given name...
DataType * GetNamedDerivedObject(const char *name, const DataNode *sourceNode, bool onlyDirectDerivations=true) const
Convenience method to get the first data object of a given data type with a given name that is derive...
DataStorageEvent ChangedNodeEvent
ChangedEvent is emitted directly after a node was changed.
Interface for evaluation conditions used in the DataStorage class GetSubset() method.
bool m_BlockNodeModifiedEvents
If this class changes nodes itself, set this to TRUE in order to suppress NodeChangedEvent to be emit...
MITKCORE_EXPORT DataNode::Pointer FindTopmostVisibleNode(const DataStorage::SetOfObjects::ConstPointer nodes, const Point3D worldPosition, const TimePointType timePoint, const BaseRenderer *baseRender)
returns the topmost visible node of a given list of nodes. The function returns a node that is visibl...
DataStorageEvent InteractorChangedNodeEvent
Class for nodes of the DataTree.
Definition: mitkDataNode.h:64