Skip to content

Commit 50862c1

Browse files
authored
Merge pull request #2740 from rciric/master
[ENH] Add afni.LocalStat and afni.ReHo, update afni.ROIStats inputs
2 parents 502fc63 + 8c65b81 commit 50862c1

File tree

6 files changed

+574
-31
lines changed

6 files changed

+574
-31
lines changed

nipype/interfaces/afni/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from .utils import (
1919
ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat, Bucket, Calc, Cat,
2020
CatMatvec, CenterMass, ConvertDset, Copy, Dot, Edge3, Eval, FWHMx,
21-
LocalBistat, MaskTool, Merge, Notes, NwarpApply, NwarpAdjust, NwarpCat,
22-
OneDToolPy, Refit, Resample, TCat, TCatSubBrick, TStat, To3D, Unifize,
23-
Undump, ZCutUp, GCOR, Zcat, Zeropad)
21+
LocalBistat, Localstat, MaskTool, Merge, Notes, NwarpApply, NwarpAdjust,
22+
NwarpCat, OneDToolPy, Refit, ReHo, Resample, TCat, TCatSubBrick, TStat,
23+
To3D, Unifize, Undump, ZCutUp, GCOR, Zcat, Zeropad)
2424
from .model import (Deconvolve, Remlfit, Synthesize)

nipype/interfaces/afni/preprocess.py

+111-19
Original file line numberDiff line numberDiff line change
@@ -1802,28 +1802,109 @@ class QualityIndex(CommandLine):
18021802

18031803
class ROIStatsInputSpec(CommandLineInputSpec):
18041804
in_file = File(
1805-
desc='input file to 3dROIstats',
1805+
desc='input dataset',
18061806
argstr='%s',
1807-
position=-1,
1807+
position=-2,
18081808
mandatory=True,
18091809
exists=True)
1810-
mask = File(desc='input mask', argstr='-mask %s', position=3, exists=True)
1810+
mask = File(desc='input mask', argstr='-mask %s', position=3, exists=True,
1811+
deprecated='1.1.4', new_name='mask_file')
1812+
mask_file = File(desc='input mask', argstr='-mask %s', exists=True)
18111813
mask_f2short = traits.Bool(
18121814
desc='Tells the program to convert a float mask to short integers, '
18131815
'by simple rounding.',
1814-
argstr='-mask_f2short',
1815-
position=2)
1816-
quiet = traits.Bool(desc='execute quietly', argstr='-quiet', position=1)
1816+
argstr='-mask_f2short')
1817+
num_roi = traits.Int(
1818+
desc='Forces the assumption that the mask dataset\'s ROIs are '
1819+
'denoted by 1 to n inclusive. Normally, the program '
1820+
'figures out the ROIs on its own. This option is '
1821+
'useful if a) you are certain that the mask dataset '
1822+
'has no values outside the range [0 n], b) there may '
1823+
'be some ROIs missing between [1 n] in the mask data-'
1824+
'set and c) you want those columns in the output any-'
1825+
'way so the output lines up with the output from other '
1826+
'invocations of 3dROIstats.',
1827+
argstr='-numroi %s')
1828+
zerofill = traits.Str(
1829+
requires=['num_roi'],
1830+
desc='For ROI labels not found, use the provided string instead of '
1831+
'a \'0\' in the output file. Only active if `num_roi` is '
1832+
'enabled.',
1833+
argstr='-zerofill %s')
1834+
roisel = traits.File(
1835+
exists=True,
1836+
desc='Only considers ROIs denoted by values found in the specified '
1837+
'file. Note that the order of the ROIs as specified in the file '
1838+
'is not preserved. So an SEL.1D of \'2 8 20\' produces the same '
1839+
'output as \'8 20 2\'',
1840+
argstr='-roisel %s')
1841+
debug = traits.Bool(
1842+
desc='print debug information',
1843+
argstr='-debug')
1844+
quiet = traits.Bool(
1845+
desc='execute quietly',
1846+
argstr='-quiet')
1847+
nomeanout = traits.Bool(
1848+
desc='Do not include the (zero-inclusive) mean among computed stats',
1849+
argstr='-nomeanout')
1850+
nobriklab = traits.Bool(
1851+
desc='Do not print the sub-brick label next to its index',
1852+
argstr='-nobriklab')
1853+
format1D = traits.Bool(
1854+
xor=['format1DR'],
1855+
desc='Output results in a 1D format that includes commented labels',
1856+
argstr='-1Dformat')
1857+
format1DR = traits.Bool(
1858+
xor=['format1D'],
1859+
desc='Output results in a 1D format that includes uncommented '
1860+
'labels. May not work optimally with typical 1D functions, '
1861+
'but is useful for R functions.',
1862+
argstr='-1DRformat')
1863+
_stat_names = ['mean', 'sum', 'voxels', 'minmax', 'sigma', 'median',
1864+
'mode', 'summary', 'zerominmax', 'zerosigma', 'zeromedian',
1865+
'zeromode']
1866+
stat = InputMultiObject(
1867+
traits.Enum(_stat_names),
1868+
desc='statistics to compute. Options include: '
1869+
' * mean = Compute the mean using only non_zero voxels.'
1870+
' Implies the opposite for the mean computed '
1871+
' by default.\n'
1872+
' * median = Compute the median of nonzero voxels\n'
1873+
' * mode = Compute the mode of nonzero voxels.'
1874+
' (integral valued sets only)\n'
1875+
' * minmax = Compute the min/max of nonzero voxels\n'
1876+
' * sum = Compute the sum using only nonzero voxels.\n'
1877+
' * voxels = Compute the number of nonzero voxels\n'
1878+
' * sigma = Compute the standard deviation of nonzero'
1879+
' voxels\n'
1880+
'Statistics that include zero-valued voxels:\n'
1881+
' * zerominmax = Compute the min/max of all voxels.\n'
1882+
' * zerosigma = Compute the standard deviation of all'
1883+
' voxels.\n'
1884+
' * zeromedian = Compute the median of all voxels.\n'
1885+
' * zeromode = Compute the mode of all voxels.\n'
1886+
' * summary = Only output a summary line with the grand '
1887+
' mean across all briks in the input dataset.'
1888+
' This option cannot be used with nomeanout.\n'
1889+
'More that one option can be specified.',
1890+
argstr='%s...')
1891+
out_file = File(
1892+
name_template='%s_roistat.1D',
1893+
desc='output file',
1894+
keep_extension=False,
1895+
argstr='> %s',
1896+
name_source='in_file',
1897+
position=-1)
18171898

