# -*- coding: utf-8 -*-
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft = python sts = 4 ts = 4 sw = 4 et:
"""
AFNI modeling interfaces.

Examples
--------
See the docstrings of the individual classes for examples.

"""
from __future__ import (print_function, division, unicode_literals,
                        absolute_import)

import os

from ..base import (CommandLineInputSpec, CommandLine, Directory, TraitedSpec,
                    traits, isdefined, File, InputMultiPath, Undefined, Str)
from ...external.due import BibTeX

from .base import (AFNICommandBase, AFNICommand, AFNICommandInputSpec,
                   AFNICommandOutputSpec, Info)


class DeconvolveInputSpec(AFNICommandInputSpec):
    in_files = InputMultiPath(
        File(exists=True),
        desc='filenames of 3D+time input datasets. More than one filename can '
        'be given and the datasets will be auto-catenated in time. '
        'You can input a 1D time series file here, but the time axis '
        'should run along the ROW direction, not the COLUMN direction as '
        'in the \'input1D\' option.',
        argstr='-input %s',
        copyfile=False,
        sep=" ",
        position=1)
    sat = traits.Bool(
        desc='check the dataset time series for initial saturation transients,'
        ' which should normally have been excised before data analysis.',
        argstr='-sat',
        xor=['trans'])
    trans = traits.Bool(
        desc='check the dataset time series for initial saturation transients,'
        ' which should normally have been excised before data analysis.',
        argstr='-trans',
        xor=['sat'])
    noblock = traits.Bool(
        desc='normally, if you input multiple datasets with \'input\', then '
        'the separate datasets are taken to be separate image runs that '
        'get separate baseline models. Use this options if you want to '
        'have the program consider these to be all one big run.'
        '* If any of the input dataset has only 1 sub-brick, then this '
        'option is automatically invoked!'
        '* If the auto-catenation feature isn\'t used, then this option '
        'has no effect, no how, no way.',
        argstr='-noblock')
    force_TR = traits.Float(
        desc='use this value instead of the TR in the \'input\' '
             'dataset. (It\'s better to fix the input using Refit.)',
        argstr='-force_TR %f',
        position=0)
    input1D = File(
        desc='filename of single (fMRI) .1D time series where time runs down '
        'the column.',
        argstr='-input1D %s',
        exists=True)
    TR_1D = traits.Float(
        desc='TR to use with \'input1D\'. This option has no effect if you do '
        'not also use \'input1D\'.',
        argstr='-TR_1D %f')
    legendre = traits.Bool(
        desc='use Legendre polynomials for null hypothesis (baseline model)',
        argstr='-legendre')
    nolegendre = traits.Bool(
        desc='use power polynomials for null hypotheses. Don\'t do this '
        'unless you are crazy!',
        argstr='-nolegendre')
    nodmbase = traits.Bool(
        desc='don\'t de-mean baseline time series', argstr='-nodmbase')
    dmbase = traits.Bool(
        desc='de-mean baseline time series (default if \'polort\' >= 0)',
        argstr='-dmbase')
    svd = traits.Bool(
        desc='use SVD instead of Gaussian elimination (default)',
        argstr='-svd')
    nosvd = traits.Bool(
        desc='use Gaussian elimination instead of SVD', argstr='-nosvd')
    rmsmin = traits.Float(
        desc='minimum rms error to reject reduced model (default = 0; don\'t '
        'use this option normally!)',
        argstr='-rmsmin %f')
    nocond = traits.Bool(
        desc='DON\'T calculate matrix condition number', argstr='-nocond')
    singvals = traits.Bool(
        desc='print out the matrix singular values', argstr='-singvals')
    goforit = traits.Int(
        desc='use this to proceed even if the matrix has bad problems (e.g., '
        'duplicate columns, large condition number, etc.).',
        argstr='-GOFORIT %i')
    allzero_OK = traits.Bool(
        desc='don\'t consider all zero matrix columns to be the type of error '
        'that \'gotforit\' is needed to ignore.',
        argstr='-allzero_OK')
    dname = traits.Tuple(
        Str,
        Str,
        desc='set environmental variable to provided value',
        argstr='-D%s=%s')
    mask = File(
        desc='filename of 3D mask dataset; only data time series from within '
        'the mask will be analyzed; results for voxels outside the mask '
        'will be set to zero.',
        argstr='-mask %s',
        exists=True)
    automask = traits.Bool(
        desc='build a mask automatically from input data (will be slow for '
        'long time series datasets)',
        argstr='-automask')
    STATmask = File(
        desc='build a mask from provided file, and use this mask for the '
        'purpose of reporting truncation-to float issues AND for '
        'computing the FDR curves. The actual results ARE not masked '
        'with this option (only with \'mask\' or \'automask\' options).',
        argstr='-STATmask %s',
        exists=True)
    censor = File(
        desc='filename of censor .1D time series. This is a file of 1s and '
        '0s, indicating which time points are to be included (1) and '
        'which are to be excluded (0).',
        argstr='-censor %s',
        exists=True)
    polort = traits.Int(
        desc='degree of polynomial corresponding to the null hypothesis '
        '[default: 1]',
        argstr='-polort %d')
    ortvec = traits.Tuple(
        File(desc='filename', exists=True),
        Str(desc='label'),
        desc='this option lets you input a rectangular array of 1 or more '
        'baseline vectors from a file. This method is a fast way to '
        'include a lot of baseline regressors in one step. ',
        argstr='-ortvec %s %s')
    x1D = File(desc='specify name for saved X matrix', argstr='-x1D %s')
    x1D_stop = traits.Bool(
        desc='stop running after writing .xmat.1D file', argstr='-x1D_stop')
    cbucket = traits.Str(
        desc='Name for dataset in which to save the regression '
        'coefficients (no statistics). This dataset '
        'will be used in a -xrestore run [not yet implemented] '
        'instead of the bucket dataset, if possible.',
        argstr='-cbucket %s')
    out_file = File(desc='output statistics file', argstr='-bucket %s')
    num_threads = traits.Int(
        desc='run the program with provided number of sub-processes',
        argstr='-jobs %d',
        nohash=True)
    fout = traits.Bool(
        desc='output F-statistic for each stimulus', argstr='-fout')
    rout = traits.Bool(
        desc='output the R^2 statistic for each stimulus', argstr='-rout')
    tout = traits.Bool(
        desc='output the T-statistic for each stimulus', argstr='-tout')
    vout = traits.Bool(
        desc='output the sample variance (MSE) for each stimulus',
        argstr='-vout')
    nofdr = traits.Bool(
        desc="Don't compute the statistic-vs-FDR curves for the bucket "
             "dataset.",
        argstr='-noFDR')
    global_times = traits.Bool(
        desc='use global timing for stimulus timing files',
        argstr='-global_times',
        xor=['local_times'])
    local_times = traits.Bool(
        desc='use local timing for stimulus timing files',
        argstr='-local_times',
        xor=['global_times'])
    num_stimts = traits.Int(
        desc='number of stimulus timing files',
        argstr='-num_stimts %d',
        position=-6)
    stim_times = traits.List(
        traits.Tuple(
            traits.Int(desc='k-th response model'),
            File(desc='stimulus timing file', exists=True),
            Str(desc='model')),
        desc='generate a response model from a set of stimulus times'
        ' given in file.',
        argstr='-stim_times %d %s \'%s\'...',
        position=-5)
    stim_label = traits.List(
        traits.Tuple(
            traits.Int(desc='k-th input stimulus'),
            Str(desc='stimulus label')),
        desc='label for kth input stimulus (e.g., Label1)',
        argstr='-stim_label %d %s...',
        requires=['stim_times'],
        position=-4)
    stim_times_subtract = traits.Float(
        desc='this option means to subtract specified seconds from each time '
        'encountered in any \'stim_times\' option. The purpose of this '
        'option is to make it simple to adjust timing files for the '
        'removal of images from the start of each imaging run.',
        argstr='-stim_times_subtract %f')
    num_glt = traits.Int(
        desc='number of general linear tests (i.e., contrasts)',
        argstr='-num_glt %d',
        position=-3)
    gltsym = traits.List(
        Str(desc='symbolic general linear test'),
        desc='general linear tests (i.e., contrasts) using symbolic '
        'conventions (e.g., \'+Label1 -Label2\')',
        argstr='-gltsym \'SYM: %s\'...',
        position=-2)
    glt_label = traits.List(
        traits.Tuple(
            traits.Int(desc='k-th general linear test'),
            Str(desc='GLT label')),
        desc='general linear test (i.e., contrast) labels',
        argstr='-glt_label %d %s...',
        requires=['gltsym'],
        position=-1)


