# vtkMRMLAnnotationROINode instantiation before changing Interaction Mode

**URL:** <https://discourse.slicer.org/t/vtkmrmlannotationroinode-instantiation-before-changing-interaction-mode/13158>\
**Category:** Development\
**Created:** [August 25, 2020, 4:12pm UTC](https://discourse.slicer.org/t/vtkmrmlannotationroinode-instantiation-before-changing-interaction-mode/13158 "2020-08-25T16:12:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![EricM](https://avatars.discourse-cdn.com/v4/letter/e/48db29/32.png) [@EricM](https://discourse.slicer.org/u/EricM)\
**Post date:** [August 25, 2020, 4:12pm UTC](https://discourse.slicer.org/t/vtkmrmlannotationroinode-instantiation-before-changing-interaction-mode/13158/1 "2020-08-25T16:12:23Z")

</div>

Hi Slicer Community,

I apologize in advance if the answer to my question is out there. I’ve seen related threads, but I haven’t been able to piece it together to get my solution working.

Basically, I would like to instantiate a `vtkMRMLAnnotationROINode` _before_ having the user switch Interaction Modes (to Place mode) in order to change certain properties of the AnnotationROINode, such as the Name etc. so that the user doesn’t see the default names (like R, R\_1, R\_2), etc.

Basically, I have created a button `addBoundingBoxButton` which is connected to a function `onAddBoundingBox`, which I would like to do the following:

```auto
def onAddBoundingBox(self):

  boundingBoxName = 'Finding {}'.format(self.findingCounter) #internal counter for number of findings identified

  #add vtkMRMLAnnotationROINode and change name
  annotationROINode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLAnnotationROINode',boundingBoxName)

  slicer.mrmlScene.GetNodeByID("vtkMRMLSelectionNodeSingleton").SetReferenceActivePlaceNodeClassName("vtkMRMLAnnotationROINode")
  slicer.mrmlScene.GetNodeByID("vtkMRMLInteractionNodeSingleton").SetCurrentInteractionMode(1)
  

```

The problem is that the `annotationROINode` object is not the one modified when the InteractionNode is changed to Place mode, and when the `vtkMRMLAnnotationROINode` is placed, a new object is created with a default name. Weirdly, when I do this same approach with `vtkMRMLMarkupsLineNode`, I get the desired behavior (i.e., I can create the `vtkMRMLMarkupsLineNode` beforehand and the InteractionNode lets me place the line that I have already created in my script). Perhaps this behavior is because of some inherent differences in the Annotations vs the Markups modules? Is there a way to link the `annotationROINode` object I’ve created to the one that will be created in Place mode?

Another method I was thinking of was creating the `vtkMRMLAnnotationROINode` and then using two fiducial points to let the user choose the center and radius of the bounding box (I suspect this is how it is done in practice, but I couldn’t find a clear procedure for this in the source code, and I would like to take advantage of this being implemented in Place mode through the Interaction Node). I have looked at other threads like [this one](https://discourse.slicer.org/t/how-to-get-input-value-from-mouse-click/5903/10) and [this one](https://discourse.slicer.org/t/capturing-mouse-input/789), but it’s not clear to me how to create a button with a connecting function that (1) lets me place two fiducial points, (2) waits for the user to place them, (3) then extracts the Control Points, and (4) creates/modifies the `vtkMRMLAnnotationROINode` with the desired properties. It seems that when I put all of these functions in a connector function, it runs to the very end of the function without waiting for the fiducial points to be placed, so obviously this produces errors downstream.

One last thing I will say is that I am aware that the AnotationROI nodes will be moved to the Markups module sometime in the near future, but I unfortunately can’t wait that long (although, I’m excited for it!).

Thanks for any guidance or help,  
Eric

---

<div class="post-metadata">

**Author:** ![EricM](https://avatars.discourse-cdn.com/v4/letter/e/48db29/32.png) [@EricM](https://discourse.slicer.org/u/EricM)\
**Post date:** [August 26, 2020, 12:17pm UTC](https://discourse.slicer.org/t/vtkmrmlannotationroinode-instantiation-before-changing-interaction-mode/13158/2 "2020-08-26T12:17:18Z")

</div>

Hello Community,

Thanks to a great tip by @Fernando, who suggested to connect the event with a function that listens and does something if there are two fiducials in the markups node, I was able to figure out how to place a `vtkMRMLAnnotationROINode` with two Fiducial Points.

I still have some follow-up questions (see below), so I would appreciate any help on those, but otherwise, here is some working code:

```auto
import numpy as np

def onFiducialPlaced(caller, event):
    numberOfFiducials = caller.GetNumberOfFiducials()
    if numberOfFiducials != 2:
        print("Not yet 2")
        return
    #turn off fiducial placement
    slicer.mrmlScene.GetNodeByID("vtkMRMLInteractionNodeSingleton").SetCurrentInteractionMode(2)
    fiducialWorldCoordinatesDict = {}
    for n in range(numberOfFiducials):
      p = [0,0,0,1]
      caller.GetNthFiducialWorldCoordinates(n,p)
      fiducialWorldCoordinatesDict[n] = p
      print("Fiducial Point {}: {}".format(n+1,p))
    #Get XYZ and RadiusXYZ
    XYZ = np.array(fiducialWorldCoordinatesDict[0])[:3] #only take x,y,z
    R = np.array(fiducialWorldCoordinatesDict[1])[:3] #only take x,y,z
    dx,dy,_ = np.abs(XYZ-R)
    #Create annotationROINode and set location
    annotationROINode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLAnnotationROINode',caller.GetName())
    annotationROINode.SetXYZ(XYZ)
    annotationROINode.SetRadiusXYZ(dx,dy,10) #fix radius in z direction to 10
    #delete markups
    caller.RemoveAllMarkups()

def onAddBoundingBox():
    fiducialList = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode",'MyNode')
    tag = fiducialList.AddObserver(slicer.vtkMRMLMarkupsNode.PointPositionDefinedEvent, lambda caller, event: onFiducialPlaced(caller,event))
    placeWidget = slicer.qSlicerMarkupsPlaceWidget()
    placeWidget.setMRMLScene(slicer.mrmlScene)
    placeWidget.setCurrentNode(fiducialList)
    placeWidget.setPlaceMultipleMarkups(placeWidget.ForcePlaceMultipleMarkups)
    placeWidget.placeButton().click()

addBoundingBoxButton = qt.QPushButton('Add')
addBoundingBoxButton.clicked.connect(onAddBoundingBox)
addBoundingBoxButton.show()

```

Question 1: I would have expected that `slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent` would have been the event for dropping the Fiducial point the first time (with the way my code is written), yet this signal is only emitted after picking it back up and dropping it (i.e., it is only emitted if you pick up the fiducial point, drag it, and drop it a second, third, etc. time). The code seems to do exactly what I want with `slicer.vtkMRMLMarkupsNode.PointPositionDefinedEvent`, so I’m not complaining, but any insights would make me feel a bit more comfortable.

Question 2: Is there a way to specify _a priori_ how many Markups can be added to a MarkupsFiducialNode whn using `placeWidget.setPlaceMultipleMarkups(placeWidget.ForcePlaceMultipleMarkups)`? For a bounding box, I just need two, so I have an if loop in `onFiducialPlaced` to check how many Fiducials are part of the node, and once I’m satisfied, I change the InteractionMode to 2 to get out of Place mode. However, this seems quite “hacky”. Is there a better way to do this?

Hope this can help the general Slicer community,  
Eric M

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [August 26, 2020, 2:57pm UTC](https://discourse.slicer.org/t/vtkmrmlannotationroinode-instantiation-before-changing-interaction-mode/13158/3 "2020-08-26T14:57:28Z")

</div>

> [@EricM](#):
>
> Question 1: I would have expected that `slicer.vtkMRMLMarkupsNode.PointEndInteractionEvent` would have been the event for dropping the Fiducial point the first time (with the way my code is written), yet this signal is only emitted after picking it back up and dropping

The event is exactly for this purpose. For example, can be used for performing operations that you don’t want to do continuously, but when the user finished interaction with the control point.

> [@EricM](#):
>
> Is there a way to specify _a priori_ how many Markups can be added to a MarkupsFiducialNode whn using `placeWidget.setPlaceMultipleMarkups(placeWidget.ForcePlaceMultipleMarkups)` ?

Yes, you can use `SetMaximumNumberOfControlPoints` to set the expected number of points. If that number is reached then placement is finished. We will tune/optimize the behavior, including predefine name of markups (@muratmaga’s team is working on this).

Also note that [@Sunderlandkyl is working on adding a markups ROI](https://github.com/Slicer/Slicer/issues/5061), which would be a much improved version of Annotation ROI (and annotation module will be deprecated).

---

<div class="post-metadata">

**Author:** ![EricM](https://avatars.discourse-cdn.com/v4/letter/e/48db29/32.png) [@EricM](https://discourse.slicer.org/u/EricM)\
**Post date:** [August 27, 2020, 7:39am UTC](https://discourse.slicer.org/t/vtkmrmlannotationroinode-instantiation-before-changing-interaction-mode/13158/4 "2020-08-27T07:39:02Z")

</div>

Hi Iassoan,

Thanks for the answer.

Regarding, my second question, I modified `onAddBoundingBox` as below and commented out the line where I add an observer just to see if Slicer goes out of Place mode after the second control point.

```auto
def onAddBoundingBox():
    fiducialList = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode",'MyNode')
    fiducialList.SetMaximumNumberOfControlPoints(2)
    #tag = fiducialList.AddObserver(slicer.vtkMRMLMarkupsNode.PointPositionDefinedEvent, lambda caller, event: onFiducialPlaced(caller,event))
    placeWidget = slicer.qSlicerMarkupsPlaceWidget()
    placeWidget.setMRMLScene(slicer.mrmlScene)
    placeWidget.setCurrentNode(fiducialList)
    placeWidget.setPlaceMultipleMarkups(placeWidget.ForcePlaceMultipleMarkups)
    placeWidget.placeButton().click()

```

But after clicking the `placeButton`, it just keeps letting me add more fiducial points (‘MyNode’, ‘F’,‘F\_1’,‘F\_2’, etc.). I tried this with `placeWidget.ForcePlaceSingleMarkup`, but it stops after the first Control Point. I imagine that I coded this incorrectly. In any case, my “hack” is working for now.

> [@lassoan](#):
>
> Also note that [@Sunderlandkyl is working on adding a markups ROI](https://github.com/Slicer/Slicer/issues/5061), which would be a much improved version of Annotation ROI (and annotation module will be deprecated).

I’m really looking forward to the new and improved markups ROI!

Thanks again,  
Eric