18181899

18191900
class ROIStatsOutputSpec(TraitedSpec):
1820-
stats = File(desc='output tab separated values file', exists=True)
1901+
out_file = File(desc='output tab-separated values file', exists=True)
18211902

18221903

18231904
class ROIStats(AFNICommandBase):
18241905
"""Display statistics over masked regions
18251906
1826-
For complete details, see the `3dROIstats Documentation.
1907+
For complete details, see the `3dROIstats Documentation
18271908
<https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dROIstats.html>`_
18281909
18291910
Examples
@@ -1832,10 +1913,11 @@ class ROIStats(AFNICommandBase):
18321913
>>> from nipype.interfaces import afni
18331914
>>> roistats = afni.ROIStats()
18341915
>>> roistats.inputs.in_file = 'functional.nii'
1835-
>>> roistats.inputs.mask = 'skeleton_mask.nii.gz'
1836-
>>> roistats.inputs.quiet = True
1916+
>>> roistats.inputs.mask_file = 'skeleton_mask.nii.gz'
1917+
>>> roistats.inputs.stat = ['mean', 'median', 'voxels']
1918+
>>> roistats.inputs.nomeanout = True
18371919
>>> roistats.cmdline
1838-
'3dROIstats -quiet -mask skeleton_mask.nii.gz functional.nii'
1920+
'3dROIstats -mask skeleton_mask.nii.gz -nomeanout -nzmean -nzmedian -nzvoxels functional.nii > functional_roistat.1D'
18391921
>>> res = roistats.run() # doctest: +SKIP
18401922
18411923
"""
@@ -1844,14 +1926,24 @@ class ROIStats(AFNICommandBase):
18441926
input_spec = ROIStatsInputSpec
18451927
output_spec = ROIStatsOutputSpec
18461928