class DeconvolveOutputSpec(TraitedSpec):
    out_file = File(desc='output statistics file', exists=True)
    reml_script = File(
        desc='automatical generated script to run 3dREMLfit', exists=True)
    x1D = File(desc='save out X matrix', exists=True)
    cbucket = File(desc='output regression coefficients file (if generated)')


class Deconvolve(AFNICommand):
    """Performs OLS regression given a 4D neuroimage file and stimulus timings

    For complete details, see the `3dDeconvolve Documentation.
    <https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dDeconvolve.html>`_

    Examples
    ========

    >>> from nipype.interfaces import afni
    >>> deconvolve = afni.Deconvolve()
    >>> deconvolve.inputs.in_files = ['functional.nii', 'functional2.nii']
    >>> deconvolve.inputs.out_file = 'output.nii'
    >>> deconvolve.inputs.x1D = 'output.1D'
    >>> stim_times = [(1, 'timeseries.txt', 'SPMG1(4)')]
    >>> deconvolve.inputs.stim_times = stim_times
    >>> deconvolve.inputs.stim_label = [(1, 'Houses')]
    >>> deconvolve.inputs.gltsym = ['SYM: +Houses']
    >>> deconvolve.inputs.glt_label = [(1, 'Houses')]
    >>> deconvolve.cmdline
    "3dDeconvolve -input functional.nii functional2.nii -bucket output.nii -x1D output.1D -num_stimts 1 -stim_times 1 timeseries.txt 'SPMG1(4)' -stim_label 1 Houses -num_glt 1 -gltsym 'SYM: +Houses' -glt_label 1 Houses"
    >>> res = deconvolve.run()  # doctest: +SKIP
    """

    _cmd = '3dDeconvolve'
    input_spec = DeconvolveInputSpec
    output_spec = DeconvolveOutputSpec

    def _format_arg(self, name, trait_spec, value):
        if name == 'gltsym':
            for n, val in enumerate(value):
                if val.startswith('SYM: '):
                    value[n] = val.lstrip('SYM: ')

        return super(Deconvolve, self)._format_arg(name, trait_spec, value)

    def _parse_inputs(self, skip=None):
        if skip is None:
            skip = []
        if len(self.inputs.stim_times) and not isdefined(
                self.inputs.num_stimts):
            self.inputs.num_stimts = len(self.inputs.stim_times)
        if len(self.inputs.gltsym) and not isdefined(self.inputs.num_glt):
            self.inputs.num_glt = len(self.inputs.gltsym)
        if not isdefined(self.inputs.out_file):
            self.inputs.out_file = 'Decon.nii'

        return super(Deconvolve, self)._parse_inputs(skip)

    def _list_outputs(self):
        outputs = self.output_spec().get()

        _gen_fname_opts = {}
        _gen_fname_opts['basename'] = self.inputs.out_file
        _gen_fname_opts['cwd'] = os.getcwd()

        if isdefined(self.inputs.x1D):
            if not self.inputs.x1D.endswith('.xmat.1D'):
                outputs['x1D'] = os.path.abspath(self.inputs.x1D + '.xmat.1D')
            else:
                outputs['x1D'] = os.path.abspath(self.inputs.x1D)
        else:
            outputs['x1D'] = self._gen_fname(
                suffix='.xmat.1D', **_gen_fname_opts)

        if isdefined(self.inputs.cbucket):
            outputs['cbucket'] = os.path.abspath(self.inputs.cbucket)

        outputs['reml_script'] = self._gen_fname(
            suffix='.REML_cmd', **_gen_fname_opts)
        # remove out_file from outputs if x1d_stop set to True
        if self.inputs.x1D_stop:
            del outputs['out_file'], outputs['cbucket']
        else:
            outputs['out_file'] = os.path.abspath(self.inputs.out_file)

        return outputs


