Can't access MarkupFiducialList control points

Slicer Version: 5.1.0-2022-07-17
OS: Windows 10

Hi,
I’m not sure why, but when I try accessing control points from my MarkupFiducialList, it says it doesn’t have the attribute “GetNthControlPoint”.
What I’m trying to do is loop through several sequences and add a new control point onto the list “originListNode” for each iteration. The initial values of these “origin” points are the same every time, but are transformed within the loop. So basically, I want to have one list of markups with unique positions using each sequence’s unique “platformVTK” and “trackerVTk” transform values:

originalPoints = slicer.util.getNode('trackLine')
        originalArray = slicer.util.arrayFromMarkupsControlPoints(originalPoints)
        originListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode", "originList")
        directionListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode", "directionList")

        print('START\n')
        #wireSequenceNode.GetNumberOfDataNodes()
        for count in range(3):  # Loops 22 times
            browserNode.SetSelectedItemNumber(count)  # Moves to next sequence


            # Gets the current sequence's unique 'PlatformToMarker2' transform values
            currentPTMNode = slicer.util.getNode('PlatformToMarker2')
            currentTrackNode = slicer.util.getNode('Marker2ToTracker')

            # copyArray = slicer.util.arrayFromMarkupsControlPoints(originalPoints)
            platformVTK = currentPTMNode.GetMatrixTransformFromParent().Invert()
            trackerVTK = currentTrackNode.GetMatrixTransformFromParent()

            # The current origin point added to the list is originally just "bigHole" from the originalPoints list
            newOriginIndex = originListNode.AddControlPoint([originalArray[0][0], originalArray[0][1], originalArray[0][2]])
            newOrigin = originListNode.GetNthControlPoint(newOriginIndex)
            originListNode.SetNthControlPointLabel(newOriginIndex, "origin" + str(count))

            # Applying the current transforms onto the origin
            transformedOrigin = newOrigin.ApplyTransformMatrix(platformVTK)
            transformedOrigin = transformedOrigin.ApplyTransformMatrix(trackerVTK)

            print(transformedOrigin)

I am able to create the list node “originListNode” (named “originList” on Slicer) and add points using “AddControlPoint”. This is outputted successfully on Slicer. I can also access each control point’s position using originListNode.GetNthControlPointPosition(newOriginIndex). But when I try accessing these control point objects in “originList” using “GetNthControlPoint(newOriginIndex)”, it says it is not an attribute of the MarkupsFiducial node:

File "C:/d/ClariusTracker/calibrationClarius/Procrustean_PTLR/PTL_Registration/PTL_Registration.py", line 259, in setup
    newOrigin = originListNode.GetNthControlPoint(newOriginIndex)
AttributeError: 'vtkSlicerMarkupsModuleMRML.vtkMRMLMarkupsFiducialN' object has no attribute 'GetNthControlPoint'

On the Slicer documentation it says this is a command that exists, but it doesn’t seem to work:
https://apidocs.slicer.org/master/classvtkMRMLMarkupsNode.html

I was going to use Fiducial functions originally, but it seems they’ve been deprecated. I might also try this on a more stable version of Slicer. Also, this might just be an issue with inheritance because I’m not too familiar with Slicer classes.

The “ControlPoint” class is not wrapped in Python, so the method is not wrapped either.
There should be functions in vtkMRMLMarkupsNode to access information on each control point from Python.

Hmm, ok. How would you recommend I Get each of these control points so I can transform them? Is there a way to convert each control point objects inside my originListNode to a transformable node? I know I could perform the transform on the entire originListNode, but that is not suited for my needs.

I’m not entirely sure what the ApplyTransformMatrix function does mathematically, but perhaps I might need to do this operation on each individual point with each individual transform (platformVTK, trackerVTk)?

You can use GetNthControlPointPosition (or GetNthControlPointPositionWorld), and transform them using the vtkMatrix4x4.

Something like:

position = list(fiducialNode.GetNthControlPointPosition(0))
position.append(1.0) # Convert to a len 4 vector
matrix.MultiplyPoint(position)

Ok, that works. I wrote this little function if you think this is a feature that might be useful on slicer, but it’s up to you.

def ApplyTransformMatrixToControlPoint(vtkMRMLMarkupsFiducialNode pointListNode, int index, vtkMatrix4x4 transformMatrix):
        position = pointListNode.GetNthControlPointPosition(index)
        position.append(1.0)
        transformMatrix.MultiplyPoint(position)

        return position

The function didn’t work on my module, but I think I might’ve just written something wrong on the parameters. The code itself works on my module, though.

Hi Kyle, so I am able to get these transforms and apply them to each point. However, I’m having the same issue as this topic I posted yesterday, where it doesn’t actually calculate the correct transformed values that normally show up on each sequence. Any idea why this might be the case? The only transform that actually is applied to trackLine is PlatformToMarker2. And PlatformToMarker2 is linked with several other transforms. But I get positions that are way off for some reason.
I might just write code to harden the transforms each time like I was planning on doing yesterday. It seems like the only solution. The reason I tried this was because I thought copying the original points every time was affecting the transforms in some way, but this code has proven that’s not really true.