<div dir="ltr">Hello Matthew & Steven<div><br></div><div>Alright, I am not sure what to make of this because the ImagePositionPatient for the part of the scan I am interested in seems to be a vector that cuts across the space diagonally. I am trying to take Steve's viewpoint here, as it looks like the "easiest" too (just rotate the "track" to align to one of the axes).</div><div><br></div><div>The values of ImagePositionPatient are:</div><div><br></div><div><div>array([[-127.773 , -105.599 ,  -94.5758],</div><div>       [-127.841 , -106.584 ,  -90.1855],</div><div>       [-127.91  , -107.569 ,  -85.7951],</div><div>       [-127.978 , -108.554 ,  -81.4048],</div><div>       [-128.046 , -109.539 ,  -77.0145],</div><div>       [-128.115 , -110.524 ,  -72.6241],</div><div>       [-128.183 , -111.509 ,  -68.2338],</div><div>       [-128.251 , -112.494 ,  -63.8435],</div><div>       [-128.32  , -113.479 ,  -59.4531],</div><div>       [-128.388 , -114.464 ,  -55.0628],</div><div>       [-128.456 , -115.449 ,  -50.6725]])</div></div><div><br></div><div>And the 3d plot of that is available further below</div><div><br></div><div><img src="cid:ii_15723892a9e9e920" alt="Inline image 1" style="margin-right: 0px;" width="562" height="267"></div><div><br></div><div>They are all regular (good) and all intermediate slice thicknesses are the same (double good).</div><div><br></div><div>Now, the "trouble" with this is that this represents the direction of one of the axes. Let's call it the Z axis. The other two define a plane that is perpendicular to this direction. I can rotate the axes so that this "Z" is aligned with one of the Zs in space.</div><div><br></div><div>The other thing that is a bit of a "problem" here of course is the third dimension of my ROI data. Because so far, in my preliminary tests, I have been ignoring it. This means, that just by looking at X,Y, I may have been seeing something that is distorted. And looking at this track, I may be seeing something that is thinner on the vertical projection than it really is although the increases in 2/3 axes are small.</div><div><br></div><div>Can I please ask the following:</div><div><br></div><div>1) Am I right to assume that the ROI data are perpendicular to this "track"?</div><div><br></div><div>2) All I have to do now then, is workout a rotation around Z and Y (or, 2/3 axes) to make this track parallel to one of the axes (?) and then apply that transformation to the ROIs so that, when I set them on the image (which is always properly alligned), it appears to be properly aligned. (By the looks of this, -45 deg around Z, -45 around Y and I am there.</div><div><br></div><div>3) How does the DICOM rotation data relate to this track? (If at all).</div><div><br></div><div>4) Is there an API (or part of an API) for a [DICOM Data Type].getPixel or [DICOM Data Type].getVoxel kind of operation? Even if it is via a class ecosystem that is making sense within the context of Slicer or other piece of software. The problem here is that I don't have a volumetric DICOM (Multiple images single file). I have a ROI DICOM that references individual images. So, I build my own volume aware data type (based on pydicom) that will implement its getVoxel method and is aware of a few other things I am going to be doing with these volumes. But if this is already done somewhere, maybe I could re-use it (?).</div><div><br></div><div>Looking forward to hearing from you<br></div><div>AA</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Sep 8, 2016 at 9:37 PM, Athanasios Anastasiou <span dir="ltr"><<a href="mailto:athanastasiou@gmail.com" target="_blank">athanastasiou@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><p dir="ltr">Hello Matthew & Steven</p>
<p dir="ltr">Thank you for your email. Of course I am missing the third column :( I am paying too much attention on the two numbers I am after right now, to bring the contour right where it should be when plotting it over the image.</p>
<p dir="ltr">Thank you for your help, I will have another go at establishing the matrix with the helpful comments provided here.</p>
<p dir="ltr">All the best<span class="HOEnZb"><font color="#888888"><br>
AA</font></span></p><div class="HOEnZb"><div class="h5">
<div class="gmail_extra"><br><div class="gmail_quote">On 6 Sep 2016 18:25, "Matthew Brett" <<a href="mailto:matthew.brett@gmail.com" target="_blank">matthew.brett@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
On Tue, Sep 6, 2016 at 6:34 AM, Steve Pieper <<a href="mailto:pieper@isomics.com" target="_blank">pieper@isomics.com</a>> wrote:<br>
> Hi Athanasios -<br>
><br>
> To get the scan direction you'll need to look at the relative<br>
> ImagePositionPatient points from slice to slice.  Note that the scan<br>
> direction is not always the cross product of the row and column orientations<br>
> since the scan may go in the other direction from a right handed cross<br>
> product or the slices can be sheared (or even at arbitrary locations)..<br>
> There are lots of other things that can happen too, like irregular spacing,<br>
> missing slices, etc, but usually just normalizing the vector between your<br>
> origin and any slice in the scan will be what you want.<br>
><br>
> This code will give you an idea:<br>
><br>
> <a href="https://github.com/Slicer/Slicer/blob/master/Modules/Scripted/DICOMPlugins/DICOMScalarVolumePlugin.py#L195-L216" rel="noreferrer" target="_blank">https://github.com/Slicer/Slic<wbr>er/blob/master/Modules/Scripte<wbr>d/DICOMPlugins/DICOMScalarVolu<wbr>mePlugin.py#L195-L216</a><br>
><br>
<br>
>From your code, you are missing a valid third column for your affine.<br>
I believe that column will be all zeros from your code. This is what<br>
the later part of the DICOM orientation page is talking about, and<br>
what Steve is referring to as the "slice direction".<br>
<br>
Steve is quite right that the slice direction need not be the<br>
cross-product of the first two, and the DICOM information can often<br>
tell you what that slice direction vector is, but assuming for a<br>
moment that it is the cross product, and that you are looking at the<br>
first slice of the volume, then you'd want something like:<br>
<br>
"""<br>
import numpy as np<br>
<br>
ImageOrientationPatient = [0.999857, 0.00390641, 0.0164496,<br>
                           -0.00741602, 0.975738, 0.218818]<br>
<br>
ImagePositionPatient = [-127.773, -105.599, -94.5758]<br>
<br>
PixelSpacing = [0.4688, 0.4688]<br>
<br>
slice_spacing = 3.0  # ?<br>
<br>
# Make F array from DICOM orientation page<br>
F = np.fliplr(np.reshape(ImageOrie<wbr>ntationPatient, (2, 3)).T)<br>
rotations = np.eye(3)<br>
rotations[:, :2] = F<br>
# Third direction cosine from cross-product of first two<br>
rotations[:, 2] = np.cross(F[:, 0], F[:, 1])<br>
# Add the zooms<br>
zooms = np.diag(PixelSpacing + [slice_spacing])<br>
<br>
# Make the affine<br>
affine = np.diag([0., 0, 0, 1])<br>
affine[:3, :3] = rotations.dot(zooms)<br>
affine[:3, 3] = ImagePositionPatient<br>
<br>
np.set_printoptions(precision=<wbr>4, suppress=True)<br>
print(affine)<br>
"""<br>
<br>
But - Steve's suggestion is more general - this code is just to give<br>
you an idea.<br>
<br>
Best,<br>
<br>
Matthew<br>
______________________________<wbr>_________________<br>
Neuroimaging mailing list<br>
<a href="mailto:Neuroimaging@python.org" target="_blank">Neuroimaging@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/neuroimaging" rel="noreferrer" target="_blank">https://mail.python.org/mailma<wbr>n/listinfo/neuroimaging</a><br>
</blockquote></div></div>
</div></div></blockquote></div><br></div>