class RemlfitInputSpec(AFNICommandInputSpec):
    # mandatory files
    in_files = InputMultiPath(
        File(exists=True),
        desc='Read time series dataset',
        argstr='-input "%s"',
        mandatory=True,
        copyfile=False,
        sep=" ")
    matrix = File(
        desc='the design matrix file, which should have been output from '
        'Deconvolve via the \'x1D\' option',
        argstr='-matrix %s',
        mandatory=True)
    # "Semi-Hidden Alternative Ways to Define the Matrix"
    polort = traits.Int(
        desc='if no \'matrix\' option is given, AND no \'matim\' option, '
        'create a matrix with Legendre polynomial regressors'
        'up to the specified order. The default value is 0, which'
        'produces a matrix with a single column of all ones',
        argstr='-polort %d',
        xor=['matrix'])
    matim = File(
        desc='read a standard file as the matrix. You can use only Col as '
        'a name in GLTs with these nonstandard matrix input methods, '
        'since the other names come from the \'matrix\' file. '
        'These mutually exclusive options are ignored if \'matrix\' '
        'is used.',
        argstr='-matim %s',
        xor=['matrix'])
    # Other arguments
    mask = File(
        desc='filename of 3D mask dataset; only data time series from within '
        'the mask will be analyzed; results for voxels outside the mask '
        'will be set to zero.',
        argstr='-mask %s',
        exists=True)
    automask = traits.Bool(
        usedefault=True,
        argstr='-automask',
        desc='build a mask automatically from input data (will be slow for '
        'long time series datasets)')
    STATmask = File(
        desc='filename of 3D mask dataset to be used for the purpose '
        'of reporting truncation-to float issues AND for computing the '
        'FDR curves. The actual results ARE not masked with this option '
        '(only with \'mask\' or \'automask\' options).',
        argstr='-STATmask %s',
        exists=True)
    addbase = InputMultiPath(
        File(
            exists=True,
            desc='file containing columns to add to regression matrix'),
        desc='file(s) to add baseline model columns to the matrix with this '
        'option. Each column in the specified file(s) will be appended '
        'to the matrix. File(s) must have at least as many rows as the '
        'matrix does.',
        copyfile=False,
        sep=" ",
        argstr='-addbase %s')
    slibase = InputMultiPath(
        File(
            exists=True,
            desc='file containing columns to add to regression matrix'),
        desc='similar to \'addbase\' in concept, BUT each specified file '
        'must have an integer multiple of the number of slices '
        'in the input dataset(s); then, separate regression '
        'matrices are generated for each slice, with the '
        'first column of the file appended to the matrix for '
        'the first slice of the dataset, the second column of the file '
        'appended to the matrix for the first slice of the dataset, '
        'and so on. Intended to help model physiological noise in FMRI, '
        'or other effects you want to regress out that might '
        'change significantly in the inter-slice time intervals. This '
        'will slow the program down, and make it use a lot more memory '
        '(to hold all the matrix stuff).',
        argstr='-slibase %s')
    slibase_sm = InputMultiPath(
        File(
            exists=True,
            desc='file containing columns to add to regression matrix'),
        desc='similar to \'slibase\', BUT each file much be in slice major '
        'order (i.e. all slice0 columns come first, then all slice1 '
        'columns, etc).',
        argstr='-slibase_sm %s')
    usetemp = traits.Bool(
        desc='write intermediate stuff to disk, to economize on RAM. '
        'Using this option might be necessary to run with '
        '\'slibase\' and with \'Grid\' values above the default, '
        'since the program has to store a large number of '
        'matrices for such a problem: two for every slice and '
        'for every (a,b) pair in the ARMA parameter grid. Temporary '
        'files are written to the directory given in environment '
        'variable TMPDIR, or in /tmp, or in ./ (preference is in that '
        'order)',
        argstr='-usetemp')
    nodmbase = traits.Bool(
        desc='by default, baseline columns added to the matrix via '
        '\'addbase\' or \'slibase\' or \'dsort\' will each have their '
        'mean removed (as is done in Deconvolve); this option turns this '
        'centering off',
        argstr='-nodmbase',
        requires=['addbase', 'dsort'])
    dsort = File(
        desc='4D dataset to be used as voxelwise baseline regressor',
        exists=True,
        copyfile=False,
        argstr='-dsort %s')
    dsort_nods = traits.Bool(
        desc='if \'dsort\' option is used, this command will output '
        'additional results files excluding the \'dsort\' file',
        argstr='-dsort_nods',
        requires=['dsort'])
    fout = traits.Bool(
        desc='output F-statistic for each stimulus', argstr='-fout')
    rout = traits.Bool(
        desc='output the R^2 statistic for each stimulus', argstr='-rout')
    tout = traits.Bool(
        desc='output the T-statistic for each stimulus; if you use '
        '\'out_file\' and do not give any of \'fout\', \'tout\','
        'or \'rout\', then the program assumes \'fout\' is activated.',
        argstr='-tout')
    nofdr = traits.Bool(
        desc='do NOT add FDR curve data to bucket datasets; FDR curves can '
        'take a long time if \'tout\' is used',
        argstr='-noFDR')
    nobout = traits.Bool(
        desc='do NOT add baseline (null hypothesis) regressor betas '
        'to the \'rbeta_file\' and/or \'obeta_file\' output datasets.',
        argstr='-nobout')
    gltsym = traits.List(
        traits.Either(
            traits.Tuple(File(exists=True), Str()), traits.Tuple(Str(),
                                                                 Str())),
        desc='read a symbolic GLT from input file and associate it with a '
        'label. As in Deconvolve, you can also use the \'SYM:\' method '
        'to provide the definition of the GLT directly as a string '
        '(e.g., with \'SYM: +Label1 -Label2\'). Unlike Deconvolve, you '
        'MUST specify \'SYM: \' if providing the GLT directly as a '
        'string instead of from a file',
        argstr='-gltsym "%s" %s...')
    out_file = File(
        desc='output dataset for beta + statistics from the REML estimation; '
        'also contains the results of any GLT analysis requested '
        'in the Deconvolve setup, similar to the \'bucket\' output '
        'from Deconvolve. This dataset does NOT get the betas '
        '(or statistics) of those regressors marked as \'baseline\' '
        'in the matrix file.',
        argstr='-Rbuck %s')
    var_file = File(
        desc='output dataset for REML variance parameters', argstr='-Rvar %s')
    rbeta_file = File(
        desc='output dataset for beta weights from the REML estimation, '
        'similar to the \'cbucket\' output from Deconvolve. This dataset '
        'will contain all the beta weights, for baseline and stimulus '
        'regressors alike, unless the \'-nobout\' option is given -- '
        'in that case, this dataset will only get the betas for the '
        'stimulus regressors.',
        argstr='-Rbeta %s')
    glt_file = File(
        desc='output dataset for beta + statistics from the REML estimation, '
        'but ONLY for the GLTs added on the REMLfit command line itself '
        'via \'gltsym\'; GLTs from Deconvolve\'s command line will NOT '
        'be included.',
        argstr='-Rglt %s')
    fitts_file = File(
        desc='ouput dataset for REML fitted model', argstr='-Rfitts %s')
    errts_file = File(
        desc='output dataset for REML residuals = data - fitted model',
        argstr='-Rerrts %s')
    wherr_file = File(
        desc='dataset for REML residual, whitened using the estimated '
        'ARMA(1,1) correlation matrix of the noise',
        argstr='-Rwherr %s')
    quiet = traits.Bool(
        desc='turn off most progress messages', argstr='-quiet')
    verb = traits.Bool(
        desc='turns on more progress messages, including memory usage '
        'progress reports at various stages',
        argstr='-verb')
    goforit = traits.Bool(
        desc='With potential issues flagged in the design matrix, an attempt '
        'will nevertheless be made to fit the model',
        argstr='-GOFORIT')
    ovar = File(
        desc='dataset for OLSQ st.dev. parameter (kind of boring)',
        argstr='-Ovar %s')
    obeta = File(
        desc='dataset for beta weights from the OLSQ estimation',
        argstr='-Obeta %s')
    obuck = File(
        desc='dataset for beta + statistics from the OLSQ estimation',
        argstr='-Obuck %s')
    oglt = File(
        desc='dataset for beta + statistics from \'gltsym\' options',
        argstr='-Oglt %s')
    ofitts = File(desc='dataset for OLSQ fitted model', argstr='-Ofitts %s')
    oerrts = File(
        desc='dataset for OLSQ residuals (data - fitted model)',
        argstr='-Oerrts %s')


