# Creating a custom Annotation node in a Python scripted module

**URL:** <https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331>\
**Category:** Development\
**Tags:** annotations\
**Created:** [March 15, 2018, 8:34pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331 "2018-03-15T20:34:42Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [March 15, 2018, 8:34pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/1 "2018-03-15T20:34:42Z")

</div>

I’m trying to create a “slider ring” in the MRML scene via a Python scripted module. The idea is to be able to grab the ring (modelled as a vtkPolyData torus) and move it along a path defined by another vtkPolyData.  
The vtkMRMLAnnotationControlPointsNode in the Annotation module looks like a place to start. It has derived classes that appear to do some of what I am trying.  
I have two questions:  
The first is whether I’m on the right track, or if there is a better way to accomplish what I’m trying to do.  
The second is, can I make a derived class of vtkMRMLAnnotationControlPointsNode in Python, or otherwise customize this class in my module? I see that Annotations is a loadable module, and my attempts so far have not worked.  
Thank you for any assistance.

---

<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:** [March 15, 2018, 8:46pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/2 "2018-03-15T20:46:35Z")

</div>

What we usually do is to define curve using markup fiducials, interpolate using Markups to models module. You can get model points as a numpy array and do least squares fit in a small neighborhood to get position and direction vector along the curve. To fully constrain the rotation, we use normal vector of the plane that is least-square-fit to the entire curve. All easily doable from Python.

Moving along the curve with a GUI slider is easy, but interacting in viewers is more tricky. Maybe you can snap the position to the closest position to the [cursor](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get_current_mouse_coordinates_in_a_slice_view) that you can move around by Shift+MouesMove.

What is the clinical application?

---

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [March 16, 2018, 3:31pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/3 "2018-03-16T15:31:44Z")

</div>

Thanks, Andras.  
The application is a viewer for MR image sets of peripheral arteries. The plan is to reformat the 2D slices so that their normals are always oriented along the centreline of the artery (hence my previous question about VMTK).  
Your description of getting the point positions and creating the path with a least-squares fit makes sense. Thank you. I’m confused by the part about constraining the rotation with a normal vector from a least-squares fit to the full curve. I understand the need to constrain the rotation, but what direction does it end up pointing in?

Regarding the object in the 3D view, I’ll experiment with ways to snap it to cursor positions as you suggest, but my first question is how to create a handle from a given polydata in Slicer. How do I create a handle that I can move with the mouse?

Thanks very much for your help.

---

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [March 16, 2018, 5:22pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/4 "2018-03-16T17:22:56Z")

</div>

This navigation style isn’t our idea. We’re trying to emulate some of the features in TeraRecon’s EVAR module:

> **[EVAR (Vessel Analysis) Planning | TeraRecon](https://www.terarecon.com/advanced-visualization/evar-planning-package)**
>
> TeraRecon's EVAR (vessel analysis) package includes an advanced measurement protocol option, user definable planning template with report output, & embedded instructions.

---

<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:** [March 16, 2018, 6:00pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/5 "2018-03-16T18:00:59Z")

</div>

Yes it is standard curved planar reformatting. The functionality is already available in Slicer, it just not easy to figure out how. It is described in detail here:

> [@Cross Sectional Area of a Ring](https://discourse.slicer.org/t/cross-sectional-area-of-a-ring/1015):
>
> I am looking to calculate the cross sectional area at multiple points around the ring (I tried to mark where I would like to slice the ring and measure the area using pairs of fiducials in the image below). I am not sure what the best method is as the orientation of the slice is constantly changing, so I’m just looking for an idea of what add-on or method would be best. Thank you!

So, you can find an example of positioning an object along a curve in Endoscopy module. I think this module uses the same method as I described above to constrain rotation around the curve direction vector. For vessels (and for any other significantly non-planar curve), I would use a Frenet-Serret frame ([SplineDrivenImageSlicer/Filters/vtkFrenetSerretFrame.h at master · djelouze/SplineDrivenImageSlicer · GitHub](https://github.com/jeromevelut/SplineDrivenImageSlicer/blob/master/Filters/vtkFrenetSerretFrame.h)) instead of a fixed constraining direction.

---

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [March 16, 2018, 6:54pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/6 "2018-03-16T18:54:18Z")

</div>

Thank you! The Frenet-Serret frame looks like a great approach. That gives me a solution to a couple of my next steps.

Back to the other question of how to customize an object that can move through the 3D view, how can I create something like the Control Points of the ROI box in the Annotations module, or the Fiducial points in the Markups module, but with my own polydata (torus) as the movable object?

 ![torus3D](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/9/2/92d1d1e9918e9784da4c674b70c24f63140c92c4.png)

---

<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:** [March 18, 2018, 12:19pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/7 "2018-03-18T12:19:41Z")

</div>

Creating custom widgets like the ROI widget is extremely difficult. You can emulate custom widgets buy using markup fiducial points as “handles” that you can move and observer the markup node changes to update model position based on that. See [this example](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Manipulating_objects_in_the_slice_viewer) in the script repository where you reposition and resize a sphere model by using markup fiducials.

---

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [March 19, 2018, 2:48pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/8 "2018-03-19T14:48:58Z")

</div>

Thank you, I’ll try that approach.

---

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [March 27, 2018, 7:51pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/9 "2018-03-27T19:51:29Z")

</div>

Regarding the Frenet-Serret frame code, is there a Python-wrapped version accessible? Alternatively, how would I do so? I believe I can create a Python class inherited from vtk.vtkPolyDataAlgorithm and translate the C++ version, though it would be great if there was a way to avoid doing so.  
Thanks again.

> <https://github.com/djelouze/SplineDrivenImageSlicer/blob/master/Filters/vtkFrenetSerretFrame.h>

---

<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:** [March 27, 2018, 8:38pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/10 "2018-03-27T20:38:37Z")

</div>

To add new C++ classes, you need to add a loadable module. It can be hidden, no widget is required. You can add this class to the logic folder. You may use [DataProbe](https://github.com/Slicer/Slicer/tree/master/Modules/Scripted/DataProbe) module as an example.

---

<div class="post-metadata">

**Author:** ![mschumaker](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/mschumaker/32/1395_2.png) [@mschumaker](https://discourse.slicer.org/u/mschumaker)\
**Post date:** [April 17, 2018, 8:42pm UTC](https://discourse.slicer.org/t/creating-a-custom-annotation-node-in-a-python-scripted-module/2331/11 "2018-04-17T20:42:45Z")

</div>

The Spline-Driven Image Slicer has been added to VTK as a Remote module. The CMake file in the VTKv9/Remote directory fetches from [https://github.com/lorensen/midas-journal-838.git](https://github.com/lorensen/midas-journal-838.git), which is more recently maintained than the djelouze repository.
