ANTsX / ANTsR

R interface to the ANTs biomedical image processing library
https://antsx.github.io/ANTsR
Apache License 2.0
127 stars 35 forks source link

Different headers on two images, but they seem identical #301

Closed dorianps closed 4 years ago

dorianps commented 4 years ago

Describe the bug Someone has used SPM to do some processing. The headers appear identical but when I compare them in R the result ends up being different. I don't understand why. Any idea what is going on.

> antsGetDirection(subLesion)
            [,1]        [,2] [,3]
[1,] -0.99992301  0.01240864    0
[2,] -0.01240864 -0.99992301    0
[3,]  0.00000000  0.00000000    1
> antsGetDirection(subImg)
            [,1]        [,2] [,3]
[1,] -0.99992301  0.01240864    0
[2,] -0.01240864 -0.99992301    0
[3,]  0.00000000  0.00000000    1
> (antsGetDirection(subLesion) != antsGetDirection(subImg) )
      [,1]  [,2]  [,3]
[1,]  TRUE  TRUE FALSE
[2,]  TRUE  TRUE FALSE
[3,] FALSE FALSE FALSE
> antsGetDirection(subLesion)[1,1]
[1] -0.999923
> antsGetDirection(subImg)[1,1]
[1] -0.999923

If I open the t1 on ITKsnap and load the segmentation on it, there is no problem. Usually ITKsnap complains if there is a mismatch in headers between baseimage and segmentation.

Also, if I copy the headers from one image to the other, there is no problem anymore.

Here are the full headers, seems like both images have identical directions but the sform fields are slightly different from the directions printed through ITK. Still, sform should be ignored by ITK, so not sure what might be the problem.

antsuser@b3aedb8ab52a:~$ PrintHeader t1_4053.nii.gz
 Spacing [1, 1, 1]
 Origin [88.0103, 101.643, -109.215]
 Direction
-0.999923 0.0124086 0
-0.0124086 -0.999923 0
0 0 1

 Size : 180 240  240

  Image Dimensions   : [180, 240, 240]
  Bounding Box       : {[88.0103 101.643 -109.215], [268.01 341.643 130.785]}
  Voxel Spacing      : [1, 1, 1]
  Intensity Range    : [0, 1.7114e+06]
  Mean Intensity     : 138692
  Direction Cos Mtx. :
-0.999923 0.0124086 0
-0.0124086 -0.999923 0
0 0 1

  Voxel->RAS x-form  :
  Image Metadata:
    ITK_FileNotes = TE=3.4;Time=185527.570
    ITK_original_direction of unsupported type N3itk6MatrixIdLj3ELj3EEE
    ITK_original_spacing of unsupported type St6vectorIdSaIdEE
    bitpix = 16
    cal_max = 0
    cal_min = 0
    datatype = 4
    descrip = TE=3.4;Time=185527.570
    dim[0] = 3
    dim[1] = 180
    dim[2] = 240
    dim[3] = 240
    dim[4] = 1
    dim[5] = 0
    dim[6] = 0
    dim[7] = 0
    dim_info = 54
    intent_code = 0
    intent_p1 = 0
    intent_p2 = 0
    intent_p3 = 0
    nifti_type = 1
    pixdim[0] = 0
    pixdim[1] = 1
    pixdim[2] = 1
    pixdim[3] = 1
    pixdim[4] = 0.0074577
    pixdim[5] = 0
    pixdim[6] = 0
    pixdim[7] = 0
    qform_code = 1
    qform_code_name = NIFTI_XFORM_SCANNER_ANAT
    qoffset_x = -88.0103
    qoffset_y = -101.643
    qoffset_z = -109.215
    quatern_b = 0
    quatern_c = 0
    quatern_d = 0.00620444
    scl_inter = 0
    scl_slope = 3422.8
    sform_code = 1
    sform_code_name = NIFTI_XFORM_SCANNER_ANAT
    slice_code = 0
    slice_duration = 0
    slice_end = 0
    slice_start = 0
    srow_x = 0.999924 -0.0124086 0 -88.0103
    srow_y = 0.0124086 0.999923 0 -101.643
    srow_z = 0 0 1 -109.215
    toffset = 0
    vox_offset = 352
    xyzt_units = 10
