MRtrix3 / mrtrix3

MRtrix3 provides a set of tools to perform various advanced diffusion MRI analyses, including constrained spherical deconvolution (CSD), probabilistic tractography, track-density imaging, and apparent fibre density
http://www.mrtrix.org
Mozilla Public License 2.0
290 stars 178 forks source link

Incorrect transform after conversion from Philips Enhanced DICOM #2977

Open bjeurissen opened 2 weeks ago

bjeurissen commented 2 weeks ago

I noticed a discrepancy in the Transform (shift of half a voxel along the in-plane dimensions) when converting a Philips DICOM data set using mrconvert vs dcm2niix.

@Lestropie suggested that it might be related to Enhanced DICOM, which turns out to be the case.

The issue seems to be specific to Philips Enhanced DICOM (other vendors and classic DICOM are fine) and can be reproduced using the dcmqa* datasets from @neurolabusc.

Using https://github.com/neurolabusc/dcm_qa_philips_enh.git which contains both a classic and an enhanced DICOM version of the same dataset, dcm2niix reports the same transform across DICOM versions, whereas mrconvert reports a shift of half a voxel along the in-plane dimensions for the enhanced DICOM dataset:

************************************************
Image name:          "cl/cl_WIP_ADNI_Sag3D_MPRAGE_20210902121816_1301.nii"
************************************************
  Dimensions:        170 x 256 x 256
  Voxel size:        1 x 1 x 1
  Data strides:      [ 1 2 3 ]
  Format:            NIfTI-1.1
  Data type:         signed 16 bit integer (little endian)
  Intensity scaling: offset = 0, multiplier = 133.88156127929688
  Transform:               0.9974    -0.03861     0.06086      -88.35
                          0.03868      0.9993           0      -121.8
                         -0.06081    0.002354      0.9981      -116.7
  comments:          TE=2.9;Time=130013.040
************************************************
Image name:          "enh/enh_WIP_ADNI_Sag3D_MPRAGE_20210902121816_1301.nii"
************************************************
  Dimensions:        170 x 256 x 256
  Voxel size:        1 x 1 x 1
  Data strides:      [ 1 2 3 ]
  Format:            NIfTI-1.1
  Data type:         signed 16 bit integer (little endian)
  Intensity scaling: offset = 0, multiplier = 133.88156127929688
  Transform:               0.9974    -0.03861     0.06086      -88.35
                          0.03868      0.9993           0      -121.8
                         -0.06081    0.002354      0.9981      -116.7
  comments:          TE=2.9;Time=130004.570
************************************************
Image name:          "classic_to_nii_with_mrconvert.nii"
************************************************
  Dimensions:        170 x 256 x 256
  Voxel size:        0.999999 x 1 x 1
  Data strides:      [ 3 -1 -2 ]
  Format:            NIfTI-1.1
  Data type:         unsigned 16 bit integer (little endian)
  Intensity scaling: offset = 0, multiplier = 2.3616604804992676
  Transform:               0.9974    -0.03861     0.06086      -88.35
                          0.03868      0.9993           0      -121.8
                         -0.06081    0.002354      0.9981      -116.7
  comments:          d2n_Philips_3T_R5
  mrtrix_version:    3.0.4-1213-gb8300082
************************************************
Image name:          "enhanced_to_nii_with_mrconvert.nii"
************************************************
  Dimensions:        170 x 256 x 256
  Voxel size:        0.999999 x 1 x 1
  Data strides:      [ 3 -1 -2 ]
  Format:            NIfTI-1.1
  Data type:         unsigned 16 bit integer (little endian)
  Intensity scaling: offset = 0, multiplier = 2.3616604804992676
  Transform:               0.9974    -0.03861     0.06086      -88.34
                          0.03868      0.9993           0      -121.3
                         -0.06081    0.002354      0.9981      -116.2
  comments:          d2n_Philips_3T_R5
  mrtrix_version:    3.0.4-1213-gb8300082

Using https://github.com/neurolabusc/dcm_qa_enh.git which contains Enhanced DICOMs from different vendors (Canon, Siemens, and Philips), dcm2niix and mrconvert agree on the Canon and Siemens data, but not on the Philips data (again half a voxel shift along the in-plane dimensions):

************************************************
Image name:          "Philips/Philips_WIP_AnatBrain_T1W3D_20180526150245_301.nii"
************************************************
  Dimensions:        256 x 256 x 32
  Voxel size:        1 x 1 x 4
  Data strides:      [ 1 2 3 ]
  Format:            NIfTI-1.1
  Data type:         signed 16 bit integer (little endian)
  Intensity scaling: offset = 0, multiplier = 2482.36376953125
  Transform:                    1           0   2.743e-05      -126.3
                                0           1           0      -133.7
                       -2.743e-05           0           1      -38.35
  comments:          TE=4.6;Time=151207.980
************************************************
Image name:          "Philips/mrconvert.nii"
************************************************
  Dimensions:        256 x 256 x 32
  Voxel size:        1 x 1 x 4
  Data strides:      [ -1 -2 3 ]
  Format:            NIfTI-1.1
  Data type:         unsigned 16 bit integer (little endian)
  Intensity scaling: offset = 0, multiplier = 1.2354090213775635
  Transform:                    1           0   2.743e-05      -125.8
                                0           1          -0      -133.2
                       -2.743e-05          -0           1      -38.35
  comments:          ROGERS_20180526 (
  mrtrix_version:    3.0.4-1213-gb8300082
neurolabusc commented 2 weeks ago

This issue is noted in dcm2niix issue 144 - Philips scanners often generate two different ImagePositionPatient (0020,0032) values for each slice. You want to use the one from the public sequence PlanePositionSequence and ignore the one stored in the private sequence (2005,140f). When I discovered this years ago, I did tell Philips clinical scientists that re-using a the public tag (0020,0032) for private purposes was likely to lead to unintended consequences. However, nothing has changed. The good news with Philips DICOMs is that they seem to be moribund, so they do not change. The unfortunate thing is that Philips enhanced DICOMs are insanely verbose with a tremendous amount of redundant information. They are in stark contrast to the lean Canon and Siemens enhanced DICOMs. I have seen Philips enhanced DICOMs that are so bloated they will crash Horos and Osirix.

For the image you reference, the duplicates look like this:

    (0020,9113) SQ (Sequence with undefined length #=1)     # u/l, 1 PlanePositionSequence
...
      (fffe,e000) na (Item with undefined length #=1)         # u/l, 1 Item
        (0020,0032) DS [-128.74297738075\-121.27660465240\-38.354631973134] #  50, 3 ImagePositionPatient
...
    (2005,140f) SQ (Sequence with undefined length #=1)     # u/l, 1 Unknown Tag & Data
      (fffe,e00d) na (ItemDelimitationItem)                   #   0, 0 ItemDelimitationItem
        (0020,0032) DS [-129.24297738075\-121.77660465240\-38.354645685758] #  50, 3 ImagePositionPatient
bjeurissen commented 2 weeks ago

Tested the suggestion of @neurolabusc by replacing

https://github.com/MRtrix3/mrtrix3/blob/d9ddbd4833e4115df926861b642511240a859896/core/file/dicom/element.cpp#L234

with

return true;

which completely ignores anything within Philips PrivatePerFrameSq, and this indeed restores the correct Transform.

@jdtournier how do we properly integrate this fix (not completely ignoring Philips PrivatePerFrameSq, but only certain tags)?