I am looking for a quick way to compute an in-between transformation between two volume nodes that are not directly connected in a transformation graph. Here is a figure of what I mean:

Assume I have several MRI contrasts (T1/T2/T2S and HR), and I want to resample T2S in the voxel grid of a high-resolution volume “HR”. Often, I need a direct transform between the two, i.e. “T2SToHR”, e.g. for a module like “Resample Scalar/Vector/DWI Volume” to function.

In PLUS, this is neatly solved with a transformation graph, and I can simply give a string “T2SToHR” which is parsed to calculate the in-between transform via graph traversal.
Is there a similar mechanism in Slicer?
I want to use the “Resample Scalar/Vector/DWI Volume” module, and I want to avoid coding the transformation chain out explicitly every time I want to do such an operation.

Thanks a lot! This looks exactly like what I need. However, I have problems with executing the command. Given the example above, I tried the following:
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(nT2SToT2.SafeDownCast(vtk.vtkGeneralTransform()), nHRToT1.SafeDownCast(vtk.vtkGeneralTransform()), T.SafeDownCast(vtk.vtkGeneralTransform()))

(note: I had to SafeDownCast() - all transforms are linear - to a vtkGeneralTransform. I could have tried the matrix4x4 version you mentioned, but I wanted to try the general approach for more complex scenarios later).
The command runs, but the result is wrong as I receive the identity matrix.
I also received the following warning in the log:
Generic Warning: In /Users/kitware/Dashboards/Package/Slicer-462/Libs/MRML/Core/vtkMRMLTransformNode.cxx, line 472 vtkMRMLTransformNode::GetTransformToNode failed: transformSourceToTarget is invalid

Could you give a hint regarding the syntax?
Thanks!

transformAToB = vtk.vtkGeneralTransform()
a = getNode('MRHead').GetParentTransformNode()
b = getNode('CTChest').GetParentTransformNode()
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(a, b, transformAToB)

If you want to use transformAToB in a transform node using SetTransformToParent then you have to deep-copy it using slicer.vtkMRMLTransformNode.DeepCopyTransform. If you only have linear transforms it is much simpler and faster to use GetMatrixTransformBetweenNodes and SetMatrixTransformToParent.

OK, I wrote a little utility function. In case it helps anyone, I’ll post it here. Apologies for poor naming etc… Also, indentation is wrong - if someone knows how to properly post formatted pieces of code, please let me know.

def calculateInbetweenLinearTransform(self,nTrfSource,nTrfTarget,nTrfSourceToTarget):
# Get concatenated transforms from source to target nodes in the MRML scene. Source
# and target nodes are allowed to be NULL, which represents the world coordinate
# system. Result is written into nTrfSourceToTarget (has to be a
# vtkMRMLLinearTransformNode)
matrixAToB = vtk.vtkMatrix4x4()
if nTrfSource is not None:
a = nTrfSource.GetParentTransformNode()
else:
a = None
if nTrfTarget is not None:
b = nTrfTarget.GetParentTransformNode()
else:
b = None
# calculate the matrix transform
slicer.vtkMRMLTransformNode.GetMatrixTransformBetweenNodes(a,b,matrixAToB)
# set the matrix transform into target
nTrfSourceToTarget.SetMatrixTransformToParent(matrixAToB)

You just need to add 4 spaces to your code, there’s even a button for it on the Discourse GUI.

def calculateInbetweenLinearTransform(self, nTrfSource, nTrfTarget, nTrfSourceToTarget):
# Get concatenated transforms from source to target nodes in the MRML scene. Source
# and target nodes are allowed to be NULL, which represents the world coordinate
# system. Result is written into nTrfSourceToTarget (has to be a
# vtkMRMLLinearTransformNode)
matrixAToB = vtk.vtkMatrix4x4()
if nTrfSource is not None:
a = nTrfSource.GetParentTransformNode()
else:
a = None
if nTrfTarget is not None:
b = nTrfTarget.GetParentTransformNode()
else:
b = None
# calculate the matrix transform
slicer.vtkMRMLTransformNode.GetMatrixTransformBetweenNodes(a,b,matrixAToB)
# set the matrix transform into target
nTrfSourceToTarget.SetMatrixTransformToParent(matrixAToB)

Hi! I am new for 3D Slicer, and when I to used your method to calculate the transform matrix, I found that
a = getNode().GetParentTransformNode,
a is NONE, same as b. This resulted in transformAToB equaled to Identity Matrix.

But if I directly use
a,b = getNode(),
transformAToB = slicer.vtkMRMLTransformNode()
slicer.vtkMRMLTransformNode.GetTransformBetweenNodes(a, b, transformAToB)

I was told method requires a vtkMRMLTransformNode, a vtkMRMLScalarVolumeNode was provided.

I am wondering if anyone could help me find out why this problem comes out.

Please post your actual code that doesn’t work because the one above for example is not valid, and it’s impossible like this to figure out what is going wrong.

GetTransformBetweenNodes argument 1: method requires a vtkMRMLTransformNode, a vtkMRMLScalarVolumeNode was provided.

I think it is because source and target are both vtkMRMLScalarVolumeNode. I am wondering how to change the vtkMRMLScalarVolumeNode to vtkMRMLTransformNode, which is not NONE.

I am also wondering how to apply this transform matrix on the source image. I have tried the code above:

The problem in your code has been using the wrong types in each case. You need to make sure that you pass/create/get the object you need, and not some related object of a different type.