# Understanding Sort and Orientation via CosineValues

**URL:** https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839
**Category:** Engineering
**Created:** [February 4, 2021, 9:07pm UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839 "2021-02-04T21:07:24Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![Akshay\_Goel](https://discourse.itk.org/user_avatar/discourse.itk.org/akshay_goel/32/1878_2.png) [@Akshay\_Goel](https://discourse.itk.org/u/Akshay_Goel)
#### Post date: [February 4, 2021, 9:07pm UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839/1 "2021-02-04T21:07:24Z")

</div>

Hello all,

I am trying to further understand how itk handles sort.

It seems like the foundation is calculating a normal vector in:

`Common/ExtendedGDCMSerieHelper.cxx`

```auto
      cosines = ImageHelper::GetDirectionCosinesValue( **it );

      // You only have to do this once for all slices in the volume. Next,
      // for each slice, calculate the distance along the slice normal
      // using the IPP ("Image Position Patient") tag.
      // ("dist" is initialized to zero before reading the first slice) :
      normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
      normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
      normal[2] = cosines[0]*cosines[4] - cosi*emphasized text*nes[1]*cosines[3];

```

Is there documentation in dicom docs or somewhere else on how this is working? I have seen many people ask a similar question on sorting so I would love to understand this solution as it seems robust against all orientations including obliques.

Thanks for any insights!

---

<div class="post-metadata">

### Author: ![mihail.isakov](https://discourse.itk.org/letter_avatar_proxy/v4/letter/m/c4cdca/32.png) [@mihail.isakov](https://discourse.itk.org/u/mihail.isakov)
#### Post date: [February 4, 2021, 10:49pm UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839/2 "2021-02-04T22:49:20Z")

</div>

```auto
normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];

```

It is cross product, calculated using 6 values in “Image Orientation (Patient)”.  
S. [C.7.6.2.1.1](http://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.7.6.2.html#sect_C.7.6.2.1.1)

Your code seems to be from ITK-Snap, but that part with plane’s normal is everywhere the same.

---

<div class="post-metadata">

### Author: ![Akshay\_Goel](https://discourse.itk.org/user_avatar/discourse.itk.org/akshay_goel/32/1878_2.png) [@Akshay\_Goel](https://discourse.itk.org/u/Akshay_Goel)
#### Post date: [February 5, 2021, 12:34am UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839/3 "2021-02-05T00:34:10Z")

</div>

Thanks. That’s really helpful @mihail.isakov.

To confirm my understanding – the normal a vector in x, y, z expressing the vector across which the imaging plane is changing then? For an axial stack this would point purely in the z direction?

---

<div class="post-metadata">

### Author: ![Akshay\_Goel](https://discourse.itk.org/user_avatar/discourse.itk.org/akshay_goel/32/1878_2.png) [@Akshay\_Goel](https://discourse.itk.org/u/Akshay_Goel)
#### Post date: [February 5, 2021, 3:58am UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839/4 "2021-02-05T03:58:20Z")

</div>

Some Google searching gave me the answer, from the original author I believe!

[https://itk.org/pipermail/insight-users/2003-September/004762.html](https://itk.org/pipermail/insight-users/2003-September/004762.html)

```auto
The steps I take when reconstructing a volume are these: First,
calculate the slice normal from IOP:

normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];

You only have to do this once for all slices in the volume. Next, for
each slice, calculate the distance along the slice normal using the IPP
tag ("dist" is initialized to zero before reading the first slice) :

for (int i = 0; i < 3; ++i) dist += normal[i]*ipp[i];

Then I order the slices according to the value "dist". Finally, once
I've read in all the slices, I calculate the z-spacing as the difference
between the "dist" values for the first two slices.

```

---

<div class="post-metadata">

### Author: ![mihail.isakov](https://discourse.itk.org/letter_avatar_proxy/v4/letter/m/c4cdca/32.png) [@mihail.isakov](https://discourse.itk.org/u/mihail.isakov)
#### Post date: [February 5, 2021, 12:45pm UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839/5 "2021-02-05T12:45:33Z")

</div>

> [@](#):
>
> You only have to do this once for all slices in the volume.  
> …  
> I calculate the z-spacing as the difference between the “dist” values for the first two slices.

Yes, but good idea is not to forget that prerequisite for this is that all slices in series have same “Image Orientation (Patient)”, are equidistant and there is no tilt. It is not always true. But it is rather advanced topic, different applications handle non-uniform series in different ways (or don’t handle).

---

<div class="post-metadata">

### Author: ![Akshay\_Goel](https://discourse.itk.org/user_avatar/discourse.itk.org/akshay_goel/32/1878_2.png) [@Akshay\_Goel](https://discourse.itk.org/u/Akshay_Goel)
#### Post date: [February 5, 2021, 9:31pm UTC](https://discourse.itk.org/t/understanding-sort-and-orientation-via-cosinevalues/3839/6 "2021-02-05T21:31:38Z")

</div>

@mihail.isakov

Thank you! Yes my objective is to have a continuous volume of the images if the IOP information is there. Small non-uniformity is not a major issue for my purposes.
