Skip to content

[ENH] Ensure that headers are consistent along the process #743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Oct 11, 2017

Conversation

oesteban
Copy link
Member

@oesteban oesteban commented Oct 7, 2017

This PR fixes #710.

The problem was the corruption of xform matrices (sform, qform). Requires nipreps/niworkflows#202

@oesteban oesteban requested a review from effigies October 8, 2017 05:40
Copy link
Member

@effigies effigies left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed this first. A couple quick comments, but I think this will probably be fine when nipreps/niworkflows#202 goes in.

@@ -31,8 +32,8 @@ class MCFLIRT2ITKInputSpec(BaseInterfaceInputSpec):
desc='input image for spatial reference')
in_source = File(exists=True, mandatory=True,
desc='input image for spatial source')
nprocs = traits.Int(1, usedefault=True, nohash=True,
desc='number of parallel processes')
n_procs = traits.Int(1, usedefault=True, nohash=True,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you set this to num_threads, then it will be synced with node.n_procs.

@@ -71,10 +87,13 @@ class MultiApplyTransformsInputSpec(ApplyTransformsInputSpec):
' through the fourth dimension')
nprocs = traits.Int(1, usedefault=True, nohash=True,
desc='number of parallel processes')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here with num_threads.

@@ -81,10 +82,13 @@ def init_enhance_and_skullstrip_bold_wf(name='enhance_and_skullstrip_bold_wf',
name='combine_masks')
apply_mask = pe.Node(fsl.ApplyMask(),
name='apply_mask')
copy_xform = pe.Node(CopyXForm(), name='copy_xform',
mem_gb=0.1, run_without_submitting=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looked at this again. The only ANTs tool here is N4BiasFieldCorrection, which we already updated to have copy_header=True option built-in in nipype. I think this node isn't actually needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That surprised me the first time. If you check output of this workflow, you'll see that it actually changes xforms. A suspicious 'descrip' field of 'FSL 5.0' makes me think that bet, apply mask or image maths may also change xforms. I don't see a problem on explicitly making sure that xforms are OK with this node.

This change of xform was the origin of #710.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's maddening. I'm going to need to get mad about this again in the morning. Sorry if I've been asking dumb questions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually unifize that seems to be causing issues here:

$ fslhd skullstrip_first_pass/ref_image_corrected_brain.nii.gz | grep -A 14 qform_name 
qform_name     Scanner Anat
qform_code     1
qto_xyz:1      -3.125000  0.000000  -0.000000  97.931519
qto_xyz:2      0.000000  3.125000  -0.000000  -68.019211
qto_xyz:3      0.000000  0.000000  4.000000  -106.650566
qto_xyz:4      0.000000  0.000000  0.000000  1.000000
qform_xorient  Right-to-Left
qform_yorient  Posterior-to-Anterior
qform_zorient  Inferior-to-Superior
sform_name     Aligned Anat
sform_code     2
sto_xyz:1      -3.125000  0.000000  0.000000  98.909752
sto_xyz:2      0.000000  3.125000  0.000000  -110.716141
sto_xyz:3      0.000000  0.000000  4.000000  -51.800713
sto_xyz:4      0.000000  0.000000  0.000000  1.000000
$ fslhd unifize/uni.nii.gz | grep -A 14 qform_name 
qform_name     Talairach
qform_code     3
qto_xyz:1      -3.125000  -0.000000  -0.000000  98.909752
qto_xyz:2      0.000000  3.125000  -0.000000  -110.716141
qto_xyz:3      -0.000000  0.000000  4.000000  -51.800713
qto_xyz:4      0.000000  0.000000  0.000000  1.000000
qform_xorient  Right-to-Left
qform_yorient  Posterior-to-Anterior
qform_zorient  Inferior-to-Superior
sform_name     Talairach
sform_code     3
sto_xyz:1      -3.125000  -0.000000  -0.000000  98.909752
sto_xyz:2      -0.000000  3.125000  -0.000000  -110.716141
sto_xyz:3      0.000000  0.000000  4.000000  -51.800713
sto_xyz:4      0.000000  0.000000  0.000000  1.000000

... What?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've submitted an issue (afni/afni#65), but unless neurodebian starts updating AFNI regularly (or we start using a more recent neurodocker build), we're still going to need to work around this for the foreseeable future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! For the 'descrip' header I assumed it was FSL, but that wouldn't rule out unifize.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, it looks like this is a WONTFIX. We'll want to consider how we interface with AFNI tools in general.

Thinking more long-term, I've proposed nipy/nipype#2223.

@oesteban
Copy link
Member Author

oesteban commented Oct 9, 2017

I'm double checking this on the dataset with freesurfer on. Also checking if this fixes also #708

@oesteban
Copy link
Member Author

Bad news: this PR either does not fix #710 when freesurfer is used or I'm seeing #703 again for reusing the pre-computed freesurfer. Either way I need to get to the bottom before merging this.

@oesteban
Copy link
Member Author

So, with the new code I don't see the problem of #708 on ds101, sub-06. I'll check more subjects from that PR.

On the other hand, I repeated (reusing pre-computed freesurfer) on ds001, sub-02 and this issue is still happening.

@oesteban
Copy link
Member Author

oesteban commented Oct 10, 2017

I am considering that we are now dealing with a side effect of #741 for two reasons:

  • I've checked the headers of the inputs (the reference BOLD for bbregister and the split volumes for the resampling step) and now they match correctly. This was wrong before the changes in this PR.
  • The BBR path seems to work well (as a consequence of the previous fix) so we are probably looking at a bbregister problem and the conversion of matrices to ITK.

WDYT @effigies?

@effigies
Copy link
Member

Ugh. That's possible. (Though at least on my tests, I get the exact same results whether we go through your branch or 0.6.5.)

@effigies
Copy link
Member

Can you update this line?

https://github.com/poldracklab/fmriprep/blob/2a2ac713bfa61c36123ea05aa227759879c58eb5/fmriprep/workflows/util.py#L239

With the latest nipype updates, we can use:

fs.ConcatenateLTA(out_type='RAS2RAS')

I don't think it should make a difference, since it should do the RAS2RAS conversion in the process of creating the ITK affine, but just to check...

@effigies
Copy link
Member

Oh, I think I see the issue. The bbregister-targeted file is T1w, but the FLIRT-targeted file is T1w downsampled to BOLD resolution. There's been no update step targeting the BOLD-resolution T1w file.

@oesteban
Copy link
Member Author

The resulting ITK transform should be in mm (meaning, the resolution of the target space is not relevant). I'm going to check apply the transform using the full-resolution T1w as reference and I bet we will get the same.

@effigies
Copy link
Member

Yeah, I just did that. Made no difference...

@oesteban
Copy link
Member Author

Basically, what the affine transform does is: for each node of the sampling grid, get the coordinates in mm (physical space) and find the coordinates in mm that correspond to that point in moving space.

Therefore, changing the fixed image resolution you only change the location of the points you want to find in moving space. The transform is the same for both images (if it is defined in mm like ITK, this changes if you define transforms in pixels like legacy registration algorithms).

@oesteban
Copy link
Member Author

The out_type='RAS2RAS' did not make any difference :(

@effigies
Copy link
Member

Okay, if I manually lta_convert to FSL and then c3d_affine_tool to ITK, then I get alignment. Want me to send you a patch, or should we keep going until we find something more elegant?

@oesteban
Copy link
Member Author

oesteban commented Oct 10, 2017 via email

@effigies
Copy link
Member

I don't love it, but I added a hacky solution in oesteban#2. I've verified that it fixes alignment for me.

I'm going to ping FreeSurfer to see if lta_convert can get fixed by 6.0.1.

Also, so we have it written down somewhere, c3d_affine_tool can do both fwd and inv transforms in a single shot. I just didn't want to go through another round of nipype editing to get this in.

c3d_affine_tool -ref <ref> -src <src> in_xfm.mat -fsl2ras -oitk itk.txt -inv -oitk itk_inv.txt

Turns out order of operations matters a whole lot, though, which also makes designing an update to the interface a little weird. I guess you could add an inverse_itk_transform = File(argstr='-inv -oitk %s', position=6).

@oesteban
Copy link
Member Author

oesteban commented Oct 10, 2017

Just note that the fix worked well on ds001, sub-02. I'll test more subjects from #708

@effigies effigies merged commit 4d25027 into nipreps:master Oct 11, 2017
@oesteban
Copy link
Member Author

Bummer, I just noticed this error in the end of the report https://320-53608443-gh.circle-artifacts.com/0/home/ubuntu/ds054/out/fmriprep/sub-100185.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CompCor contours misaligned with reference BOLD image
2 participants