Repository: nipy/nipype

Issue:
add porcupine and nipype tutorial pointers in the user section of the documentation
porcupine: https://timvanmourik.github.io/Porcupine/examples/
tutorial: https://miykael.github.io/nipype_tutorial/

to both quickstart and to user docs.

Comments:

Patch:
diff --git a/doc/users/index.rst b/doc/users/index.rst
index d509191f0..a66d8d7a1 100644
--- a/doc/users/index.rst
+++ b/doc/users/index.rst
@@ -12,9 +12,12 @@
 
    install
    neurodocker
-   
    caching_tutorial
 
+.. toctree::
+   Nipype tutorials <https://miykael.github.io/nipype_tutorial/>
+   Porcupine graphical interface <https://timvanmourik.github.io/Porcupine/getting-started/>
+
 .. toctree::
    :maxdepth: 1
 
diff --git a/nipype/interfaces/afni/__init__.py b/nipype/interfaces/afni/__init__.py
index b28e5961f..925011a19 100644
--- a/nipype/interfaces/afni/__init__.py
+++ b/nipype/interfaces/afni/__init__.py
@@ -18,7 +18,7 @@ from .svm import (SVMTest, SVMTrain)
 from .utils import (
     ABoverlap, AFNItoNIFTI, Autobox, Axialize, BrickStat, Bucket, Calc, Cat,
     CatMatvec, CenterMass, ConvertDset, Copy, Dot, Edge3, Eval, FWHMx,
-    MaskTool, Merge, Notes, NwarpApply, NwarpCat, OneDToolPy, Refit, Resample,
-    TCat, TCatSubBrick, TStat, To3D, Unifize, Undump, ZCutUp, GCOR, Zcat,
-    Zeropad)
+    MaskTool, Merge, Notes, NwarpApply, NwarpAdjust, NwarpCat, OneDToolPy,
+    Refit, Resample, TCat, TCatSubBrick, TStat, To3D, Unifize, Undump, ZCutUp,
+    GCOR, Zcat, Zeropad)
 from .model import (Deconvolve, Remlfit, Synthesize)
diff --git a/nipype/interfaces/afni/utils.py b/nipype/interfaces/afni/utils.py
index 6cc187a97..9f306c7b8 100644
--- a/nipype/interfaces/afni/utils.py
+++ b/nipype/interfaces/afni/utils.py
@@ -1511,6 +1511,81 @@ class Notes(CommandLine):
         return outputs
 
 
+class NwarpAdjustInputSpec(AFNICommandInputSpec):
+    warps = InputMultiPath(
+        File(exists=True),
+        minlen=5,
+        mandatory=True,
+        argstr='-nwarp %s',
+        desc='List of input 3D warp datasets')
+    in_files = InputMultiPath(
+        File(exists=True),
+        minlen=5,
+        argstr='-source %s',
+        desc='List of input 3D datasets to be warped by the adjusted warp '
+             'datasets.  There must be exactly as many of these datasets as '
+             'there are input warps.')
+    out_file = File(
+        desc='Output mean dataset, only needed if in_files are also given. '
+             'The output dataset will be on the common grid shared by the '
+             'source datasets.',
+        argstr='-prefix %s',
+        name_source='in_files',
+        name_template='%s_NwarpAdjust',
+        keep_extension=True,
+        requires=['in_files'])
+
+
+class NwarpAdjust(AFNICommandBase):
+    """This program takes as input a bunch of 3D warps, averages them,
+    and computes the inverse of this average warp.  It then composes
+    each input warp with this inverse average to 'adjust' the set of
+    warps.  Optionally, it can also read in a set of 1-brick datasets
+    corresponding to the input warps, and warp each of them, and average
+    those.
+
+    For complete details, see the `3dNwarpAdjust Documentation.
+    <https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dNwarpAdjust.html>`_
+
+    Examples
+    ========
+
+    >>> from nipype.interfaces import afni
+    >>> adjust = afni.NwarpAdjust()
+    >>> adjust.inputs.warps = ['func2anat_InverseWarp.nii.gz', 'func2anat_InverseWarp.nii.gz', 'func2anat_InverseWarp.nii.gz', 'func2anat_InverseWarp.nii.gz', 'func2anat_InverseWarp.nii.gz']
+    >>> adjust.cmdline
+    '3dNwarpAdjust -nwarp func2anat_InverseWarp.nii.gz func2anat_InverseWarp.nii.gz func2anat_InverseWarp.nii.gz func2anat_InverseWarp.nii.gz func2anat_InverseWarp.nii.gz'
+    >>> res = adjust.run()  # doctest: +SKIP
+
+    """
+    _cmd = '3dNwarpAdjust'
+    input_spec = NwarpAdjustInputSpec
+    output_spec = AFNICommandOutputSpec
+
+    def _parse_inputs(self, skip=None):
+        if not self.inputs.in_files:
+            if skip is None:
+                skip = []
+            skip += ['out_file']
+        return super(NwarpAdjust, self)._parse_inputs(skip=skip)
+
+    def _list_outputs(self):
+        outputs = self.output_spec().get()
+
+        if self.inputs.in_files:
+            if self.inputs.out_file:
+                outputs['out_file'] = os.path.abspath(self.inputs.out_file)
+            else:
+                basename = os.path.basename(self.inputs.in_files[0])
+                basename_noext, ext = op.splitext(basename)
+                if '.gz' in ext:
+                    basename_noext, ext2 = op.splitext(basename_noext)
+                    ext = ext2 + ext
+                outputs['out_file'] = os.path.abspath(
+                    basename_noext + '_NwarpAdjust' + ext)
+        return outputs
+
+
 class NwarpApplyInputSpec(CommandLineInputSpec):
     in_file = traits.Either(
         File(exists=True),


Test patch:
diff --git a/nipype/interfaces/afni/tests/test_auto_NwarpAdjust.py b/nipype/interfaces/afni/tests/test_auto_NwarpAdjust.py
new file mode 100644
index 000000000..cf427dd41
--- /dev/null
+++ b/nipype/interfaces/afni/tests/test_auto_NwarpAdjust.py
@@ -0,0 +1,51 @@
+# AUTO-GENERATED by tools/checkspecs.py - DO NOT EDIT
+from __future__ import unicode_literals
+from ..utils import NwarpAdjust
+
+
+def test_NwarpAdjust_inputs():
+    input_map = dict(
+        args=dict(argstr='%s', ),
+        environ=dict(
+            nohash=True,
+            usedefault=True,
+        ),
+        ignore_exception=dict(
+            deprecated='1.0.0',
+            nohash=True,
+            usedefault=True,
+        ),
+        in_files=dict(argstr='-source %s', ),
+        num_threads=dict(
+            nohash=True,
+            usedefault=True,
+        ),
+        out_file=dict(
+            argstr='-prefix %s',
+            keep_extension=True,
+            name_source='in_files',
+            name_template='%s_NwarpAdjust',
+            requires=['in_files'],
+        ),
+        outputtype=dict(),
+        terminal_output=dict(
+            deprecated='1.0.0',
+            nohash=True,
+        ),
+        warps=dict(
+            argstr='-nwarp %s',
+            mandatory=True,
+        ),
+    )
+    inputs = NwarpAdjust.input_spec()
+
+    for key, metadata in list(input_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(inputs.traits()[key], metakey) == value
+def test_NwarpAdjust_outputs():
+    output_map = dict(out_file=dict(), )
+    outputs = NwarpAdjust.output_spec()
+
+    for key, metadata in list(output_map.items()):
+        for metakey, value in list(metadata.items()):
+            assert getattr(outputs.traits()[key], metakey) == value