BIC-MNI / minc-tools

Basic minc-tools from former minc repository
Other
30 stars 25 forks source link

Feature Idea: Allow mnc2nii to use transform from a nifti file #42

Open gdevenyi opened 8 years ago

gdevenyi commented 8 years ago

I have run into the following problem on many occasions:

1) Receive from collaborator some kind of nifti file, which has been "processed" by SPM or FSL (aka has sform/qform data) 2) Convert said file to minc using nii2mnc which properly handles sform/qform and provides me with a reasonably oriented minc file 3) Process said file (for example, produce label files for it using magetbrain) 4) Convert label files back to nifti using mnc2nii 5) Problem arises -> resulting nifti file is not in the space of the original nifti file, due to not having any transforms applied.

Proposed solution: Provide an option for mnc2nii which reads from a given "reference" NIFTI file the sform/qform information, and applies it during conversion so that the resulting file is in the right space.

gdevenyi commented 8 years ago

@rdvincent let me know if you need example files, I have some

rdvincent commented 8 years ago

@gdevenyi Always happy to have a few examples.

andrewjanke commented 8 years ago

Can I suggest an alternate approach that will achieve the same result? Before Bert updated mnc2nii and nii2mnc in C, I had a perl version (ana2mnc) I put extra functionality in there based upon querying $0. So if you called ana2mnc as spm2xfm it would read a SPM triple (.mat, .hdr, .img) and create a minc .xfm.

https://github.com/BIC-MNI/minc-tools/blob/master/conversion/ana2mnc/ana2mnc#L212

The code is now out of date as a better way to read the .mat file is via octave but could we perhaps entertain the idea in which the q-form s-form disambiguation is done by using one as the voxel to world transform in the resulting MINC file (current behaviour) but instead of concatenating them if both exist to keep the other as a .xfm (to model space)?

I think this makes sense given the NifTi way of including the to model transform in the header. SPM didn't allow you to disambiguate the two so I used to go through a number of contortions to extract the "anything over 90deg" rotations as the dimension order and the remainder as the voxel to world. Not sure if this is still correct.

gdevenyi commented 8 years ago

@andrewjanke I've played around with ana2mnc and related, I found I don't fully understand the NIFTI sform/qform maddness (maybe there's some docs somewhere that describe everything coherently?) Additionally, this dataset didn't have .mat, it had headers in the NIFTI file, which I don't think ana2mnc handles?

My major goal is a workflow that goes from/to NIFTI without special casing every dataset I get, I was hoping this might accomplish this.

andrewjanke commented 8 years ago

Sorry, to clarify.

I wasn't suggesting that ana2mnc understands the qform and sform transforms. (it doesn't as it predates the ratified nifti spec).

I was suggesting that instead of combining the qform and sform we could also add an accompanying .xfm with the .mnc file. In this manner when then converting back to .nii there could be an optional .xfm input that would then in combination with the .mnc voxel to world transform populate the nifti qform and sform fields in the header.

Doing it this way would to my way of thinking be cleaner as it retains all the information from the Nifti header in a logical fashion and not require a hack-around -like/-template nifti file.

The fundamental problem is that a MINC file contains one transform (voxel to world). A Nifti file also contains a voxel to world transform (qform) but can optionally contain a "to model" transformation (sform).

See here for more detailed information:

http://nifti.nimh.nih.gov/nifti-1/documentation/nifti1fields/nifti1fields_pages/qsform_brief_usage

gdevenyi commented 8 years ago

Thanks @andrewjanke I get it now. Yes, if nii2mnc would provide an xfm file which I could use with mnc2nii to get back into the same space, I would be a-okay with that as an alternative.

gdevenyi commented 8 years ago

@rdvincent any movement on this? I've got a new batch of nifti->minc->nifti conversion I'll need to do for another dataset

I see some changes in rdv-nifti branch

rdvincent commented 8 years ago

@gdevenyi No change to address this specifically. It would be good to have a clear example of a situation in which this doesn't work, so that I could see if the proposed fix would deal with it.

gdevenyi commented 8 years ago

Sorry, I don't understand "in which this doesn't work".

My report in the first comment stands as being the problem I run into. My proposal of a "reference" nifti or @andrewjanke's of a mnc2nii xfm would both allow me to convert/transform labels back into the original nifti space.

rdvincent commented 8 years ago

