Direction/Orientation matrix DICOM vs Nifti

Hi everyone,

I’m re-posting a question that I recently asked in the SimpleITK Discourse (https://discourse.itk.org/t/direction-orientation-matrix-dicom-vs-nifti/3289). It may seem a bit redundant, but I would like to have your thoughts considering that conversion DICOM to Nifti is the initial step in the creation of a BIDS structure.

In short, using ITK based tools (elastix, ANTS, SimpleITK, MeVisLab, and maybe more), I notice that the Direction Matrix I read from DICOMs is different compared to the one is set in Niftis for the same image. This affects some algorithms working in world coordinates, particularly registration operations.

Have any of you perceived these inconsistencies with the Niftis ? There is a good amount of info on the q_form and s_form of the orientation matrix in Niftis, but I have not seen any formal consistency checks between the original DICOMs and generated Niftis. Are you aware of anything like this?

Thanks!!

RaC

I’m not sure I understand the questions posed here. From the linked thread, it seems that there is concern over losing the precision when moving from a 64-bit float affine matrix to a 32-bit float affine matrix.

This seems plausible, but are these effects problematic in some way? If you consider your starting point a few nm off from where it is otherwise, then the transformation found by your registration algorithm may also be a few nm different, but I would be surprised if the registration was worse in a measurable way.

I would assume that this is built into the testing framework of the converters, such as dcm2niix.


If what you want is to be able to encode your affine matrices as 64-bit floats, the NIfTI-2 format will do that for you. It doesn’t look like dcm2niix supports NIfTI-2, but you should be able to recover it pretty easily in Python (I haven’t tested this…):

import nibabel as nb
from nibabel.nicom.dicomwrappers import wrapper_from_file
dcm = wrapper_from_file(dcm_fname)
nii = nb.load(nii_fname)
nii2 = nb.Nifti2Image(nii.dataobj, dcm.affine, nii.header)
nb.save(nii2, nii2_fname)

There are two issues here. First, the NIfTI uses a different spatial coordinate system than DICOM. Specifically, NIfTI uses Talairach-Tournoux coordinates:
X: Increasing value toward the Right
Y: Increasing value toward the Anterior
Z: Increasing value toward the Superior
In contrast, the DICOM coordinate system is
X: Increasing value toward the Left
Y: Increasing value toward the Posterior
Z: Increasing value toward the Superior
The other thing to remember is the row order. Following NIfTI convention I will refer to the stored order as I,J,K instead of X,Y,Z to avoid confusion with spatial dimensions. The data is stored Columns (I) followed by Rows (J) followed by slices (K). For a NIfTI image
I: first column on LEFT of screen, columns ascending toward RIGHT
J: first row at BOTTOM of screen, subsequent columns ascending toward TOP
with DICOM
I: first column on LEFT of screen, columns ascending toward RIGHT
J: first row at TOP of screen, subsequent columns ascending toward BOTTOM
I like to think of how we draw a 2D Cartesian graph, with a higher position on the graph showing a higher value. In contrast, DICOM is how I write English, with the first row at the top of the screen and subsequent rows descending down the page.

dcm2niix will losslessly convert DICOM to NIfTI. It will preserve spatial information. By default, it will also flip the row order. This flipping means that a viewing tool that ignores the Form/QForm will display a 2D slice in the same way that a DICOM viewer would with respect to the top and bottom of the computer screen. The undocumented argument -y n will disable this row flipping. Since the SForm/QForm are also updated, the resulting images will look identical in a tool that respects the SForm/QForm, but will look flipped in tools that ignore this. To see this, launch MRIcron and choose Preferences. Make sure both the “Reorient images when loading” and “Rotate to nearest orthogonal angle” options are unchecked. This will show the order data is saved to disk.

1 Like

rcorredorj here are the consistency checks used by dcm2niix. Each commit of code for the dcm2niix code is automatically run through several of these validation datasets to detect regressions. Each validation set includes some DICOMs and their correct conversion to NIfTI. Different validation datasets are used to test different features of the DICOM format (which is very complex and has been interpreted differently by different vendors). DICOM is like the English language and used differently by different groups (e.g. for the British “pants” means “underwear”, but in the USA “pants” means “trousers”.

Thank you for your replies.

@effigies, I know that the changes are very tiny. It sounds negligible, however registration tools such as elastix and ANTs are sensitive to these small variations in the orientation matrix (as indicated by the ITK colleagues here https://github.com/InsightSoftwareConsortium/ITK/pull/1868). I’ve perceived intensity variations in contours that may affect consequent segmentation tasks, specially when you’re detecting small structures. I did notice that our Python code uses mostly Nifti1Images from nibabel. I was not aware of the Nifti2Image. Thanks for your advice!

@Chris_Rorden, thank you so much for this detailed explanation of how dcm2niix works. To be honest, I have not used it myself but I’ll definitely explore it a bit more and check compatibility with the tools we currently use.I also liked very much your definition of DICOM and I’ll quote you on that :)! I just hope that Nifti does not become like Spanish, another language with different interpretations in each country/group/tool.

nipype.interfaces.dcm2nii

Why dcm2nii has the reorient option (default is true, right?)
and dcm2niix do not?

I understand that dcm2niix reorients 3D images to the nearest orthogonal to an identity matrix. As the EPI is 2D images, it won’t apply to them. (to preserve the slice order)
In other words, when using dcm2niix, the default will reorient the mprage (anatomy) by not the functional 2D EPI?
If I use fslreorient2std on my nifti, I do not need to use reorient in dcm2nii stage?

There are 48 possible combinations for losslessly transposing a 3D volume (e.g. shifting the order and polarity of the rows, columns and slices). Here is an example of the same data saved to all 48 combinations.

For convenience, dcm2niix will lossless rotate a 3D non-EPI acquisition to be as close to possible to the NIfTI identity matrix. Most people would refer to this as RAS orientation (columns ascend Right, rows ascend Anterior, slices ascend Superior). As a concrete example, the T1 scan from here will be described as follows by dcm2niix:

sto_xyz:1	0.999611 -0.027633 -0.001937 -86.609787 
sto_xyz:2	0.027696 0.998292 0.051431 -113.560699 
sto_xyz:3	0.000512 -0.051464 0.998675 -132.386383 
sto_xyz:4	0.000000 0.000000 0.000000 1.000000 
sform_xorient	Left-to-Right
sform_yorient	Posterior-to-Anterior
sform_zorient	Inferior-to-Superior

However, dcm2niix is designed to create images that are compatible with the BIDS format. This requires that EPI images have the SliceTiming field of the JSON sidecar populated. This field requires that the NIfTI slices (dimension k) corresponds to the temporal order. Therefore, slices as saved to disk must correspond to the head-foot direction for axial acquisitions, the left-right direction for sagittal acquisitions and anterior-posterior for coronal acquisitions. If your call to fslreorient2std manipulates the order of slices (k), the SliceTiming parameter will not be correct.

By the way, you can adjust the way dcm2niix stores data in plane. For example, as I describe here the conversion for EPI DICOMs will be a tiny bit faster with dcm2niix -x i -y n /path/to/DICOMs. The default orientation of dcm2niix is designed to mimic dicm2nii.

1 Like