For the TransformMatrix / Orientation / Rotation tags - which are storing the image rotation in the MetaIO (MHD/MHA) format - the actual serialization convention (row-major vs. column major) does not seem to be documented anywhere (at least I could not really find anything beyond https://itk.org/Wiki/ITK/MetaIO/Documentation#Associated_transformations).
On the other hand, experiments with a mesh and an associated image (TransformMatrix = 0 0 1 1 0 0 0 1 0 - i.e. not invariant to transposition) in 3D Slicer suggest that the orientation is actually stored / interpreted as a column-major.
Finally, I actually wanted to do the same experiment with ParaView, which unfortunately seems to completely ignore the image orientation.
Would anyone be able to confirm what is the standard convention and where this is documented? I did find 22_Transforms saying that “Matrices are represented by vector-like data types in row major order” but I am unsure whether this applies for the MetaIO/MHD/MHA file format or is only internal to SimpleITK? I guess this should be highly relevant for registration topics, no?
The storage in the meta-io image is in column major order.
SimpleITK’s convention of representing a matrix is in row major order, so [0,0,-1,0,1,0,1,0,0] represents the matrix \left[\begin{array}{ccc} 0 & 0 & -1\\ 0 & 1 & 0 \\ 1 & 0 & 0 \end{array}\right].
Trust but verify:
import SimpleITK as sitk
image = sitk.Image([2]*3, sitk.sitkUInt8)
image.SetDirection([0,0,-1,0,1,0,1,0,0])
print(image) # look at the Direction matrix
sitk.WriteImage(image, 'image.mhd')
Perhaps I am misreading it, but I believe that the code you cited is also column major ordering, i.e., the column variable (j) is in the inner loop. So, I think it is consistent, but you’re right that it isn’t documented. I’m adding it to the wiki page you cited.
@Stephen_Aylward just wondering: doesn’t column variable j in inner loop mean that it’s in row major order? Or is m_TransformMatrix already column major too (i.e. following he OpenGL convention I believe)?
From the signature TransformMatrix(int _i, int _j ..) I assumed _i would be rows and _j would be columns