class RemlfitOutputSpec(AFNICommandOutputSpec):
    out_file = File(
        desc='dataset for beta + statistics from the REML estimation (if '
        'generated')
    var_file = File(desc='dataset for REML variance parameters (if generated)')
    rbeta_file = File(
        desc='dataset for beta weights from the REML estimation (if '
        'generated)')
    rbeta_file = File(
        desc='output dataset for beta weights from the REML estimation (if '
        'generated')
    glt_file = File(
        desc='output dataset for beta + statistics from the REML estimation, '
        'but ONLY for the GLTs added on the REMLfit command '
        'line itself via \'gltsym\' (if generated)')
    fitts_file = File(
        desc='ouput dataset for REML fitted model (if generated)')
    errts_file = File(
        desc='output dataset for REML residuals = data - fitted model (if '
        'generated')
    wherr_file = File(
        desc='dataset for REML residual, whitened using the estimated '
        'ARMA(1,1) correlation matrix of the noise (if generated)')
    ovar = File(desc='dataset for OLSQ st.dev. parameter (if generated)')
    obeta = File(desc='dataset for beta weights from the OLSQ estimation (if '
                 'generated)')
    obuck = File(
        desc='dataset for beta + statistics from the OLSQ estimation (if '
        'generated)')
    oglt = File(
        desc='dataset for beta + statistics from \'gltsym\' options (if '
        'generated')
    ofitts = File(desc='dataset for OLSQ fitted model (if generated)')
    oerrts = File(desc='dataset for OLSQ residuals = data - fitted model (if '
                  'generated')


