# How to handle images defined in left-handed coordinate system

**URL:** <https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133>\
**Category:** Development\
**Created:** [September 17, 2018, 9:10pm UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133 "2018-09-17T21:10:04Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 17, 2018, 9:10pm UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133/1 "2018-09-17T21:10:04Z")

</div>

> [@How to convert to .stl from .nii](https://discourse.slicer.org/t/how-to-convert-to-stl-from-nii/4088/3):
>
> invalid coordinate system (determinant of voxel-\>physical transform is negative,

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](https://github.com/Kitware/vtk-js/issues/858),

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 17, 2018, 9:26pm UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133/2 "2018-09-17T21:26:10Z")

</div>

> [@How to convert to .stl from .nii](https://discourse.slicer.org/t/how-to-convert-to-stl-from-nii/4088/4):
>
> voxel-to-physical coordinate system that describes acquisition geometry can be left handed

From [this specification](https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform.html) it seems that left-handed is not permitted in nifti (search for left-handed on the page and see also axes specification a few paragraphs above).

> [@How to convert to .stl from .nii](https://discourse.slicer.org/t/how-to-convert-to-stl-from-nii/4088/4):
>
> ITK readers re-arrange the data to enforce right-handedness

Is this something that has been added recently? What direction matrix do you see in Volumes module when you load the above-referenced volume into Slicer?

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 17, 2018, 9:56pm UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133/3 "2018-09-17T21:56:12Z")

</div>

> [@How to convert to .stl from .nii](https://discourse.slicer.org/t/how-to-convert-to-stl-from-nii/4088/5):
>
> From [this specification](https://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform.html) it seems that left-handed is not permitted in nifti (search for left-handed on the page and see also axes specification a few paragraphs above).

Yes, file formats may not support left handed coordinates - I see now that you were referring to the nifti file being invalid not that directions can’t be invalid as a general rule.

> [@How to convert to .stl from .nii](https://discourse.slicer.org/t/how-to-convert-to-stl-from-nii/4088/5):
>
> Is this something that has been added recently? What direction matrix do you see in Volumes module when you load the above-referenced volume into Slicer?

Not new, that was the original design and is still in the documentation. To be honest though I’m not sure which readers enforce it:

> <https://github.com/Kitware/ITK/blob/master/Modules/Core/Common/include/itkImageBase.h#L200-L209>

I’d need to dig back in, but as I recall the GDCM reader rearranges the order of the slices so that the direction turns out right-handed.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [September 17, 2018, 11:00pm UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133/4 "2018-09-17T23:00:09Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [September 17, 2018, 11:40pm UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133/5 "2018-09-17T23:40:41Z")

</div>

> [@lassoan](#):
>
> Should we add a helper function in volumes logic that converts images to right-handed coordinate system (by reordering slices and flipping z axis)

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.

---

<div class="post-metadata">

**Author:** ![Mihail\_Isakov](https://avatars.discourse-cdn.com/v4/letter/m/a9adbd/32.png) [@Mihail\_Isakov](https://discourse.slicer.org/u/Mihail_Isakov)\
**Post date:** [September 18, 2018, 6:12am UTC](https://discourse.slicer.org/t/how-to-handle-images-defined-in-left-handed-coordinate-system/4133/6 "2018-09-18T06:12:49Z")

</div>

Hello,  
Such Nifti files are common (e.g. MNI152 space).  
Here are very useful test files with R/L marks here  
[https://nifti.nimh.nih.gov/nifti-1/data](https://nifti.nimh.nih.gov/nifti-1/data)

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

Regards

Edited:  
also s.  
[https://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q14](https://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q14)  
[https://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q15](https://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q15)
