# Nifti file orientation change between 2019-08-26 and ITK v5.1rc01

**URL:** <https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594>\
**Category:** Engineering\
**Created:** [January 9, 2020, 3:57am UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594 "2020-01-09T03:57:58Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 3:57am UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/1 "2020-01-09T03:57:58Z")

</div>

We are updating 3D Slicer to use ITK v5.1rc01 and two of our tests now fail. The problem is that a nifti file loads with different image directions now compared to previously:

- ITK master as of 2019-08-26 =\> image directions `[-1 0 0; 0 -1 0; 0 0 1]`
- ITK v5.1rc01 =\> image directions `[1 0 0; 0 -1 0; 0 0 1]`

Here is the nifti file: [OAS10001.hdr](https://github.com/Slicer/SlicerTestingData/releases/download/MD5/43e5d6676b7d3d83f56d2fa1251e94bc), [OAS10001.img](https://github.com/Slicer/SlicerTestingData/releases/download/MD5/32a988e290dcbb1f78e625e514efaba1). It is originally downloaded from the OASIS database (probably it is [this](https://central.xnat.org/app/action/DisplayItemAction/search_value/OAS1_0001/search_element/xnat:subjectData/search_field/xnat:subjectData.ID/project/CENTRAL_OASIS_CS) image).

Most probably the behavior change is caused by [this commit](https://github.com/InsightSoftwareConsortium/ITK/commit/2579bd3e17fbc768e56d6c94e17b383f139fd6e2). While some explanation for the change is provided in the commit comment, I’m not sure if it is a good enough justification for suddenly changing fundamental image loading behavior in ITK that has been the same for 11 years (the test was added to Slicer in since 2009 and it has been successfully passing until now).

I avoid nifti file format as much as possible (mostly because of these seemingly never-ending problems around how their orientation is defined), so I don’t mind if interpretation of their orientation takes another twist (we can just switch to another data set). However, such behavior change may break many other projects.

I would recommend to reconsider this behavior change and if the decision is made to keep the new behavior then take steps to minimize chance of causing serious problems in various projects (warning in release notes, runtime warning message, configuration option to retain previous behavior, etc. could help).

---

<div class="post-metadata">

**Author:** ![pieper](https://discourse.itk.org/user_avatar/discourse.itk.org/pieper/32/22_2.png) [@pieper](https://discourse.itk.org/u/pieper)\
**Post date:** [January 9, 2020, 1:32pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/2 "2020-01-09T13:32:09Z")

</div>

I agree with @lassoan, this change in behavior is likely to cause trouble.

Looking at the linked commit, it seems the intention was to make reading of legacy analyze files consistent with some previous interpretation at one site. But the entire motivation for nifti was to address the problem that analyze files did not have a well accepted meaning with respect to orientation. Changing ITK’s behavior is only going to make the bad situation worse.

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 2:03pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/3 "2020-01-09T14:03:28Z")

</div>

Previously, 3D Slicer and ITK-Snap displayed the OAS10001 data consistently with each other, but incorrectly (patient face is towards P direction):

 ![image](https://discourse.itk.org/uploads/default/original/2X/7/737a8e45984fb48f2b3fe9530965b982de547e5c.jpeg)

 ![image](https://discourse.itk.org/uploads/default/original/2X/b/b1ccf62eb66d751d2e25d78f0822ff960480ccbe.png)

WIth latest latest ITK master, the image is loaded correctly:

 ![image](https://discourse.itk.org/uploads/default/original/2X/0/0ef0544d53c8f8baf0d5e8a3b5f8cf8cbc06f291.jpeg)

By the way, with current ITK master, the IJK to LPS matrix is left-handed - `diag(1,-1,1)` - which could cause various issues. It could be fixed by reordering slices and it would be nice if ITK could do it, but it is manageable at application level, too.

**Since there is no one good option (you either cause a serious breaking change or load some images incorrectly), the behavior should not be hardcoded in ITK**. A safe solution would be display a warning when ambiguous nifti image is encountered and allow users to choose loading behavior in the nifti reader. One flag could be added to choose old/new behavior and another flag to suppress the warning message.

---

<div class="post-metadata">

**Author:** ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)\
**Post date:** [January 9, 2020, 2:21pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/4 "2020-01-09T14:21:11Z")

</div>

@Vladimir_Fonov @seanm please pitch in.

---

<div class="post-metadata">

**Author:** ![dclunie](https://discourse.itk.org/user_avatar/discourse.itk.org/dclunie/32/2178_2.png) [@dclunie](https://discourse.itk.org/u/dclunie)\
**Post date:** [January 9, 2020, 2:23pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/5 "2020-01-09T14:23:08Z")

</div>

See also this classic Analyze (Not NIfTI) test file, that has burned in RL text indicating how the image (with Analyze orientation of 0 (TRANSVERSE\_UNFLIPPED) and positive pixdim values) “should” (?) be displayed:

[http://web.archive.org/web/20060108143626/http://www.fmrib.ox.ac.uk/~steve/ftp/avg152T1\_LR-marked.tar.gz](http://web.archive.org/web/20060108143626/http://www.fmrib.ox.ac.uk/~steve/ftp/avg152T1_LR-marked.tar.gz)

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 2:35pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/6 "2020-01-09T14:35:28Z")

</div>

This avg152T1 data set loads incorrectly with both the old and new ITK behavior:

Old (both LR and AP axes are incorrectly oriented):

 ![image](https://discourse.itk.org/uploads/default/original/2X/3/355357142f8337edb922ba99de4e8c1fc0ed855a.jpeg)

 ![image](https://discourse.itk.org/uploads/default/original/2X/7/7366075624043aa82a2fd7712087f5c1584b4cd7.png)

New (only LR axis is incorreclty oriented):

 ![image](https://discourse.itk.org/uploads/default/original/2X/f/f441ada1a750f9f1c3173cb0550452177440e0ea.jpeg)

It seems that Nifty/Analyze is kind of hopeless… Since there does not seem to be a chance to consistently get correct orientation for all images, probably the best is to keep the old behavior by default and allow the proposed new behavior (which could fix some orientation errors on some images, at the cost of breaking backward compatibility) as an option.

---

<div class="post-metadata">

**Author:** ![Vladimir\_Fonov](https://discourse.itk.org/user_avatar/discourse.itk.org/vladimir_fonov/32/247_2.png) [@Vladimir\_Fonov](https://discourse.itk.org/u/Vladimir_Fonov)\
**Post date:** [January 9, 2020, 2:41pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/7 "2020-01-09T14:41:02Z")

</div>

what’s the contents of the header of avg152T1 ?

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 2:55pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/8 "2020-01-09T14:55:43Z")

</div>

If you can recommend a Windows tool that can dump the header to a text file then I can copy the results here. Otherwise, you have to download the file from the URL [above](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/5).

---

<div class="post-metadata">

**Author:** ![dclunie](https://discourse.itk.org/user_avatar/discourse.itk.org/dclunie/32/2178_2.png) [@dclunie](https://discourse.itk.org/u/dclunie)\
**Post date:** [January 9, 2020, 2:59pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/9 "2020-01-09T14:59:17Z")

</div>

[main] INFO com.pixelmed.convert.AnalyzeHeader Is BigEndian

[main] INFO com.pixelmed.convert.AnalyzeHeader Have Analyze header

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[0] = 4

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[1] = 91

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[2] = 109

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[3] = 91

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[4] = 1

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[5] = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[6] = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader dim[7] = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader unused8 = 28013

[main] INFO com.pixelmed.convert.AnalyzeHeader unused9 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader unused10 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader unused11 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader unused12 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader unused13 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader unused14 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader datatype = 2 UNSIGNED\_CHAR

[main] INFO com.pixelmed.convert.AnalyzeHeader bitpix = 8

[main] INFO com.pixelmed.convert.AnalyzeHeader dim\_un0 = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[0] = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[1] = -2.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[2] = 2.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[3] = 2.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[4] = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[5] = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[6] = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader pixdim[7] = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader vox\_offset = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader funused1 = 1715.0446

[main] INFO com.pixelmed.convert.AnalyzeHeader funused2 = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader funused3 = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader cal\_max = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader cal\_min = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader compressed = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader verified = 0.0

[main] INFO com.pixelmed.convert.AnalyzeHeader glmax = 255

[main] INFO com.pixelmed.convert.AnalyzeHeader glmin = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader description = ICBM AVG 152 T1 TAL LIN

[main] INFO com.pixelmed.convert.AnalyzeHeader aux\_file = none

[main] INFO com.pixelmed.convert.AnalyzeHeader orient = 0 TRANSVERSE\_UNFLIPPED

[main] INFO com.pixelmed.convert.AnalyzeHeader originator = .@%

[main] INFO com.pixelmed.convert.AnalyzeHeader generated =

[main] INFO com.pixelmed.convert.AnalyzeHeader scannum =

[main] INFO com.pixelmed.convert.AnalyzeHeader patient\_id =

[main] INFO com.pixelmed.convert.AnalyzeHeader exp\_date =

[main] INFO com.pixelmed.convert.AnalyzeHeader exp\_time =

[main] INFO com.pixelmed.convert.AnalyzeHeader hist\_un0 =

[main] INFO com.pixelmed.convert.AnalyzeHeader views = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader vols\_added = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader start\_field = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader field\_skip = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader omax = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader omin = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader smax = 0

[main] INFO com.pixelmed.convert.AnalyzeHeader smin = 0

---

<div class="post-metadata">

**Author:** ![Vladimir\_Fonov](https://discourse.itk.org/user_avatar/discourse.itk.org/vladimir_fonov/32/247_2.png) [@Vladimir\_Fonov](https://discourse.itk.org/u/Vladimir_Fonov)\
**Post date:** [January 9, 2020, 3:04pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/10 "2020-01-09T15:04:33Z")

</div>

Ok, so , just to clarify - I tried restoring the original behaviour of Analyze reader , from ITK 4.XX, that got obsoleted by NIFTI reader: [https://github.com/InsightSoftwareConsortium/ITK/blob/release-4.13/Modules/Compatibility/Deprecated/src/itkAnalyzeImageIO.cxx#L1033](https://github.com/InsightSoftwareConsortium/ITK/blob/release-4.13/Modules/Compatibility/Deprecated/src/itkAnalyzeImageIO.cxx#L1033)

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 3:12pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/11 "2020-01-09T15:12:01Z")

</div>

> [@Vladimir\_Fonov](#):
>
> I tried restoring the original behaviour of Analyze reader , from ITK 4.XX, that got obsoleted by NIFTI reader

OK, so the flag in nifti reader could be called “AnalyzeCompatibility” or something like that. It could be also possible to keep around a simple AnalyzeImageIO class, which would be derived from NiftiImageIO and it would set the AnalyzeCompatibility flag to true in its constructor and otherwise it would be empty.

---

<div class="post-metadata">

**Author:** ![Vladimir\_Fonov](https://discourse.itk.org/user_avatar/discourse.itk.org/vladimir_fonov/32/247_2.png) [@Vladimir\_Fonov](https://discourse.itk.org/u/Vladimir_Fonov)\
**Post date:** [January 9, 2020, 3:12pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/12 "2020-01-09T15:12:19Z")

</div>

```
nifti_tool -disp_ana -infile avg152T1_LR-marked.hdr
...
pixdim 76 8 0.0 -2.0 2.0 2.0 0.0 0.0 0.0 0.0
...
orient 252 1 0
...

```

So, based on what [http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm](http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm) says

the actual interpretation of what it means depends on the software (i.e FSL ignores negative dimension sizes, and SPM would flip voxel order ).

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 3:14pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/13 "2020-01-09T15:14:04Z")

</div>

> [@Vladimir\_Fonov](#):
>
> the actual interpretation of what it means depends on the software (i.e FSL ignores negative dimension sizes, and SPM would flip voxel order ).

Maybe then we could add an enum instead of flag to specify file format variant: Nifti, AnalyzeFSL, AnalyzeSPM.

---

<div class="post-metadata">

**Author:** ![Vladimir\_Fonov](https://discourse.itk.org/user_avatar/discourse.itk.org/vladimir_fonov/32/247_2.png) [@Vladimir\_Fonov](https://discourse.itk.org/u/Vladimir_Fonov)\
**Post date:** [January 9, 2020, 3:15pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/14 "2020-01-09T15:15:48Z")

</div>

> [@lassoan](#):
>
> Maybe then we could add an enum instead of flag to specify file format variant: Nifti, AnalyzeFSL, AnalyzeSPM.

I don’t think there is a way to find out which flavour of Analyze it is.

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 3:18pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/15 "2020-01-09T15:18:31Z")

</div>

> [@Vladimir\_Fonov](#):
>
> I don’t think there is a way to find out which flavour of Analyze it is.

Exactly. That’s why the behavior would not be hardcoded in the IO class but it would be an enum that applications can set (based on application preferences, user choice, some heuristics, etc.).

---

<div class="post-metadata">

**Author:** ![Vladimir\_Fonov](https://discourse.itk.org/user_avatar/discourse.itk.org/vladimir_fonov/32/247_2.png) [@Vladimir\_Fonov](https://discourse.itk.org/u/Vladimir_Fonov)\
**Post date:** [January 9, 2020, 3:20pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/16 "2020-01-09T15:20:16Z")

</div>

OK, but ITK 5.0 was neither SPM or FSL, so it would be AnalyzeITK5.0 ?

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.itk.org/user_avatar/discourse.itk.org/lassoan/32/27_2.png) [@lassoan](https://discourse.itk.org/u/lassoan)\
**Post date:** [January 9, 2020, 3:37pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/17 "2020-01-09T15:37:35Z")

</div>

In Slicer, ITK has been reading img+hdr files for 10+ years the same way. For us, nothing has changed until your recent commit. Maybe the behavior depended on how you initialized ITK image IO factories and you somehow ended up using AnalyzeImageIO, while Slicer always ended up using NiftiImageIO.

The file format variant can be called Nifti, AnalyzeITK5, etc., whatever folks who use Nifty/Analyze find the most informative.

---

<div class="post-metadata">

**Author:** ![hjmjohnson](https://discourse.itk.org/user_avatar/discourse.itk.org/hjmjohnson/32/23_2.png) [@hjmjohnson](https://discourse.itk.org/u/hjmjohnson)\
**Post date:** [January 9, 2020, 3:38pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/18 "2020-01-09T15:38:17Z")

</div>

Clarification: These images are _NOT_ nifti formatted images. They are ancient analyze formatted images, and there is/has always been some irreconcilable ambiguities how those analyze files were written.

The FSL/SPM/ and various laboratories interpret the field names differently. The NIFTI format attempted to address and document one accepted format (for which it partially succeeded).

Regarding the commit that was provided, I think it should be reverted in ITK. Only 1/2 of the community will be satisfied with any default value that is chosen for reading these ancient analyze files.

---

<div class="post-metadata">

**Author:** ![Vladimir\_Fonov](https://discourse.itk.org/user_avatar/discourse.itk.org/vladimir_fonov/32/247_2.png) [@Vladimir\_Fonov](https://discourse.itk.org/u/Vladimir_Fonov)\
**Post date:** [January 9, 2020, 3:49pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/19 "2020-01-09T15:49:03Z")

</div>

> [@lassoan](#):
>
> In Slicer, ITK has been reading img+hdr files for 10+ years the same way.

The ITK Analyze Reader was deprecated since 9 years ago. But it was used when ITKV3\_COMPATIBILITY was enabled in ITK 4.XX , I think.

Maybe we can introduce ITKV3\_ANALYZE\_COMPATIBILITY Cmake Flag?

---

<div class="post-metadata">

**Author:** ![hjmjohnson](https://discourse.itk.org/user_avatar/discourse.itk.org/hjmjohnson/32/23_2.png) [@hjmjohnson](https://discourse.itk.org/u/hjmjohnson)\
**Post date:** [January 9, 2020, 3:49pm UTC](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594/20 "2020-01-09T15:49:59Z")

</div>

Here is my suggestion.

Add a flag to the NIFTIIO reader that is based on the following enumeration:

enum class Analyze75FormatCompatibility  
{  
REJECT=0, //NiftiIO will not read analyze 7.5 formatted files  
FSL\_CONVENTIONS=1, //NiftiIO will read and use implied directions based on old FSL conventions  
SPM\_CONVENTIONS=2 //NiftiIO will read and use implied directions based on old SPM/AFNI conventions  
}

If the image does not have the “magic” string at byte #344 that indicates that it is a modern nifti file (i.e. it is an old Analyze file), then ITK should NOT READ THE FILE BY DEFAULT, and the CanRead() function should return false.

I don’t have time to work on this at the moment.

NOTE: This was discussed/argued about extensively, and the current behavior was weakly agreed upon nearly a decade ago. I prefer “breakage with explicit messaging” to quiet behavior change.

[Next page](https://discourse.itk.org/t/nifti-file-orientation-change-between-2019-08-26-and-itk-v5-1rc01/2594.md?page=2)
