Tuesday, June 27, 2023

Getting Oriented using the Image Plane Module

Just before diving into how to get oriented using the Image Plane Module, so we can put the letters right in our viewer, I want to get equipped with few more latin words so we understand what Radiologists are mumbling. If you're a Doctor, please be patient with us programmers. 

Cuts! Three major cuts we have (or planes): 

Transverse (AKA Axial) divides head from feet
Axial Cut

Sagittall Cut - right between the eyes
Sagittal Cut

and Coronal Cut - the Filet
Coronal Cut

And now that we're done with Anatomy let's do some Geometry. In this post I'm going to start explaining the use of the Image Plane Module. To refresh on Modules read chapter 4 of the DICOM Tutorial. The Image Plane module is part of the CT Image IOD and the MR Image IOD and any other object that have a frame of reference, i.e. that has a spatial coordinates system related to the patient or in other words is a 3D scan of the body.

The Image Plane Module (in page 409 of part 3 of the standard) defines the direction of the image with respect to the patient body and mapping between the pixels in the image plane and the patient. It also gives the dimensions of the pixels (or voxels if you like) in mm. Note that with this module you can measure distances between voxels but not absolute positions because there's no anchor to the coordinate system within the patient body. Such anchor or marker is called Fiducial in image processing.

The reminder of this post is about a single attribute of the Image Plane Module: Tag (0020,0037), Image Orientation (Patient). We'll also get to know 

DICOM defines a term: "Reference Coordinates System" or RCS.  The RCS is a very intuitive coordinate system of the patient body: X direction is from Right to Left. So if the patient is standing in front of you with the arm raised to the sides, then X direction is from the right hand to the left hand.
Y direction is from front to back or medical-wise from Anterior to Posterior so if the patient is standing in front of you so you see him/her from his/her left side, then Y goes from your left to your right (confusing? look at the picture).
Z direction goes from Feet to Head. At least this is simple to explain.
Now that we know the directions, there are letters assigned to the ends of each direction:

[R] - Right - The direction in which X decreases. 
[L] - Left - The direction in which X increases. 
[A] - Anterior - The direction in which Y decreases. 
[P] - Posterior - The direction in which Y increases. 
[F] - Feet - The direction in which Z decreases. 
[H] - Head - The direction in which Z increases.

Simple?! Now we can figure out the small letters on the sides of the DICOM Viewer. They can combine too. For example in this picture taken from part 17 of the standard (the explanatory part, a must read):
Transverse Plane with patient looking at 45 deg.

This is a transverse cut with oblique patient, of course, ha?! Lets look at the letters: L is left of the patient. R is Right of the patient. P is posterior (back) and A is Anterior (Front). So this miserable patient was cut in half right through his chest (you can see the shadow of his hurt and a Thoracic Vertebrae). His feet is pointing in the direction of your nose and his head is on the other side of your screen where hopefully there's a pale Apple shaped white neon light glowing in the dark.

From some reason this patient is not in line with the image. He's Oblique to the image frame so that's more interesting because we have these two letters combinations - [PR] for posterior right and [RA] for Right Anterior. 

It can get worse and we can have three letters combinations for example [PRF] for [Posterior Right Feet] if the cut was oblique too and the side where the PR is now would have been closer to your nose then the side where the AL is that would then be ALH (figure this one yourself).

The DICOM Tag (0020,0037) is "Image Orientation (Patient)". It should always have 6 values (VM = 6). It's two Normalized 3D vectors(i.e. directions). The first one we will call X and it has three components (Xx, Xy, Xz) and the second one is Y and strangely it has three components too (Yx, Yy, Yz). Xx is the projection of X on x Axis, Xy is the projection (or Cosine) of X on y Axis and so on. These are direction cosines of the image plane relative to the RCS. The first direction is the direction of the image rows in the RCS and the second direction is the direction of the image columns in the RCS.

Lets do an example. Say you got a DICOM CT Image. When you read the value of (0020,0037) good chances it will be 1\0\0\0\1\0. The X vector is (1,0,0) meaning it is exactly directed with the image pixel matrix row direction and the Y vector is (0,1,0) meaning it is exactly directed with the image pixel matrix column direction.

