InsightSoftwareConsortium / ITK

Insight Toolkit (ITK) -- Official Repository. ITK builds on a proven, spatially-oriented architecture for processing, segmentation, and registration of scientific images in two, three, or more dimensions.
https://itk.org
Apache License 2.0
1.37k stars 660 forks source link

BUG: Set NIFTI header xyzt_units field correctly in output #4595

Closed cookpa closed 2 months ago

cookpa commented 2 months ago

Previously, the correct xyzt code was assigned to the 'xyz_units' variable, but time gets masked out because it's only for space units, resulting in xyzt_units=2.

Fix by setting 'time_units' to NIFTI_UNITS_SEC.

This produces images with xyzt_units == 10, which is correct for ITK output (NIFTI_UNITS_MM | NIFTI_UNITS_SEC)

PR Checklist

Refer to the ITK Software Guide for further development details if necessary.

cookpa commented 2 months ago

Quick update, I found some further problems with nonstandard units. Here are two headers with the same physical space, except one is in units of micron | milliseconds (xyzt_units = 19) and the other is in the usual mm | s (xyzt_units = 10).

 Spacing [0.4, 0.4, 0.4, 1.2]                     |  Spacing [0.4, 0.4, 0.4, 1200]
 Origin [-0.5, -0.5, 0.5, 0]                      |  Origin [-500, -500, 500, 0]
 Direction                           Direction 
1 0 0 0                             1 0 0 0
0 -1 0 0                            0 -1 0 0
0 0 1 0                             0 0 1 0
0 0 0 1                             0 0 0 1

 Size : [8, 8, 4, 5]                         Size : [8, 8, 4, 5]

  Image Dimensions   : [8, 8, 4, 5]               Image Dimensions   : [8, 8, 4, 5]
  Bounding Box       : {[-0.5 -0.5 0.5 0], [2.7 2.7 2.1 6]}   |   Bounding Box       : {[-500 -500 500 0], [-496.8 -496.8 501
  Voxel Spacing      : [0.4, 0.4, 0.4, 1.2]           |   Voxel Spacing      : [0.4, 0.4, 0.4, 1200]
  Intensity Range    : [0, 0]                     Intensity Range    : [0, 0]
  Mean Intensity     : 0                      Mean Intensity     : 0
  Direction Cos Mtx. :                        Direction Cos Mtx. : 
1 0 0 0                             1 0 0 0
0 -1 0 0                            0 -1 0 0
0 0 1 0                             0 0 1 0
0 0 0 1                             0 0 0 1

  Voxel->RAS x-form  :                        Voxel->RAS x-form  : 
  Image Metadata:                         Image Metadata: 
    ITK_original_direction of unsupported type N3itk6MatrixId       ITK_original_direction of unsupported type N3itk6MatrixId
    ITK_original_spacing of unsupported type NSt3__16vectorId       ITK_original_spacing of unsupported type NSt3__16vectorId
    ITK_sform_corrected = NO                        ITK_sform_corrected = NO
    bitpix = 64                             bitpix = 64
    cal_max = 0                             cal_max = 0
    cal_min = 0                             cal_min = 0
    datatype = 64                           datatype = 64
    dim[0] = 4                              dim[0] = 4
    dim[1] = 8                              dim[1] = 8
    dim[2] = 8                              dim[2] = 8
    dim[3] = 4                              dim[3] = 4
    dim[4] = 5                              dim[4] = 5
    dim[5] = 1                              dim[5] = 1
    dim[6] = 1                              dim[6] = 1
    dim[7] = 1                              dim[7] = 1
    dim_info = 0                            dim_info = 0
    intent_code = 0                         intent_code = 0
    intent_p1 = 0                           intent_p1 = 0
    intent_p2 = 0                           intent_p2 = 0
    intent_p3 = 0                           intent_p3 = 0
    nifti_type = 1                          nifti_type = 1
    pixdim[0] = 0                           pixdim[0] = 0
    pixdim[1] = 0.4                       |     pixdim[1] = 400
    pixdim[2] = 0.4                       |     pixdim[2] = 400
    pixdim[3] = 0.4                       |     pixdim[3] = 400
    pixdim[4] = 1.2                       |     pixdim[4] = 1200
    pixdim[5] = 0                           pixdim[5] = 0
    pixdim[6] = 0                           pixdim[6] = 0
    pixdim[7] = 0                           pixdim[7] = 0
    qfac = -1                               qfac = -1
    qform_code = 1                          qform_code = 1
    qform_code_name = NIFTI_XFORM_SCANNER_ANAT              qform_code_name = NIFTI_XFORM_SCANNER_ANAT
    qoffset_x = 0.5                       |     qoffset_x = 500
    qoffset_y = 0.5                       |     qoffset_y = 500
    qoffset_z = 0.5                       |     qoffset_z = 500
    qto_xyz of unsupported type N3itk6MatrixIfLj4ELj4EEE        qto_xyz of unsupported type N3itk6MatrixIfLj4ELj4EEE
    quatern_b = 0                           quatern_b = 0
    quatern_c = 1                           quatern_c = 1
    quatern_d = 0                           quatern_d = 0
    scl_inter = 0                           scl_inter = 0
    scl_slope = 1                           scl_slope = 1
    sform_code = 1                          sform_code = 1
    sform_code_name = NIFTI_XFORM_SCANNER_ANAT              sform_code_name = NIFTI_XFORM_SCANNER_ANAT
    slice_code = 0                          slice_code = 0
    slice_duration = 0                          slice_duration = 0
    slice_end = 0                           slice_end = 0
    slice_start = 0                         slice_start = 0
    srow_x = -0.4 0 0 0.5                     |     srow_x = -400 0 -0 500
    srow_y = 0 0.4 0 0.5                      |     srow_y = 0 400 -0 500
    srow_z = 0 0 0.4 0.5                      |     srow_z = 0 0 400 500
    toffset = 0                             toffset = 0
    vox_offset = 352                            vox_offset = 352
    xyzt_units = 10                       |     xyzt_units = 19

Correctly scaled:

Incorrectly scaled:

To do for me:

cookpa commented 2 months ago

I think this is good to go now. I made some more changes to ensure that both space and time get scaled into mm and seconds respectively, in both the pixel dimensions and the origin fields. The xyzt_units should now be read and written correctly.

dzenanz commented 2 months ago

/azp run ITK.macOS.Python

jhlegarreta commented 2 months ago

@cookpa itkNiftiSpatialTemporalUnitsTest2 is failing on a number of sites in the dashboard: https://open.cdash.org/index.php?project=Insight

See the +1/+2 failing indicators.

cookpa commented 2 months ago

Apologies, will look at this today