antsuser@b3aedb8ab52a:~$ PrintHeader bles_4053.nii.gz
 Spacing [1, 1, 1]
 Origin [88.0103, 101.643, -109.215]
 Direction
-0.999923 0.0124086 0
-0.0124086 -0.999923 0
0 0 1

 Size : 180 240  240

  Image Dimensions   : [180, 240, 240]
  Bounding Box       : {[88.0103 101.643 -109.215], [268.01 341.643 130.785]}
  Voxel Spacing      : [1, 1, 1]
  Intensity Range    : [0, 1]
  Mean Intensity     : 0.00448129
  Direction Cos Mtx. :
-0.999923 0.0124086 0
-0.0124086 -0.999923 0
0 0 1

  Voxel->RAS x-form  :
  Image Metadata:
    ITK_FileNotes = Binary lesion map obtained by LPA within LST toolbox
    ITK_original_direction of unsupported type N3itk6MatrixIdLj3ELj3EEE
    ITK_original_spacing of unsupported type St6vectorIdSaIdEE
    bitpix = 32
    cal_max = 0
    cal_min = 0
    datatype = 16
    descrip = Binary lesion map obtained by LPA within LST toolbox
    dim[0] = 3
    dim[1] = 180
    dim[2] = 240
    dim[3] = 240
    dim[4] = 1
    dim[5] = 1
    dim[6] = 1
    dim[7] = 1
    dim_info = 0
    intent_code = 0
    intent_p1 = 0
    intent_p2 = 0
    intent_p3 = 0
    nifti_type = 1
    pixdim[0] = 0
    pixdim[1] = 1
    pixdim[2] = 1
    pixdim[3] = 1
    pixdim[4] = 4.8
    pixdim[5] = 0
    pixdim[6] = 0
    pixdim[7] = 0
    qform_code = 2
    qform_code_name = NIFTI_XFORM_ALIGNED_ANAT
    qoffset_x = -88.0103
    qoffset_y = -101.643
    qoffset_z = -109.215
    quatern_b = 0
    quatern_c = 0
    quatern_d = 0.00620444
    scl_inter = 0
    scl_slope = 1761.34
    sform_code = 2
    sform_code_name = NIFTI_XFORM_ALIGNED_ANAT
    slice_code = 0
    slice_duration = 0
    slice_end = 0
    slice_start = 0
    srow_x = 0.999924 -0.0124086 0 -88.0103
    srow_y = 0.0124087 0.999923 0 -101.643
    srow_z = 0 0 1 -109.215
    toffset = 0
    vox_offset = 352
    xyzt_units = 10

To Reproduce Can't share the data yet, will direct the user to this thread if he can share the data.

Expected behavior No difference between headers.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Smartphone (please complete the following information): NA

Additional context NA

muschellij2 commented 4 years ago

Probably floating point arithmetic issues.

Have you tried all.equal/identical: http://uc-r.github.io/comparing_numeric_values/

Best, John

On Thu, Mar 5, 2020 at 1:05 PM dorianps notifications@github.com wrote:

Describe the bug Someone has used SPM to do some processing. The headers appear identical but when I compare them in R the result ends up being different. I don't understand why. Any idea what is going on.

antsGetDirection(subLesion) [,1] [,2] [,3] [1,] -0.99992301 0.01240864 0 [2,] -0.01240864 -0.99992301 0 [3,] 0.00000000 0.00000000 1 antsGetDirection(subImg) [,1] [,2] [,3] [1,] -0.99992301 0.01240864 0 [2,] -0.01240864 -0.99992301 0 [3,] 0.00000000 0.00000000 1 (antsGetDirection(subLesion) != antsGetDirection(subImg) ) [,1] [,2] [,3] [1,] TRUE TRUE FALSE [2,] TRUE TRUE FALSE [3,] FALSE FALSE FALSE antsGetDirection(subLesion)[1,1] [1] -0.999923 antsGetDirection(subImg)[1,1] [1] -0.999923

If I open the t1 on ITKsnap and load the segmentation on it, there is no problem. Usually ITKsnap complains if there is a mismatch in headers between baseimage and segmentation.

Also, if I copy the headers from one image to the other, there is no problem anymore.

Here are the full headers, seems like both images have identical directions but the sform fields are slightly different from the directions printed through ITK. Still, sform should be ignored by ITK, so not sure what might be the problem.

