Frequently Asked Questions

for MATLAB NIfTI Tools

This FAQ was updated on July 03, 2009

Click http://www.rotman-baycrest.on.ca/~jimmy/NIfTI/#update for the update of the tools

 


 

Question in Orientation

 

What I was observing is a flip with the normal load_nii and save_nii tools. Fslview displays the loaded and saved image in a different orientation ... (Extracted from Richard at University of Manchester, UK)

 

Answer

 

As a matter of fact, it is FSL View that flips the ANALYZE image, not my tools. If you are still using ANALYZE image, I strongly suggest that you take a look at the table that I summarized:

 

http://www.rotman-baycrest.on.ca/~jimmy/UseANALYZE.htm

 

 


 

Question in Orientation

 

I am working with "load_untouch_nii". What is the orientation of the XYZ? How can I transfer it into MNI coordinates? (Extracted from Asaf at Tel-Aviv University, Israel)

 

Answer

 

First, I have to let you know that "load_untouch_nii.m" is a very special function. Please type: help load_untouch_nii, and read the instruction very carefully. You will find that this function only properly reads the header and data; however it does not apply any appropriate affine geometric transform or voxel intensity scaling in the header to the data. Therefore, the user will have the responsibility to do the interpretation by themselves.

 

If your image file is in ANALYZE format, no one can tell you the XYZ orientation. If your image file is in NIfTI format, please use "load_nii.m", and your data will always be converted to RAS orientation (Neurological Convention). If you use "load_nii.m", you can also find the location of origin at "nii.hdr.hist.originator", and the size of voxel at "nii.hdr.dime.pixdim". You can easily obtain the coordinate in millimeter by subtracting the origin location and multiplying the voxel size.

 

If there is no AC Origin information in the header, you won't be able to obtain "coordinate in millimeter". In addition, both "MNI coordinate" and "Talairach coordinate" are brain atlas. So I believe that you are mean "coordinate in millimeter" by saying "MNI coordinate".

 

 


 

Question about Orientation

 

When we use "load_nii.m" to process our data containing non-orthogonal affine transform matrix, the values are not correct since we have compared them with MRIcroN. So, how to deal with the data with such an affine matrix? (Extracted from Chaogan at Beijing Normal University, China)

 

Answer

 

When you use "load_nii.m" to load your NIfTI data, we usually allow 10% of distortion tolerance by default. If it is too oblique, it will notify you. You can adjust the tolerance parameter when you use "load_nii.m". For example, you can set it to 0, so that your NIfTI image will not be loaded if it contains any slightly non-orthogonal rotation.

 

For those NIfTI file that cannot be loaded with "load_nii.m", you should use my "reslice_nii.m" to reslice your NIfTI image, which is exactly what MRIcroN does. It will not cause negative effect, as long as you remember not to do slice time correction after using "reslice_nii.m".

 

 


 

Question about Orientation

 

When I load my data using your NIfTI tools, which side is left and which side is right? Was my data stored in RAS orientation? (Extracted from Katja at University of Nottingham, UK)

 

Answer

 

The answer is that it depends on your data.

 

If your data is in old ANALYZE 7.5 format, this tool cannot tell if an ANALYZE data is in RAS or LAS orientation. You may notice that strict ANALYZE 7.5 format has a field called "hist.orient". The value of this field ranges from 0 to 5 covering 6 orientations. However, many other important orientations (e.g. images in neurological convention or RAS) can not be expressed using Strict ANALYZE 7.5 format, which poses a critical problem for this "hist.orient" field. You can find more details from: http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm. Therefore, many software (e.g. PLSGUI, SPM, AFNI, FSL, MRIcro, etc.) choose to ignore this field, and the orientation will totally depend on the ANALYZE image data itself. If you are a radiologist, you can assume your data are in LAS orientation; if you are a neurologist, you can assume your data are in RAS orientation. In order to be compatible with ANALYZE images saved by other software, this tool will also ignore the "hist.orient" field.

 