1847-
def aggregate_outputs(self, runtime=None, needed_outputs=None):
1848-
outputs = self._outputs()
1849-
output_filename = 'roi_stats.csv'
1850-
with open(output_filename, 'w') as f:
1851-
f.write(runtime.stdout)
1852-
1853-
outputs.stats = os.path.abspath(output_filename)
1854-
return outputs
1929+
def _format_arg(self, name, spec, value):
1930+
_stat_dict = {
1931+
'mean': '-nzmean',
1932+
'median': '-nzmedian',
1933+
'mode': '-nzmode',
1934+
'minmax': '-nzminmax',
1935+
'sigma': '-nzsigma',
1936+
'voxels': '-nzvoxels',
1937+
'sum': '-nzsum',
1938+
'summary': '-summary',
1939+
'zerominmax': '-minmax',
1940+
'zeromedian': '-median',
1941+
'zerosigma': '-sigma',
1942+
'zeromode': '-mode'
1943+
}
1944+
if name == 'stat':
1945+
value = [_stat_dict[v] for v in value]
1946+
return super(ROIStats, self)._format_arg(name, spec, value)
18551947

18561948

18571949
class RetroicorInputSpec(AFNICommandInputSpec):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..utils import Localstat
4+
5+
6+
def test_Localstat_inputs():
7+
input_map = dict(
8+
args=dict(argstr='%s', ),
9+
automask=dict(argstr='-automask', ),
10+
environ=dict(
11+
nohash=True,
12+
usedefault=True,
13+
),
14+
grid_rmode=dict(
15+
argstr='-grid_rmode %s',
16+
requires=['reduce_restore_grid'],
17+
),
18+
in_file=dict(
19+
argstr='%s',
20+
mandatory=True,
21+
position=-1,
22+
),
23+
mask_file=dict(argstr='-mask %s', ),
24+
neighborhood=dict(
25+
argstr="-nbhd '%s(%s)'",
26+
mandatory=True,
27+
),
28+
nonmask=dict(argstr='-use_nonmask', ),
29+
num_threads=dict(
30+
nohash=True,
31+
usedefault=True,
32+
),
33+
out_file=dict(
34+
argstr='-prefix %s',
35+
keep_extension=True,
36+
name_source='in_file',
37+
name_template='%s_localstat',
38+
position=0,
39+
),
40+
outputtype=dict(),
41+
overwrite=dict(argstr='-overwrite', ),
42+
quiet=dict(argstr='-quiet', ),
43+
reduce_grid=dict(
44+
argstr='-reduce_grid %s',
45+
xor=['reduce_restore_grid', 'reduce_max_vox'],
46+
),
47+
reduce_max_vox=dict(
48+
argstr='-reduce_max_vox %s',
49+
xor=['reduce_restore_grid', 'reduce_grid'],
50+
),
51+
reduce_restore_grid=dict(
52+
argstr='-reduce_restore_grid %s',
53+
xor=['reduce_max_vox', 'reduce_grid'],
54+
),
55+
stat=dict(
56+
argstr='-stat %s...',
57+
mandatory=True,
58+
),
59+
)
60+
inputs = Localstat.input_spec()
61+
62+
for key, metadata in list(input_map.items()):
63+
for metakey, value in list(metadata.items()):
64+
assert getattr(inputs.traits()[key], metakey) == value
65+
def test_Localstat_outputs():
66+
output_map = dict(out_file=dict(), )
67+
outputs = Localstat.output_spec()
68+
69+
for key, metadata in list(output_map.items()):
70+
for metakey, value in list(metadata.items()):
71+
assert getattr(outputs.traits()[key], metakey) == value

nipype/interfaces/afni/tests/test_auto_ROIStats.py

