<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<p>Hi David,</p>
<p><br>
</p>
<p>I am still confused by this. Volumes that ITK tells me have the
same bounds, VTK displays in Paraview as not having the same
bounds. <br>
</p>
<p>Consider this header from <br>
</p>
<p>vtkNIFTIImageHeader (0x221e6b0)<br>
Debug: Off<br>
Modified Time: 85<br>
Reference Count: 1<br>
Registered Events: (none)<br>
DimInfo: 0x0<br>
Dim: 3 224 153 52 1 1 1 1 <br>
PixDim: 1 0.9195 1.40018 2.89048 0 0 0 0 <br>
VoxOffset:352<br>
IntentP1: 0<br>
IntentP2: 0<br>
IntentP3: 0<br>
IntentCode: 0<br>
DataType: 2<br>
BitPix: 8<br>
SliceStart: 0<br>
SclSlope: 1<br>
SclInter: 0<br>
SliceEnd: 0<br>
SliceCode: 0<br>
XYZTUnits: 0x2<br>
CalMax: 0<br>
CalMin: 0<br>
SliceDuration: 0<br>
TOffset: 0<br>
Descrip: ""<br>
AuxFile: ""<br>
QFormCode: 2<br>
SFormCode: 1<br>
QuaternB: 0<br>
QuaternC: 0<br>
QuaternD: 1<br>
QOffsetX: 102.536<br>
QOffsetY: 106.413<br>
QOffsetZ: 30.1491<br>
SRowX: -0.9195 0 0 102.536<br>
SRowY: 0 -1.40018 0 106.413<br>
SRowZ: 0 0 2.89048 30.1491<br>
IntentName: ""<br>
Magic: "n+1"<br>
</p>
<p>That is the same as the affine from nibabel <br>
</p>
<p><br>
</p>
<p>array([[ -0.91949999, 0. , 0. ,
102.53600311],<br>
[ 0. , -1.40017998, 0. ,
106.41300201],<br>
[ 0. , 0. , 2.89048004,
30.14909935],<br>
[ 0. , 0. , 0. , 1.
]])<br>
</p>
<p><br>
</p>
<p>If you look at the SForm matrix below shouldn't the bounds be <br>
</p>
<p>X: (224-1)*-0.9195 + 102.536 = -102.51249999999999<br>
</p>
<p>Y: (153-1)*-1.40018 + 106.413 =--106.41436<br>
</p>
Z: (52-1)*2.89048 + 30.1491 = 177.56358<br>
<br>
<br>
In ITK I have checked the physical coordinates of the image and
found the bounds to be, as expected from the above,<br>
<br>
[-102.536, -106.413, 30.1491][102.512, 106.414, 177.564]<br>
<br>
In VTK I have checked the centre and origin with <br>
<br>
vtkNew<vtkNIFTIImageReader> niiReader;<br>
niiReader->SetFileName(str);<br>
niiReader->Update();<br>
int size[3];<br>
double center[3], spacing[3], bounds[6];<br>
niiReader->GetOutput()->GetDimensions(size);<br>
niiReader->GetOutput()->GetCenter(center);<br>
niiReader->GetOutput()->GetBounds(bounds);<br>
std::vector<double>
bounds_vec(&bounds[0],&bounds[6]);<br>
std::cout << bounds[0] << " " << bounds[1]
<< " " << bounds[2] << " " << bounds[3]
<< " " << bounds[4] << " " << bounds[5]
<< std::endl;<br>
niiReader->GetOutput()->GetSpacing(spacing);<br>
double center1[3] = { center[0], center[1], center[2] };<br>
double center2[3] = { center[0], center[1], center[2] };<br>
std::cout << center[0] << " " << center[1]
<< " " << center[2] << std::endl;<br>
std::cout << size[0] << " " << size[1]
<< " " << size[2] << std::endl;<br>
<br>
and get <br>
<br>
0 205.048 0 212.827 0 147.414<br>
102.524 106.414 73.7072<br>
224 153 52<br>
<br>
<div class="moz-cite-prefix">On 12/11/16 15:39, David Gobbi wrote:<br>
</div>
<blockquote
cite="mid:CANwS1=FejmtjG2=8aZzTYCXTuAfZODmEgomkLxBrcc++9kM1BA@mail.gmail.com"
type="cite">
<div dir="ltr">Hi Padraig,
<div><br>
</div>
<div>The "direction" or "orientation" is the 3x3 portion of the
4x4 matrix, after dividing out the scale.</div>
<div><br>
</div>
<div>So if ITK is giving a direction like the following, it
means that ITK allows the direction to include a mirror-flip
(in this case, it's a flip along the z-axis):</div>
<div><br>
</div>
<div>1 0 0<br>
0 1 0<br>
0 0 -1</div>
<div><br>
</div>
<div>The vtkNIFTIImageReader doesn't allow a mirror flip in the
QFormMatrix, so instead it re-orders the nifti slices in
memory to undo the flip. When it does this, it also has to
adjust the 4th column of the QFormMatrix since the 4th column
now indicates the position of the last slice in the file,
instead of the first slice in the file. The difference in
position between the first slice and the last slice is (n -
1)*sz, where n is the number of slices and sz is the slice
spacing. For your image, we can add (n - 1)*sz to -117.265 in
order to get 30.149:</div>
<div><br>
</div>
<div> -117.265 + (52 - 1)*2.89048 = 30.149</div>
<div><br>
</div>
<div>
<div class="gmail_extra">
<div class="gmail_extra">This accounts for the discrepancy.</div>
<div class="gmail_extra"><br>
</div>
<div class="gmail_extra"> - David</div>
<div class="gmail_extra"><br>
</div>
<div class="gmail_quote">On Sat, Nov 12, 2016 at 7:42 AM,
padraig <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:padraig.looney@gmail.com" target="_blank">padraig.looney@gmail.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">
<div bgcolor="#FFFFFF">
<div>
<div class="gmail-h5">
<p>Hi David,</p>
<p><br>
</p>
<p>vtkNIFTIImageHeader (0x3346680)<br>
Debug: Off<br>
Modified Time: 85<br>
Reference Count: 1<br>
Registered Events: (none)<br>
DimInfo: 0x0<br>
Dim: 3 224 153 52 1 1 1 1 <br>
PixDim: -1 0.9195 1.40018 2.89048 0 0 0 0 <br>
VoxOffset:352<br>
IntentP1: 0<br>
IntentP2: 0<br>
IntentP3: 0<br>
IntentCode: 0<br>
DataType: 2<br>
BitPix: 8<br>
SliceStart: 0<br>
SclSlope: 1<br>
SclInter: 0<br>
SliceEnd: 0<br>
SliceCode: 0<br>
XYZTUnits: 0x2<br>
CalMax: 0<br>
CalMin: 0<br>
SliceDuration: 0<br>
TOffset: 0<br>
Descrip: ""<br>
AuxFile: ""<br>
QFormCode: 2<br>
SFormCode: 1<br>
QuaternB: 0<br>
QuaternC: 0<br>
QuaternD: 1<br>
QOffsetX: 102.536<br>
QOffsetY: 106.413<br>
QOffsetZ: 30.1491<br>
SRowX: -0.9195 0 -0 102.536<br>
SRowY: 0 -1.40018 -0 106.413<br>
SRowZ: 0 0 -2.89048 30.1491<br>
IntentName: ""<br>
Magic: "n+1"<br>
<br>
The direction in ITK is</p>
<p><br>
</p>
<p>1 0 0<br>
0 1 0<br>
0 0 -1<br>
</p>
I don't know how to see the direction in nibabel<br>
<br>
<br>
<div
class="gmail-m_-5251641299272646700moz-cite-prefix">On
12/11/16 14:10, David Gobbi wrote:<br>
</div>
</div>
</div>
<div>
<div class="gmail-h5">
<blockquote type="cite">
<div dir="ltr">
<div>
<div>Hi Padraig,</div>
<div><br>
</div>
<div>Can you show us the raw qform and sform
fields from the NIFTI header itself? In
VTK, you can do this as follows:</div>
<div><br>
</div>
<div>>>>
print(reader.GetNIFTIHeader())<br>
</div>
<div><br>
</div>
<div>The difference you see between nibabel,
ITK, and VTK has to do with differences in
the way these packages deal with the
pixdim and the qfac of the nifti file. If
you print the Direction from the ITK image
you might find that it differs from
nibabel, too.</div>
<div><br>
</div>
<div>For VTK, you can read all the gory
details here:</div>
<div><br>
</div>
<div><a moz-do-not-send="true"
href="http://gitlab.kitware.com/vtk/vtk/blob/v7.0.0/IO/Image/vtkNIFTIImageReader.cxx#L738"
target="_blank">http://gitlab.kitware.com/vtk/<wbr>vtk/blob/v7.0.0/IO/Image/<wbr>vtkNIFTIImageReader.cxx#L738</a></div>
</div>
<div><br>
</div>
<div> - David</div>
<div><br>
</div>
<div class="gmail_extra"><br>
<div class="gmail_quote">On Sat, Nov 12,
2016 at 6:10 AM, padraig <span dir="ltr"><<a
moz-do-not-send="true"
href="mailto:padraig.looney@gmail.com"
target="_blank">padraig.looney@gmail.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">
<div bgcolor="#FFFFFF">
<div
class="gmail-m_-5251641299272646700gmail-m_-103140333611607564moz-text-flowed"
style="font-family:-moz-fixed;font-size:12px" lang="x-unicode">I have
noticed some inconsistencies in how
NIFTI images are handled in VTK,
ITK, and NiBabel. ITK and NiBabel
are in agreement with each other and
differ with VTK on the position of
the volume. The VTK output for a
file is below. <br>
<br>
vtkNIFTIImageReader (0x1de67d0) <br>
Debug: Off <br>
Modified Time: 91 <br>
Reference Count: 2 <br>
Registered Events: (none) <br>
Executive: 0x1de7720 <br>
ErrorCode: Success <br>
Information: 0x1de6ad0 <br>
AbortExecute: Off <br>
Progress: 1 <br>
Progress Text: (None) <br>
FileName:
/home/padraig/Desktop/59674/Se<wbr>eding/I0000003_59674_sn.nii
<br>
FileNames: 0 <br>
FilePrefix: (none) <br>
FilePattern: %s.%d <br>
FileNameSliceOffset: 0 <br>
FileNameSliceSpacing: 1 <br>
DataScalarType: unsigned char <br>
NumberOfScalarComponents: 1 <br>
File Dimensionality: 3 <br>
File Lower Left: On <br>
Swap Bytes: Off <br>
DataIncrements: (1, 1) <br>
DataExtent: (0, 223, 0, 152, 0,
51) <br>
DataSpacing: (0.9195, 1.40018,
2.89048) <br>
DataOrigin: (0, 0, 0) <br>
HeaderSize: 352 <br>
Internal File Name: (none) <br>
TimeAsVector: Off <br>
TimeDimension: 1 <br>
TimeSpacing: 1 <br>
RescaleSlope: 1 <br>
RescaleIntercept: 0 <br>
QFac: -1 <br>
QFormMatrix: -1 0 0 102.536 0 -1 0
106.413 0 0 1 -117.265 0 0 0 1 <br>
SFormMatrix: -1 0 -0 102.536 0 -1
-0 106.413 0 0 1 -117.265 0 0 0 1 <br>
NIFTIHeader: <br>
PlanarRGB: Off <br>
<br>
the qform given by nibabel is <br>
<br>
>>> ni_ob.get_qform() <br>
array([[ -0.91949999, 0.
, 0. , 102.53600311], <br>
[ 0. ,
-1.40017998, 0. ,
106.41300201], <br>
[ 0. , 0.
, 2.89048004, 30.14909935], <br>
[ 0. , 0.
, 0. , 1. ]]) <br>
<br>
<br>
ITK has the origin at <br>
<br>
[-102.536, -106.413, 30.1491] <br>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</blockquote>
<br>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>