Transformix is always necessary now because we need to generate a resampled moving volume and/or a displacement field. Both are provided by Transformix.
We could avoid the need to run Transformix if we could read the proprietary Elastix transformation file format. I’ve started implementing a reader for linear transforms, but did not finish it. I include it below - it would be great if you could finish it and integrate it into SlicerElastix module. We should probably implement bspline reader, too.
# Example input:
transformStr="(TransformParameters 0.022507 0.013835 0.013726 7.760838 4.879223 -0.014589)"
transformParams = transformStr.strip("()").split(" ")
transformParams.pop(0)
transformParams = [ float(x) for x in transformParams ]
(roll, pitch, yaw) = np.array(transformParams)[0:3]
computeZYX=False
[rx,ry,rz]=transformParams[0:3]
[tx,ty,tz]=transformParams[3:6]
from math import sin, cos
rotX = np.array([[1.0, 0.0, 0.0], [0.0, cos(rx), -sin(rx)], [0.0, sin(rx), cos(rx)]])
rotY = np.array([[cos(ry), 0.0, sin(ry)], [0.0, 1.0, 0.0], [-sin(ry), 0.0, cos(ry)]])
rotZ = np.array([[cos(rz), -sin(rz), 0.0], [sin(rz), cos(rz), 0.0], [0.0, 0.0, 1.0]])
if computeZYX:
# Aply the rotation first around Y then X then Z
fixedToMovingDirection = np.dot(np.dot(rotZ, rotY), rotX)
else:
# Like VTK transformation order
fixedToMovingDirection = np.dot(np.dot(rotZ, rotX), rotY)
fixedToMoving = np.eye(4)
fixedToMoving[0:3,0:3] = fixedToMovingDirection
fixedToMoving[0:3,3] = transformParams[3:6]
# Create Slicer linear transform ("to parent" direction, in RAS)
ras2lps = np.array([[-1,0,0,0],[0,-1,0,0],[0,0,1,0],[0,0,0,1]])
movingToFixed = np.dot(np.dot(ras2lps, np.linalg.inv(fixedToMoving)), ras2lps)
slicer.util.updateTransformMatrixFromArray(getNode('Transform_1'),movingToFixed)