spinicist / QUIT

A set of tools for processing Quantitative MR Images
Mozilla Public License 2.0
58 stars 20 forks source link

itk::ERROR: ApplyAlgorithmFilter(0x7f9237d020b0): Inputs do not occupy the same physical space! #11

Closed mathieuboudreau closed 6 years ago

mathieuboudreau commented 6 years ago

Hi!

I successfully compiled from source last week, and today wanted to try fitting some simple VFA/DESPOT1 data (using the ones we provide with qMRLab: https://osf.io/7wcvh/).

The json file I used was:

{
    "SPGR": {
        "TR": 0.015,
        "FA": [3, 20]
    }
}

Unfortunately, I encountered the following error:

mathieuboudreau@brassens:~/neuropoly/github/qMRLab/tmp/vfa_t1_demo_quit/vfa_t1_data$ qidespot1 VFAData.nii.gz --mask=Mask.nii.gz --B1=B1map.nii.gz < input.json
libc++abi.dylib: terminating with uncaught exception of type itk::ExceptionObject: ../External/ITK/Modules/Core/Common/include/itkImageToImageFilter.hxx:241:
itk::ERROR: ApplyAlgorithmFilter(0x7f9237d020b0): Inputs do not occupy the same physical space! 
InputImage Origin: [1.2394485e+02, 1.0995890e+02, 1.1329514e+01], InputImage_1 Origin: [1.2394485e+02, 1.0995890e+02, 0.0000000e+00]
    Tolerance: 2.0000000e-06
InputImage Spacing: [2.0000000e+00, 2.0000000e+00, 1.9999983e+00], InputImage_1 Spacing: [2.0000000e+00, 2.0000000e+00, 1.0000000e+00]
    Tolerance: 2.0000000e-06
InputImage Direction: -1.0000000e+00 0.0000000e+00 0.0000000e+00
0.0000000e+00 -9.9121554e-01 -1.3225641e-01
0.0000000e+00 -1.3225642e-01 9.9121554e-01
, InputImage_1 Direction: -1.0000000e+00 0.0000000e+00 0.0000000e+00
0.0000000e+00 -1.0000000e+00 0.0000000e+00
0.0000000e+00 0.0000000e+00 1.0000000e+00

    Tolerance: 1.0000000e-06

Abort trap: 6
mathieuboudreau@brassens:~/neuropoly/github/qMRLab/tmp/vfa_t1_demo_quit/vfa_t1_data$

I tried debugging this several ways (up to even manually editing the header so that the files match), but haven't been successful. It doesn't occur if I try fitting only the VFA data (without the mask or B1 map), only when any 2 or 3 combinations of each are used. I can't find the actual values that the error throws in the header using FSL, which is what's making debugging hard for me.

While I realise that it may not be a QUIT issue but a data or ITK issue (similar errors have been reported here in ANTs, and it's not clear what their solution was/is), I thought I'd bring it to your attention.

That being said, I've tried fitting other VFA datasets that I acquired during my PhD, and this resulted in the same error for each that I tried. The common denominator between all three may be 1- the scanner that was used (3T Siemens Tim TRIO at the Montreal Neurological Institute), and 2 - that a conversion was used (our scanner outputs MINC format, so these data files were converted from MINC to NIFTI).

If anyone out there knows a way to fix this issue, I would be greatly appreciate it. Since this is simply single-slice images, I feel like it shouldn't throw an origin/spacing issue since there's not much that can be done with the data to fix either šŸ¤”, and we can fit this data with no issue in qMRLab (likely because these parameters aren't checked).

spinicist commented 6 years ago

Hi, I downloaded the data (thanks for making that available!), and the problem is that VFAData.nii.gz is a 3D nifti containing a single slice, whereas B1map.nii.gz and Mask.nii.gz are true 2D files. You can check this using qihdr, which will print out the header as ITK sees it:

qihdr output ``` āžœ vfa_t1 ls B1map.nii.gz FitResults Mask.nii.gz VFAData.nii.gz āžœ vfa_t1 qihdr VFAData.nii.gz Dimension: 4 Voxel Type: scalar float Size: 128 128 1 2 Spacing: 2 2 2 1 Origin: 123.945 109.959 11.3295 0 Direction: -1 -0 -0 0 0 -0.991216 -0.132256 0 -0 -0.132256 0.991216 0 0 0 0 1 Voxel vol: 7.99999 āžœ vfa_t1 qihdr B1map.nii.gz Dimension: 2 Voxel Type: scalar float Size: 128 128 Spacing: 2 2 Origin: 123.945 109.959 Direction: -1 -0 0 -1 Voxel vol: 4 āžœ vfa_t1 qihdr Mask.nii.gz Dimension: 2 Voxel Type: scalar short Size: 128 128 Spacing: 2 2 Origin: 123.945 109.959 Direction: -1 -0 0 -1 Voxel vol: 4 ```

The FSL tools sadly obscure the problem. If you run fslhd on B1map.nii.gz you get:

fslhd output ``` filename B1map.nii.gz sizeof_hdr 348 data_type FLOAT32 dim0 2 dim1 128 dim2 128 dim3 1 dim4 1 dim5 1 dim6 1 dim7 1 vox_units mm time_units s datatype 16 nbyper 4 bitpix 32 pixdim0 0.000000 pixdim1 2.000000 pixdim2 2.000000 pixdim3 1.999998 pixdim4 0.000000 pixdim5 0.000000 pixdim6 0.000000 pixdim7 0.000000 vox_offset 352 cal_max 0.0000 cal_min 0.0000 scl_slope 1.000000 scl_inter 0.000000 phase_dim 0 freq_dim 0 slice_dim 0 slice_name Unknown slice_code 0 slice_start 0 slice_end 0 slice_duration 0.000000 time_offset 0.000000 intent Unknown intent_code 0 intent_name intent_p1 0.000000 intent_p2 0.000000 intent_p3 0.000000 qform_name Scanner Anat qform_code 1 qto_xyz:1 2.000000 -0.000000 0.000000 -123.944855 qto_xyz:2 0.000000 1.982431 0.264513 -109.958900 qto_xyz:3 -0.000000 -0.264513 1.982429 11.329514 qto_xyz:4 0.000000 0.000000 0.000000 1.000000 qform_xorient Left-to-Right qform_yorient Posterior-to-Anterior qform_zorient Inferior-to-Superior sform_name Scanner Anat sform_code 1 sto_xyz:1 2.000000 0.000000 0.000000 -123.944855 sto_xyz:2 0.000000 1.982431 0.264513 -109.958900 sto_xyz:3 0.000000 -0.264513 1.982429 11.329514 sto_xyz:4 0.000000 0.000000 0.000000 1.000000 sform_xorient Left-to-Right sform_yorient Posterior-to-Anterior sform_zorient Inferior-to-Superior file_type NIFTI-1+ file_code 1 descrip FSL5.0 aux_file ```

Which indicates that it is a 2D file but somehow fills out the 3D dimension information. If you run fsledithd then you get:

fsledithd output ```

Note that here, nz and dz do not exist. I used fsledithd to change ndim to 3, and then ran it again to set dz to 2 to match VFAdata.nii.gz, and then qidespot1 ran successfully.

I think a similar issue has come up in the qMRLab issues, because ideally you would be able to indicate that a file is 2D but has multiple "timepoints", but this isn't possible with nifti (a 4D file must have a 3rd dimension).

Sadly I don't think there are any checks I can put in the QUIT code to deal with true 2D files.

Note that you should be able to re-compile QUIT to have MINC support. It involves editing CMakeLists.txt in the QUIT directory - see here: http://spinicist.github.io/QUIT/Developer/#file-formats. The MINC module is called ITKIOMINC, add it next to ITKIONIFTI and then re-compile QUIT (only QUIT, not ITK). If you then set the environment variable QUIT_EXT to .mnc, it should even output MINC (completely untested, let me know what happens!).

spinicist commented 6 years ago

we can fit this data with no issue in qMRLab (likely because these parameters aren't checked)

This was one of the major benefits of swapping to ITK where these things are checked rigorously. Multiple times I have tried fitting models to images with different voxel spacings and been confused by the results, now I get an error up front that the images are incompatible

mathieuboudreau commented 6 years ago

@spinicist Thanks for investigating and the quick response ā€“ your fix worked for me!

You can check this using qihdr

I didn't know about that command yet! šŸŽŠ

The FSL tools sadly obscure the problem.

This was really unfortunate, and what mislead me I think. I might mention it to them, though it's unlikely that they'll care too much, as single-slice imaging isn't a primary focus of theirs I'd imagine.

I think a similar issue has come up in the qMRLab issues, because ideally you would be able to indicate that a file is 2D but has multiple "timepoints", but this isn't possible with nifti (a 4D file must have a 3rd dimension).

I think the issue it relates to is the "singleton dimension" issue we have in MATLAB, if that's what you mean. In some cases, single-slice data is loaded to be a m x n matrix, instead of a m x n x 1 array. It's an issue I've had with MINC tools too.

I think for this case here, the issue likely (not 100% sure) happened on the MINC side ā€“ the VFA data was acquired as a full 3D volume and resampled down to a single slice, whereas the B1 map was acquired using a single-pulse sequence. It's likely that extracting a slice from a volume in MINC doesn't mimic the same dimension configuration that acquiring a single-slice does, leading to their missing nz dimension. I might raise this up with them ā€“ it's an issue that I've dealt with dating back at least 5 years.

Sadly I don't think there are any checks I can put in the QUIT code to deal with true 2D files.

Since you are able to check the # of dimensions with qihdr, you could use that as a check for dimension matching between inputs?

Note that you should be able to re-compile QUIT to have MINC support. It involves editing CMakeLists.txt in the QUIT directory - see here: http://spinicist.github.io/QUIT/Developer/#file-formats. The MINC module is called ITKIOMINC, add it next to ITKIONIFTI and then re-compile QUIT (only QUIT, not ITK). If you then set the environment variable QUIT_EXT to .mnc, it should even output MINC (completely untested, let me know what happens!).

Cool! I might try it!

This was one of the major benefits of swapping to ITK where these things are checked rigorously. Multiple times I have tried fitting models to images with different voxel spacings and been confused by the results, now I get an error up front that the images are incompatible

Agreed ā€“ this isn't an issue we've encountered yet, but risk doing so in the future. I just checked, and unfortunately the only MATLAB ITK package doesn't seem to have been updated since 2007 =(