antsuser@b3aedb8ab52a:~$ PrintHeader t1_4053.nii.gz Spacing [1, 1, 1] Origin [88.0103, 101.643, -109.215] Direction -0.999923 0.0124086 0 -0.0124086 -0.999923 0 0 0 1

Size : 180 240 240

Image Dimensions : [180, 240, 240] Bounding Box : {[88.0103 101.643 -109.215], [268.01 341.643 130.785]} Voxel Spacing : [1, 1, 1] Intensity Range : [0, 1.7114e+06] Mean Intensity : 138692 Direction Cos Mtx. : -0.999923 0.0124086 0 -0.0124086 -0.999923 0 0 0 1

Voxel->RAS x-form : Image Metadata: ITK_FileNotes = TE=3.4;Time=185527.570 ITK_original_direction of unsupported type N3itk6MatrixIdLj3ELj3EEE ITK_original_spacing of unsupported type St6vectorIdSaIdEE bitpix = 16 cal_max = 0 cal_min = 0 datatype = 4 descrip = TE=3.4;Time=185527.570 dim[0] = 3 dim[1] = 180 dim[2] = 240 dim[3] = 240 dim[4] = 1 dim[5] = 0 dim[6] = 0 dim[7] = 0 dim_info = 54 intent_code = 0 intent_p1 = 0 intent_p2 = 0 intent_p3 = 0 nifti_type = 1 pixdim[0] = 0 pixdim[1] = 1 pixdim[2] = 1 pixdim[3] = 1 pixdim[4] = 0.0074577 pixdim[5] = 0 pixdim[6] = 0 pixdim[7] = 0 qform_code = 1 qform_code_name = NIFTI_XFORM_SCANNER_ANAT qoffset_x = -88.0103 qoffset_y = -101.643 qoffset_z = -109.215 quatern_b = 0 quatern_c = 0 quatern_d = 0.00620444 scl_inter = 0 scl_slope = 3422.8 sform_code = 1 sform_code_name = NIFTI_XFORM_SCANNER_ANAT slice_code = 0 slice_duration = 0 slice_end = 0 slice_start = 0 srow_x = 0.999924 -0.0124086 0 -88.0103 srow_y = 0.0124086 0.999923 0 -101.643 srow_z = 0 0 1 -109.215 toffset = 0 vox_offset = 352 xyzt_units = 10 antsuser@b3aedb8ab52a:~$ PrintHeader bles_4053.nii.gz Spacing [1, 1, 1] Origin [88.0103, 101.643, -109.215] Direction -0.999923 0.0124086 0 -0.0124086 -0.999923 0 0 0 1

Size : 180 240 240

Image Dimensions : [180, 240, 240] Bounding Box : {[88.0103 101.643 -109.215], [268.01 341.643 130.785]} Voxel Spacing : [1, 1, 1] Intensity Range : [0, 1] Mean Intensity : 0.00448129 Direction Cos Mtx. : -0.999923 0.0124086 0 -0.0124086 -0.999923 0 0 0 1

Voxel->RAS x-form : Image Metadata: ITK_FileNotes = Binary lesion map obtained by LPA within LST toolbox ITK_original_direction of unsupported type N3itk6MatrixIdLj3ELj3EEE ITK_original_spacing of unsupported type St6vectorIdSaIdEE bitpix = 32 cal_max = 0 cal_min = 0 datatype = 16 descrip = Binary lesion map obtained by LPA within LST toolbox dim[0] = 3 dim[1] = 180 dim[2] = 240 dim[3] = 240 dim[4] = 1 dim[5] = 1 dim[6] = 1 dim[7] = 1 dim_info = 0 intent_code = 0 intent_p1 = 0 intent_p2 = 0 intent_p3 = 0 nifti_type = 1 pixdim[0] = 0 pixdim[1] = 1 pixdim[2] = 1 pixdim[3] = 1 pixdim[4] = 4.8 pixdim[5] = 0 pixdim[6] = 0 pixdim[7] = 0 qform_code = 2 qform_code_name = NIFTI_XFORM_ALIGNED_ANAT qoffset_x = -88.0103 qoffset_y = -101.643 qoffset_z = -109.215 quatern_b = 0 quatern_c = 0 quatern_d = 0.00620444 scl_inter = 0 scl_slope = 1761.34 sform_code = 2 sform_code_name = NIFTI_XFORM_ALIGNED_ANAT slice_code = 0 slice_duration = 0 slice_end = 0 slice_start = 0 srow_x = 0.999924 -0.0124086 0 -88.0103 srow_y = 0.0124087 0.999923 0 -101.643 srow_z = 0 0 1 -109.215 toffset = 0 vox_offset = 352 xyzt_units = 10

