<div dir="ltr">I'll briefly follow-up with a link that describes how vtkNIFTIImageReader<div>handles coordinates. The (x,y,z) it mentions are RAS.</div><div><a href="https://gitlab.kitware.com/vtk/vtk/blob/master/IO/Image/vtkNIFTIImageReader.cxx#L738">https://gitlab.kitware.com/vtk/vtk/blob/master/IO/Image/vtkNIFTIImageReader.cxx#L738</a><br></div><div><br></div><div> - David</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 18, 2018 at 1:55 PM, David Gobbi <span dir="ltr"><<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Panos,<div><br></div><div>Regarding the RASMatrix (or equivalently the QFormMatrix), there are</div><div>two ways that it can be used. The first way is to apply it directly to the</div><div>actor, e.g. actor->SetUserMatrix(reader->G<wbr>etQFormMatrix()) where the</div><div>'actor' is a vtkImageSlice object or a vtkImageActor object. This will</div><div>correctly place the data within VTK's world coordinate system, without</div><div>the need for any image filters to flip or permute the IJK coordinates.</div><div><br></div><div>A different way to use the matrix is to use it to reslice the data, i.e. use</div><div>it to perform an image reformat. The easiest way to do this is by passing</div><div>the vtkImageData through vtkImageReslice, with reslice->SetResliceAxes()</div><div>set to the inverse of the matrix. The output will be a reoriented volume,</div><div>where IJK are mapped to new directions.</div><div><br></div><div>There are special considerations needed for oblique acquisitions, and I</div><div>won't go into those here.</div><div><br></div><div><br></div><div>Regarding what the reader does, let's start with vtkNIFTIImageReader.</div><div>The IJ coordinates are the same as stored in the file. The K coordinate</div><div>is flipped of necessary to make the IJK axes follow the right-hand-rule.</div><div>This is done because it is required by the NIFTI qform, and also because</div><div>coordinate systems that don't follow the right-hand-rule are troublesome.</div><div>For more info, search for "qfac" in the NIFTI documentation or in the</div><div>docs for vtkNIFTIImageReader.</div><div><br></div><div>For vtkDICOMReader (from vtk-dicom), with SetRowOrderingToFileNative(),</div><div>it also keeps the IJ coordinates as stored in the file. As for K, it also flips</div><div>it as necessary so that the coordinates follow the right-hand-rule.</div><div>The vtkDICOMImageReader and vtkGDCMImageReader will keep IJ the<br></div><div>same if you use FileLowerLeftOn(), I won't go into how they manage K.</div><div><br></div><div><br></div><div>All of the readers store the spacing (in mm) in the vtkImageData. So you</div><div>call VTK's data coordinates (x',y',z') if you want to, but these are not RAS</div><div>coords. To get RAS coords, you need to multiply (x',y',z') by the</div><div>QFormMatrix, which will rotate them and shift them to give (x,y,z).</div><div>Moving along the 'J' data axis will only move you along the 'y' RAS axis</div><div>if the QFormMatrix encodes an identity rotation.</div><div><br></div><div>Unfortunately I don't have time to give a longer answer today, so I've left</div><div>some of your questions unanswered. But feel free to follow up if there</div><div>are things you still aren't sure about after reading this.</div><span class="HOEnZb"><font color="#888888"><div><br></div><div> - David</div></font></span><div><div class="h5"><div><br></div><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 18, 2018 at 5:20 AM, ochampao <span dir="ltr"><<a href="mailto:ochampao@hotmail.com" target="_blank">ochampao@hotmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi David,<br>
<br>
Thanks for all the information you’ve been sending. It has been very<br>
helpful. <br>
<br>
Indeed, I have confused the RAS coordinate system with the neurological<br>
convention. I also assumed that because Slicer uses RAS it automatically<br>
meant that it also used the neurological viewing convention, which is not<br>
the case. <br>
<br>
My intention with the camera configuration posted in my previous comment was<br>
to use the neurological convention because I will be displaying images of<br>
the brain (this explains why I thought that all my images appeared flipped<br>
compared to Slicer). With the RAS coordinate system and the neurological<br>
viewing convention in mind, I think the camera configuration as posted above<br>
is correct now. To be more specific, this is what I am aiming for with that<br>
camera configuration:<br>
<br>
Axial (Looking towards patient’s inferior):<br>
 * Patient's Right  <= maps to => View Right<br>
 * Patient's Anterior <= maps to => View Up<br>
 * (Patient's Superior points "outside" the screen)<br>
<br>
Coronal (Looking towards Patient's Anterior):<br>
 * Patient's Right  <= maps to => View Right<br>
 * Patient's Superior <= maps to => View Up<br>
 * (Patient's Anterior points "inside" the screen)<br>
<br>
Sagittal (Looking towards Patient's Right):<br>
 * Patient's Posterior <= maps to => View Right<br>
 * Patient's Superior <= maps to => View Up<br>
 * (Patient's Right points "inside" the screen)<br>
<br>
<<a href="http://vtk.1045678.n5.nabble.com/file/t341857/2018-05-17_14_52_58-kPlan_TPM.png" rel="noreferrer" target="_blank">http://vtk.1045678.n5.nabble.<wbr>com/file/t341857/2018-05-17_14<wbr>_52_58-kPlan_TPM.png</a>> <br>
<br>
I found the following resources very helpful:<br>
Slicer Coordinate systems <<a href="https://www.slicer.org/wiki/Coordinate_systems" rel="noreferrer" target="_blank">https://www.slicer.org/wiki/C<wbr>oordinate_systems</a>>Â <br>
and all the links therein. Especially the table ""Radiological" vs<br>
"Neurological" Orientation in Viewers" from:Â Orientation Terms<br>
<<a href="http://www.grahamwideman.com/gw/brain/orientation/orientterms.htm" rel="noreferrer" target="_blank">http://www.grahamwideman.com/<wbr>gw/brain/orientation/orientter<wbr>ms.htm</a>>Â Â <br>
<br>
Regarding the computed vtkMatrix4x4 (RASMatrix, QFormMatrix), if it is not<br>
the identity, then this means that we need to either transform the data<br>
(e.g. flip the respective axis) or apply the vtkMatrix4x4 to the respective<br>
actor?<br>
<br>
Another source of confusion was (and probably still is), what is done by the<br>
readers for us and what remains to be done by the programmer to properly<br>
display the volume. Also, if nothing is done to the reconstructed output<br>
volume of the reader, how is it positioned/oriented in VTK's world? Here is<br>
my current understanding:<br>
 * The reader loads the raw voxels which are stored in indexed/structured<br>
coordinates (scanner's i,j,k).<br>
 * The reader reconstructs the volume and transforms the uniteless (i,j,k)<br>
coordinates to (x',y',z') data coordinates with dimensions (e.g. mm):<br>
  - If, for example, the file format is using an RAS convention, then<br>
increasing i/j/k corresponds to increasing x'/y'/z' which in turn<br>
corresponds to moving towards R/A/S respectively. <br>
  - This volume is not oriented or positioned in the Patient's coordinate<br>
system yet i.e. its origin (i.e. voxel 0,0,0) is still at (0,0,0)mm and its<br>
RAS axes have not been mapped to VTK's world (X,Y,Z) coordinates.<br>
     -> This was probably my biggest point of confusion. I was assuming that<br>
even if the volume was not translated to the Patient's origin, it at least<br>
had its RAS axes mapped to VTK's positive X,Y,Z axes.<br>
  - This is actually the output of the reader i.e. the volume is still not<br>
positioned and oriented in Patient's corrdinate system but has the correct<br>
dimensions.<br>
  - The above coordinates refer to coordinates within the volume (user<br>
coordinates in VTK's terminology?).<br>
  - How is this volume positioned in VTK's world, without applying the<br>
transofmration matrix? <check this by plotting axes, and bounding box><br>
 * the reader also computes the transformation matrix for orienting and<br>
positioning the reconstructed volume. The matrix should be applied by the<br>
programmer.<br>
 * this is where the job of the reader stops<br>
<br>
 * Let's assume that the file uses RAS and that the camera is setup using<br>
the neurological viewing convnetion. Then, if the volume is displayed using<br>
a vtkImageSlice prop without applying the UserMatrix, I was expecting VTK's<br>
world (X+,Y+,Z+) to map to the volumes (R,A,S) and the origin of VTK's world<br>
to coincide with the volume' s 0,0,0. When I apply this in prctice with a<br>
volume form a Nifti file, it clearly does not work.<br>
 * This is where the computed vtkMatrix4x4 (RASMatrix, QFormMatrix) that<br>
you mentioned comes into play. <br>
  - If the top left 3x3 of the matrix is identity, it means that the RAS<br>
axes are aligned with VTK's world positive XYZ coordinates, but the origin<br>
is at (0,0,0)mm, rather at the Patient's Origin.<br>
    - If the top left 3x3 is not identiy, then we need to apply the computed<br>
vtkMatrix4x4 to the actor, or transform the data accordingly (e.g. flipping<br>
the respective dimension or maybe passing it through a vtkTransformFilter?)<br>
<br>
I apologise for the long post. I hope that the above are not completely<br>
wrong and may be helpful.<br></blockquote></div></div></div></div></div></div>
</blockquote></div><br></div>