However, since the NIfTI image includes affine transformation, this tools can tell if a NIfTI image is in RAS or LAS orientation. Two example datasets, "avg152T1_LR_nifti.nii" and "avg152T1_RL_nifti.nii", are provided under NIfTI web site http://nifti.nimh.nih.gov/nifti-1/data. As is indicated on NIfTI web site, "The first image (LR) is stored in radiological convention (LAS). The second image (RL) is stored in neurological convention (RAS). Any NIfTI compliant viewing software should display these images identically".

 

Therefore, there could be 3 situations when you use the command:  nii = load_nii('filename.nii');

 

1.      If you find "nii.filetype" is 0, it means that the orientation is whatever in your image data, because your data is in old ANALYZE 7.5 format. I can neither tell you which side is left (right), nor tell you your data was stored in which orientation.

2.      If "nii.filetype" is not 0, and there are no "rot_orient" / "flip_orient" fields under "nii.hdr.hist" or if they are empty, it means that your data was stored in RAS orientation, and it is still in RAS orientation (left side is left, right side is right).

3.      If "nii.filetype" is not 0, and "rot_orient" / "flip_orient" fields under "nii.hdr.hist" are not empty, it means that your data was not stored in RAS orientation, but is converted to RAS orientation (left side is left, right side is right).

 

 


 

Question about Orientation

 

According the NIfTI standard, xyz's world space coordinates are always in RAS, but ijk's voxel space coordinates can be in any orientation. So what your program actually seems to be doing is to take the transform matrix from the header and re-index each voxel so that voxel indices in ijk's space conform to RAS. Is it right? (Extracted from Sam at University of Wisconsin, US)

 

Answer

 

This is what the transformation does in my programs.

 

If the transformation only includes several flips and orthogonal rotations, the "load_nii.m" can do it; otherwise, you can always use "reslice_nii.m" to do the transformation with non-orthogonal rotation or shearing.

 

After the transformation is done, ijk will be aligned to xyz respectively. Therefore, the relationship between ijk & xyz is now simplified to just a scaling factor of "hdr.dime.pixdim(2:4)", and it is much easier to tell the location a voxel that is close to left, right, anterior, posterior, superior, or inferior.

 

 


 

Question about Orientation

 

I noticed a problem when I use save_nii to write out a NIfTI file. Basically, I tried reading a NIfTI file and then write it out without making any changes, then I found the "flip_orient" and "rot_orient" in the "hdr.hist" of the original NIfTI structure become empty in the new .nii file that is written out by save_nii. Could you please let me know what the problem is and how to fix it if possible? (Extracted from Ying at Emory University, US)

 

Answer

 

This is not a problem.

 

First, "flip_orient" and "rot_orient" fields in the "hdr.hist" are used internally for information only, which indicate how the transformation is done. If you found that there were "flip_orient" and "rot_orient" fields in the "hdr.hist" of the original NIfTI structure and they were not empty, it means that the file you were reading is a NIfTI format file, and it is not in RAS orientation. In addition, fields like "hdr.hist.new_affine", "hdr.hist.old_affine", and "original" are also for information only.

 

Second, the NIfTI file that you saved is changed by the program, because the NIfTI header information is appropriately applied to the data. The NIfTI header is also changed to indicate that its information has been properly applied. When you use "load_nii.m" again to load the new NIfTI file, there is nothing to flip or rotate. So the "flip_orient" and "rot_orient" fields in “hdr.hist” of the NIfTI structure is empty.

 

If you would like to save exactly as loaded, you have to use "load_untouch_nii.m" to load a NIfTI or ANALYZE file. In this case, nothing is changed. That means, you have no idea where (e.g. Left | Right) is a voxel in loaded 3D matrix without matrix computation together with the sform / qform transformation matrix in the header. Therefore, you cannot view or save the untouched data with "view_nii.m" or "save_nii.m" program. If you use "save_untouch_nii.m" to save the data that is loaded with "load_untouch_nii.m", the new file is untouched.

 

 


 