+30-8
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,48 @@
66
def test_ROIStats_inputs():
77
input_map = dict(
88
args=dict(argstr='%s', ),
9+
debug=dict(argstr='-debug', ),
910
environ=dict(
1011
nohash=True,
1112
usedefault=True,
1213
),
14+
format1D=dict(
15+
argstr='-1Dformat',
16+
xor=['format1DR'],
17+
),
18+
format1DR=dict(
19+
argstr='-1DRformat',
20+
xor=['format1D'],
21+
),
1322
in_file=dict(
1423
argstr='%s',
1524
mandatory=True,
16-
position=-1,
25+
position=-2,
1726
),
1827
mask=dict(
1928
argstr='-mask %s',
29+
deprecated='1.1.4',
30+
new_name='mask_file',
2031
position=3,
2132
),
22-
mask_f2short=dict(
23-
argstr='-mask_f2short',
24-
position=2,
33+
mask_f2short=dict(argstr='-mask_f2short', ),
34+
mask_file=dict(argstr='-mask %s', ),
35+
nobriklab=dict(argstr='-nobriklab', ),
36+
nomeanout=dict(argstr='-nomeanout', ),
37+
num_roi=dict(argstr='-numroi %s', ),
38+
out_file=dict(
39+
argstr='> %s',
40+
keep_extension=False,
41+
name_source='in_file',
42+
name_template='%s_roistat.1D',
43+
position=-1,
2544
),
26-
quiet=dict(
27-
argstr='-quiet',
28-
position=1,
45+
quiet=dict(argstr='-quiet', ),
46+
roisel=dict(argstr='-roisel %s', ),
47+
stat=dict(argstr='%s...', ),
48+
zerofill=dict(
49+
argstr='-zerofill %s',
50+
requires=['num_roi'],
2951
),
3052
)
3153
inputs = ROIStats.input_spec()
@@ -34,7 +56,7 @@ def test_ROIStats_inputs():
3456
for metakey, value in list(metadata.items()):
3557
assert getattr(inputs.traits()[key], metakey) == value
3658
def test_ROIStats_outputs():
37-
output_map = dict(stats=dict(), )
59+
output_map = dict(out_file=dict(), )
3860
outputs = ROIStats.output_spec()
3961

4062
for key, metadata in list(output_map.items()):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
2+
from __future__ import unicode_literals
3+
from ..utils import ReHo
4+
5+
6+
def test_ReHo_inputs():
7+
input_map = dict(
8+
args=dict(argstr='%s', ),
9+
chi_sq=dict(argstr='-chi_sq', ),
10+
ellipsoid=dict(
11+
argstr='-neigh_X %s -neigh_Y %s -neigh_Z %s',
12+
xor=['sphere', 'neighborhood'],
13+
),
14+
environ=dict(
15+
nohash=True,
16+
usedefault=True,
17+
),
18+
in_file=dict(
19+
argstr='-inset %s',
20+
mandatory=True,
21+
position=1,
22+
),
23+
label_set=dict(argstr='-in_rois %s', ),
24+
mask_file=dict(argstr='-mask %s', ),
25+
neighborhood=dict(
26+
argstr='-nneigh %s',
27+
xor=['sphere', 'ellipsoid'],
28+
),
29+
out_file=dict(
30+
argstr='-prefix %s',
31+
keep_extension=True,
32+
name_source='in_file',
33+
name_template='%s_reho',
34+
position=0,
35+
),
36+
overwrite=dict(argstr='-overwrite', ),
37+
sphere=dict(
38+
argstr='-neigh_RAD %s',
39+
xor=['neighborhood', 'ellipsoid'],
40+
),
41+
)
42+
inputs = ReHo.input_spec()
43+
44+
for key, metadata in list(input_map.items()):
45+
for metakey, value in list(metadata.items()):
46+
assert getattr(inputs.traits()[key], metakey) == value
47+
def test_ReHo_outputs():
48+
output_map = dict(
49+
out_file=dict(),
50+
out_vals=dict(),
51+
)
52+
outputs = ReHo.output_spec()
53+
54+
for key, metadata in list(output_map.items()):
55+
for metakey, value in list(metadata.items()):
56+
assert getattr(outputs.traits()[key], metakey) == value

0 commit comments

Comments
 (0)