Repository: nipy/nipype

Issue:
documentation of fsl.utils.Smooth
documentation says:

fwhm: (a float)
        flag: -kernel gauss %f -fmean, position: 1

when it should note that the value is passed after transforming from fwhm to sigma

documentation of fsl.utils.Smooth
documentation says:

fwhm: (a float)
        flag: -kernel gauss %f -fmean, position: 1

when it should note that the value is passed after transforming from fwhm to sigma



Discussion:
This might be a broader issue really, as quite a few interfaces reformat the nipype arguments somehow before passing them to the underlying command. If memory serves, showing the actual argstring in the help is a more recent development and probably wasn't anticipated by the original `_format_arg` pattern. Maybe the answer is a general metadata field that will allow `_format_arg` logic to be described in the help?

This might be a broader issue really, as quite a few interfaces reformat the nipype arguments somehow before passing them to the underlying command. If memory serves, showing the actual argstring in the help is a more recent development and probably wasn't anticipated by the original `_format_arg` pattern. Maybe the answer is a general metadata field that will allow `_format_arg` logic to be described in the help?


Resolving patch:
diff --git a/nipype/interfaces/fsl/utils.py b/nipype/interfaces/fsl/utils.py
--- a/nipype/interfaces/fsl/utils.py
+++ b/nipype/interfaces/fsl/utils.py
@@ -139,10 +139,14 @@ def _gen_filename(self, name):
 
 class SmoothInputSpec(FSLCommandInputSpec):
     in_file = File(exists=True, argstr="%s", position=0, mandatory=True)
-    fwhm = traits.Float(argstr="-kernel gauss %f -fmean", position=1,
-                        mandatory=True)
+    sigma = traits.Float(
+        argstr="-kernel gauss %.03f -fmean", position=1, xor=['fwhm'], mandatory=True,
+        desc='gaussian kernel sigma in mm (not voxels)')
+    fwhm = traits.Float(
+        argstr="-kernel gauss %.03f -fmean", position=1, xor=['sigma'], mandatory=True,
+        desc='gaussian kernel fwhm, will be converted to sigma in mm (not voxels)')
     smoothed_file = File(
-        argstr="%s", position=2, genfile=True, hash_files=False)
+        argstr="%s", position=2, name_source=['in_file'], name_template='%s_smooth', hash_files=False)
 
 
 class SmoothOutputSpec(TraitedSpec):
@@ -150,27 +154,44 @@ class SmoothOutputSpec(TraitedSpec):
 
 
 class Smooth(FSLCommand):
-    '''Use fslmaths to smooth the image
-    '''
+    """
+    Use fslmaths to smooth the image
+
+    Examples
+    --------
+
+    Setting the kernel width using sigma:
+
+    >>> sm = Smooth()
+    >>> sm.inputs.in_file = 'functional2.nii'
+    >>> sm.inputs.sigma = 8.0
+    >>> sm.cmdline #doctest: +ELLIPSIS
+    'fslmaths functional2.nii -kernel gauss 8.000 -fmean functional2_smooth.nii.gz'
+
+    Setting the kernel width using fwhm:
+
+    >>> sm = Smooth()
+    >>> sm.inputs.in_file = 'functional2.nii'
+    >>> sm.inputs.fwhm = 8.0
+    >>> sm.cmdline #doctest: +ELLIPSIS
+    'fslmaths functional2.nii -kernel gauss 3.397 -fmean functional2_smooth.nii.gz'
+
+    One of sigma or fwhm must be set:
+
+    >>> from nipype.interfaces.fsl import Smooth
+    >>> sm = Smooth()
+    >>> sm.inputs.in_file = 'functional2.nii'
+    >>> sm.cmdline #doctest: +ELLIPSIS
+    Traceback (most recent call last):
+     ...
+    ValueError: Smooth requires a value for one of the inputs ...
+
+    """
 
     input_spec = SmoothInputSpec
     output_spec = SmoothOutputSpec
     _cmd = 'fslmaths'
 
-    def _gen_filename(self, name):
-        if name == 'smoothed_file':
-            return self._list_outputs()['smoothed_file']
-        return None
-
-    def _list_outputs(self):
-        outputs = self._outputs().get()
-        outputs['smoothed_file'] = self.inputs.smoothed_file
-        if not isdefined(outputs['smoothed_file']):
-            outputs['smoothed_file'] = self._gen_fname(self.inputs.in_file,
-                                                       suffix='_smooth')
-        outputs['smoothed_file'] = os.path.abspath(outputs['smoothed_file'])
-        return outputs
-
     def _format_arg(self, name, trait_spec, value):
         if name == 'fwhm':
             sigma = float(value) / np.sqrt(8 * np.log(2))


Test patch:
diff --git a/nipype/interfaces/fsl/tests/test_auto_Smooth.py b/nipype/interfaces/fsl/tests/test_auto_Smooth.py
--- a/nipype/interfaces/fsl/tests/test_auto_Smooth.py
+++ b/nipype/interfaces/fsl/tests/test_auto_Smooth.py
@@ -9,9 +9,10 @@ def test_Smooth_inputs():
     environ=dict(nohash=True,
     usedefault=True,
     ),
-    fwhm=dict(argstr='-kernel gauss %f -fmean',
+    fwhm=dict(argstr='-kernel gauss %.03f -fmean',
     mandatory=True,
     position=1,
+    xor=['sigma'],
     ),
     ignore_exception=dict(nohash=True,
     usedefault=True,
@@ -21,9 +22,15 @@ def test_Smooth_inputs():
     position=0,
     ),
     output_type=dict(),
+    sigma=dict(argstr='-kernel gauss %.03f -fmean',
+    mandatory=True,
+    position=1,
+    xor=['fwhm'],
+    ),
     smoothed_file=dict(argstr='%s',
-    genfile=True,
     hash_files=False,
+    name_source=['in_file'],
+    name_template='%s_smooth',
     position=2,
     ),
     terminal_output=dict(nohash=True,