Question about Orientation

 

I want to know how I could make a NIfTI file which is in LAS orientation. The reason why I need to use LAS is because my output files use that; also the functions I use are batch processes, so each image that is created has to be switched from RAS to LAS manually. (Extracted from Felipe at UTHSCSA, US)

 

Answer

 

Program "flip_lr.m" is provided to do LAS->RAS (or RAS->LAS) conversion for any NIfTI or ANALYZE file format. However, please make sure that you save those flipped NIfTI file separately, since you can confuse yourself if you mix them with other normal NIfTI file.

 

 


 

Question in general

 

When I tried to load my NIfTI file with "load_nii.m" and resave it with "save_nii.m", I ran into some trouble. The new file is quite different in the header. I just want to average some frames along the time-series, how do I save exactly as loaded? (Extracted from Michael at Rotman Research Institute, Canada)

 

Answer

 

When you use "load_nii.m" to load a NIfTI file, the information in NIfTI header is appropriately applied, which includes affine space transformation and voxel intensity scaling etc. The NIfTI header is then changed to indicate that its information has been properly applied.

 

If you would like to save exactly as loaded, you have to use "load_untouch_nii.m" to load a NIfTI or ANALYZE file. In this case, nothing is changed. That means, you have no idea where (e.g. Left | Right) is a voxel in loaded 3D matrix without matrix computation together with the sform / qform transformation matrix in the header. Therefore, you cannot view or save the untouched data with "view_nii.m" or "save_nii.m" program.

 

If you use "save_untouch_nii.m" to save the data that is loaded with "load_untouch_nii.m", the new file is untouched. In your case, you can average frames along the 4th dimension of the 4D matrix, and adjust hdr.dime.dim(5) before save into new file with "save_untouch_nii.m".

 

 


 

Question in general

 

Can I run this package under MATLAB R2008a?

 

Answer

 

Basically, you can any programs in this package under any version of MATLAB on any platform. However, the speed of "reslice_nii.m" program would be much slower if you run it under MATLAB 6.5 (R13) or below. This is because MATLAB overhauled its computation kernel on MATLAB 6.5 (R13) and above.

 

 


 

Question about originator

 

I am trying to set the origin of my images to the centre, so that if I read them into SPM2 there is some overlap between my images and their templates. At the bottom of this email I have copied my header fields in full. When I load my image the first time, I noticed that "one_tp_nii.hdr.hist.originator" is [32 32 15 0 0], and "one_tp_nii.original.hdr.hist.originator" is also [32 32 15 0 0]. After I write the image out with "save_nii(one_tp_nii, 'temp')" and then read it in again with "image_nii = load_nii('temp')", "image_nii.hdr.hist.originator" is still [32 32 15 0 0], but "image_nii.original.hdr.hist.originator" array is now [256 0 0 0 0]. SPM2 takes [256 0 0] as the origin. Has "save_nii.m" not written out the originator, or is there another problem with my header? (From Simon at University of Trento, Italy)

 

Answer

 

First, when you loaded your image, and found that both "hdr.hist.originator" and "original.hdr.hist.originator" are [32 32 15 0 0], it means that the image you loaded is an ANALYZE format image. After you wrote the loaded image with "save_nii.m", the new image is now in NIfTI format. That is why you see "image_nii.original.hdr.hist.originator" arrary is [256 0 0 0 0], because unlike ANALYZE image, NIfTI image does not explicitly have a field called "originator". Please note that the "image_nii.original" field is what explicitly stored in the image header (except the originator), which is for your reference only, and you should really don’t have to worry about it. "image_nii.hdr" is the one that you have to look at. In your case, "image_nii.hdr.hist.originator" is still [32 32 15 0 0].

 

