Hi,
I made a sequence where I tracked 1 transformed markup list at 22 different positions (as 22 sequences). However, when I try copy and pasting each of the unique marker positions into a new markup list, it just pastes the original position of the markups rather than each tracked and transformed position. For example, when I try copy and pasting “bigHole”:
At 0.10s, the position of the points “bigHole” and “smallHole” in “trackLine” are this:
Then when I try copy and pasting the position of “bigHole” into the new markup list “tracked_BigHole”, it just gives the original untransformed and untracked position of “bigHole”:
Also, the reason why I’m doing this manually is because when I took the tracked points, the sequence “wireToProbe” I created to record these markup positions didn’t take any of the positions for some reason. This may have been a mistake on my part, though:
I just tried that, and it does work the first time. But then when I try applying “trackLine” back to its original transform “PlatformToMarker2” so I can get the position of the next sequence, I think it applies “PlatformToMarker2” to the hardened transformed points rather than the original points. This causes my points to move into this strange position:
One other solution I’ve been working on is writing a small Slicer Module instead. So far, I can loop through each sequence and acquire the values of the transform “PlatformToMarker2”, and have the original untransformed points of “trackLine”. Right now, I’m trying to use a Slicer transform function which I thought would just do the same thing as dragging my Markup list onto a Slicer transform, but the new positions end up looking like this instead:
The code I’ve tried using looks like this:
wireSequenceNode = slicer.util.getNode('boxToProbe-boxToProbe-Seq')
browserNode = slicer.modules.sequences.logic().GetFirstBrowserNodeForSequenceNode(wireSequenceNode)
browserNode.SetSelectedItemNumber(0)
originalPoints = slicer.util.getNode('trackLine')
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
originalID = shNode.GetItemByDataNode(originalPoints)
print('START\n')
for count in range(wireSequenceNode.GetNumberOfDataNodes()): # Loops 22 times
browserNode.SetSelectedItemNumber(count) # Moves to next sequence
# Creates a copy of the original untransformed line points
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, originalID)
clonedNode = shNode.GetItemDataNode(clonedItemID)
# 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()
trackerVTK = currentTrackNode.GetMatrixTransformFromParent()
print("ITERATION:", count+1, "\n")
print("TRANSFORM PTM:", platformVTK, "\n")
print("TRANSFORM TRACK:", trackerVTK, "\n")
print("POINTS:", slicer.util.arrayFromMarkupsControlPoints(clonedNode), "\n")
clonedNode.ApplyTransformMatrix(platformVTK)
clonedNode.ApplyTransformMatrix(trackerVTK)
print("PTS TRANSFORMED:", slicer.util.arrayFromMarkupsControlPoints(clonedNode), "\n")
#copyPoints.SetAndObserveTransformNodeID(currentTransformNode.GetID())
#print(slicer.util.arrayFromMarkupsControlPoints(copyPoints))
#print(slicer.util.arrayFromTransformMatrix(currentTransformNode))
print('FINISH\n')
I might also try finding some code to harden/unharden the markup list and then just reuse a copy of the original points at each new sequence.
Yes, you need a script for this, as there is no module offered for this yet.
Your script looks quite good and it could be actually quite easily generalized so that it works for any node and transform (for each time point in the sequence, clone the transformed node and apply and harden the transform). The script could then be added to a Python scripted module so that it can be used with a convenient GUI. Let us know if you would be interested to contribute this (maybe in the Sandbox extension).
So when I tried to clone and harden the “trackLine” markup list, it just gave me the original untransformed positions. Is it possible to copy the markup list with the points already transformed? I know I can manually harden the original point at the start (as I spoke about earlier), which I’ll use as a starting point. The code looks like this:
originListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode", "originList")
directionListNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode", "directionList")
print('START\n')
#wireSequenceNode.GetNumberOfDataNodes()
for count in range(1): # Loops 22 times
# Moves to current sequence
browserNode.SetSelectedItemNumber(count)
# Get the sequence's current transformed node
currentNode = slicer.util.getNode('trackLine')
# Clone the sequence's current transformed node
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
itemIDToClone = shNode.GetItemByDataNode(currentNode)
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)
clonedNode = shNode.GetItemDataNode(clonedItemID)
# Harden the clone and copy its points onto each markup list
clonedNode.HardenTransform()
print(slicer.util.arrayFromMarkupsControlPoints(clonedNode))
UPDATE:
Yes, when I just harden the currentNode, it does print the correct positions the first time. But after that, it just gives incorrect values again like I explained earlier. Perhaps I can undo a Harden but maintain the original position using some commands?
Excellent, I got it working. I’m sure this could be generalized and put into one of your Extensions, as you mentioned. And yes, I would be interested in doing this. The code is here:
transformSequenceNode = slicer.util.getNode("PlatformToMarker2")
originalListNode = slicer.util.getNode('trackLine')
wireSequenceNode = slicer.util.getNode('boxToProbe-boxToProbe-Seq')
browserNode = slicer.modules.sequences.logic().GetFirstBrowserNodeForSequenceNode(wireSequenceNode)
browserNode.SetSelectedItemNumber(0)
print('START\n')
print("Unhardened Original Points:", slicer.util.arrayFromMarkupsControlPoints(originalListNode))
#wireSequenceNode.GetNumberOfDataNodes()
for index in range(3):
# Moves sequence browser to the current sequence
browserNode.SetSelectedItemNumber(index)
# Obtain the current sequence's unique "PlatformToMarker2" transform values
currentTransform = wireSequenceNode.GetNthDataNode(index).GetTransformToParent()
# Clone the original markup list node
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
itemIDToClone = shNode.GetItemByDataNode(originalListNode)
clonedItemID = slicer.modules.subjecthierarchy.logic().CloneSubjectHierarchyItem(shNode, itemIDToClone)
clonedNode = shNode.GetItemDataNode(clonedItemID)
clonedNode.ApplyTransform(currentTransform)
clonedNode.HardenTransform()
print("Hardened Clone Point ", index, ":\n", slicer.util.arrayFromMarkupsControlPoints(clonedNode), "\n")
# Removing the cloned node since it is no longer needed.
slicer.mrmlScene.RemoveNode(clonedNode)