Skip to content

Support for motion parameters produced by AFNI (FD) #1840

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 4 commits into from
Feb 24, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions nipype/algorithms/confounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,10 @@ def _list_outputs(self):


class FramewiseDisplacementInputSpec(BaseInterfaceInputSpec):
in_plots = File(exists=True, mandatory=True, desc='motion parameters as written by FSL MCFLIRT')
in_file = File(exists=True, mandatory=True, desc='motion parameters as written by FSL MCFLIRT or AFNI 3dvolreg')
parameter_source = traits.Enum("FSL", "AFNI",
Copy link
Member

Choose a reason for hiding this comment

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

FSFAST can be supported pretty easily, given AFNI support. See other comment. And I believe SPM and FSL parameter files are the same?

desc="Source of movement parameters",
mandatory=True)
radius = traits.Float(50, usedefault=True,
desc='radius in mm to calculate angular FDs, 50mm is the '
'default since it is used in Power et al. 2012')
Expand Down Expand Up @@ -249,9 +252,11 @@ class FramewiseDisplacement(BaseInterface):
}]

def _run_interface(self, runtime):
mpars = np.loadtxt(self.inputs.in_plots) # mpars is N_t x 6
mpars = np.loadtxt(self.inputs.in_file) # mpars is N_t x 6
diff = mpars[:-1, :] - mpars[1:, :]
diff[:, :3] *= self.inputs.radius
if self.inputs.parameter_source == "AFNI":
diff[:, :3] *= (np.pi / 180)
fd_res = np.abs(diff).sum(axis=1)
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest modifying the mpars rather than the diff, just to make it a little clearer what's going on. Following also adds FSFAST support.

mpars = np.loadtxt(self.inputs.in_file)  # mpars is N_t x 6 (N_t x 7 for FSFAST)
if self.inputs.parameter_source in ('AFNI', 'FSFAST'):
    mpars = mpars[np.asarray([4, 5, 3, 1, 2, 0]) + (mpars.shape[1] > 6)]
    mpars[:, 3:] *= np.pi / 180
diff = np.diff(mpars, axis=0)
diff[:, :3] *= self.inputs.radius
fd_res = np.abs(diff).sum(axis=1)

Copy link
Member

Choose a reason for hiding this comment

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

UGH. Do not use the above, which re-sorts the parameters. This can be done more simply by taking the last 6 columns.

mpars = np.loadtxt(self.inputs.in_file)[:, -6:]  # mpars is N_t x 6
if self.inputs.parameter_source in ('AFNI', 'FSFAST'):
    mpars[:, :3] *= np.pi / 180
diff = np.diff(mpars, axis=0)
diff[:, :3] *= self.inputs.radius
fd_res = np.abs(diff).sum(axis=1)

And this doesn't handle SPM, contra my previous comment, because SPM puts its rotation parameters first. (Though my confused comments may support the idea of solving the "load normalized motion params" issue once and reusing.)


self._results = {
Expand Down
2 changes: 1 addition & 1 deletion nipype/algorithms/tests/test_auto_FramewiseDisplacement.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def test_FramewiseDisplacement_inputs():
ignore_exception=dict(nohash=True,
usedefault=True,
),
in_plots=dict(mandatory=True,
in_file=dict(mandatory=True,
),
normalize=dict(usedefault=True,
),
Expand Down
5 changes: 3 additions & 2 deletions nipype/algorithms/tests/test_confounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
def test_fd(tmpdir):
tempdir = str(tmpdir)
ground_truth = np.loadtxt(example_data('fsl_motion_outliers_fd.txt'))
fdisplacement = FramewiseDisplacement(in_plots=example_data('fsl_mcflirt_movpar.txt'),
out_file=tempdir + '/fd.txt')
fdisplacement = FramewiseDisplacement(in_file=example_data('fsl_mcflirt_movpar.txt'),
out_file=tempdir + '/fd.txt',
parameter_source="FSL")
res = fdisplacement.run()

with open(res.outputs.out_file) as all_lines:
Expand Down