# Question about the affine transform

**URL:** <https://community.mrtrix.org/t/question-about-the-affine-transform/7990>\
**Category:** Uncategorized\
**Created:** [October 15, 2024, 10:08pm UTC](https://community.mrtrix.org/t/question-about-the-affine-transform/7990 "2024-10-15T22:08:45Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rveltz](https://community.mrtrix.org/letter_avatar_proxy/v4/letter/r/eb8c5e/32.png) [@rveltz](https://community.mrtrix.org/u/rveltz)\
**Post date:** [October 15, 2024, 10:08pm UTC](https://community.mrtrix.org/t/question-about-the-affine-transform/7990/1 "2024-10-15T22:08:45Z")

</div>

Hi,

Thank you for your amazing library. I am impressed by the functionalities and the speed.

I am trying to understand what the affine transform is doing. I have a `nii` file with following information:

```auto
shell> mrinfo -all fodf.nii
************************************************
Image name: "fodf.nii"
************************************************
  Dimensions: 145 x 174 x 145 x 45
  Voxel size: 1.25 x 1.25 x 1.25 x 1
  Data strides: [-1 2 3 4]
  Format: NIfTI-1.1
  Data type: 32 bit float (little endian)
  Intensity scaling: offset = 0, multiplier = 1
  Transform: 1 0 0 -90
                               -0 1 0 -126
                               -0 0 1 -72
  comments: FSL5.0
  mrtrix_version: 3.0.4

```

NIBabel reports the following affine transform

```python
array([[-1.25, 0. , 0. , 90.],
       [0. , 1.25, 0. , -126.],
       [0. , 0. , 1.25, -72.],
       [0. , 0. , 0. , 1.]])

```

From mrview, I can see the following:

```auto
voxel index: [85, 62, 64, 0]
position = [16.38, -48.68, 8.507]

```

Doing `affine @ np.array([85, 62, 64, 1])`, I get:

```python
 array([-16.25, -48.5 , 8. , 1.])

```

which looks quite similar to `position` but there is a minus discrepancy in front of the x value.

How come mrtrix gives this sign?

Thank you a lot for your help,

Best regards

---

<div class="post-metadata">

**Author:** ![jdtournier](https://community.mrtrix.org/user_avatar/community.mrtrix.org/jdtournier/32/2594_2.png) [@jdtournier](https://community.mrtrix.org/u/jdtournier)\
**Post date:** [October 16, 2024, 2:02pm UTC](https://community.mrtrix.org/t/question-about-the-affine-transform/7990/2 "2024-10-16T14:02:41Z")

</div>

Hi @rveltz,

This is indeed one of the most common sources of confusion amongst users. I’ll try to give a brief explanation, but I have a feeling it’ll end up huge anyway… Here goes:

First off, have a look at [our documentation for how we handle the transform information](https://mrtrix.readthedocs.io/en/latest/getting_started/image_data.html#the-image-transfom). You’ll note two ways our handling differs from straight NIfTI (and by extension, other packages, including NIBabel):

- the transform we report is a _unitary_ transformation, without the scaling by the voxel size. You can see the voxel size is 1.25 isotropic, but you can also see that this is included in the diagonal of the sform reported by NIBabel¹. In MRtrix, we store the transform as a unitary matrix giving the _unit_ vectors for each axis, _indepedent_ of the voxel size.

- We perform an [internal ‘reshuffling’ of the transform](https://mrtrix.readthedocs.io/en/latest/getting_started/image_data.html#interaction-between-strides-and-transform) to convert it to a near-axial form, where the _x_ axis is closest to anatomical left → right, the _y_ axis is closest to anatomical posterior → anterior, and the _z_ axis is closest to anatomical inferior → superior. We can do that because [we have the flexibility to manipulate the _strides_](https://mrtrix.readthedocs.io/en/latest/getting_started/image_data.html#strides) – and you can see, the strides reported by `mrinfo` include a -1 along the _x_ axis, indicating that the voxels are stored right → left (not the true NIfTI standard frame, but equivalent to the older Analyze format)².

So that should account for all the differences you see. For that last discrepancy in position, the voxel index you’re using is _not_ equivalent between MRtrix and NIBabel: NIBabel would index strictly along the axis specified in the NIfTI transform, which runs right → left, whereas MRtrix would index along the axis it has identified as closest to left → right (in this case, it is pure left → right since your transform is pure axial).

I expect you’ll get the equivalent real position is you use voxel index with the _x_ component = xdim-1-x = 145-1-85 = 59 for NIBabel. I also recommend you turn off linear interpolation in `mrview`, in which case you should get the position of the nearest voxel, rather than the exact position of the crosshairs.

Hopefully that’ll clear up any confusion… 😕  
All the best,

Donald.

* * *

¹ By the way, the voxel size is _not_ be encoded in the NIfTI qform, since it can only represent a pure rigid rotation – so there’s a discrepancy between the sform & the qform anyway, even though both encode the transform…

² Alternatively, you might see this described as _FSL-style_, _radiological convention_, or LAS – whereas a pure NIfTI might be labelled as _neurological convention_ or RAS (beware the terms _radiological_ & _neurological_ in this context though, they really aren’t the right way to think about it – but it’s often how people talk about it…).

---

<div class="post-metadata">

**Author:** ![rveltz](https://community.mrtrix.org/letter_avatar_proxy/v4/letter/r/eb8c5e/32.png) [@rveltz](https://community.mrtrix.org/u/rveltz)\
**Post date:** [October 16, 2024, 3:35pm UTC](https://community.mrtrix.org/t/question-about-the-affine-transform/7990/3 "2024-10-16T15:35:28Z")

</div>

Thank you a lot for your detailed answer. It makes more sense. Indeed

```auto
affine @ np.array([59, 62, 64, 1]),

```

reports the mrview result.

I need to read your links now.

Best regards
