Skip to content

Commit 9a988d6

Browse files
authored
Merge pull request #2201 from salma1601/afni_3dCM
Afni 3dCM
2 parents 2f422f0 + d130211 commit 9a988d6

File tree

3 files changed

+160
-1
lines changed

3 files changed

+160
-1
lines changed

nipype/interfaces/afni/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
TShift, Volreg, Warp, QwarpPlusMinus, Qwarp)
2121
from .svm import (SVMTest, SVMTrain)
2222
from .utils import (ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat,
23-
Bucket, Calc, Cat, CatMatvec, Copy, Dot,
23+
Bucket, Calc, Cat, CatMatvec, CenterMass, Copy, Dot,
2424
Edge3, Eval, FWHMx, MaskTool, Merge, Notes, NwarpApply,
2525
OneDToolPy,
2626
Refit, Resample, TCat, TCatSubBrick, TStat, To3D, Unifize,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..utils import CenterMass
4+
5+
6+
def test_CenterMass_inputs():
7+
input_map = dict(all_rois=dict(argstr='-all_rois',
8+
),
9+
args=dict(argstr='%s',
10+
),
11+
automask=dict(argstr='-automask',
12+
),
13+
cm_file=dict(argstr='> %s',
14+
descr='File to write center of mass to',
15+
hash_files=False,
16+
keep_extension=False,
17+
name_source='in_file',
18+
name_template='%s_cm.out',
19+
position=-1,
20+
),
21+
environ=dict(nohash=True,
22+
usedefault=True,
23+
),
24+
ignore_exception=dict(nohash=True,
25+
usedefault=True,
26+
),
27+
in_file=dict(argstr='%s',
28+
copyfile=True,
29+
mandatory=True,
30+
position=-2,
31+
),
32+
local_ijk=dict(argstr='-local_ijk',
33+
),
34+
mask_file=dict(argstr='-mask %s',
35+
),
36+
roi_vals=dict(argstr='-roi_vals %s',
37+
),
38+
set_cm=dict(argstr='-set %f %f %f',
39+
),
40+
terminal_output=dict(nohash=True,
41+
),
42+
)
43+
inputs = CenterMass.input_spec()
44+
45+
for key, metadata in list(input_map.items()):
46+
for metakey, value in list(metadata.items()):
47+
assert getattr(inputs.traits()[key], metakey) == value
48+
49+
50+
def test_CenterMass_outputs():
51+
output_map = dict(cm=dict(),
52+
cm_file=dict(),
53+
out_file=dict(),
54+
)
55+
outputs = CenterMass.output_spec()
56+
57+
for key, metadata in list(output_map.items()):
58+
for metakey, value in list(metadata.items()):
59+
assert getattr(outputs.traits()[key], metakey) == value

nipype/interfaces/afni/utils.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,106 @@ def _format_arg(self, name, spec, value):
642642
return spec.argstr%(' '.join([i[0]+' -'+i[1] for i in value]))
643643
return super(CatMatvec, self)._format_arg(name, spec, value)
644644

645+
646+
class CenterMassInputSpec(CommandLineInputSpec):
647+
in_file = File(
648+
desc='input file to 3dCM',
649+
argstr='%s',
650+
position=-2,
651+
mandatory=True,
652+
exists=True,
653+
copyfile=True)
654+
cm_file = File(
655+
name_source='in_file',
656+
name_template='%s_cm.out',
657+
hash_files=False,
658+
keep_extension=False,
659+
descr="File to write center of mass to",
660+
argstr="> %s",
661+
position=-1)
662+
mask_file = File(
663+
desc='Only voxels with nonzero values in the provided mask will be '
664+
'averaged.',
665+
argstr='-mask %s',
666+
exists=True)
667+
automask = traits.Bool(
668+
desc='Generate the mask automatically',
669+
argstr='-automask')
670+
set_cm = traits.Tuple(
671+
(traits.Float(), traits.Float(), traits.Float()),
672+
desc='After computing the center of mass, set the origin fields in '
673+
'the header so that the center of mass will be at (x,y,z) in '
674+
'DICOM coords.',
675+
argstr='-set %f %f %f')
676+
local_ijk = traits.Bool(
677+
desc='Output values as (i,j,k) in local orienation',
678+
argstr='-local_ijk')
679+
roi_vals = traits.List(
680+
traits.Int,
681+
desc='Compute center of mass for each blob with voxel value of v0, '
682+
'v1, v2, etc. This option is handy for getting ROI centers of '
683+
'mass.',
684+
argstr='-roi_vals %s')
685+
all_rois = traits.Bool(
686+
desc='Don\'t bother listing the values of ROIs you want: The program '
687+
'will find all of them and produce a full list',
688+
argstr='-all_rois')
689+
690+
691+
class CenterMassOutputSpec(TraitedSpec):
692+
out_file = File(
693+
exists=True,
694+
desc='output file')
695+
cm_file = File(
696+
desc='file with the center of mass coordinates')
697+
cm = traits.Either(
698+
traits.Tuple(traits.Float(), traits.Float(), traits.Float()),
699+
traits.List(traits.Tuple(traits.Float(), traits.Float(),
700+
traits.Float())),
701+
desc='center of mass')
702+
703+
704+
class CenterMass(AFNICommandBase):
705+
"""Computes center of mass using 3dCM command
706+
707+
.. note::
708+
709+
By default, the output is (x,y,z) values in DICOM coordinates. But
710+
as of Dec, 2016, there are now command line switches for other options.
711+
712+
713+
For complete details, see the `3dCM Documentation.
714+
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dCM.html>`_
715+
716+
Examples
717+
========
718+
719+
>>> from nipype.interfaces import afni
720+
>>> cm = afni.CenterMass()
721+
>>> cm.inputs.in_file = 'structural.nii'
722+
>>> cm.inputs.cm_file = 'cm.txt'
723+
>>> cm.inputs.roi_vals = [2, 10]
724+
>>> cm.cmdline # doctest: +ALLOW_UNICODE
725+
'3dCM -roi_vals 2 10 structural.nii > cm.txt'
726+
>>> res = 3dcm.run() # doctest: +SKIP
727+
"""
728+
729+
_cmd = '3dCM'
730+
input_spec = CenterMassInputSpec
731+
output_spec = CenterMassOutputSpec
732+
733+
def _list_outputs(self):
734+
outputs = super(CenterMass, self)._list_outputs()
735+
outputs['out_file'] = os.path.abspath(self.inputs.in_file)
736+
outputs['cm_file'] = os.path.abspath(self.inputs.cm_file)
737+
sout = np.loadtxt(outputs['cm_file']) # pylint: disable=E1101
738+
if len(sout) > 1:
739+
outputs['cm'] = [tuple(s) for s in sout]
740+
else:
741+
outputs['cm'] = tuple(sout)
742+
return outputs
743+
744+
645745
class CopyInputSpec(AFNICommandInputSpec):
646746
in_file = File(
647747
desc='input file to 3dcopy',

0 commit comments

Comments
 (0)