dipterix / threeBrain

3D Visualization of Brain MRI
https://dipterix.org/threeBrain/
42 stars 10 forks source link

Improper transform when rendering volumes #15

Closed dipterix closed 2 years ago

dipterix commented 2 years ago

The Nifti IJK to XYZ calculation is wrong when slicing space is not 1mm.

This bug flaws the localization module. To fix the issue,

The transform by Nifti maps voxels to scanner space. However, users might co-register CT to FreeSurfer-generated T1 (sits in tkrRAS). Therefore in the localization, we need to add options on whether XYZ to RAS should be added to transform.

dipterix commented 2 years ago

In specification (https://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h),

In NifTi-1, there are 3 different IJK (The i index varies most rapidly, j index next, k index slowest) to XYZ methods by which continuous coordinates can attached to voxels. In methods 2 and 3, the (x,y,z) axes refer to a subject-based coordinate system, with

+x = Right +y = Anterior +z = Superior.

This is a right-handed coordinate system. In method 1, which is ANALYZE 7.5 coordinate system,

+x = Left +y = Anterior +z = Superior

Note 1: threeBrain is (probably) not going to support ANALYZE 7.5 coordinate system, as it's "too difficult to tolerate". I personally don't have samples with such format.

The actual XYZ space depends on qform_code (Method 2) and sform_code (Method 3).

METHOD 1 (the "old" way, used only when qform_code = 0):

Method 1 is provided only for backwards compatibility.

     x = pixdim[1] * i
     y = pixdim[2] * j
     z = pixdim[3] * k

METHOD 2 (used when qform_code > 0, which should be the "normal" case):

The intention is that Method 2 (qform_code > 0) represents the nominal voxel locations as reported by the scanner, or as rotated to some fiducial orientation and location.

In Method 2, the origin of coordinates would generally be whatever the scanner origin is; for example, in MRI, (0,0,0) is the center of the gradient coil.

[ x ] = [ R11 R12 R13 ] [        pixdim[1] * i ]   [ qoffset_x ]
[ y ] = [ R21 R22 R23 ] [        pixdim[2] * j ] + [ qoffset_y ]
[ z ] = [ R31 R32 R33 ] [ qfac * pixdim[3] * k ]   [ qoffset_z ]
qfac = pixdim[0]

METHOD 3 (used when sform_code > 0):

Method 3, if present (sform_code > 0), is to be used to give the location of the voxels in some standard space. The sform_code indicates which standard space is present.

In Method 3, the origin of coordinates would depend on the value of sform_code; for example, for the Talairach coordinate system, (0,0,0) corresponds to the Anterior Commissure.

     x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3]
     y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3]
     z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3]
dipterix commented 2 years ago

For [qs]form_code, the following doc explains what x,y,z coordinate system refers to: