Skip to content

Commit a8243aa

Browse files
ShotgunosineDylan
authored andcommitted
[FIX] Address review comments
1 parent 27ba736 commit a8243aa

File tree

4 files changed

+67
-64
lines changed

4 files changed

+67
-64
lines changed

nipype/interfaces/afni/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
"""
99

1010
from .base import Info
11-
from .preprocess import (AlignEpiAnatPy,Allineate, Automask,
12-
AutoTcorrelate,AutoTLRC,
11+
from .preprocess import (AlignEpiAnatPy, Allineate, Automask,
12+
AutoTcorrelate, AutoTLRC,
1313
Bandpass, BlurInMask, BlurToFWHM,
1414
ClipLevel, DegreeCentrality, Despike,
1515
Detrend, ECM, Fim, Fourier, Hist, LFCD,
@@ -19,8 +19,8 @@
1919
TNorm,
2020
TShift, Volreg, Warp, QwarpPlusMinus, Qwarp)
2121
from .svm import (SVMTest, SVMTrain)
22-
from .utils import (ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat, Bucket,
23-
Calc, Cat, CatMatvec, Copy, Dot,
22+
from .utils import (ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat,
23+
Bucket, Calc, Cat, CatMatvec, Copy, Dot,
2424
Edge3, Eval, FWHMx, MaskTool, Merge, Notes, NwarpApply,
2525
OneDToolPy,
2626
Refit, Resample, TCat, TStat, To3D, Unifize, ZCutUp, GCOR,

nipype/interfaces/afni/base.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import os
1010
from sys import platform
11+
from distutils import spawn
1112

1213
from ... import logging
1314
from ...utils.filemanip import split_filename, fname_presuffix
@@ -144,7 +145,6 @@ class AFNICommandOutputSpec(TraitedSpec):
144145
out_file = File(desc='output file',
145146
exists=True)
146147

147-
148148
class AFNICommand(AFNICommandBase):
149149
"""Shared options for several AFNI commands """
150150
input_spec = AFNICommandInputSpec
@@ -283,3 +283,20 @@ def no_afni():
283283
if Info.version() is None:
284284
return True
285285
return False
286+
287+
288+
class AFNIPythonCommandInputSpec(CommandLineInputSpec):
289+
outputtype = traits.Enum('AFNI', list(Info.ftypes.keys()),
290+
desc='AFNI output filetype')
291+
py27_path = traits.Either('python2', File(exists=True),
292+
usedefault=True,
293+
default='python2')
294+
295+
class AFNIPythonCommand(AFNICommand):
296+
@property
297+
def cmd(self):
298+
return spawn.find_executable(super(AFNIPythonCommand, self).cmd)
299+
300+
@property
301+
def cmdline(self):
302+
return "{} {}".format(self.inputs.py27_path, super(AFNIPythonCommand, self).cmdline)

nipype/interfaces/afni/preprocess.py

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
import os
1616
import os.path as op
17-
from distutils import spawn
1817

1918
from ...utils.filemanip import (load_json, save_json, split_filename)
2019
from ..base import (
@@ -23,7 +22,7 @@
2322

2423
from .base import (
2524
AFNICommandBase, AFNICommand, AFNICommandInputSpec, AFNICommandOutputSpec,
26-
Info, no_afni)
25+
AFNIPythonCommandInputSpec, AFNIPythonCommand, Info, no_afni)
2726

2827

2928
class CentralityInputSpec(AFNICommandInputSpec):
@@ -47,17 +46,7 @@ class CentralityInputSpec(AFNICommandInputSpec):
4746
desc='Mask the dataset to target brain-only voxels',
4847
argstr='-automask')
4948

50-
class AlignEpiAnatPyInputSpec(CommandLineInputSpec):
51-
outputtype = traits.Enum('AFNI', list(Info.ftypes.keys()),
52-
desc='AFNI output filetype')
53-
py27_path = File(
54-
desc='Path to Python 2.7 executable for running afni python scripts',
55-
argstr='%s '+spawn.find_executable('align_epi_anat.py'),
56-
exists=True,
57-
#default='/opt/miniconda/envs/py27/bin/python',
58-
mandatory=True,
59-
position=0
60-
)
49+
class AlignEpiAnatPyInputSpec(AFNIPythonCommandInputSpec):
6150
in_file = File(
6251
desc='EPI dataset to align',
6352
argstr='-epi %s',
@@ -70,13 +59,14 @@ class AlignEpiAnatPyInputSpec(CommandLineInputSpec):
7059
mandatory=True,
7160
exists=True,
7261
copyfile=False)
73-
epi_base = traits.Str(
62+
epi_base = traits.Either(
63+
traits.Range(low=0),
64+
traits.Enum('mean', 'median', 'max'),
7465
desc='the epi base used in alignment'
7566
'should be one of (0/mean/median/max/subbrick#)',
7667
mandatory=True,
7768
argstr='-epi_base %s')
7869
anat2epi = traits.Bool(
79-
default = True,
8070
desc='align anatomical to EPI dataset (default)',
8171
argstr='-anat2epi')
8272
epi2anat = traits.Bool(
@@ -86,24 +76,30 @@ class AlignEpiAnatPyInputSpec(CommandLineInputSpec):
8676
desc='save skull-stripped (not aligned)',
8777
argstr='-save_skullstrip')
8878
suffix = traits.Str(
79+
'_al',
8980
desc='append suffix to the original anat/epi dataset to use'
9081
'in the resulting dataset names (default is "_al")',
82+
usedefault=True,
9183
argstr='-suffix %s')
92-
epi_strip = traits.Enum(('3dSkullStrip','3dAutomask','None'),
93-
desc='method to mask brain in EPI data'
84+
epi_strip = traits.Enum(
85+
('3dSkullStrip', '3dAutomask', 'None'),
86+
desc='method to mask brain in EPI data'
9487
'should be one of[3dSkullStrip]/3dAutomask/None)',
9588
argstr='-epi_strip %s')
96-
volreg = traits.Enum(('on','off'),
89+
volreg = traits.Enum(
90+
'on', 'off',
91+
usedefault=True,
9792
desc='do volume registration on EPI dataset before alignment'
9893
'should be \'on\' or \'off\', defaults to \'on\'',
99-
default='on',
10094
argstr='-volreg %s')
101-
tshift = traits.Enum(('on','off'),
95+
tshift = traits.Enum(
96+
'on', 'off',
97+
usedefault=True,
10298
desc='do time shifting of EPI dataset before alignment'
10399
'should be \'on\' or \'off\', defaults to \'on\'',
104-
default='on',
105100
argstr='-tshift %s')
106101

102+
107103
class AlignEpiAnatPyOutputSpec(TraitedSpec):
108104
anat_al_orig = File(
109105
desc="A version of the anatomy that is aligned to the EPI")
@@ -129,8 +125,8 @@ class AlignEpiAnatPyOutputSpec(TraitedSpec):
129125
skullstrip = File(
130126
desc="skull-stripped (not aligned) volume")
131127

132-
class AlignEpiAnatPy(AFNICommand):
133-
"""align EPI to anatomical datasets or vice versa
128+
class AlignEpiAnatPy(AFNIPythonCommand):
129+
"""Align EPI to anatomical datasets or vice versa
134130
This Python script computes the alignment between two datasets, typically
135131
an EPI and an anatomical structural dataset, and applies the resulting
136132
transformation to one or the other to bring them into alignment.
@@ -165,48 +161,48 @@ class AlignEpiAnatPy(AFNICommand):
165161
========
166162
>>> from nipype.interfaces import afni
167163
>>> al_ea = afni.AlignEpiAnatPy()
168-
>>> al_ea.inputs.py27_path = "/opt/miniconda/envs/py27/bin/python"
169164
>>> al_ea.inputs.anat = "structural.nii"
170165
>>> al_ea.inputs.in_file = "functional.nii"
171-
>>> al_ea.inputs.epi_base = '0'
166+
>>> al_ea.inputs.epi_base = 0
172167
>>> al_ea.inputs.epi_strip = '3dAutomask'
173168
>>> al_ea.inputs.volreg = 'off'
174169
>>> al_ea.inputs.tshift = 'off'
175170
>>> al_ea.inputs.save_skullstrip = True
176171
>>> al_ea.cmdline # doctest: +ALLOW_UNICODE
177-
'echo "" && /opt/miniconda/envs/py27/bin/python /root/abin/align_epi_anat.py -anat structural.nii -epi_base 0 -epi_strip 3dAutomask -epi functional.nii -save_skullstrip -tshift off -volreg off'
172+
'python2 /usr/lib/afni/bin/align_epi_anat.py -anat structural.nii -epi_base 0 -epi_strip 3dAutomask -epi functional.nii -save_skullstrip -suffix _al -tshift off -volreg off'
178173
>>> res = allineate.run() # doctest: +SKIP
179174
"""
180-
_cmd = 'echo "" && '
175+
_cmd = 'align_epi_anat.py'
181176
input_spec = AlignEpiAnatPyInputSpec
182177
output_spec = AlignEpiAnatPyOutputSpec
183178

184179
def _list_outputs(self):
185180
outputs = self.output_spec().get()
186181
anat_prefix = ''.join(self._gen_fname(self.inputs.anat).split('+')[:-1])
187182
epi_prefix = ''.join(self._gen_fname(self.inputs.in_file).split('+')[:-1])
188-
ext = '.HEAD'
189-
matext='.1D'
190-
if not isdefined(self.inputs.suffix):
191-
suffix = '_al'
183+
outputtype = self.inputs.outputtype
184+
if outputtype == 'AFNI':
185+
ext = '.HEAD'
192186
else:
193-
suffix = '_'+self.inputs.suffix
187+
Info.output_type_to_ext(outputtype)
188+
matext = '.1D'
189+
suffix = self.inputs.suffix
194190
if self.inputs.anat2epi:
195-
outputs['anat_al_orig'] = os.path.abspath(self._gen_fname(anat_prefix, suffix=suffix+'+orig')+ext)
196-
outputs['anat_al_mat'] = os.path.abspath(self._gen_fname(anat_prefix, suffix=suffix+'_mat.aff12')+matext)
191+
outputs['anat_al_orig'] = self._gen_fname(anat_prefix, suffix=suffix+'+orig', ext=ext)
192+
outputs['anat_al_mat'] = self._gen_fname(anat_prefix, suffix=suffix+'_mat.aff12', ext=matext)
197193
if self.inputs.epi2anat:
198-
outputs['epi_al_orig'] = os.path.abspath(self._gen_fname(epi_prefix, suffix=suffix+'+orig')+ext)
199-
outputs['epi_al_mat'] = os.path.abspath(self._gen_fname(epi_prefix, suffix=suffix+'_mat.aff12')+matext)
194+
outputs['epi_al_orig'] = self._gen_fname(epi_prefix, suffix=suffix+'+orig', ext=ext)
195+
outputs['epi_al_mat'] = self._gen_fname(epi_prefix, suffix=suffix+'_mat.aff12', ext=matext)
200196
if self.inputs.volreg == 'on':
201-
outputs['epi_vr_al_mat'] = os.path.abspath(self._gen_fname(epi_prefix, suffix='_vr'+suffix+'_mat.aff12')+matext)
197+
outputs['epi_vr_al_mat'] = self._gen_fname(epi_prefix, suffix='_vr'+suffix+'_mat.aff12', ext=matext)
202198
if self.inputs.tshift == 'on':
203-
outputs['epi_vr_motion'] = os.path.abspath(self._gen_fname(epi_prefix, suffix='tsh_vr_motion')+matext)
199+
outputs['epi_vr_motion'] = self._gen_fname(epi_prefix, suffix='tsh_vr_motion', ext=matext)
204200
elif self.inputs.tshift == 'off':
205-
outputs['epi_vr_motion'] = os.path.abspath(self._gen_fname(epi_prefix, suffix='vr_motion')+matext)
201+
outputs['epi_vr_motion'] = self._gen_fname(epi_prefix, suffix='vr_motion', ext=matext)
206202
if self.inputs.volreg == 'on' and self.inputs.epi2anat:
207-
outputs['epi_reg_al_mat']= os.path.abspath(self._gen_fname(epi_prefix, suffix='_reg'+suffix+'_mat.aff12')+matext)
203+
outputs['epi_reg_al_mat'] = self._gen_fname(epi_prefix, suffix='_reg'+suffix+'_mat.aff12', ext=matext)
208204
if self.inputs.save_skullstrip:
209-
outputs.skullstrip = os.path.abspath(self._gen_fname(anat_prefix, suffix='_ns'+'+orig')+ext)
205+
outputs.skullstrip = self._gen_fname(anat_prefix, suffix='_ns'+'+orig', ext=ext)
210206
return outputs
211207

212208
class AllineateInputSpec(AFNICommandInputSpec):

nipype/interfaces/afni/utils.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
CommandLineInputSpec, CommandLine, Directory, TraitedSpec,
2626
traits, isdefined, File, InputMultiPath, Undefined, Str)
2727
from ...external.due import BibTeX
28-
from distutils import spawn
2928
from .base import (
30-
AFNICommandBase, AFNICommand, AFNICommandInputSpec, AFNICommandOutputSpec)
29+
AFNICommandBase, AFNICommand, AFNICommandInputSpec, AFNICommandOutputSpec,
30+
AFNIPythonCommandInputSpec, AFNIPythonCommand)
3131

3232
class ABoverlapInputSpec(AFNICommandInputSpec):
3333
in_file_a = File(
@@ -330,7 +330,6 @@ class BucketInputSpec(AFNICommandInputSpec):
330330
traits.Tuple(
331331
(File(
332332
exists=True,
333-
desc='input file',
334333
copyfile=False),
335334
traits.Str(argstr="'%s'")),
336335
artstr="%s%s"),
@@ -768,7 +767,7 @@ class Dot(AFNICommand):
768767
>>> res = copy3d.run() # doctest: +SKIP
769768
770769
"""
771-
_cmd='3dDot'
770+
_cmd = '3dDot'
772771
input_spec = DotInputSpec
773772
output_spec = AFNICommandOutputSpec
774773

@@ -785,7 +784,7 @@ class Edge3InputSpec(AFNICommandInputSpec):
785784
position=-1,
786785
argstr='-prefix %s')
787786
datum = traits.Enum(
788-
'byte','short','float',
787+
'byte', 'short', 'float',
789788
argstr='-datum %s',
790789
desc='specify data type for output. Valid types are \'byte\', '
791790
'\'short\' and \'float\'.')
@@ -1494,20 +1493,12 @@ class NwarpApply(AFNICommandBase):
14941493
input_spec = NwarpApplyInputSpec
14951494
output_spec = AFNICommandOutputSpec
14961495

1497-
class OneDToolPyInputSpec(AFNICommandInputSpec):
1496+
class OneDToolPyInputSpec(AFNIPythonCommandInputSpec):
14981497
in_file = File(
14991498
desc='input file to OneDTool',
15001499
argstr='-infile %s',
15011500
mandatory=True,
15021501
exists=True)
1503-
py27_path = File(
1504-
desc='Path to Python 2.7 executable for running afni python scripts',
1505-
argstr='%s '+spawn.find_executable('1d_tool.py'),
1506-
exists=True,
1507-
default='/opt/miniconda/envs/py27/bin/python',
1508-
usedefault=True,
1509-
position=0
1510-
)
15111502
set_nruns = traits.Int(
15121503
desc='treat the input data as if it has nruns',
15131504
argstr='-set_nruns %d')
@@ -1553,23 +1544,22 @@ class OneDToolPyInputSpec(AFNICommandInputSpec):
15531544
class OneDToolPyOutputSpec(AFNICommandOutputSpec):
15541545
out_file = File(desc='output of 1D_tool.py')
15551546

1556-
class OneDToolPy(AFNICommandBase):
1547+
class OneDToolPy(AFNIPythonCommand):
15571548
"""This program is meant to read/manipulate/write/diagnose 1D datasets.
15581549
Input can be specified using AFNI sub-brick[]/time{} selectors.
15591550
15601551
>>> from nipype.interfaces import afni
15611552
>>> odt = afni.OneDToolPy()
15621553
>>> odt.inputs.in_file = 'f1.1D'
1563-
>>> odt.inputs.py27_path = "/opt/miniconda/envs/py27/bin/python"
15641554
>>> odt.inputs.set_nruns = 3
15651555
>>> odt.inputs.demean = True
15661556
>>> odt.inputs.out_file = 'motion_dmean.1D'
15671557
>>> odt.cmdline # doctest: +ALLOW_UNICODE
1568-
'echo "" && /opt/miniconda/envs/py27/bin/python /root/abin/1d_tool.py -demean -infile f1.1D -write motion_dmean.1D -set_nruns 3'
1558+
'python2 /usr/lib/afni/bin/1d_tool.py -demean -infile f1.1D -write motion_dmean.1D -set_nruns 3'
15691559
>>> res = odt.run() # doctest: +SKIP
15701560
"""
15711561

1572-
_cmd = 'echo "" && '
1562+
_cmd = '1d_tool.py'
15731563

15741564
input_spec = OneDToolPyInputSpec
15751565
output_spec = OneDToolPyOutputSpec

0 commit comments

Comments
 (0)