The following pictures explains what this means:
What we have here is the pixel data matrix in black. On the top left is pixel (0,0) and at the bottom right, pixel (512, 512) (please forgive me that the pixels are not square. It's OK in DICOM). So That's the image. Now we have the patient coordinate system in Red. So the coordinate system of the image is exactly in the same direction of the coordinate system of the patient. The image plane is parallel to the patient Axial Plane. So now we can put the letters. R at the begging of X axis, L at the end of the X Axis, A at the beginning of Y Axis and P at the end of Y Axis.

Lets do another example and take the traverse oblique example from above.

The patient's X axis directed from right to left is (√1/2,√1/2,0) and The patient's Y axis is directed from Anterior to Posterior (front to back) is (√1/2,√1/2,0). As you can see because the RCS is a right hand side coordinates system, if you turn X right, towards Y, you tighten Z directly into the screen so the head of the patient is indeed away from you. In this example the value of (0020,0037) should be 0.707\0.707\0\0.707\0.707\0.

Let's do the other way round. You get a DICOM file with (0020,0037) = 0.5\0\-0.8660254\0\1\0.
Now you need to draw the image and put the letters on the screen. How do you do this? Here's how the image looks like when you display it on screen.
Put the right letters for (0020,0037) = 0.5\0\-0.8660254\0\1\0
The First vector (0.5,0,-0.8660254) is the direction of the image rows in the RCS.

The Second vector (0,1,0) is the direction of the image columns in the RCS.

Note that  0.5 is cos(600) and -0.8660254 is cos(1500).

So if we try to draw the RCS X Direction, it is

The First vector is (0.5,0,-0.8660254) is the direction of the image rows in the patient coordinate system. 0.5 is cos(600) and -0.8660254 is cos(1500). So the image rows are rotated 600 from the patient's X direction (right-to-left) and 1500 from the patient's Z direction (feet-to-head) and the patient's Y direction is perpendicular to the image X axis.

The second vector is (0,1,0) and is the direction of the image columns in the patient coordinate system. So the Y axis of the patient (front-to-back) is in the same direction as the Y axis of the patient. So we can now draw the projections of the patient coordinate axes on the image and mark the the letters.

We put the [A] at the negative side of Y, The [P] at the positive side of Y and so on. You can see that I've unified H and R to [HR] and F and L to [FL]. That's it.
Here's the last image from the explanatory part with the image plane shown exemplified.

Now we can write the algorithm for marking the letters but let's leave something for the next post or as Homework.


  1. In the 45 degree example shouldn't the x component of the column vector be negative? The way it is presented now the col and row vectors are equivalent which should never be the case since they are supposed to be orthogonal.

    1. Yes, you're right.
      It should have been -0.707/0.707/0.
      I'll fix it

    2. I believe the X vector should be (0.707/-0.707/0) the Y vector is correct as (0.707/0.707/0). This is because up in our CT frame of reference is negative.

    3. Was this correction made? I'm confused

    4. This comment has been removed by the author.

    5. wait - which is correct? It doesn't seem like any change was made to the example.

    6. wait - which is correct? It doesn't seem like any change was made to the example.

    7. The 45 degree example is provided as text and image (0.707/0.707/0 which is incorrect), none of them were corrected until this moment. However what Roni said is correct, it should be -0.707/0.707/0 to reflect RP.

    8. The 45 degree example is provided as text and image (0.707/0.707/0 which is incorrect) and none of them were corrected until this moment. However what Roni said is correct and it should be -0.707/0.707/0 which reflects RP.

  2. In the sentence, "On the top left is pixel (0,0) and at the bottom right, pixel (512, 512)" don't you mean the bottom right pixel is (511, 511) since we are talking about 512 pixels in each direction but starting or counting at 0, not 1?

  3. Hi,
    in this article talk about scout image which help physician to figure out the disk number in lumbar MRI.
    my question is:
    How you can set lines in scout image?
    which elements tell you where are the lines?

    1. You should calculate reference line by yourself.

  4. I have a question. ¿The ImagePositionPatient have to have the same value for each series (T2, T1, DWI, etc.)?

  5. The orientation data only gives the orientation, but how do I know where exactly the slice is. For example, let's assume that there are 200 slices of the head, and are purely sagittal (0,1,0,0,0,-1), how do we know if the sweep was done from left to right, or right to left?

    1. The Image Position (Patient) field will give you "where exactly the slice is," in space, but it won't tell you which direction the sweep was done. Maybe there are some private tags for your specific scanner?

    2. There doesn't have to be order in series images. I have series of CT images where sweep was done head to foot and back in one pass. Cardiac CT series can have time series where multiple images are done on same image position. On MRI it is common that first series is localizer series where 3 images are perpendicular to each other.

  6. I have a question:
    I have a Volume DICOM CT where the 3rd value of (0020,0032) is positive (809) and the value of (0020,1041) is negative (-809) and so on for all CT-Slices. I do not understand which is the position of my slice in z-direction.
    Thanks in advance

    1. Slice location is type 3 attributes. So it may or may not be present. Image Position patient is type 1, so you should use Image Position Patient if possible.
      The point that slice location is negative in your case has no meaning because it is relative to an unknown plane as the standard states. So you can translate it in whatever direction, add or subtract a constant for it, it still doesn't change the sort order. When it is present, you can just sort by its value. Better use Image position patient though

  7. So, I have another question:
    Now that a negative slice location means a lower location relative to an standard states, then how does the DICOM define this standard states? or is defined by the CT machine factory

    1. I'm not sure I understand the question, but DICOM doesn't define the origin of the coordinate system. The goal is to define a common coordinate system for all images within a series (or across series). The origin point has no meaning.

  8. I have a small query can any one help, in Multi-frame images like NM,US and XA is we can find the orientation ? because those scans doesn't have the (0020,0032) and (0020,0037) tags.

  9. this helped a lot with gcse homework

  10. Is the [0,0,0] the patient's isocenter (x,y, is the fixed center of the circular bore, where z=0 is where "0" is marked on patient)?

    Here is a real example:


    How to draw this slice (plan) in the dicom coordinates?

  11. You spelt Sagittal wrong in the picture area at the top.

  12. You spelt Sagittal wrong at the image section at the top

  13. Thanks so much for this great post!
    I think I've got this figured out (making a DICOM exporter script for a commercial Radiation Oncology Treatment Planning system), would this be correct?
    FeetFirstDecubitusLeft: { 0, 1, 0, -1, 0, 0 }
    FeetFirstDecubitusRight: { 0, -1, 0, 1, 0, 0 }
    FeetFirstProne: { 1, 0, 0, 0, -1, 0 }
    FeetFirstSupine: { -1, 0, 0, 0, 1, 0 }
    HeadFirstDecubitusLeft: { 0, 1, 0, 1, 0, 0 }
    HeadFirstDecubitusRight: { 0, -1, 0, -1, 0, 0 }
    HeadFirstProne: { -1, 0, 0, 0, -1, 0 }
    HeadFirstSupine: { 1, 0, 0, 0, 1, 0 }
    Sitting: { ??? }
    NoOrientation: { ??? }

  14. I have one question about dicom informations. How can I establish the link between X,Y,Z directions and M,P,S directions from dicom informations ?
    Thanks a lot for your help

    1. I’m not sure I understand what are the “m, p, s directions”

  15. Is it possible t make ou the view(axial,coronal)from the orientation vector when it is oblique

  16. Hi , i have to draw a line on scout image to indicate the position of a slice. example: "slice location" is 26.500 and "image position" is -209.500\-193.000\26.500. The "z" has a reference point, but where is it ?
    Thanks for help !

  17. Hi, I can plot the dicom slice image on x-y plane but how can I draw the images in x-z and y-z plane? Is there any possible function in python that can be directly use to achieve my goal? Thx

  18. Thank you very useful. But what happens if you get a dicom with a bad orientation. So the head is a bit twisted once you have applied the orientation?. Thanks

  19. Is it possible to show ,where a particular DICOM slice is present in a 3D surface rendered output using this Image Position(0020,0032),Image Orientation(0020,0037) and Slice Location(0020,1041) and any other DICOM tags?

  20. Is it possible to show ,where a particular DICOM slice is present in a 3D surface rendered output using this Image Position(0020,0032),Image Orientation(0020,0037) and Slice Location(0020,1041) and any other DICOM tags?

    I have tried building a 4x4 matrix by Image Position(0020,0032),Image Orientation(0020,0037) and set that to vtkActor's SetUserMatrix() function.But it is not showing the desired output.

  21. thanks a lot for the article! very useful!

  22. how to find out dicom origin. which tag contains this information.