class Remlfit(AFNICommand):
    """Performs Generalized least squares time series fit with Restricted
    Maximum Likelihood (REML) estimation of the temporal auto-correlation
    structure.

    For complete details, see the `3dREMLfit Documentation.
    <https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dREMLfit.html>`_

    Examples
    ========

    >>> from nipype.interfaces import afni
    >>> remlfit = afni.Remlfit()
    >>> remlfit.inputs.in_files = ['functional.nii', 'functional2.nii']
    >>> remlfit.inputs.out_file = 'output.nii'
    >>> remlfit.inputs.matrix = 'output.1D'
    >>> remlfit.inputs.gltsym = [('SYM: +Lab1 -Lab2', 'TestSYM'), ('timeseries.txt', 'TestFile')]
    >>> remlfit.cmdline
    '3dREMLfit -gltsym "SYM: +Lab1 -Lab2" TestSYM -gltsym "timeseries.txt" TestFile -input "functional.nii functional2.nii" -matrix output.1D -Rbuck output.nii'
    >>> res = remlfit.run()  # doctest: +SKIP
    """

    _cmd = '3dREMLfit'
    input_spec = RemlfitInputSpec
    output_spec = RemlfitOutputSpec

    def _parse_inputs(self, skip=None):
        if skip is None:
            skip = []
        return super(Remlfit, self)._parse_inputs(skip)

    def _list_outputs(self):
        outputs = self.output_spec().get()

        for key in outputs.keys():
            if isdefined(self.inputs.get()[key]):
                outputs[key] = os.path.abspath(self.inputs.get()[key])

        return outputs


