Is there a Setter similar for the Getter GetInteractionHandleToWorldMatrix?

Hello,
I am using SlicerJupyter and I’m trying to use the interaction handle for the MarkupsLineNode to control the position and orientation of other objects. That part works fine with this kind of code:

implantlinenode = slicer.vtkMRMLMarkupsLineNode()

implantlinenode.SetName(‘Implant line’)

slicer.mrmlScene.AddNode(implantlinenode)

implantlinenode.AddControlPoint(0, 0, 0, ‘P0’)
implantlinenode.AddControlPoint(0, 10, 0, ‘P1’)

Ldn = implantlinenode.GetDisplayNode()

Ldn.SetVisibility2D(True)
Ldn.SetVisibility3D(True)

Ldn.SetHandlesInteractive(True)

handlematrix = implantlinenode.GetInteractionHandleToWorldMatrix()

However, I also need to update the InteractionHandle orientations programmatically based on the orientation of other objects.

How would I do this? I tried a transformation of the MarkupsLineNode but that does not change the orientation of the InteractionHandle.

Thanks for any ideas

I have very good news for you! Thanks to @Sunderlandkyl, it is no longer necessary to create markups to position and orientation nodes. In recent Slicer Preview Releases (since last week), transformation handles can be enabled for any nodes.

This looks great. Thanks @Sunderlandkyl (and andras). Quick question:

I set the MRHead under a transform, and I hit the visibility (eye icon) of the transform node, with the expectation that the widget will become visible. But it didn’t. The only way I managed to turn it on is from the Transforms module’s Interaction tab.

Is there any reason why visibility shouldn’t be considered as the interaction in this context? Or is it specifically referring to the visibility of the Glyphs or Grids?

Thanks @Sunderlandkyl and Andras. That sounds amazing.
Do you have some documentation on it how to use it in Python or can you roughly tell me how to set it up in Python?
Thanks, such great timing!

Exactly. This is consistent with how visibility refers to visibility of every other nodes.

To move around a node, the easiest is to go to “Data” module, right-click on the eye icon of the node, and enable “Interaction in 3D view”. This adds a positioning transforms and enables interaction handles. We’ll change the behavior of this menu action so that it will show the transformation in 2D as well and we might need to find a better name (maybe “Transform interaction”).

I appreciate your work on the continuous Slicer improvements.

However, I find it very hard to switch to a new version because I have to re-install all the Extensions I’ve been using, set up another Slicer Kernel for Jupyter, and possibly also re-check my slicerrc file to be in the right location even if it was in a default location. The same applies to the DICOM database location and sometimes version.

Is there a less painful way to do all this? Do you have a post-installation script that does all this repetitive work automatically but fails gracefully when it can’t do some parts?

Any suggestions would be greatly appreciated. Thanks.

It should be painless to upgrade. You can bookmark all your installed extensions and reinstall them in the new Slicer version by a single click. All other settings are preserved. There is a whole new DICOM browser (another reason to upgrade), with a slightly different DICOM database schema, so you may need to upgrade the DICOM database (it should be a single click when you are asked). If you find any unnecessary inconvenience then let us know.

Thanks, Andras.

Until now I had not noticed the Bookmark feature. That’s really great to know. If it was described in a Manual somewhere I certainly failed to catch it. My apologies.

It is described here: How to install extensions. Feel free to make any suggestions on how to improve the documentation.

This is how far I’ve gotten:

arcmodel = modelsLogic.AddModel(extrude_arc.GetOutputPort())

arcmodel.SetName(‘arc’)

dn = arcmodel.GetDisplayNode()
dn.SetSliceIntersectionVisibility(True)
dn.SetSliceDisplayModeToIntersection()
dn.SetSliceIntersectionThickness(3)
dn.SetColor(0.902, 0.020, 0.902)

dn.SetVisibility2D(True)
dn.SetVisibility3D(True)

Now I have to manually right click on arcmodel node and set “Interaction in 3D view” to create an Interaction_arc transformation node. How can I do this programmatically?

arctransform = arcmodel.GetParentTransformNode()
print(arctransform)

tdn = arctransform.GetDisplayNode()

tdn.SetVisibility(True)

tdn.SetVisibility2D(False)
tdn.SetVisibility3D(False)

tdn.SetEditorVisibility(True)
tdn.SetEditorSliceIntersectionVisibility(True)

tdn.SetEditorTranslationEnabled(True)
tdn.SetTranslationHandleComponentVisibility(True, True, True, True)
tdn.SetEditorRotationEnabled(True)
tdn.SetRotationHandleComponentVisibility(True, True, True, True)
tdn.SetEditorScalingEnabled(True)
tdn.SetScaleHandleComponentVisibility(True, True, True, True)

Now I can do several things:

arctransform.SetCenterOfTransformation(0, 0, 0)
arctransform.SetMatrixTransformToParent(slicer.util.vtkMatrixFromArray(newtransform))

But how can I set the scaling in my program? Where can I read the scaling that I manipulate in the GUI?

Thanks

You can find examples for every commonly needed operations in the script repository. For example, apply a transform.

You can either get familiar with homogeneous transformation matrices and set the matrix values directly (e.g., scaling is the column norm) or you can use vtkTransform to compute the matrix from a sequence of operations (scale, rotate, translate, etc.).

What is your end goal? Planning needle insertion with a stereotactic frame (guessing from the “arc” word)? If yes then check out the Stereotactic extension. There are many other extensions that can be relevant, depending on what you plan to do.

Ok, thanks. I did not understand that now any transform node has the interaction display attach to it? I’ve done the transform before, so thanks for the clarification.

With respect to the scaling, I had not noticed that the transformation matrix changed in a way that the column vectors weren’t just normalized direction vectors any more, but had scaling information. Thanks for pointing that out.

Eventually I want to parameterize the location and shape of an implant that will get 3D printed. I will print different versions according to some parameters and then test them on the benchtop. The implant shape is derived from a couple of prototypical shapes, that’s why one of them is called ‘arc’ because it’s been made from the vtkEllipseArcSource to make an elliptical cylinder.

1 Like

Sounds interesting. Keep us updated on your progress, maybe post some pictures when you have some success (and feel free to ask any questions if you get stuck with something).

Sure, I will post some pictures when I get it all working.

I’m trying to set up everything programmatically, so right now I’m still stuck at the point where I want to enable the new visualization for the transformation node:

arctransform = slicer.vtkMRMLTransformNode()
arctransform.SetName(‘Transform arc’)

slicer.mrmlScene.AddNode(arctransform)

arcmodel.SetAndObserveTransformNodeID(arctransform.GetID())

But, if I want to modify the DisplayNode of the transform node, I get None:
arctransform.GetDisplayNode() → None

Only when I manually right-click on the transform node in Data (Edit propertires) and then manually expand/open the Display submenu, then I can programmatically modify the DisplayNode:
<MRMLCorePython.vtkMRMLTransformDisplayNode(0x000001E85A8304C0) at 0x000001E861DF3640>

I tried to manually add some display node but that did not work, it did not create the new manipulation handle display:
tdn = slicer.vtkMRMLTransformDisplayNode()
arctransform.AddAndObserveDisplayNodeID(tdn.GetID())

Has this not been implemented yet?
Thanks, Juergen

You can call displayableNode.CreateDefaultDisplayNodes() to create default display node.

For future postings on the forum: if you include code snippets in your post, you can put it between triple-backticks for better formatting.