Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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.