To Reproduce Can't share the data yet, will direct the user to this thread if he can share the data.

Expected behavior No difference between headers.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Smartphone (please complete the following information): NA

Additional context NA

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ANTsX/ANTsR/issues/301?email_source=notifications&email_token=AAIGPLWIH67RQPCTZ6BF5JLRF7SUXA5CNFSM4LCPO4TKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4IS3XGPQ, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAIGPLXOLRMGU6OVP7WXTNLRF7SUXANCNFSM4LCPO4TA .

dorianps commented 4 years ago

That indeed helps:

> antsGetDirection(subLesion)[1,1] == 
+   antsGetDirection(subImg)[1,1]
[1] FALSE
> antsGetDirection(subLesion)[1,1]
[1] -0.999923
>   antsGetDirection(subImg)[1,1]
[1] -0.999923
> all.equal( antsGetDirection(subLesion)[1,1],  
+   antsGetDirection(subImg)[1,1] )
[1] TRUE

But are we sure this difference is not creating errors in ANTs tools later ?

miguelrivasfdez commented 4 years ago

Dear Dorian and John,

I performed the sccan analysis in LESYMAP with those images and it seems that there was not any problem with the ANTs tools. Thanks for your help. Just a little question:

I am a begginer in programming and I trying to create a for loop in R in order to apply the registerLesionToTemplate function over several subjects before running the lesymap analysis. I have in the same folder the t1 and the binary lesion maps of several subjects (both in the same space). I tried this R for loop as an example in two subjects but did not work, can you help me?

setwd ("/home/miguel/Desktop/lesy/") library('LESYMAP')

subjects <- c('t1_4001.nii', 't1_4007.nii') ## anatomical image lesions <- c('bles_4001.nii', 'bles_4007.nii') ## binary lesion maps

for (i in subjects) {

subImg = antsImageRead(subjects)
subLesion = antsImageRead(lesions)

subLesionCopy = antsImageClone(subLesion)     ## solving header info issues
subLesionCopy = antsCopyImageInfo(subImg, subLesionCopy)
temp = registerLesionToTemplate(subImg, subLesionCopy, outprefix = reg_, saveDir = '/home/miguel/Desktop/lesy/template_registration')

}

Thanks in advance for your help.

Best regards,

muschellij2 commented 4 years ago

you're not using i for anything, aka the loop is not looping but working on everything. Also "but did not work" is not generally easy to diagnose. See https://stackoverflow.com/help/minimal-reproducible-example on how to create a reproducible example and reprex package for reproducible examples in the future: https://github.com/tidyverse/reprex. Also reg_ should be quoted. You need to adapt the output though, as this loop may rewrite the same data over and over (probably should do

outprefix = paste0("reg_", sub("t1_(.*)[.]nii.*", "\\1", basename(subjects[i])), "_" )
setwd ("/home/miguel/Desktop/lesy/")
library('LESYMAP')

subjects <- c('t1_4001.nii', 't1_4007.nii')     ## anatomical image
lesions <- c('bles_4001.nii', 'bles_4007.nii')  ## binary lesion maps

for (i in seq_along(subjects)) {

    subImg = antsImageRead(subjects[i])
    subLesion = antsImageRead(lesions[i])

    subLesionCopy = antsImageClone(subLesion)     ## solving header info issues
    subLesionCopy = antsCopyImageInfo(subImg, subLesionCopy)
    temp = registerLesionToTemplate(subImg, subLesionCopy, outprefix = "reg_", saveDir = '/home/miguel/Desktop/lesy/template_registration')

}

Glad to help but please open new issues for your issues - you've seemed to hijack this issue which is completely unrelated. If the issue is for LESYMAP, please post there, not on the issue page for ANTsR.

dorianps commented 4 years ago

Thanks John for chipping in. Closing this issue.

Miguel, please use LESYMAP issues if you need help. Among other things, this was an interesting case and is only in my emails. It is better if issues and solutions are all found online.

Dorian