Using observer tags

Hi there,
I am creating a module that will continually calculate the angle between two planes as one is moved. I followed the tutorial on the wiki to add an observer to the transform which is getting moved and it works great but I am having trouble removing the observer. My code to remove the observer doesn’t seem to work as after I run it the angle is still continually calculated. I have copied my code below:

  def onSelect(self):
    self.applyButton.enabled = self.plannedTransformSelector.currentNode() and self.actualTransformSelector.currentNode()
    self.clearButton.enabled = self.actualTransformSelector.currentNode()

  def onApplyButton(self):
    logic = CalculateActualFibulaCutsLogic()
    logic.Results(self.plannedTransformSelector.currentNode(), self.actualTransformSelector.currentNode())
    self.angleDif.text = str(logic.angle)
    self.actualTransformNode = self.actualTransformSelector.currentNode()
    self.sawobserverTag = self.actualTransformNode.AddObserver(vtk.vtkCommand.ModifiedEvent, self.onTransformUpdated)

  def onTransformUpdated(self, caller = None, event = None):
    self.onApplyButton()

  def continuousDisplay(self):
    self.logic.Result(self.plannedTransformSelector.currentNode(), self.actualTransformSelector.currentNode())
    print(self.logic.angle)
    self.angleDif.text = str(self.logic.angle)

  def onClearButton(self):
    if self.sawobserverTag:
      print("removing...")
      self.actualTransformNode.RemoveObserver(self.sawobserverTag)
      self.actualTransformNode = None
      self.sawobserverTag = None
    self.angleDif.text = "0"

Any chance you can help me out?
Thanks

The problem is that you did not add any check that would prevent adding multiple observers. Before you add a new observation, usually you remove previous observation (because it might have been added for a different node). You also need to remove the observation on Cleanup. See these examples (the syntax is slightly different syntax, as VTKObservationMixin is used, so you don’t need to store observation tags):

Thanks for the quick reply. I am still struggling to get this to work. I have updated the code to this:

  def cleanup(self):
    self.removeObservers()
 
 def onApplyButton(self):
    logic = CalculateActualFibulaCutsLogic()
    logic.Results(self.plannedTransformSelector.currentNode(), self.actualTransformSelector.currentNode())
    self.angleDif.text = str(logic.angle)
    self.disDif.text = str(logic.dis)
    self.actualTransformNode = self.actualTransformSelector.currentNode()
    if self.actualTransformNode is not None:
      self.removeObserver(self.actualTransformNode,vtk.vtkCommand.ModifiedEvent, self.onTransformUpdated)
    if self.actualTransformNode is not None:
      self.addObserver(self.actualTransformNode,vtk.vtkCommand.ModifiedEvent, self.onTransformUpdated)
 
 def onClearButton(self):
    if self.actualTransformNode is not None:
      print("removing...")
      self.removeObserver(self.actualTransformNode,vtk.vtkCommand.ModifiedEvent, self.onTransformUpdated)
      self.actualTransformNode = None
    self.angleDif.text = "0"
    self.disDif.text = "0"

but when I try to run it, I get this error:
AttributeError: CalculateActualFibulaCutsWidget instance has no attribute ‘removeObservers’

I have tried importing VTKObservationMixin but it doesn’t seem to solve the problem.

You can create a new skeleton for your module using the Extension Wizard in latest Slicer Stable Release. It has the observation mixin preconfigured.

If you send a link to your repository then we can have a look at your source code and give advice. These incomplete code snippets give a very vague idea of what might happen in your code.

Thanks, I really appreciate the help. That worked perfectly.

1 Like