Second, the reason that SPM2 takes [256 0 0] as the origin is because all earlier versions of SPM (before SPM5) can not handle NIfTI image. If the NIfTI file extension is ".nii", it can not be recognized. If the NIfTI file extension is ".img / .hdr", the affine matrix where the originator is defined will not be interpreted.

 

Now, when you want to save your image into ".img / .hdr" file extension, the "save_nii.m" in my tools will also save an extra affine matrix into a ".mat" file, so earlier versions of SPM can also open it with correct originator and orientation. If you have an SPM generated image file with its corresponding ".mat" affine matrix file, the “load_nii” in my tools will also be able to load that affine matrix and integrate it into the .hdr structure.

 

 


 

Question about scl_slope

 

I have 3D ANALYZE volumes with different scale factors and I want to store them as a 4D NIfTI file. Can your toolbox (or the NIfTI format) handle this so the different scale factors still can be available. It seems to me like the scale factor is set to zero. (Extracted from Peter at Lund University, Sweden)

 

Answer

 

Because my NIfTI toolbox has already taken care of the scale factor, the scale factor has to be set to zero.

 

When you use "load_nii.m" to load the 3D ANALYZE volumes, you don't have to worry about the scale factor any more, because scl_slope & scl_inter from each different ANALYZE volumes have been applied to the corresponding img matrix, and the scale factors are all set to 0.

 

All you need to do is to concatenate those 3D img matrices into a 4D matrix, and run:

nii = make_nii(4Dmatrix, [options]);      % build 4D NIfTI structure

save_nii(nii, '4D.nii');     % store as a 4D NIfTI file.

 

 


 

Question about scl_slope

 

There is a discrepancy to read voxel values between the two cases:  (1) Values are read using combination of inbuilt functions fread() and fopen();  (2) Values are read using load_nii().  The values read by fread() function is different from the values in "nii.img". Can you throw some light on the problem of getting too small values? (Extracted from Harshal)

 

Answer

 

You may want to look at the following URL:

http://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/scl_slopeinter.html/view?searchterm=scl_slope

 

Since your scl_slope value is nonzero (9.4500e-003), each voxel value in your "nii.img" has to be scaled by:

y = scl_slope * x + scl_inter;

where, x is the stored voxel value in your image file, and y is the true voxel value in "nii.img".

 

You can get your original "scl_slope" and "scl_inter" in "nii.original.hdr.dime" structure. If you want, you can restore original "nii.img" by:

stored_val_img = (nii.img - scl_inter) / scl_slope;

 

 


 

Question about scl_slope

 

I'm having some problems with the scaling factor. The value of nii.hdr.dime.scl_slope is zero, instead of the correct value (0.003922) that I am expecting using spm5 or avwhd from FSL. (Extracted from Ged at University College London, UK)

 

Answer

 

Actually both "scl_slope" and "scl_inter" parameters have been correctly read and applied to the "img" variable of the output NIfTI structure (see "xform_nii.m" file): nii.img = scl_slope * double(nii.img) + hdr.dime.scl_inter;

 

The reason to display "hdr.dime.scl_slope" as zero is a feature of my package. It signifies that the "img" variable has already been modified. You can also find that "hdr.hist.qform_code" and "hdr.hist.sform_code" will be set to zero after you use "load_nii.m".

 

The original value of "hdr" can be easily found by: hdr = load_nii_hdr(filename); You should have correct value (0.003922) there.

 

 


 

Question about overlay

 

I have been using your program "Tools for NIfTI and ANALYZE image". I try to map a "color.nii" on "background.nii". With FAQ on the website, I still

got errors and I do not know how come. Can you help me please? (Extracted from Karla at Katholieke Universiteit Leuven, Belgium)

 

Answer

 

The cause of the problem is from your "color.nii" data. when you use "opt.setvalue.idx = find(map.img>0)" to find index, the result is empty, since there is one -1 and all 0 in that file. In addition, you will need at least 2 different colors in "color.nii" in order to display properly. Hopefully this will clear your problem.

 

 


 

