BUG when reading mha file with AnatomicalOrientation

I’m working on adding support for orientation in VTK image data and what depends on it (filters, mappers, IO… more details here).

I was working on the MetaIO (.mha, .mhd) reader and tested using a sample dataset with the following header:

ObjectType = Image
NDims = 3
BinaryData = True
BinaryDataByteOrderMSB = False
CompressedData = True
CompressedDataSize = 1486837
TransformMatrix = 1 7.5286998857393448e-16 4.3888503942213362e-16 7.4766581814600425e-16 -1 -3.8487811825327185e-47 0 0 -1
Offset = -9.360019529721862e-29 360.00000000000006 332.5
CenterOfRotation = 0 0 0
AnatomicalOrientation = RPS
ElementSpacing = 1.4062499999999947 1.4062500000000002 2.4999999999999813
DimSize = 256 256 133
ElementType = MET_UCHAR
ElementDataFile = LOCAL

Note that the anatomical orientation for this file is RPS, spacing is ~ [1.4, 1.4, 2.5] and the orientation matrix is, after rounding:
1 0 0
0 -1 0
0 0 -1

In VTK the system is XYZ=LPS, so after flipping the first axis, the orientation matrix becomes, in LPS:
-1 0 0
0 -1 0
0 0 -1

Now… I use 3DSlicer as the ground truth in term of orientation when I test things for VTK, and the data read in my VTK example with the MHA reader was flipped along the Sagittal axis (L/R) compared to 3D Slicer…

I then proceed to export the dataset to NRRD from Slicer, and this is the resulting header:

# Complete NRRD file format specification at:
# http://teem.sourceforge.net/nrrd/format.html
type: unsigned char
dimension: 3
space: left-posterior-superior
sizes: 256 256 133
space directions: (1.4062499999999947,1.0587234214320913e-15,6.171820866873731e-16) (1.0514050567678187e-15,-1.4062500000000002,-5.4123485379366359e-47) (0,0,-2.4999999999999813)
kinds: domain domain domain
encoding: gzip
space origin: (-9.360019529721862e-29,360.00000000000006,332.5)

With rounding, the direction matrix here is:
1.4 0 0
0 -1.4 0
0 0 -2.5

If we extract the spacing (1.4, 1.4, 2.5) we get:
1 0 0
0 -1 0
0 0 -1

That’s the same as in the MHA header… however, the space is now left-posterior-superior instead of RPS in MHA: here we find the flip along the X-axis again.

So two possible reasons:

  1. MHA reader is incorrect
  2. NRRD writer is incorrect

Given that my VTK implementation gives me a flip from the one loaded by Slicer, my guess is on number 1. I followed up by looking at itkMetaImageIO and there are numerous mentions of AnatomicalOrientation in MetaImageIO::Write, but none in MetaImageIO::Read.

Based on all this, would you all agree we are indeed ignoring the anatomical orientation when reading MHA/MHD files?

cc: @dzenanz @thewtex

Hi @agirault - yes, this has come up a couple of times. I believe the post from Andras sums up the current understanding.

Right on, thank you Steve.

Well… we probably won’t have that in VTK, and I’m afraid that is going to confuse more than one. I don’t understand why it has to be like this in ITK: any of its maintainers would like to explain the argument (@dzenanz, @thewtex)?


I agree, I don’t like having this standard field for “informational purposes” only (that readers should ignore), especially because similar field in nrrd is actually used by the readers.

However, I understand the reluctance in investing more time into improving the file format, as there are already too many file formats (metaio, nrrd, nifti, mgz, …) for storing biomedical images in research applications. It would be probably better if we would focus on maintenance and improvement of a single file format.


@lassoan in the other thread linked above, you mention that the TransforMatrix (is that different from the Orientation field?) is a rotation from ijk to RAS. However, when saved as a NRRD, the transformation matrix is the same, but in LPS, as shown above. So either:

  1. the actual transform is IJKtoRAS but IJKtoLPS
  2. is is IJKtoRAS but we read it as IJKtoLPS

Would you agree?

Also, I’m currently updating those readers & writers in VTK. What do you suggest I do for MetaIO?

  1. Same as NRRD (use the AnatomicalOrientation as the target coordinate system)
  2. enforce as LPS (do nothing)
  3. enforce as RAS (flip I and J)

After discussion with @thewtex and @aylward, we agreed that the current integration of MetaIO inside ITK is incorrect, namely:

  1. The reader ignores the anatomical orientation and assumes the data is always in LPS. It should instead adjust the orientation matrix described in the file to go from IJK to LPS if the anatomical orientation differs from LPS
  2. The writer uses the direction matrix to infer an anatomical orientation (somehow?). It should instead write LPS and the associated direction matrix in that space.

As a result:

  • We’ve agreed that this will need to be fixed in ITK.
  • VTK will properly use those fields when adding orientation support.

FYI: an attempt at updating the MetaIO reader and writer in VTK can be found here: https://gitlab.kitware.com/vtk/vtk/merge_requests/5656