Small aside on this - the voxel-to-physical coordinate system that describes acquisition geometry can be left handed (e.g. axial foot-first vs head-first). ITK readers re-arrange the data to enforce right-handedness.
VTKjs supports direction vectors on image data and it was recently fixed to allow left handed matrices recently came up in vtkjs,
We may also end up with left-handed image coordinate system axes if a mirroring transform is applied.
Should we add a helper function in volumes logic that converts images to right-handed coordinate system (by reordering slices and flipping z axis) and call it after image import and after hardening a transform on a volume?
I think that would make sense, yes. Because we use ITK so much for processing we should try to ensure that our image data conforms to its expectations. Hardening seems like the right place to put it.
But probably easiest just to resample into an appropriate right-handed reference grid so not much special code is required.
Actually that reminds me of another issue a student had the other day. She was setting transforms manually that included shears and then hardening them, which works because the volume node can have non-orthonormal directions. But when she saved to nifti and reloaded the images were different (unfortunately in a subtle way) because nifti changes the directions to a quaternion. The workaround was to resample rather than harden.
So I think the code should detect both these cases and resample for hardening or importing.
User’s file (triggered this discussion) has orientation RPI (in ITK terminology, notation “from”),
file named avg152T1_LR_nifti.nii.gz from the link above has the same orientation.
Good news, both test files are correctly displayed in Slicer volume viewer and Slicer
can correctly save them in MetaImage file (not sure about all modules).
I guess because in ITK (and MetaImage format) matrices are fully defined,
this one is
1 0 0
0 -1 0
0 0 1
so there is no need to use cross product (whatever left or right handed) to get 3rd row (Z direction) from 1st and 2nd,
(remember DICOM’s direction cosines, they were in particular case 1,0,0,0,-1,0 and 3rd row (Z direction were cross product, here is a problem. But luckily not visible in classic series thanks to sorting by IPP/IOP,
resulting orientation after correct sorting were RPS (in ITK terminology).
To be sure and safe one can e.g. use ITK’s change orientation filter and
re-orient to RPS (in ITK terminology)
1 0 0
0 -1 0
0 0 -1
or LPI (in ITK terminology)
-1 0 0
0 -1 0
0 0 1
BTW, look at MHA header to see ITK’s orientation code and transform matrix:
TransformMatrix = 1 0 0 0 -1 0 0 0 1
AnatomicalOrientation = RPI