Question about overlay

 

I have been trying to overlay my activation map with a jet colormap onto a background MRI (with a gray colormap) just as in the opening figure in the webpage, and I can't seem to find a way to do it. On the FAQ it only explains how to overlay more than two images. (Extracted from José at Universidade de Coimbra, Portugal)

 

Answer

 

There are 2 FAQ regarding to overlay, and the other one is much closer to yours. Let me customize that one into your case, and here is how to use this advanced feature:

 

1.      Use "bg = load_nii(bg.img)" to load your background image to "bg" struct, and make sure that variable "bg.img" is either in "single" or "double". If not, use step 2 to convert it; otherwise, goto step 3.

2.      To convert variable "bg.img" to "single", you need to use "make_nii" command: "bg = make_nii(single(bg.img), bg.hdr.dime.pixdim(2:4), bg.hdr.hist.originator(1:3), 16);".

3.      You need to know the threshold of your activation map, and know how to use "find" command to get the index of the thresholded activation map. Assuming that your threshold is 0, you can use "map = load_nii(map.img)" to load your activation map to "map" struct, and extract its value and index to "opt" struct: "opt.setvalue.idx = find(map.img); opt.setvalue.val = map.img(find(map.img));". You can see more detail to use "setvalue" by command: "help view_nii".

4.      Add other values to "opt" struct: "opt.command = 'init';".

5.      If you want to have an interpolated view, also set "opt.useinterp = 1;".

6.      Plot activation map with background image by command: "view_nii(bg,opt);". Please don't click "interp on/off" menu in the view window, because it will not work properly under this situation. Instead, you should use: "opt.useinterp=0" or "opt.useinterp=1".

7.      In the view window, you can change the colormap of your activation map by selecting "Jet".

 

 


 

Question about overlay

 

I have been using your NIfTI toolbox for MATLAB recently and was wondering whether it is possible to make an overlay of a thresholded image onto an ANALYZE image. In effect that would mean that all 0 values of the thresholded image should be transparent so that the underlying functional image can be seen. (Extracted from Henry at Max Planck Institute for Biophysical Chemistry, Germany)

 

Answer

 

This is an advanced feature, and it is already included in my tools.

 

Here is the brief guide to use this feature:

 

1.      Use "ana = load_nii(ana.img)" to load your ANALYZE image to "ana" struct, and make sure that variable "ana.img" is either in "single" or "double". If not, use step 2 to convert it.

2.      To convert variable "ana.img" to "single", you need to use "make_nii" command: "ana = make_nii(single(ana.img), ana.hdr.dime.pixdim(2:4), ana.hdr.hist.originator(1:3))".

3.      Use "thresh = load_nii(thresh.img)" to load your thresholded image to "thresh" struct, and extract its value and index to "opt" struct: "opt.setvalue.idx = find(thresh.img); opt.setvalue.val = thresh.img(find(thresh.img));". You can see more detail to use "setvalue" by command: "help view_nii".

4.      Add other values to "opt" struct: "opt.command = 'init'; opt.useinterp = 0;".

5.      Plot thresholded image with underlaid ANALYZE image by command: "view_nii(ana, opt);".

6.      Don't click "interp on/off" menu. It doesn't work properly. If you would like to see the interpolated one, use: "opt.useinterp = 1; view_nii(ana, opt);" instead.

 

 


 

Question about overlay

 

Could you please tell me:  (1) How to overlay 2 or 3 other images together?  (2) How to choose different threshold? (Extracted from rhuang at Forschungszentrum Jülich in der Helmholtz Gemeinschaft, Germany)

 

Answer

 

You can always overlay 2 or more other images together manually with the following simple procedures, if dimensions of all the images are the same. Please do not click "Interp on" when you view the integrated image, because it will be a mess if the interpolation could not be separated.

 