class SynthesizeInputSpec(AFNICommandInputSpec):
    cbucket = File(
        desc='Read the dataset output from '
        '3dDeconvolve via the \'-cbucket\' option.',
        argstr='-cbucket %s',
        copyfile=False,
        mandatory=True)
    matrix = File(
        desc='Read the matrix output from '
        '3dDeconvolve via the \'-x1D\' option.',
        argstr='-matrix %s',
        copyfile=False,
        mandatory=True)
    select = traits.List(
        Str(desc='selected columns to synthesize'),
        argstr='-select %s',
        desc='A list of selected columns from the matrix (and the '
        'corresponding coefficient sub-bricks from the '
        'cbucket). Valid types include \'baseline\', '
        ' \'polort\', \'allfunc\', \'allstim\', \'all\', '
        'Can also provide \'something\' where something matches '
        'a stim_label from 3dDeconvolve, and \'digits\' where digits '
        'are the numbers of the select matrix columns by '
        'numbers (starting at 0), or number ranges of the form '
        '\'3..7\' and \'3-7\'.',
        mandatory=True)
    out_file = File(
        name_template='syn',
        desc='output dataset prefix name (default \'syn\')',
        argstr='-prefix %s')
    dry_run = traits.Bool(
        desc='Don\'t compute the output, just '
        'check the inputs.',
        argstr='-dry')
    TR = traits.Float(
        desc='TR to set in the output.  The default value of '
        'TR is read from the header of the matrix file.',
        argstr='-TR %f')
    cenfill = traits.Enum(
        'zero',
        'nbhr',
        'none',
        argstr='-cenfill %s',
        desc='Determines how censored time points from the '
        '3dDeconvolve run will be filled. Valid types '
        'are \'zero\', \'nbhr\' and \'none\'.')


class Synthesize(AFNICommand):
    """Reads a '-cbucket' dataset and a '.xmat.1D' matrix from 3dDeconvolve,
       and synthesizes a fit dataset using user-selected sub-bricks and
       matrix columns.

    For complete details, see the `3dSynthesize Documentation.
    <https://afni.nimh.nih.gov/pub/dist/doc/program_help/3dSynthesize.html>`_

    Examples
    ========

    >>> from nipype.interfaces import afni
    >>> synthesize = afni.Synthesize()
    >>> synthesize.inputs.cbucket = 'functional.nii'
    >>> synthesize.inputs.matrix = 'output.1D'
    >>> synthesize.inputs.select = ['baseline']
    >>> synthesize.cmdline
    '3dSynthesize -cbucket functional.nii -matrix output.1D -select baseline'
    >>> syn = synthesize.run()  # doctest: +SKIP
    """

    _cmd = '3dSynthesize'
    input_spec = SynthesizeInputSpec
    output_spec = AFNICommandOutputSpec

    def _list_outputs(self):
        outputs = self.output_spec().get()

        for key in outputs.keys():
            if isdefined(self.inputs.get()[key]):
                outputs[key] = os.path.abspath(self.inputs.get()[key])

        return outputs