@gdevenyi What I meant is this: in general, conversion nii2mnc -> -> mnc2nii should preserve the voxel-to-world transformation. So assuming everything is working correctly (a large assumption, I'll admit), the only reason to add some additional option to pick up a transform from another file would be if the "other stuff" made changes that you didn't want copied back into the mnc2nii header, or if you specifically wanted to set the sform or the qform of the resulting NIfTI file in some particular way.

gdevenyi commented 8 years ago

Okay.

> PrintHeader orig.nii
  Image Dimensions   : [256, 256, 170]
  Bounding Box       : {[106.16 -127.203 127.053], [362.16 128.797 331.054]}
  Voxel Spacing      : [1, 1, 1.20001]
  Intensity Range    : [0, 2468.78]
  Mean Intensity     : 124.467
  Direction Cos Mtx. : 
-0.019162 -0.00906867 -0.999775
0.999816 -3.2766e-08 -0.0191628
0.000173748 -0.999959 0.00906701

  Voxel->RAS x-form  : 
  Image Metadata: 
    bitpix = 32
    cal_max = 0
    cal_min = 0
    datatype = 16
    dim[0] = 3
    dim[1] = 256
    dim[2] = 256
    dim[3] = 170
    dim[4] = 1
    dim[5] = 1
    dim[6] = 1
    dim[7] = 1
    intent_code = 0
    intent_p1 = 0
    intent_p2 = 0
    intent_p3 = 0
    pixdim[0] = 1
    pixdim[1] = 1
    pixdim[2] = 1
    pixdim[3] = 1.20001
    pixdim[4] = 0
    pixdim[5] = 0
    pixdim[6] = 0
    pixdim[7] = 0
    qform_code = 2
    qoffset_x = -106.16
    qoffset_y = 127.203
    qoffset_z = 127.053
    quatern_b = -0.502517
    quatern_c = 0.492892
    quatern_d = -0.49747
    scl_inter = 0
    scl_slope = 1
    sform_code = 1
    slice_duration = 0
    slice_end = 0
    slice_start = 0
    srow_x = 0.019162 0.00906865 1.19974 -106.16
    srow_y = -0.999816 -6.11378e-12 0.0229955 127.203
    srow_z = 0.000173781 -0.999959 0.0108805 127.053
    toffset = 0
    vox_offset = 352
> nii2mnc 3T0356.nii there.mnc
> mnc2nii there.mnc back.nii
> PrintHeader back.nii
  Image Dimensions   : [170, 256, 256]
  Bounding Box       : {[98.8966 131.133 -127.892], [302.898 387.133 128.108]}
  Voxel Spacing      : [1.20001, 1, 1]
  Intensity Range    : [0, 2468.78]
  Mean Intensity     : 124.467
  Direction Cos Mtx. : 
-0.999775 0.019162 0.00906865
-0.0191628 -0.999816 -6.11378e-12
0.00906699 -0.000173781 0.999959

  Voxel->RAS x-form  : 
  Image Metadata: 
    ITK_FileNotes = mnc2nii there.mnc back.nii
    bitpix = 32
    cal_max = 0
    cal_min = 0
    datatype = 16
    descrip = mnc2nii there.mnc back.nii
    dim[0] = 3
    dim[1] = 170
    dim[2] = 256
    dim[3] = 256
    dim[4] = 1
    dim[5] = 1
    dim[6] = 0
    dim[7] = 0
    intent_code = 0
    intent_p1 = 0
    intent_p2 = 0
    intent_p3 = 0
    pixdim[0] = 0
    pixdim[1] = 1.20001
    pixdim[2] = 1
    pixdim[3] = 1
    pixdim[4] = 0
    pixdim[5] = 1
    pixdim[6] = 0
    pixdim[7] = 0
    qform_code = 0
    qoffset_x = 0
    qoffset_y = 0
    qoffset_z = 0
    quatern_b = 0
    quatern_c = 0
    quatern_d = 0
    scl_inter = 0
    scl_slope = 0
    sform_code = 1
    slice_duration = 0
    slice_end = 0
    slice_start = 0
    srow_x = 1.19974 -0.019162 -0.00906865 -98.8966
    srow_y = 0.0229955 0.999816 6.11378e-12 -131.133
    srow_z = 0.0108805 -0.000173781 0.999959 -127.892
    toffset = 0
    vox_offset = 352

orig.nii and back.nii do not have the same orientation anymore, I expect that they should.

See email for attachment.