In addition, if the datatypes are different, you must use "make_nii" to convert a datatype to the highest storage. For example, after you load a background image with bg = load_nii('background_image.img') and find the bg.img is uint8 (i.e. datatype = 2), but some image is single (datatype = 16), you need to convert bg to single datatype with bg = make_nii(single(bg.img), bg.hdr.dime.pixdim(2:4), bg.hdr.hist.originator(1:3), 16).

 

How to choose different thresholds depends on which regions of your activation image you would like to display. For example, if the values in your first activation map range from [-6  +7], and you want to view regions whose values are from [-6  -2] and from [+3  +7], you can use the following procedures:

 

1.      Load your first activation map:  map1 = load_nii('activation_map1.img')

2.      Get index of that activation map:  idx1 = find(map1.img < -2 | map1.img > +3);

3.      Get map2 / idx2 etc. in the same way.

4.      Load background image:  bg = load_nii('background_image.img')

5.      Make sure bg.img and all map.img must have the same dimension & datatype.

6.      Overlay the 1st layer above the background:  bg.img(idx1) = map1.img(idx1);

7.      Overlay the layer above till the top layer:  bg.img(idx2) = map2.img(idx2);

8.      Display the integrated image:  view_nii(bg);

 

 


 

Question about NIfTI data dimensions

 

I would write feedback for the limitations that I have found, and hope they will be included in a new version. It would be fantastic to access the 5th, 6th and 7th dimensions so I can neatly store my multi-channel multi-echo phase and magnitude MR as (x, y, z, echo, channel, phase/magnitude) in a single file. In addition, would it be possible to read a particular slice z of a 4D NIfTI data (:,:,z,:) and still carry out the image transformation? (Extracted from Simon at University of Trento, Italy)

 

Answer

 

I have extended Load / Save / Make programs to N-Dimension, where N can be from 3 to 7 for NIfTI data and from 3 to 4 for ANALYZE data. The size of data, however, will be a big concern. Each element on the 5th dimension will take the size of a 4D time-series image, not to mention the 6th or 7th dimension. This is especially a concern when your data is in 32-bit or 64-bit.

 

For your second question, if you extract a particular slice (z = k) on the 3rd dimension, that slice index will be moved from k to 1 (z = 1). Since affine transformation matrix uses the x, y, and z indices for its input, the image transformation will no longer be able to carry out if you only read a particular range of x, y, or z. Therefore, "load_nii" only allows a subset data retrieval for the 4th dimension and up.

 

 


 

Question about AVW file format

 

I try to read ANALYZE file in MATLAB. I am not using ".img / .hdr" or ".nii" format, but ".avw" format where the header is also embedded. I cannot read those file using your tool. Am I missing something or is this file format not supported? (Extracted from Olivier at Case Western Reserve University, US)

 

Answer

 

The ".avw" file format that you mentioned is only used by Analyze software from AnalyzeDirect Inc. It is not the old ANALYZE 7.5 file format that people usually referred to, and ".avw" file format is not compatible with NIfTI file format at all. So it is not supported by my tools.

 

The ".img / .hdr" file format is used by both NIfTI file format and old ANALYZE 7.5 file format, while the ".nii" file formats is used by NIfTI only. NIfTI file format inherited old ANALYZE 7.5 file format, and added much more new features. e.g. it can include time series into the file (4-D file) etc. Therefore, old ANALYZE 7.5 file format is compatible with NIfTI, and both are supported by my tools.

 

If your .avw file is in non-compressed format, thanks to Jeff Gunter from Mayo Clinic, you can use  loadavw.m  to load your .avw file into avw structure in MATLAB. Since the data sits in avw.Image, you can then use my "make_nii.m" to convert it to NIfTI structure.

 

If your .avw file is in compressed format, you will have to load it back with that Analyze software, and then save as AnalyzeImage7.5 file format again, which can be loaded by my NIfTI tools directly.