Medical Imaging Interaction Toolkit  2018.4.99-6ca56567
Medical Imaging Interaction Toolkit
mitkTool.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 #include "mitkTool.h"
14 
16 #include "mitkDisplayInteractor.h"
18 #include "mitkImageReadAccessor.h"
19 #include "mitkImageWriteAccessor.h"
22 #include "mitkProperties.h"
25 
26 // us
27 #include <usGetModuleContext.h>
28 #include <usModuleResource.h>
29 
30 // itk
31 #include <itkObjectFactory.h>
32 
33 mitk::Tool::Tool(const char *type, const us::Module *interactorModule)
34  : m_EventConfig("DisplayConfigMITK.xml"),
35  m_ToolManager(nullptr),
36  m_PredicateImages(NodePredicateDataType::New("Image")), // for reference images
37  m_PredicateDim3(NodePredicateDimension::New(3, 1)),
38  m_PredicateDim4(NodePredicateDimension::New(4, 1)),
39  m_PredicateDimension(mitk::NodePredicateOr::New(m_PredicateDim3, m_PredicateDim4)),
40  m_PredicateImage3D(NodePredicateAnd::New(m_PredicateImages, m_PredicateDimension)),
41  m_PredicateBinary(NodePredicateProperty::New("binary", BoolProperty::New(true))),
42  m_PredicateNotBinary(NodePredicateNot::New(m_PredicateBinary)),
43  m_PredicateSegmentation(NodePredicateProperty::New("segmentation", BoolProperty::New(true))),
44  m_PredicateNotSegmentation(NodePredicateNot::New(m_PredicateSegmentation)),
45  m_PredicateHelper(NodePredicateProperty::New("helper object", BoolProperty::New(true))),
46  m_PredicateNotHelper(NodePredicateNot::New(m_PredicateHelper)),
47  m_PredicateImageColorful(NodePredicateAnd::New(m_PredicateNotBinary, m_PredicateNotSegmentation)),
48  m_PredicateImageColorfulNotHelper(NodePredicateAnd::New(m_PredicateImageColorful, m_PredicateNotHelper)),
49  m_PredicateReference(NodePredicateAnd::New(m_PredicateImage3D, m_PredicateImageColorfulNotHelper)),
50  m_IsSegmentationPredicate(
51  NodePredicateAnd::New(NodePredicateOr::New(m_PredicateBinary, m_PredicateSegmentation), m_PredicateNotHelper)),
52  m_InteractorType(type),
53  m_DisplayInteractorConfigs(),
54  m_InteractorModule(interactorModule)
55 {
56 }
57 
59 {
60 }
61 
63 {
64  return true;
65 }
66 
68 {
69  if (m_InteractorType.empty())
70  return;
71 
72  try
73  {
74  auto isThisModule = nullptr == m_InteractorModule;
75 
76  auto module = isThisModule
78  : m_InteractorModule;
79 
80  LoadStateMachine(m_InteractorType + ".xml", module);
81  SetEventConfig(isThisModule ? "SegmentationToolsConfig.xml" : m_InteractorType + "Config.xml", module);
82  }
83  catch (const std::exception &e)
84  {
85  MITK_ERROR << "Could not load statemachine pattern " << m_InteractorType << ".xml with exception: " << e.what();
86  }
87 }
88 
89 void mitk::Tool::Notify(InteractionEvent *interactionEvent, bool isHandled)
90 {
91  // to use the state machine pattern,
92  // the event is passed to the state machine interface to be handled
93  if (!isHandled)
94  {
95  this->HandleEvent(interactionEvent, nullptr);
96  }
97 }
98 
100 {
101 }
102 
104 {
105  return true;
106 }
107 
108 const char *mitk::Tool::GetGroup() const
109 {
110  return "default";
111 }
112 
114 {
115  m_ToolManager = manager;
116 }
117 
119 {
120  // As a legacy solution the display interaction of the new interaction framework is disabled here to avoid conflicts
121  // with tools
122  // Note: this only affects InteractionEventObservers (formerly known as Listeners) all DataNode specific interaction
123  // will still be enabled
124  m_DisplayInteractorConfigs.clear();
125  std::vector<us::ServiceReference<InteractionEventObserver>> listEventObserver =
127  for (auto it = listEventObserver.begin(); it != listEventObserver.end(); ++it)
128  {
129  auto displayInteractor = dynamic_cast<DisplayInteractor*>(us::GetModuleContext()->GetService<InteractionEventObserver>(*it));
130  if (displayInteractor != nullptr)
131  {
132  // remember the original configuration
133  m_DisplayInteractorConfigs.insert(std::make_pair(*it, displayInteractor->GetEventConfig()));
134  // here the alternative configuration is loaded
135  displayInteractor->SetEventConfig(m_EventConfig.c_str());
136  }
137 
138  auto displayActionEventBroadcast = dynamic_cast<DisplayActionEventBroadcast*>(us::GetModuleContext()->GetService<InteractionEventObserver>(*it));
139  if (displayActionEventBroadcast != nullptr)
140  {
141  // remember the original configuration
142  m_DisplayInteractorConfigs.insert(std::make_pair(*it, displayActionEventBroadcast->GetEventConfig()));
143  // here the alternative configuration is loaded
144  displayActionEventBroadcast->SetEventConfig(m_EventConfig.c_str());
145  }
146  }
147 }
148 
150 {
151  // Re-enabling InteractionEventObservers that have been previously disabled for legacy handling of Tools
152  // in new interaction framework
153  for (auto it = m_DisplayInteractorConfigs.begin(); it != m_DisplayInteractorConfigs.end(); ++it)
154  {
155  if (it->first)
156  {
157  auto displayInteractor = static_cast<DisplayInteractor*>(us::GetModuleContext()->GetService<InteractionEventObserver>(it->first));
158  if (displayInteractor != nullptr)
159  {
160  // here the regular configuration is loaded again
161  displayInteractor->SetEventConfig(it->second);
162  }
163 
164  auto displayActionEventBroadcast = dynamic_cast<DisplayActionEventBroadcast*>(us::GetModuleContext()->GetService<InteractionEventObserver>(it->first));
165  if (displayActionEventBroadcast != nullptr)
166  {
167  // here the regular configuration is loaded again
168  displayActionEventBroadcast->SetEventConfig(it->second);
169  }
170  }
171  }
172  m_DisplayInteractorConfigs.clear();
173 }
174 
175 itk::Object::Pointer mitk::Tool::GetGUI(const std::string &toolkitPrefix, const std::string &toolkitPostfix)
176 {
177  itk::Object::Pointer object;
178 
179  std::string classname = this->GetNameOfClass();
180  std::string guiClassname = toolkitPrefix + classname + toolkitPostfix;
181 
182  std::list<itk::LightObject::Pointer> allGUIs = itk::ObjectFactoryBase::CreateAllInstance(guiClassname.c_str());
183  for (auto iter = allGUIs.begin(); iter != allGUIs.end(); ++iter)
184  {
185  if (object.IsNull())
186  {
187  object = dynamic_cast<itk::Object *>(iter->GetPointer());
188  }
189  else
190  {
191  MITK_ERROR << "There is more than one GUI for " << classname << " (several factories claim ability to produce a "
192  << guiClassname << " ) " << std::endl;
193  return nullptr; // people should see and fix this error
194  }
195  }
196 
197  return object;
198 }
199 
201 {
202  return m_PredicateReference.GetPointer();
203 }
204 
206 {
207  return m_IsSegmentationPredicate.GetPointer();
208 }
209 
211  const std::string &organName,
212  const mitk::Color &color)
213 {
214  // we NEED a reference image for size etc.
215  if (!original)
216  return nullptr;
217 
218  // actually create a new empty segmentation
219  PixelType pixelType(mitk::MakeScalarPixelType<DefaultSegmentationDataType>());
221 
222  if (original->GetDimension() == 2)
223  {
224  const unsigned int dimensions[] = {original->GetDimension(0), original->GetDimension(1), 1};
225  segmentation->Initialize(pixelType, 3, dimensions);
226  segmentation->AddLayer();
227  }
228  else
229  {
230  segmentation->Initialize(original);
231  }
232 
234  label->SetName(organName);
235  label->SetColor(color);
236  label->SetValue(1);
237  segmentation->GetActiveLabelSet()->AddLabel(label);
238  segmentation->GetActiveLabelSet()->SetActiveLabel(1);
239 
240  unsigned int byteSize = sizeof(mitk::Label::PixelType);
241 
242  if (segmentation->GetDimension() < 4)
243  {
244  for (unsigned int dim = 0; dim < segmentation->GetDimension(); ++dim)
245  {
246  byteSize *= segmentation->GetDimension(dim);
247  }
248 
249  mitk::ImageWriteAccessor writeAccess(segmentation.GetPointer(), segmentation->GetVolumeData(0));
250 
251  memset(writeAccess.GetData(), 0, byteSize);
252  }
253  else
254  {
255  // if we have a time-resolved image we need to set memory to 0 for each time step
256  for (unsigned int dim = 0; dim < 3; ++dim)
257  {
258  byteSize *= segmentation->GetDimension(dim);
259  }
260 
261  for (unsigned int volumeNumber = 0; volumeNumber < segmentation->GetDimension(3); volumeNumber++)
262  {
263  mitk::ImageWriteAccessor writeAccess(segmentation.GetPointer(), segmentation->GetVolumeData(volumeNumber));
264 
265  memset(writeAccess.GetData(), 0, byteSize);
266  }
267  }
268 
269  if (original->GetTimeGeometry())
270  {
271  TimeGeometry::Pointer originalGeometry = original->GetTimeGeometry()->Clone();
272  segmentation->SetTimeGeometry(originalGeometry);
273  }
274  else
275  {
276  Tool::ErrorMessage("Original image does not have a 'Time sliced geometry'! Cannot create a segmentation.");
277  return nullptr;
278  }
279 
280  return CreateSegmentationNode(segmentation, organName, color);
281 }
282 
284  const std::string &organName,
285  const mitk::Color &color)
286 {
287  if (!image)
288  return nullptr;
289 
290  // decorate the datatreenode with some properties
291  DataNode::Pointer segmentationNode = DataNode::New();
292  segmentationNode->SetData(image);
293 
294  // name
295  segmentationNode->SetProperty("name", StringProperty::New(organName));
296 
297  // visualization properties
298  segmentationNode->SetProperty("binary", BoolProperty::New(true));
299  segmentationNode->SetProperty("color", ColorProperty::New(color));
301  lut->SetType(mitk::LookupTable::MULTILABEL);
303  lutProp->SetLookupTable(lut);
304  segmentationNode->SetProperty("LookupTable", lutProp);
305  segmentationNode->SetProperty("texture interpolation", BoolProperty::New(false));
306  segmentationNode->SetProperty("layer", IntProperty::New(10));
307  segmentationNode->SetProperty("levelwindow", LevelWindowProperty::New(LevelWindow(0.5, 1)));
308  segmentationNode->SetProperty("opacity", FloatProperty::New(0.3));
309  segmentationNode->SetProperty("segmentation", BoolProperty::New(true));
310  segmentationNode->SetProperty("reslice interpolation",
311  VtkResliceInterpolationProperty::New()); // otherwise -> segmentation appears in 2
312  // slices sometimes (only visual effect, not
313  // different data)
314  // For MITK-3M3 release, the volume of all segmentations should be shown
315  segmentationNode->SetProperty("showVolume", BoolProperty::New(true));
316 
317  return segmentationNode;
318 }
319 
321 {
322  // Each specific tool should load its own resource. This one will be invalid
323  return us::ModuleResource();
324 }
325 
327 {
328  // Each specific tool should load its own resource. This one will be invalid
329  return us::ModuleResource();
330 }
void Notify(InteractionEvent *interactionEvent, bool isHandled) override
Definition: mitkTool.cpp:89
DataNode::Pointer CreateSegmentationNode(Image *image, const std::string &organName, const mitk::Color &color)
Definition: mitkTool.cpp:283
virtual const char * GetGroup() const
Name of a group.
Definition: mitkTool.cpp:108
~Tool() override
Definition: mitkTool.cpp:58
Predicate that evaluates if the given DataNode has a specific property. If the second parameter is nu...
Composite predicate that negates its child predicate Changed: NodePredicateNot now derives from NodeP...
Base class to implement InteractionEventObservers.
Observer that manages the interaction with the display.
virtual void Activated()
Called when the tool gets activated.
Definition: mitkTool.cpp:118
Base of all data objects.
Definition: mitkBaseData.h:42
Predicate that evaluates if the given DataNodes data object has the specified dimension, for datasets where dimension is applicable.
static Pointer New()
virtual void SetToolManager(ToolManager *)
Definition: mitkTool.cpp:113
#define MITK_ERROR
Definition: mitkLogMacros.h:20
bool HandleEvent(InteractionEvent *event, DataNode *dataNode)
static Pointer New()
bool LoadStateMachine(const std::string &filename, const us::Module *module=nullptr)
Loads XML resource.
DataCollection - Class to facilitate loading/accessing structured data.
Message1< std::string > ErrorMessage
To send error messages (to be shown by some GUI)
Definition: mitkTool.h:99
virtual bool CanHandle(BaseData *referenceData) const
Definition: mitkTool.cpp:62
void * GetService(const ServiceReferenceBase &reference)
std::string m_EventConfig
Let subclasses change their event configuration.
Definition: mitkTool.h:218
virtual us::ModuleResource GetIconResource() const
Returns the tool button icon of the tool wrapped by a usModuleResource.
Definition: mitkTool.cpp:320
The LevelWindow class Class to store level/window values.
static Pointer New()
static Pointer New()
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:66
virtual void Deactivated()
Called when the tool gets deactivated.
Definition: mitkTool.cpp:149
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
static Pointer New()
static Pointer New()
This class serves as an event state machine while simultaneously observing interaction events...
virtual void InitializeStateMachine()
Definition: mitkTool.cpp:67
Module * GetModule() const
Image class for storing images.
Definition: mitkImage.h:72
virtual NodePredicateBase::ConstPointer GetReferenceDataPreference() const
Definition: mitkTool.cpp:200
DataNode::Pointer CreateEmptySegmentationNode(const Image *original, const std::string &organName, const mitk::Color &color)
Definition: mitkTool.cpp:210
mitk::Image::Pointer image
std::vector< ServiceReferenceU > GetServiceReferences(const std::string &clazz, const std::string &filter=std::string())
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
static Pointer New()
virtual us::ModuleResource GetCursorIconResource() const
Returns the path of a cursor icon.
Definition: mitkTool.cpp:326
static Pointer New()
static Pointer New()
void ConnectActionsAndFunctions() override
Definition: mitkTool.cpp:99
ToolManager * m_ToolManager
Definition: mitkTool.h:228
unsigned short PixelType
Definition: mitkLabel.h:36
bool FilterEvents(InteractionEvent *, DataNode *) override
Definition: mitkTool.cpp:103
ImageWriteAccessor class to get locked write-access for a particular image part.
virtual itk::Object::Pointer GetGUI(const std::string &toolkitPrefix, const std::string &toolkitPostfix)
Interface for GUI creation.
Definition: mitkTool.cpp:175
Predicate that evaluates if the given DataNodes data object is of a specific data type...
Pointer Clone() const
static Pointer New()
virtual NodePredicateBase::ConstPointer GetWorkingDataPreference() const
Definition: mitkTool.cpp:205
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
static Pointer New()
Composite predicate that forms a logical AND relation from its child predicates.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57
Composite predicate that forms a logical OR relation from its child predicates.
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
Manages and coordinates instances of mitk::Tool.
bool SetEventConfig(const std::string &filename, const us::Module *module=nullptr)
Loads a configuration from an XML resource.