Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkLevelWindowManager.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkLevelWindowManager.h"
18 #include "mitkDataStorage.h"
19 #include "mitkImage.h"
20 #include "mitkMessage.h"
21 #include "mitkNodePredicateAnd.h"
22 #include "mitkNodePredicateBase.h"
24 #include "mitkNodePredicateNot.h"
25 #include "mitkNodePredicateOr.h"
27 #include "mitkProperties.h"
29 #include <itkCommand.h>
30 
32  : m_DataStorage(NULL),
33  m_LevelWindowProperty(NULL),
34  m_AutoTopMost(true),
35  m_IsObserverTagSet(false),
36  m_CurrentImage(NULL),
37  m_IsPropertyModifiedTagSet(false),
38  m_SettingImgForLvlWinProp(false)
39 {
40 }
41 
43 {
44  if (m_DataStorage.IsNotNull())
45  {
46  m_DataStorage->AddNodeEvent.RemoveListener(
48  m_DataStorage->RemoveNodeEvent.RemoveListener(
50  m_DataStorage = NULL;
51  }
52 
53  if (m_IsPropertyModifiedTagSet && m_LevelWindowProperty.IsNotNull())
54  {
55  m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag);
56  m_IsPropertyModifiedTagSet = false;
57  }
58 
59  // clear both observer maps
60  this->ClearPropObserverLists();
61 }
62 
64 {
65  if (ds == NULL)
66  return;
67 
68  /* remove listeners of old DataStorage */
69  if (m_DataStorage.IsNotNull())
70  {
71  m_DataStorage->AddNodeEvent.RemoveListener(
73  m_DataStorage->RemoveNodeEvent.RemoveListener(
75  }
76 
77  /* register listener for new DataStorage */
78  m_DataStorage = ds; // register
79  m_DataStorage->AddNodeEvent.AddListener(
81  m_DataStorage->RemoveNodeEvent.AddListener(
83 
84  this->DataStorageAddedNode(); // update us with new DataStorage
85 }
86 
87 void mitk::LevelWindowManager::OnPropertyModified(const itk::EventObject &)
88 {
89  Modified();
90 }
91 
92 void mitk::LevelWindowManager::SetAutoTopMostImage(bool autoTopMost, const mitk::DataNode *removedNode)
93 {
94  m_AutoTopMost = autoTopMost;
95  if (m_AutoTopMost == false)
96  return;
97 
98  if (m_IsPropertyModifiedTagSet && m_LevelWindowProperty.IsNotNull())
99  {
100  m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag);
101  m_IsPropertyModifiedTagSet = false;
102  }
103 
104  /* search topmost image */
105  if (m_DataStorage.IsNull())
106  {
107  itkExceptionMacro("DataStorage not set");
108  }
109 
110  int maxLayer = itk::NumericTraits<int>::min();
111  m_LevelWindowProperty = NULL;
112 
113  mitk::DataNode::Pointer topLevelNode;
114 
115  mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes();
116  for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
117  {
118  mitk::DataNode::Pointer node = it->Value();
119  if (node.IsNull() || (removedNode != NULL && node == removedNode))
120  continue;
121 
122  m_SettingImgForLvlWinProp = true;
123  node->SetBoolProperty("imageForLevelWindow", false);
124  m_SettingImgForLvlWinProp = false;
125 
126  if (node->IsVisible(NULL) == false)
127  continue;
128 
129  int layer = 0;
130  node->GetIntProperty("layer", layer);
131  if (layer < maxLayer)
132  continue;
133 
134  mitk::LevelWindowProperty::Pointer levelWindowProperty =
135  dynamic_cast<mitk::LevelWindowProperty *>(node->GetProperty("levelwindow"));
136  if (levelWindowProperty.IsNull())
137  continue;
138 
141 
143  dynamic_cast<mitk::RenderingModeProperty *>(node->GetProperty("Image Rendering.Mode"));
144 
145  if (mode.IsNotNull())
146  {
147  int currMode = mode->GetRenderingMode();
148  if (currMode == nonLvlWinMode1 || currMode == nonLvlWinMode2)
149  {
150  continue;
151  }
152  }
153  else
154  continue;
155 
156  m_LevelWindowProperty = levelWindowProperty;
157  m_CurrentImage = dynamic_cast<mitk::Image *>(node->GetData());
158  topLevelNode = node;
159 
160  maxLayer = layer;
161  }
162 
163  if (topLevelNode.IsNotNull())
164  {
165  m_SettingImgForLvlWinProp = true;
166  topLevelNode->SetBoolProperty("imageForLevelWindow", true);
167  m_SettingImgForLvlWinProp = false;
168  }
169 
170  this->SetLevelWindowProperty(m_LevelWindowProperty);
171 
172  if (m_LevelWindowProperty.IsNull())
173  {
174  Modified();
175  }
176  // else SetLevelWindowProperty will call Modified();
177 }
178 
179 // sets an specific LevelWindowProperty, all changes will affect the image belonging to this property.
181 {
182  if (levelWindowProperty.IsNull())
183  return;
184 
185  /* search image than belongs to the property */
186  typedef mitk::DataStorage::SetOfObjects NodeSetType;
187  NodeSetType::ConstPointer nodes = m_DataStorage->GetAll();
188  NodeSetType::ConstIterator it = nodes->Begin();
189  mitk::DataNode::Pointer propNode = 0;
190  while (it != nodes->End())
191  {
192  mitk::DataNode::Pointer node = it.Value();
194  dynamic_cast<mitk::LevelWindowProperty *>(node->GetProperty("levelwindow"));
195  if (prop == levelWindowProperty)
196  {
197  propNode = node;
198  }
199  else
200  {
201  m_SettingImgForLvlWinProp = true;
202  node->SetBoolProperty("imageForLevelWindow", false);
203  m_SettingImgForLvlWinProp = false;
204  }
205 
206  ++it;
207  }
208 
209  if (propNode.IsNull())
210  {
211  mitkThrow() << "No Image in DataStorage that belongs to LevelWindow property" << m_LevelWindowProperty;
212  }
213 
214  if (m_IsPropertyModifiedTagSet) // remove listener for old property
215  {
216  m_LevelWindowProperty->RemoveObserver(m_PropertyModifiedTag);
217  m_IsPropertyModifiedTagSet = false;
218  }
219 
220  m_LevelWindowProperty = levelWindowProperty;
221 
223  itk::ReceptorMemberCommand<LevelWindowManager>::New(); // register listener for new property
224  command->SetCallbackFunction(this, &LevelWindowManager::OnPropertyModified);
225  m_PropertyModifiedTag = m_LevelWindowProperty->AddObserver(itk::ModifiedEvent(), command);
226  m_IsPropertyModifiedTagSet = true;
227 
228  m_CurrentImage = dynamic_cast<mitk::Image *>(propNode->GetData());
229 
230  m_SettingImgForLvlWinProp = true;
231  propNode->SetBoolProperty("imageForLevelWindow", true);
232  m_SettingImgForLvlWinProp = false;
233 
234  this->Modified();
235 }
236 
237 // returns the current mitkLevelWindowProperty object from the image that is affected by changes
239 {
240  return m_LevelWindowProperty;
241 }
242 
243 // returns Level/Window values for the current image
245 {
246  if (m_LevelWindowProperty.IsNotNull())
247  {
248  return m_LevelWindowProperty->GetLevelWindow();
249  }
250  else
251  {
252  itkExceptionMacro("No LevelWindow available!");
253  }
254 }
255 
256 // sets new Level/Window values and informs all listeners about changes
258 {
259  if (m_LevelWindowProperty.IsNotNull())
260  {
261  m_LevelWindowProperty->SetLevelWindow(levelWindow);
262  }
263  this->Modified();
264 }
265 
267 {
268  // update observers with new data storage
269  UpdateObservers();
270 
271  // Initialize LevelWindowsManager to new image
272  SetAutoTopMostImage(true);
273 
274  // check if everything is still ok
275  if ((m_PropObserverToNode.size() != m_PropObserverToNode2.size()) ||
276  (m_PropObserverToNode2.size() != this->GetRelevantNodes()->size()))
277  {
278  mitkThrow() << "Wrong number of observers in Level Window Manager!";
279  }
280 }
281 
283 {
284  // first: check if deleted node is part of relevant nodes. If not, abort method because there is no need change
285  // anything.
286  if ((this->GetRelevantNodes()->size() == 0))
287  return;
288  bool removedNodeIsRelevant = false;
289  /* Iterator code: is crashing, don't know why... so using for loop
290  for (mitk::DataStorage::SetOfObjects::ConstIterator it = this->GetRelevantNodes()->Begin();
291  it != this->GetRelevantNodes()->End();
292  ++it)
293  {if (it->Value() == removedNode) {removedNodeIsRelevant=true;}}*/
294  for (unsigned int i = 0; i < this->GetRelevantNodes()->size(); i++)
295  {
296  if (this->GetRelevantNodes()->at(i) == removedNode)
297  {
298  removedNodeIsRelevant = true;
299  }
300  }
301  if (!removedNodeIsRelevant)
302  return;
303 
304  // remember node which will be removed
305  m_NodeMarkedToDelete = removedNode;
306 
307  // update observers
308  UpdateObservers();
309 
310  /* search image than belongs to the property */
311  if (m_LevelWindowProperty.IsNull())
312  {
313  SetAutoTopMostImage(true, removedNode);
314  }
315  else
316  {
317  mitk::NodePredicateProperty::Pointer p2 = mitk::NodePredicateProperty::New("levelwindow", m_LevelWindowProperty);
318  mitk::DataNode *n = m_DataStorage->GetNode(p2);
319  if (n == NULL || m_AutoTopMost) // if node was deleted, change our behaviour to AutoTopMost, if AutoTopMost is true
320  // change level window to topmost node
321  {
322  SetAutoTopMostImage(true, removedNode);
323  }
324  }
325 
326  // reset variable
327  m_NodeMarkedToDelete = NULL;
328 
329  // check if everything is still ok
330  if ((m_PropObserverToNode.size() != m_PropObserverToNode2.size()) ||
331  (m_PropObserverToNode2.size() != (this->GetRelevantNodes()->size() - 1)))
332  {
333  mitkThrow() << "Wrong number of observers in Level Window Manager!";
334  }
335 }
336 
338 {
339  this->ClearPropObserverLists(); // remove old observers
340  CreatePropObserverLists(); // create new observer lists
341 }
342 
344 {
345  return m_PropObserverToNode.size();
346 }
347 
349 {
350  return m_DataStorage.GetPointer();
351 }
352 
353 // true if changes on slider or line-edits will affect always the topmost layer image
355 {
356  return m_AutoTopMost;
357 }
358 
360 {
361  mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes();
362  for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
363  {
364  mitk::DataNode::Pointer node = it->Value();
365  if (node.IsNull())
366  continue;
367 
368  bool isSelected = false;
369  node->GetBoolProperty("selected", isSelected);
370  if (isSelected)
371  {
372  mitk::LevelWindow selectedLevelWindow;
373  node->GetLevelWindow(selectedLevelWindow); // node is an image node because of predicates
374 
375  mitk::Image *image = dynamic_cast<mitk::Image *>(node->GetData());
376  int displayedComponent = 0;
377  if (image && (node->GetIntProperty("Image.Displayed Component", displayedComponent)))
378  { // we found a selected image with a displayed component
379  // let's recalculate the levelwindow for this.
380  selectedLevelWindow.SetAuto(image, true, true, static_cast<unsigned>(displayedComponent));
381  node->SetLevelWindow(selectedLevelWindow);
382  }
383  }
384 
385  mitk::LevelWindow levelWindow;
386  node->GetLevelWindow(levelWindow);
387  }
388 
389  this->Update(event);
390 }
391 
392 void mitk::LevelWindowManager::Update(const itk::EventObject &) // visible property of a image has changed
393 {
394  if (m_SettingImgForLvlWinProp) // no mutex, should still help
395  {
396  return;
397  }
398 
399  if (m_AutoTopMost)
400  {
401  SetAutoTopMostImage(true);
402  return;
403  }
404 
405  int maxVisibleLayer = itk::NumericTraits<int>::min();
406  mitk::DataNode::Pointer highestVisible = NULL;
407  std::vector<mitk::DataNode::Pointer> visProbNodes;
408 
409  mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes();
410  for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
411  {
412  mitk::DataNode::Pointer node = it->Value();
413 
414  if (node.IsNull())
415  {
416  continue;
417  }
418 
419  bool visible = node->IsVisible(NULL);
420 
421  if (node->IsVisible(NULL))
422  {
423  int layer = -1;
424  node->GetIntProperty("layer", layer);
425  if (layer > maxVisibleLayer)
426  {
427  maxVisibleLayer = layer;
428  highestVisible = node;
429  }
430  }
431 
432  bool prop = false;
433  node->GetBoolProperty("imageForLevelWindow", prop);
434 
435  if (prop && visible)
436  {
437  visProbNodes.push_back(node);
438  }
439  }
440 
441  int numVisProbNodes = visProbNodes.size();
442  if (numVisProbNodes > 2)
443  {
444  MITK_ERROR << "Error: not more than two visible nodes are expected to have the imageForLevelWindow property set at "
445  "any point.";
446  }
447  else if (numVisProbNodes == 2)
448  {
449  for (std::vector<mitk::DataNode::Pointer>::const_iterator it = visProbNodes.begin(); it != visProbNodes.end(); ++it)
450  {
452  dynamic_cast<mitk::LevelWindowProperty *>((*it)->GetProperty("levelwindow"));
453  if (newProp != m_LevelWindowProperty)
454  {
455  this->SetLevelWindowProperty(newProp);
456  return;
457  }
458  }
459  }
460  else if (numVisProbNodes == 1)
461  {
463  dynamic_cast<mitk::LevelWindowProperty *>(visProbNodes[0]->GetProperty("levelwindow"));
464  if (newProp != m_LevelWindowProperty)
465  {
466  this->SetLevelWindowProperty(newProp);
467  return;
468  }
469  }
470  else if (highestVisible)
471  {
473  dynamic_cast<mitk::LevelWindowProperty *>(highestVisible->GetProperty("levelwindow"));
474 
475  this->SetLevelWindowProperty(lvlProp);
476  }
477  else
478  {
479  Modified();
480  }
481 }
482 
484 {
485  if (m_DataStorage.IsNull())
487 
490  mitk::NodePredicateProperty::Pointer hasLevelWindow = mitk::NodePredicateProperty::New("levelwindow", NULL);
491 
497  predicateTypes->AddPredicate(isImage);
498  predicateTypes->AddPredicate(isDImage);
499  predicateTypes->AddPredicate(isTImage);
500  predicateTypes->AddPredicate(isQImage);
501 
503  predicate->AddPredicate(notBinary);
504  predicate->AddPredicate(hasLevelWindow);
505  predicate->AddPredicate(predicateTypes);
506 
507  mitk::DataStorage::SetOfObjects::ConstPointer relevantNodes = m_DataStorage->GetSubset(predicate);
508 
509  return relevantNodes;
510 }
511 
513 {
514  return m_CurrentImage;
515 }
516 
518 {
519  for (ObserverToPropertyMap::iterator iter = m_PropObserverToNode.begin(); iter != m_PropObserverToNode.end(); ++iter)
520  {
521  (*iter).second->RemoveObserver((*iter).first.first);
522  (*iter).second = 0;
523  }
524  m_PropObserverToNode.clear();
525 
526  for (ObserverToPropertyMap::iterator iter = m_PropObserverToNode2.begin(); iter != m_PropObserverToNode2.end();
527  ++iter)
528  {
529  (*iter).second->RemoveObserver((*iter).first.first);
530  (*iter).second = 0;
531  }
532  m_PropObserverToNode2.clear();
533 
534  for (ObserverToPropertyMap::iterator iter = m_PropObserverToNode3.begin(); iter != m_PropObserverToNode3.end();
535  ++iter)
536  {
537  (*iter).second->RemoveObserver((*iter).first.first);
538  (*iter).second = 0;
539  }
540  m_PropObserverToNode3.clear();
541 
542  for (ObserverToPropertyMap::iterator iter = m_PropObserverToNode4.begin(); iter != m_PropObserverToNode4.end();
543  ++iter)
544  {
545  (*iter).second->RemoveObserver((*iter).first.first);
546  (*iter).second = 0;
547  }
548  m_PropObserverToNode4.clear();
549 
550  for (ObserverToPropertyMap::iterator iter = m_PropObserverToNode5.begin(); iter != m_PropObserverToNode5.end();
551  ++iter)
552  {
553  (*iter).second->RemoveObserver((*iter).first.first);
554  (*iter).second = 0;
555  }
556  m_PropObserverToNode5.clear();
557 }
558 
560 {
561  if (m_DataStorage.IsNull()) // check if data storage is set
562  {
563  itkExceptionMacro("DataStorage not set");
564  }
565 
566  /* add observers for all relevant nodes */
567  mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetRelevantNodes();
568  for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
569  {
570  if ((it->Value().IsNull()) || (it->Value() == m_NodeMarkedToDelete))
571  {
572  continue;
573  }
574 
575  /* register listener for changes in visible property */
578  command->SetCallbackFunction(this, &LevelWindowManager::Update);
579  unsigned long visIdx = it->Value()->GetProperty("visible")->AddObserver(itk::ModifiedEvent(), command);
580  m_PropObserverToNode[PropDataPair(visIdx, it->Value())] = it->Value()->GetProperty("visible");
581 
582  /* register listener for changes in layer property */
585  command2->SetCallbackFunction(this, &LevelWindowManager::Update);
586  unsigned long layerIdx = it->Value()->GetProperty("layer")->AddObserver(itk::ModifiedEvent(), command2);
587  m_PropObserverToNode2[PropDataPair(layerIdx, it->Value())] = it->Value()->GetProperty("layer");
588 
589  /* register listener for changes in layer property */
592  command3->SetCallbackFunction(this, &LevelWindowManager::Update);
593  mitk::BaseProperty::Pointer imageRenderingMode = it->Value()->GetProperty("Image Rendering.Mode");
594  if (imageRenderingMode.IsNotNull())
595  {
596  unsigned long rendIdx = imageRenderingMode->AddObserver(itk::ModifiedEvent(), command3);
597  m_PropObserverToNode3[PropDataPair(rendIdx, it->Value())] = imageRenderingMode.GetPointer();
598  }
599 
602  command4->SetCallbackFunction(this, &LevelWindowManager::RecaluclateLevelWindowForSelectedComponent);
603  mitk::BaseProperty::Pointer displayedImageComponent = it->Value()->GetProperty("Image.Displayed Component");
604  if (displayedImageComponent.IsNotNull())
605  {
606  unsigned long dispIdx = displayedImageComponent->AddObserver(itk::ModifiedEvent(), command4);
607  m_PropObserverToNode4[PropDataPair(dispIdx, it->Value())] = displayedImageComponent.GetPointer();
608  }
609 
612  command5->SetCallbackFunction(this, &LevelWindowManager::Update);
613  mitk::BaseProperty::Pointer imgForLvlWin = it->Value()->GetProperty("imageForLevelWindow");
614  if (imgForLvlWin.IsNull())
615  {
616  it->Value()->SetBoolProperty("imageForLevelWindow", false);
617  imgForLvlWin = it->Value()->GetProperty("imageForLevelWindow");
618  }
619  unsigned long lvlWinIdx = imgForLvlWin->AddObserver(itk::ModifiedEvent(), command5);
620  m_PropObserverToNode5[PropDataPair(lvlWinIdx, it->Value())] = it->Value()->GetProperty("imageForLevelWindow");
621  }
622 }
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
static Pointer New()
void DataStorageRemovedNode(const DataNode *removedNode=nullptr)
This method is called when a node is removed to the data storage. A listener on the data storage is u...
The LevelWindowProperty class Property for the mitk::LevelWindow.
itk::VectorContainer< unsigned int, mitk::DataNode::Pointer > SetOfObjects
A Container of objects that is used as a result set of GetSubset() query operations (Set of...
void SetLevelWindow(const LevelWindow &levelWindow)
Sets new Level/Window values and informs all listeners about changes.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void ClearPropObserverLists()
internal help method to clear both lists/maps.
static Pointer New()
static void Update(vtkPolyData *)
Definition: mitkSurface.cpp:35
const LevelWindow & GetLevelWindow()
void Update(const itk::EventObject &e)
gets called if a visible property changes
itk::SmartPointer< const Self > ConstPointer
DataStorage::SetOfObjects::ConstPointer GetRelevantNodes()
std::pair< unsigned long, DataNode::Pointer > PropDataPair
The LevelWindow class Class to store level/window values.
static Pointer New()
mitk::DataStorage::Pointer m_DataStorage
void OnPropertyModified(const itk::EventObject &e)
change notifications from mitkLevelWindowProperty
LevelWindowProperty::Pointer GetLevelWindowProperty()
void DataStorageAddedNode(const DataNode *n=nullptr)
This method is called when a node is added to the data storage. A listener on the data storage is use...
void CreatePropObserverLists()
internal help method to create both lists/maps.
#define mitkThrow()
Image class for storing images.
Definition: mitkImage.h:76
void SetAuto(const Image *image, bool tryPicTags=true, bool guessByCentralSlice=true, unsigned selectedComponent=0)
sets level/window to optimize the contrast of the given Image
void SetLevelWindowProperty(LevelWindowProperty::Pointer levelWindowProperty)
Sets an specific LevelWindowProperty, all changes will affect the image belonging to this property...
static Pointer New(const char *_arg)
DataStorage * GetDataStorage()
returns the datastorage
static Pointer New(const char *_arg)
static T min(T x, T y)
Definition: svm.cpp:67
void SetAutoTopMostImage(bool autoTopMost, const DataNode *removedNode=nullptr)
(Re-)Initializes the LevelWindowManager by setting the topmost image. Use the removedNode parameter i...
void RecaluclateLevelWindowForSelectedComponent(const itk::EventObject &)
void SetDataStorage(DataStorage *ds)
Image * GetCurrentImage()
return the currently active image
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.