3
d                @   s  d Z ddlZddlZddlZddlZddlZddljZddl	Z	ddl
Z
ddlZddlZddlZddlmZmZ ddlmZ ddlmZmZ ddlmZmZmZmZmZ ddlmZmZ d	d
lmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, ej-dZ.deddZ/dfddZ0dd Z1G dd de$Z2G dd de3Z4G dd de(e*Z5G dd deZ6G dd de2Z7G dd de(e*Z8G dd  d e+e2Z9G d!d" d"e(e*Z:G d#d$ d$e2Z;G d%d& d&e(e*Z<G d'd( d(e2Z=G d)d* d*e(e*Z>G d+d, d,e2Z?G d-d. d.e*Z@G d/d0 d0eZAG d1d2 d2e2ZBG d3d4 d4e(e*ZCG d5d6 d6e+e2ZDG d7d8 d8e(e*ZEG d9d: d:e+e2ZFd;d< ZGd=d> ZHd?d@ ZIdAdB ZJdCdD ZKG dEdF dFe(e*ZLG dGdH dHe+e2ZMG dIdJ dJe(e*ZNG dKdL dLe2ZOG dMdN dNe:ZPG dOdP dPe+e;ZQG dQdR dRe(e*ZRG dSdT dTe2ZSG dUdV dVe(e*ZTG dWdX dXeZUG dYdZ dZe2ZVG d[d\ d\e(ZWG d]d^ d^e+e2ZXG d_d` d`e*ZYG dadb dbeZZG dcdd dde,Z[dS )ga    Set of interfaces that allow interaction with data. Currently
    available interfaces are:

    DataSource: Generic nifti to named Nifti interface
    DataSink: Generic named output from interfaces to data store
    XNATSource: preliminary interface to XNAT

    To come :
    XNATSink
    N)joindirname)warn   )configlogging)copyfilesimplify_listensure_listget_related_filessplit_filename)human_order_sortedstr2bool   )TraitedSpectraitsStrFile	DirectoryBaseInterfaceInputMultiPath	isdefinedOutputMultiPathDynamicTraitedSpec	UndefinedBaseInterfaceInputSpecLibraryBaseInterfaceSimpleInterfaceznipype.interfaceFc       
       C   s,  t j| }yt j| W n2 tk
rJ } zd|jkr6n|W Y dd}~X nX g }x|D ]}t jj| |}t jj||}y0t jj|rt||| nt	||dd|d W qV t
t jfk
r } z|j||t|f W Y dd}~X qV tk
r }	 z|j|	jd  W Y dd}	~	X qVX qVW |r(t|dS )a  Recursively copy a directory tree using
    nipype.utils.filemanip.copyfile()

    This is not a thread-safe routine. However, in the case of creating new
    directories, it checks to see if a particular directory has already been
    created by another process.
    zFile existsNTcontent)
hashmethoduse_hardlinkr   )oslistdirmakedirsOSErrorstrerrorpathr   isdircopytreer   IOErrorerrorappendstr	Exceptionextendargs)
srcdstr    nameswhyerrorsnamesrcnamedstnameerr r9   6/tmp/pip-build-7vycvbft/nipype/nipype/interfaces/io.pyr(   9   s4    


$&r(   c             C   sd   |dkrt j}i }x |D ]}| j|| t||< qW | jf ddi| x|D ]}t| |}qNW | S )zSAdd traits to a traited class.

    All traits are set to Undefined by default
    Ntrait_change_notifyF)r   Any	add_traitr   	trait_setgetattr)baser2   Z
trait_typeundefined_traitskey_r9   r9   r:   
add_traitsb   s    

rD   c             C   s   ddl }y| jjj|d W n |jjk
r } zXt|jd d }|dkr^d| }t|n&|dkrxd	| }t|nd
||f }W Y dd}~X n6 tk
r } zd
||f }t|W Y dd}~X nX dS )zcTry to get the header info of a bucket, in order to
    check if it exists and its permissions
    r   N)BucketErrorZCodei  z1Access to bucket: %s is denied; check credentialsi  z7Bucket: %s does not exist; check spelling and try againz2Unable to connect to bucket: %s. Error message:
%s)	botocoremetaclientZhead_bucket
exceptionsClientErrorintresponser-   )s3_resourcebucket_namerG   excZ
error_codeerr_msgr9   r9   r:   _get_head_buckett   s(    

rR   c                   s4   e Zd Zdd Zdd Z fddZdd Z  ZS )	IOBasec             C   s   |S )Nr9   )selfruntimer9   r9   r:   _run_interface   s    zIOBase._run_interfacec             C   s   t d S )N)NotImplementedError)rT   r9   r9   r:   _list_outputs   s    zIOBase._list_outputsc                s   | j tt| j S )N)_add_output_traitssuperrS   _outputs)rT   )	__class__r9   r:   r[      s    zIOBase._outputsc             C   s   |S )Nr9   )rT   r@   r9   r9   r:   rY      s    zIOBase._add_output_traits)__name__
__module____qualname__rV   rX   r[   rY   __classcell__r9   r9   )r\   r:   rS      s   rS   c               @   s    e Zd ZdZdd Zdd ZdS )ProgressPercentagezl
    Callable class instsance (via __call__ method) that displays
    upload percentage of a file to S3
    c             C   s4   ddl }|| _ttjj|| _d| _|j | _	dS ) r   N)
	threading	_filenamefloatr!   r&   getsize_size_seen_so_farLock_lock)rT   filenamerc   r9   r9   r:   __init__   s
    zProgressPercentage.__init__c             C   st   ddl }| j\ |  j|7  _| jdkr:| j| j d }nd}d| j| j|f }|jj| |jj  W dQ R X dS )rb   r   Nd   z%d / %d (%.2f%%))sysrj   rh   rg   stdoutwriteflush)rT   Zbytes_amountrn   
percentageZprogress_strr9   r9   r:   __call__   s    
zProgressPercentage.__call__N)r]   r^   r_   __doc__rl   rs   r9   r9   r9   r:   ra      s   ra   c                   s   e Zd ZdZeddZeddZejddddZ	eddZ
eejeed	dZeejeed
dZejei ddZejddddZeddZejddZejddZeddZ fddZ  ZS )DataSinkInputSpecrb   z,Path to the base directory for storing data.)descz5Folder within base directory in which to store outputTz&store output in parametrized structure)
usedefaultrv   zpath to strip out of filenamezNList of 2-tuples reflecting string to substitute and string to replace it withz|List of 2-tuples reflecting a pair of a Python regexp pattern and a replacement string. Invoked after string `substitutions`)valuerw   Fz'remove dest directory when copying dirszFilepath to AWS credentials file for S3 bucket access; if not specified, the credentials will be taken from the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variablesz@Flag indicating whether to use S3 server-side AES-256 encryptionz-Boto3 S3 bucket for manual override of bucketz*Copy files locally as well as to S3 bucketc                s\   || j  kr2t|s&tt| j|| || j|< n&|| jkrF|| j|< tt| j|| d S )N)copyable_trait_namesr   rZ   ru   __setattr__r[   )rT   rB   rx   )r\   r9   r:   rz      s    

zDataSinkInputSpec.__setattr__)r]   r^   r_   rt   r   base_directory	containerr   Boolparameterization	strip_dirr   Tuplesubstitutionsregexp_substitutionsDictr[   remove_dest_dir
creds_pathencrypt_bucket_keysr<   bucket
local_copyrz   r`   r9   r9   )r\   r:   ru      s,   





ru   c               @   s   e Zd ZejddZdS )DataSinkOutputSpeczdatasink output)rv   N)r]   r^   r_   r   r<   out_filer9   r9   r9   r:   r     s   r   c                   sb   e Zd ZdZeZeZd fdd	Zdd Z	dd	 Z
d
d Zdd Zdd Zdd Zdd Z  ZS )DataSinka  
    Generic datasink module to store structured outputs.

    Primarily for use within a workflow. This interface allows arbitrary
    creation of input attributes. The names of these attributes define the
    directory structure to create for storage of the files or directories.

    The attributes take the following form::

      string[[.[@]]string[[.[@]]string]] ...

    where parts between ``[]`` are optional.

    An attribute such as contrasts.@con will create a 'contrasts' directory
    to store the results linked to the attribute. If the ``@`` is left out, such
    as in 'contrasts.con', a subdirectory 'con' will be created under
    'contrasts'.

    The general form of the output is::

       'base_directory/container/parameterization/destloc/filename'

    ``destloc = string[[.[@]]string[[.[@]]string]]`` and
    ``filename`` come from the input to the connect statement.

    .. warning::

        This is not a thread-safe node because it can write to a common
        shared location. It will not complain when it overwrites a file.

    .. note::

        If both substitutions and regexp_substitutions are used, then
        substitutions are applied first followed by regexp_substitutions.

        This interface **cannot** be used in a MapNode as the inputs are
        defined only when the connect statement is executed.

    Examples
    --------
    >>> ds = DataSink()
    >>> ds.inputs.base_directory = 'results_dir'
    >>> ds.inputs.container = 'subject'
    >>> ds.inputs.structural = 'structural.nii'
    >>> setattr(ds.inputs, 'contrasts.@con', ['cont1.nii', 'cont2.nii'])
    >>> setattr(ds.inputs, 'contrasts.alt', ['cont1a.nii', 'cont2a.nii'])
    >>> ds.run()  # doctest: +SKIP

    To use DataSink in a MapNode, its inputs have to be defined at the
    time the interface is created.

    >>> ds = DataSink(infields=['contasts.@con'])
    >>> ds.inputs.base_directory = 'results_dir'
    >>> ds.inputs.container = 'subject'
    >>> ds.inputs.structural = 'structural.nii'
    >>> setattr(ds.inputs, 'contrasts.@con', ['cont1.nii', 'cont2.nii'])
    >>> setattr(ds.inputs, 'contrasts.alt', ['cont1a.nii', 'cont2a.nii'])
    >>> ds.run()  # doctest: +SKIP

    NTc                sv   t t| jf | i }|| _|rRx0|D ](}| jj|tj t| jj	|< t||< q&W | jj
f ddi| |rrd| _dS )z
        Parameters
        ----------
        infields : list of str
            Indicates the input fields to be dynamically created
        r;   FTN)rZ   r   rl   	_infieldsinputsr=   r   r<   r   r[   r>   _always_run)rT   infields	force_runkwargsrA   rB   )r\   r9   r:   rl   W  s    
zDataSink.__init__c             C   s   |j tjj}tjj|\}}| jjr|}t| jjrF|j	| jjd}dd |jtjjD }tjjj
|}|rtjj
||}n|r|}n|jtjjd }|d tjjkr|dd  }|S )N c             S   s   g | ]}|j d r|qS )rC   )
startswith).0Zfolderr9   r9   r:   
<listcomp>w  s    z%DataSink._get_dst.<locals>.<listcomp>r   r   )rstripr!   r&   sepsplitr   r~   r   r   replacer   )rT   r0   r&   fnamer1   Zfoldersr9   r9   r:   _get_dstm  s     zDataSink._get_dstc             C   s   |}t | jjrPx>| jjD ]2\}}|}|j||}||krtjd|||| qW t | jjrxD| jjD ]8\}}|}tj|||\}}||krftjd|||| qfW ||krtj	d|| |S )Nz sub.str: %s -> %s using %r -> %rz#sub.regexp: %s -> %s using %r -> %rzsub: %s -> %s)
r   r   r   r   ifloggerdebugr   resubninfo)rT   ZpathstrZpathstr_rB   valZ
oldpathstrrC   r9   r9   r:   _substitute  s4    

zDataSink._substitutec             C   sX   d}d}| j j}t|s$d}||fS |j j|}|rP|t|d jdd }||fS )a/  
        Method to see if the datasink's base directory specifies an
        S3 bucket path; if it does, it parses the path for the bucket
        name in the form 's3://bucket_name/...' and returns it

        Parameters
        ----------

        Returns
        -------
        s3_flag : boolean
            flag indicating whether the base_directory contained an
            S3 bucket path
        bucket_name : string
            name of the S3 bucket to connect to; if the base directory
            is not a valid S3 path, defaults to '<N/A>'
        zs3://z<N/A>FN/r   )r   r{   r   lowerr   len	partition)rT   s3_strrO   r{   s3_flagr9   r9   r:   _check_s3_base_dir  s    zDataSink._check_s3_base_dirc       	   
   C   s   ddl }| jj}|r|jj|rt|d}|j }|j }W dQ R X d|krl|jdd }|jdd }n2d|kr|jd	d }|jd	d }nd
}t||j	ddj	dd}|j	ddj	dd}n|j
d}|j
d}||fS )a  
        Method to return AWS access key id and secret access key using
        credentials found in a local file.

        Parameters
        ----------
        self : nipype.interfaces.io.DataSink
            self for instance method

        Returns
        -------
        aws_access_key_id : string
            string of the AWS access key ID
        aws_secret_access_key : string
            string of the AWS secret access key
        r   Nrz	User Name,r   r   ZAWSAccessKeyId=z6Credentials file not recognized, check file is correctr   
ZAWS_ACCESS_KEY_IDZAWS_SECRET_ACCESS_KEY)r!   r   r   r&   existsopenreadliner   r-   r   getenv)	rT   r!   r   Zcreds_inZrow1Zrow2aws_access_key_idaws_secret_access_keyrQ   r9   r9   r:   _return_aws_keys  s(    


zDataSink._return_aws_keysc          ,   C   sN  yddl }ddl}W n. tk
rB } zd}t|W Y dd}~X nX | jj}y| j \}}W n6 tk
r } zd||f }t|W Y dd}~X nX |r|rtjd| |j	j
||d}	ntjd| |j	j
 }	|	jdd	d
}
yt|
| W nR tk
r> } z4|
jjjjjd|jj tjd| t|
| W Y dd}~X nX |
j|}|S )a-  
        Method to return a bucket object which can be used to interact
        with an AWS S3 bucket using credentials found in a local file.

        Parameters
        ----------
        self : nipype.interfaces.io.DataSink
            self for instance method
        bucket_name : string
            string corresponding to the name of the bucket on S3

        Returns
        -------
        bucket : boto3.resources.factory.s3.Bucket
            boto3 s3 Bucket object which is used to interact with files
            in an S3 bucket on AWS
        r   Nz=Boto3 package is not installed - install boto3 and try again.zdThere was a problem extracting the AWS credentials from the credentials file provided: %s. Error:
%sz/Connecting to S3 bucket: %s with credentials...)r   r   z,Connecting to S3 bucket: %s with IAM role...s3T)Zuse_sslzchoose-signer.s3.*z$Connecting to AWS: %s anonymously...)boto3rG   ImportErrorr-   r   r   r   r   r   sessionSessionresourcerR   rH   rI   eventsregisterhandlersZdisable_signingrE   )rT   rO   r   rG   rP   rQ   r   r   r   r   rN   r   r9   r9   r:   _fetch_bucket   s>    



zDataSink._fetch_bucketc                s  ddl }ddlddlm} d}||j } j j|rL| t|d   jj	rg }x2j
D ]$\}	}
|jfdd|
D  qhW  fdd|D }ng} g}xt|D ]\}}|| }|j|djd	}y\|j|d
}|jjd}t|dj }|j|j }||kr0tjd| wn
tjd W n  |k
r\   tjd Y nX tjd||j| | jjrddi}ni }|j|||t|d qW dS )zP
        Method to upload outputs to S3 bucket instead of on local disk
        r   N)rK   zs3://c                s   g | ]} j j|qS r9   )r&   r   )r   Zfil)r!   rootr9   r:   r   h  s    z*DataSink._upload_to_s3.<locals>.<listcomp>c                s$   g | ]}j j |jd  qS )r   )r&   r   r   )r   src_f)r1   r!   r0   r9   r:   r   j  s    r   r   )rB   "rbz)File %s already exists on S3, skipping...zOverwriting previous S3 file...zNew file to S3z'Uploading %s to S3 bucket, %s, as %s...ZServerSideEncryptionZAES256)Z	ExtraArgsZCallback)hashlibr!   Zbotocore.exceptionsrK   r5   r   r   r   r&   r'   walkr.   	enumerater   lstripZObjectZe_tagstripr   readmd5	hexdigestr   r   r   r   Zupload_filera   )rT   r   r0   r1   r   rK   r   Z	s3_prefixZ	src_filesdirsfilesZ	dst_filesZsrc_idxr   Zdst_fZdst_kZdst_objZdst_md5Zsrc_readZsrc_md5
extra_argsr9   )r1   r!   r   r0   r:   _upload_to_s3R  sF    



zDataSink._upload_to_s3c          3   C   s  | j  j }g }ttjdd}t| jjr6| jj}n| jj}t|sJd}| j \}}|r| jj}| jj	rt| jj	}qy| j
|}W q tk
r }	 zBd}t| jjstjjtjjdd| }
|
}tjd||	 W Y dd}	~	X qX nd}t| jjrtjj|| jj}tjj|| jj}||krtjj|}tjj|sytj| W n6 tk
r } zd	|jkrnn|W Y dd}~X nX xzt| jjj D ]d\}}t|sqtjd
|t| t|}|}|r|}xH|jdD ]:}|d dkrqtjj||}|rtjj||}qW t|trLt|d trLdd |D }xt|D ]}tjj|}tjj |stjj|d}| j!|}|rtjj||}| j"|}tjj||}| j"|}tjj|\}}|r| j#||| |j$| | s
t| jjrXtjj|s^ytj| W n6 tk
r\ } zd	|jkrHn|W Y dd}~X nX tjj |rtjd|| t%||dd|d |j$| n^tjj&|rXtjj|r| jj'rtjd| t(j)| tjd|| t*|| |j$| qXW qW ||d< |S )zExecute this module.Z	executionZtry_hard_link_datasink.z<N/A>~Zs3_datasink_z=Access to S3 failed! Storing outputs locally at: %s
Error: %sNzFile existszkey: %s files: %sr   @c             S   s   g | ]}|D ]}|qqS r9   r9   )r   Zsublistitemr9   r9   r:   r     s    z*DataSink._list_outputs.<locals>.<listcomp>r   zcopyfile: %s %sTr   )copyr   r    zremoving: %szcopydir: %s %sr   )+output_specgetr   r   r   r   r   r{   r   r   r   r-   r!   r&   r   
expanduserr   r   r|   abspathr   r#   r$   r%   listr[   itemsr   r,   r
   r   
isinstanceisfiler   r   r   r+   r   r'   r   shutilrmtreer(   )rT   outputsZ	out_filesr    outdirr   rO   Zs3dirr   rP   Zlocal_out_exceptioninstrB   r   Z
tempoutdirZs3tempoutdirdr0   r1   Zs3dstr&   rC   r9   r9   r:   rX     s    









zDataSink._list_outputs)NT)r]   r^   r_   rt   ru   
input_specr   r   rl   r   r   r   r   r   r   rX   r`   r9   r9   )r\   r:   r     s   <"9RBr   c               @   s   e Zd ZejddddZeddddZedddZed	dd
dZ	e
dddZejddddZejdddZedddZejeejejddZdS )S3DataGrabberInputSpecFTzUse anonymous connection to s3.  If this is set to True, boto may print a urlopen error, but this does not prevent data from being downloaded.)rw   rv   z	us-east-1zRegion of s3 bucketz*Amazon S3 bucket where your data is stored)	mandatoryrv   r   z-Location within your bucket for subject data.zmPath to the local directory for subject data to be downloaded and accessed. Should be on HDFS for Spark jobs.)r   rv   z5Generate exception if list is empty for a given fieldz+Sort the filelist that matches the templatezjLayout used to get files. Relative to bucket_path if defined.Uses regex rather than glob style formatting.z!Information to plug into template)	key_traitvalue_traitrv   N)r]   r^   r_   r   r}   anonr   Zregionr   bucket_pathr   local_directoryraise_on_emptysort_filelisttemplater   Listtemplate_argsr9   r9   r9   r:   r   "  s0   

r   c                   sJ   e Zd ZdZeZeZdZdZ	d fdd	Z
dd Zd	d
 Zdd Z  ZS )S3DataGrabbera+  
    Pull data from an Amazon S3 Bucket.

    Generic datagrabber module that wraps around glob in an
    intelligent way for neuroimaging tasks to grab files from
    Amazon S3

    Works exactly like DataGrabber, except, you must specify an
    S3 "bucket" and "bucket_path" to search for your data and a
    "local_directory" to store the data. "local_directory"
    should be a location on HDFS for Spark jobs. Additionally,
    "template" uses regex style formatting, rather than the
    glob-style found in the original DataGrabber.

    Examples
    --------
    >>> s3grab = S3DataGrabber(infields=['subj_id'], outfields=["func", "anat"])
    >>> s3grab.inputs.bucket = 'openneuro'
    >>> s3grab.inputs.sort_filelist = True
    >>> s3grab.inputs.template = '*'
    >>> s3grab.inputs.anon = True
    >>> s3grab.inputs.bucket_path = 'ds000101/ds000101_R2.0.0/uncompressed/'
    >>> s3grab.inputs.local_directory = '/tmp'
    >>> s3grab.inputs.field_template = {'anat': '%s/anat/%s_T1w.nii.gz',
    ...                                 'func': '%s/func/%s_task-simon_run-1_bold.nii.gz'}
    >>> s3grab.inputs.template_args = {'anat': [['subj_id', 'subj_id']],
    ...                                'func': [['subj_id', 'subj_id']]}
    >>> s3grab.inputs.subj_id = 'sub-01'
    >>> s3grab.run()  # doctest: +SKIP

    TbotoNc                s   |s
dg}t t| jf | i }|| _|| _|rVx$|D ]}| jj|tj t	||< q6W | jjdtj
tj|dd t	|d< t| jjsi | j_x8|D ]0}|| jjkr|r|g| jj|< qg | jj|< qW | jjf ddi| dS )a  
        Parameters
        ----------
        infields : list of str
            Indicates the input fields to be dynamically created

        outfields: list of str
            Indicates output fields to be dynamically created

        See class examples for usage

        outfilesfield_templatez arguments that fit into template)rv   r;   FN)rZ   r   rl   r   
_outfieldsr   r=   r   r<   r   r   Enumr   r   r>   )rT   r   	outfieldsr   rA   rB   )r\   r9   r:   rl   m  s.    

zS3DataGrabber.__init__c             C   s   t |t| jjj S )z
        S3 specific: Downloads relevant files to a local folder specified

        Using traits.Any instead out OutputMultiPath till add_trait bug
        is fixed.
        )rD   r   r   r   keys)rT   r@   r9   r9   r:   rY     s    z S3DataGrabber._add_output_traitsc             C   sn  dd l }| jrJx:| jD ]0}t| j|}t|sd| jj|f }t|qW i }|j| jj	d}|j
| jj}tdd |j| jjdD }xtt| jjj D ]^\}}	g ||< | jj}
t| jdrt| jjr|| jjkr| jj| }
t| jjrtjj| jj|
}
|	sg }x&|D ]}tj|
|r|j| qW t|dkrrd||
f }| jjrht|nt| n| jjrt|}t|||< xt |	D ] \}}d	}x~|D ]v}t!|t"t#frt| j|rt| j|}t!|tr|d	krt||krtd
| t||krt|}qW g }xjt$|D ]\}g }x^|D ]V}t!|t"t#frxt| j|rxt| j|}t!|tr|j||  n
|j| qJW |
}|r y|
t%| }W n@ t&k
r } z"t&| d|
 dt%| W Y d d }~X nX g }x&|D ]}tj||r
|j| q
W t|dkrrd||f }| jjrZt|nt| || jd  n$| jjrt|}|| jt| q:W qW t'dd || D rg ||< t|| dkrd ||< qt|| d	kr|| d ||< qW xf|j D ]Z\}}t!|tt%t(frTx<t |D ]\}}| j)|||| |< q0W n| j)||||< qW |S )Nr   zF%s requires a value for input '%s' because it was listed in 'infields')r   c             s   s   | ]}|j V  qd S )N)rB   )r   kr9   r9   r:   	<genexpr>  s    z.S3DataGrabber._list_outputs.<locals>.<genexpr>)prefixr   z-Output key: %s Template: %s returned no filesr   z'incompatible number of arguments for %sz: Template z failed to convert with args c             S   s   g | ]}|d kqS )Nr9   )r   r   r9   r9   r:   r     s    z/S3DataGrabber._list_outputs.<locals>.<listcomp>)*r   r   r?   r   r   r\   r]   
ValueErrorZ
connect_s3r   Z
get_bucketr   r   r   r   r   r   hasattrr   r!   r&   r   r   matchr+   r   r   r)   r   r   r   r	   r   r   r,   bytesrangetuple	TypeErroranyset	s3tolocal)rT   r   rB   rx   msgr   connbktZ	bkt_filesr/   r   filelistr   argnumarglistmaxlenargr   iargtuplefilledtemplateer   r&   r9   r9   r:   rX     s    







,




zS3DataGrabber._list_outputsc       
      C   s   dd l }t| jj}t| jj}t| jj}tjj|dksD|d7 }tjj|dks\|d7 }|d dkrt|dd  }|j	||}tjj
|d }tjj|stj| |jjj|}	||	_|	j| |S )Nr   r   r   r   )r   r,   r   r   r   r   r!   r&   basenamer   r   r   r#   r   rB   ZKeyZget_contents_to_filename)
rT   Zs3pathr  r   r   r   r   Z	localpathZlocaldirr   r9   r9   r:   r    s$    

zS3DataGrabber.s3tolocal)NN)r]   r^   r_   rt   r   r   r   r   r   _pkgrl   rY   rX   r  r`   r9   r9   )r\   r:   r   G  s   +	~r   c               @   sj   e Zd ZedddZejddddZejddddZejddd	Z	e
dd
d	Zeje
ejejddZdS )DataGrabberInputSpecTz6Path to the base directory consisting of subject data.)r   rv   z5Generate exception if list is empty for a given field)rw   rv   Fz)Remove ``None`` entries from output listsz+Sort the filelist that matches the template)r   rv   z?Layout used to get files. relative to base directory if definedz!Information to plug into template)r   r   rv   N)r]   r^   r_   r   r{   r   r}   r   drop_blank_outputsr   r   r   r   r   r   r9   r9   r9   r:   r  7  s"   


r  c                   s>   e Zd ZdZeZeZdZd
 fdd	Z	dd Z
dd	 Z  ZS )DataGrabbera  
    Find files on a filesystem.

    Generic datagrabber module that wraps around glob in an
    intelligent way for neuroimaging tasks to grab files

    .. important::

       Doesn't support directories currently

    Examples
    --------
    >>> from nipype.interfaces.io import DataGrabber

    Pick all files from current directory

    >>> dg = DataGrabber()
    >>> dg.inputs.template = '*'

    Pick file foo/foo.nii from current directory

    >>> dg.inputs.template = '%s/%s.dcm'
    >>> dg.inputs.template_args['outfiles']=[['dicomdir','123456-1-1.dcm']]

    Same thing but with dynamically created fields

    >>> dg = DataGrabber(infields=['arg1','arg2'])
    >>> dg.inputs.template = '%s/%s.nii'
    >>> dg.inputs.arg1 = 'foo'
    >>> dg.inputs.arg2 = 'foo'

    however this latter form can be used with iterables and iterfield in a
    pipeline.

    Dynamically created, user-defined input and output fields

    >>> dg = DataGrabber(infields=['sid'], outfields=['func','struct','ref'])
    >>> dg.inputs.base_directory = '.'
    >>> dg.inputs.template = '%s/%s.nii'
    >>> dg.inputs.template_args['func'] = [['sid',['f3','f5']]]
    >>> dg.inputs.template_args['struct'] = [['sid',['struct']]]
    >>> dg.inputs.template_args['ref'] = [['sid','ref']]
    >>> dg.inputs.sid = 's1'

    Change the template only for output field struct. The rest use the
    general template

    >>> dg.inputs.field_template = dict(struct='%s/struct.nii')
    >>> dg.inputs.template_args['struct'] = [['sid']]

    TNc                s   |s
dg}t t| jf | i }|| _|| _|rVx$|D ]}| jj|tj t	||< q6W | jjdtj
tj|dd t	|d< t| jjsi | j_x8|D ]0}|| jjkr|r|g| jj|< qg | jj|< qW | jjf ddi| dS )a  
        Parameters
        ----------
        infields : list of str
            Indicates the input fields to be dynamically created

        outfields: list of str
            Indicates output fields to be dynamically created

        See class examples for usage

        r   r   z arguments that fit into template)rv   r;   FN)rZ   r  rl   r   r   r   r=   r   r<   r   r   r   r   r   r>   )rT   r   r   r   rA   rB   )r\   r9   r:   rl     s.    

zDataGrabber.__init__c             C   s   t |t| jjj S )zd

        Using traits.Any instead out OutputMultiPath till add_trait bug
        is fixed.
        )rD   r   r   r   r   )rT   r@   r9   r9   r:   rY     s    zDataGrabber._add_output_traitsc             C   s  | j rBx:| j D ]0}t| j|}t|sd| jj|f }t|qW i }xft| jjj	 D ]P\}}g ||< | jj
}t| jdrt| jjr|| jjkr| jj| }t| jjrtjjtjj| jj|}ntjj|}|s>tj|}t|dkr d||f }| jjrt|nt| n| jjr2t|}t|||< xt|D ]\}}	d}
x~|	D ]v}t|ttfrt| j|rt| j|}t|tr^|
dkrt||
krtd| t||
kr^t|}
q^W g }xHt|
D ]:}g }x^|	D ]V}t|ttfr&t| j|r&t| j|}t|trB|j||  n
|j| qW |}|ry|t | }W n@ t!k
r } z"t!| d| dt | W Y d d }~X nX tj|}t|dkrd||f }| jjrt|nt| || jd  n$| jjrt|}|| jt| qW qJW | jj"rPd	d
 || D ||< n t#dd
 || D rpg ||< t|| dkrd ||< qZt|| dkrZ|| d ||< qZW |S )NzF%s requires a value for input '%s' because it was listed in 'infields'r   r   z-Output key: %s Template: %s returned no filesr   z'incompatible number of arguments for %sz: Template z failed to convert with args c             S   s   g | ]}|d k	r|qS )Nr9   )r   xr9   r9   r:   r     s    z-DataGrabber._list_outputs.<locals>.<listcomp>c             S   s   g | ]}|d kqS )Nr9   )r   r   r9   r9   r:   r     s    )$r   r?   r   r   r\   r]   r   r   r   r   r   r   r   r{   r!   r&   r   r   globr   r   r)   r   r   r   r	   r   r   r,   r   r   r+   r  r  r  r  )rT   rB   rx   r  r   r/   r   r	  r
  r  r  r  r   r  r  r  r  r9   r9   r:   rX     s    







,





zDataGrabber._list_outputs)NN)r]   r^   r_   rt   r  r   r   r   r   rl   rY   rX   r`   r9   r9   )r\   r:   r  Q  s   3+r  c               @   sX   e Zd ZedddZejddddZejddddZej	ej ej
e dddd	Zd
S )SelectFilesInputSpecTzRoot path common to templates.)r   rv   z:When matching mutliple files, return them in sorted order.)rw   rv   z:Raise an exception if a template pattern matches no files.FzWhether to return outputs as a list even when only one file matches the template. Either a boolean that applies to all output fields or a list of output field names to coerce to a list)defaultrw   rv   N)r]   r^   r_   r   r{   r   r}   r   r   Eitherr   r   force_listsr9   r9   r9   r:   r  #  s   
r  c                   s<   e Zd ZdZeZeZdZ fddZ	dd Z
dd Z  ZS )	SelectFilesa  
    Flexibly collect data from disk to feed into workflows.

    This interface uses Python's {}-based string formatting syntax to plug
    values (possibly known only at workflow execution time) into string
    templates and collect files from persistant storage. These templates can
    also be combined with glob wildcards (``*``, ``?``) and character ranges (``[...]``).
    The field names in the formatting template (i.e. the terms in braces) will
    become inputs fields on the interface, and the keys in the templates
    dictionary will form the output fields.

    Examples
    --------
    >>> import pprint
    >>> from nipype import SelectFiles, Node
    >>> templates={"T1": "{subject_id}/struct/T1.nii",
    ...            "epi": "{subject_id}/func/f[0,1].nii"}
    >>> dg = Node(SelectFiles(templates), "selectfiles")
    >>> dg.inputs.subject_id = "subj1"
    >>> pprint.pprint(dg.outputs.get())  # doctest:
    {'T1': <undefined>, 'epi': <undefined>}

    Note that SelectFiles does not support lists as inputs for the dynamic
    fields. Attempts to do so may lead to unexpected results because brackets
    also express glob character ranges. For example,

    >>> templates["epi"] = "{subject_id}/func/f{run}.nii"
    >>> dg = Node(SelectFiles(templates), "selectfiles")
    >>> dg.inputs.subject_id = "subj1"
    >>> dg.inputs.run = [10, 11]

    would match f0.nii or f1.nii, not f10.nii or f11.nii.

    Tc       
         s   t t| jf | g }xbt|j D ]R\}}xHtj j|D ]6\}}}}|dk	r<tj	d|j
 }||kr<|j| q<W q$W || _t|| _|| _i }x$|D ]}	| jj|	tj t||	< qW | jjf ddi| dS )a  Create an instance with specific input fields.

        Parameters
        ----------
        templates : dictionary
            Mapping from string keys to string template values.
            The keys become output fields on the interface.
            The templates should use {}-formatting syntax, where
            the names in curly braces become inputs fields on the interface.
            Format strings can also use glob wildcards to match multiple
            files. At runtime, the values of the interface inputs will be
            plugged into these templates, and the resulting strings will be
            used to select files.

        Nz\w+r;   F)rZ   r  rl   r   r   string	Formatterparser   r   groupr+   r   r   
_templatesr   r=   r   r<   r   r>   )
rT   Z	templatesr   r   r5   r   rC   
field_namerA   field)r\   r9   r:   rl   g  s     

zSelectFiles.__init__c             C   s   t |t| jj S )zAdd the dynamic output fields)rD   r   r"  r   )rT   r@   r9   r9   r:   rY     s    zSelectFiles._add_output_traitsc                s  i }t  fddt jjj D } jj}t|trF|rB jng }t	|t	 j }|rdj
t|}t|dkrzdnd}t|dkrdnd}d	|||f }t|xt jj D ]\}}	|	d tjk}
t jjrtjtj
 jj|	}	n
tj|	}	|
r|	tj7 }	|	jf |}tj|}|sPd
||f } jjrHt|nt|  jjrbt|}||krtt|}|||< qW |S )z4Find the files and expose them as interface outputs.c                s"   g | ]\}}| j kr||fqS r9   )r   )r   r   v)rT   r9   r:   r     s   z-SelectFiles._list_outputs.<locals>.<listcomp>z, r   sr   werewasz@The field%s '%s' %s set in 'force_lists' and not in 'templates'.z,No files were found matching %s template: %sr   )dictr   r   __dict__r   r  r   boolr   r  r   r   r   r"  r!   r   r   r{   opr   formatr  r   r)   r   r   r   r	   )rT   r   r   r  Z
bad_fieldspluralZverbr  r$  r   Z	find_dirsZfilled_templater	  r9   )rT   r:   rX     sJ    








zSelectFiles._list_outputs)r]   r^   r_   rt   r  r   r   r   r   rl   rY   rX   r`   r9   r9   )r\   r:   r  ?  s   "&r  c               @   sd   e Zd Zejej e ddZeddddZejddZ	ej
ddZej
d	dZejd
dddZdS )DataFinderInputSpecT)r   z(.+)z&Regular expression for matching paths.)rw   rv   zFList of regular expressions, if any match the path it will be ignored.)rv   z2The maximum depth to search beneath the root_pathsz2The minimum depth to search beneath the root pathsFzUnpack single results from listN)r]   r^   r_   r   r  r   r   
root_pathsmatch_regexignore_regexesZInt	max_depth	min_depthr}   unpack_singler9   r9   r9   r:   r/    s   r/  c               @   s4   e Zd ZdZeZeZdZdd Z	dd Z
dd Zd	S )

DataFindera  Search for paths that match a given regular expression. Allows a less
    proscriptive approach to gathering input files compared to DataGrabber.
    Will recursively search any subdirectories by default. This can be limited
    with the min/max depth options.
    Matched paths are available in the output 'out_paths'. Any named groups of
    captured text from the regular expression are also available as ouputs of
    the same name.

    Examples
    --------
    >>> from nipype.interfaces.io import DataFinder
    >>> df = DataFinder()
    >>> df.inputs.root_paths = '.'
    >>> df.inputs.match_regex = r'.+/(?P<series_dir>.+(qT1|ep2d_fid_T1).+)/(?P<basename>.+)\.nii.gz'
    >>> result = df.run() # doctest: +SKIP
    >>> result.outputs.out_paths  # doctest: +SKIP
    ['./027-ep2d_fid_T1_Gd4/acquisition.nii.gz',
     './018-ep2d_fid_T1_Gd2/acquisition.nii.gz',
     './016-ep2d_fid_T1_Gd1/acquisition.nii.gz',
     './013-ep2d_fid_T1_pre/acquisition.nii.gz']
    >>> result.outputs.series_dir  # doctest: +SKIP
    ['027-ep2d_fid_T1_Gd4',
     '018-ep2d_fid_T1_Gd2',
     '016-ep2d_fid_T1_Gd1',
     '013-ep2d_fid_T1_pre']
    >>> result.outputs.basename  # doctest: +SKIP
    ['acquisition',
     'acquisition'
     'acquisition',
     'acquisition']

    Tc             C   s   x| j D ]}|j|rd S qW | jj|}|d k	r|j }| jd krndg i| _xt|j D ]}g | j|< q\W | jd j| x(t|j D ]\}}| j| j| qW d S )N	out_paths)	r2  searchr1  	groupdictresultr   r   r+   r   )rT   target_pathZ	ignore_rer   Z
match_dictrB   r   r9   r9   r:   _match_path  s    


zDataFinder._match_pathc             C   sL  t | jjttfr | jjg| j_tj| jj| _| jjt	krBd }n| jj}| jj
t	kr\d}n| jj
}| jjt	krxg | _ndd | jjD | _d | _x| jjD ]}tjjtjjtjj|}tjj|r|dkr| j| qxtj|D ]\}}}|jtj|jtj }|d k	r.||kr.g |d d < g }||krB| j| ||d krx&|D ]}	tjj||	}
| j|
 qTW qW qW | jjrt| jd dkrxt| jj D ]\}}|d | j|< qW nnxXt| jj D ]F}|dkrqttt| jd | j| }dd |D | j|< qW t| jd | jd< | jsHtd|S )Nr   c             S   s   g | ]}t j|qS r9   )r   compile)r   regexr9   r9   r:   r   .  s    z-DataFinder._run_interface.<locals>.<listcomp>r   r7  c             S   s   g | ]\}}|qS r9   r9   )r   rC   r  r9   r9   r:   r   V  s    z+Regular expression did not match any files!) r   r   r0  r,   r   r   r=  r1  r3  r   r4  r2  r:  r!   r&   normpath
expandvarsr   r   r<  r   countr   r   r5  r   r   r   r   r   zipRuntimeError)rT   rU   r3  r4  	root_pathZcurr_dirZsub_dirsr   Z
curr_depthinfile	full_pathrB   valsZsort_tuplesr9   r9   r:   rV     sX    




zDataFinder._run_interfacec             C   s   | j  j }|j| j |S )N)r[   r   updater:  )rT   r   r9   r9   r:   rX   ^  s    zDataFinder._list_outputsN)r]   r^   r_   rt   r/  r   r   r   r   r<  rV   rX   r9   r9   r9   r:   r6    s    Ar6  c               @   s:   e Zd ZeddddZedddZejddddd	d
Z	dS )FSSourceInputSpecTzFreesurfer subjects directory.)r   r   rv   z&Subject name for whom to retrieve data)r   rv   bothZlhZrhz#Selects hemisphere specific outputs)rw   rv   N)
r]   r^   r_   r   subjects_dirr   
subject_idr   r   hemir9   r9   r9   r:   rI  d  s
   rI  c               @   s  e Zd ZeddddZeddddZeddddZeddddZedd	ddZedd
ddZ	eddddZ
eddddZeddddZeeddddddZeddddZeddddZeedddddZeedddddZeedddddZeedddddZeeddddddZeeddddddZeedddddZeeddd ddZeeddd!ddZeedddd"dZeeddd#ddZeeddd$ddZeeddd%ddZeeddd&dd'd(gdZeeddd)d*d+dZeeddd,d*d-dZ eedddd.d/d0Z!eedddd1d2d0Z"eeddd3d4d5d0Z#eeddd3d6d7d0Z$eeddd3d8d9d0Z%eeddd3d:d;d0Z&eeddd3d<d=d0Z'eeddd3d>d?d0Z(eeddd3d@dAd0Z)dBS )CFSSourceOutputSpecTz&Intensity normalized whole-head volumemri)r   rv   locz5Volumetric map of regions from automatic segmentation)r   rP  rv   z&Intensity normalized brain-only volumez"Skull-stripped (brain-only) volumezSubcortical mass volumez Normalized skull-stripped volumez*Non-uniformity corrected whole-head volumez(Base image conformed to Freesurfer spacez'Volume formed by averaging input images)r   z#Volumetric maps of cortical ribbonsz*ribbon)rv   rP  altkeyzSegmented white-matter volumez:Aparc parcellation projected into subcortical white matterzMaps of surface curvaturesurf)rv   rP  z+Average atlas curvature, sampled to subjectzInflated surface meshesz$Gray matter/pia mater surface mesheszIMean area of triangles each vertex on the pial surface is associated withz	area.pialzCurvature of pial surfacez	curv.pialz Smoothed original surface meshes)rP  rv   zSpherical surface mesheszSurface maps of sulcal depthz"Surface maps of cortical thicknesszSurface maps of cortical volumez White/gray matter surface meshesz2Distortion required to register to spherical atlasz#Graymid/midthickness surface meshesgraymidZmidthicknesszVolume and surface label fileslabelz*labelzSurface annotation filesz*annotz
aparc*asegz-Aparc parcellation projected into aseg volume)rP  rQ  rv   z
sphere.regzSpherical registration filestatsasegz&Automated segmentation statistics filewmparcz)White matter parcellation statistics fileZaparcz#Aparc parcellation statistics filesZBAzBrodmann Area statistics fileszaparc.a2009sz*Aparc a2009s parcellation statistics filescurvzCurvature statistics filesZentorhinal_exvivoz"Entorhinal exvivo statistics filesN)*r]   r^   r_   r   ZT1rV  ZbrainZ	brainmaskZfilledZnormnuorigZrawavgr   ribbonZwmrW  rX  Zavg_curvZinflatedZpialZ	area_pialZ	curv_pialZsmoothwmZsphereZsulcZ	thicknessvolumeZwhiteZjacobian_whiterS  rT  ZannotZ
aparc_asegZ
sphere_reg
aseg_statswmparc_statsZaparc_statsZBA_statsZaparc_a2009s_statsZ
curv_statsZentorhinal_exvivo_statsr9   r9   r9   r:   rN  n  s   rN  c               @   s6   e Zd ZdZeZeZdZddgZ	d
ddZ
dd	 ZdS )FreeSurferSourceap  Generates freesurfer subject info from their directories.

    Examples
    --------
    >>> from nipype.interfaces.io import FreeSurferSource
    >>> fs = FreeSurferSource()
    >>> #fs.inputs.subjects_dir = '.'
    >>> fs.inputs.subject_id = 'PWS04'
    >>> res = fs.run() # doctest: +SKIP

    >>> fs.inputs.hemi = 'lh'
    >>> res = fs.run() # doctest: +SKIP

    TrP  rQ  Nc                s   d}|dkrd}n|dkrd}d}|dkrV| j jdkrD| j jd	 }nd
}|dkr|d}n&|dkr|| j jdkrx| j jd	 }nd}|rt|n|g}tjj||dj|d|f  fdd|D S )Nr   rO  z.mgzrU  z.statsrR  rT  rJ  r   z?h.r]  r^  r[  *z{}c                s.   g | ]&}t j  j|D ]}tjj|qqS r9   )r  r-  r!   r&   r   )r   rB   f)globfmtr9   r:   r   +  s    z/FreeSurferSource._get_files.<locals>.<listcomp>)rR  rT  rU  )r]  r^  )r   rM  r
   r!   r&   r   )rT   r&   rB   ZdirvalrQ  Z
globsuffixZ
globprefixr   r9   )rb  r:   
_get_files  s&    zFreeSurferSource._get_filesc             C   sx   | j j}tjj|| j j}| j }|j }xHt|j	 D ]8}| j
|||j | j|j | j}|r8t|||< q8W |S )N)r   rK  r!   r&   r   rL  r[   r   r   r   rc  r   rP  rQ  r	   )rT   rK  Zsubject_pathZoutput_traitsr   r   r   r9   r9   r:   rX   .  s    zFreeSurferSource._list_outputs)N)r]   r^   r_   rt   rI  r   rN  r   r   Z_additional_metadatarc  rX   r9   r9   r9   r:   r_     s   
r_  c               @   st   e Zd ZedddZejeejejeg ddddZ	edddgd	gd
Z
e Zej ZeddgdZeddZdS )XNATSourceInputSpecTz?Layout used to get files. Relative to base directory if defined)r   rv   )r   z!Information to plug into template)rx   rw   rv   userpwdr   )r   requiresxorserver)r   rh  zCache directory)rv   N)r]   r^   r_   r   query_templater   r   r   r)  query_template_argsri  re  Passwordrf  r   r   r   	cache_dirr9   r9   r9   r:   rd  ?  s   
rd  c                   s>   e Zd ZdZeZeZdZd
 fdd	Z	dd Z
dd	 Z  ZS )
XNATSourcea  
    Pull data from an XNAT server.

    Generic XNATSource module that wraps around the pyxnat module in
    an intelligent way for neuroimaging tasks to grab files and data
    from an XNAT server.

    Examples
    --------
    Pick all files from current directory

    >>> dg = XNATSource()
    >>> dg.inputs.template = '*'

    >>> dg = XNATSource(infields=['project','subject','experiment','assessor','inout'])
    >>> dg.inputs.query_template = '/projects/%s/subjects/%s/experiments/%s'                '/assessors/%s/%s_resources/files'
    >>> dg.inputs.project = 'IMAGEN'
    >>> dg.inputs.subject = 'IMAGEN_000000001274'
    >>> dg.inputs.experiment = '*SessionA*'
    >>> dg.inputs.assessor = '*ADNI_MPRAGE_nii'
    >>> dg.inputs.inout = 'out'

    >>> dg = XNATSource(infields=['sid'],outfields=['struct','func'])
    >>> dg.inputs.query_template = '/projects/IMAGEN/subjects/%s/experiments/*SessionA*'                '/assessors/*%s_nii/out_resources/files'
    >>> dg.inputs.query_template_args['struct'] = [['sid','ADNI_MPRAGE']]
    >>> dg.inputs.query_template_args['func'] = [['sid','EPI_faces']]
    >>> dg.inputs.sid = 'IMAGEN_000000001274'

    pyxnatNc                s   t t| jf | i }|| _|rTx$|D ]}| jj|tj t||< q&W |g| jj	d< |r| jjdtj
tj|dd t|d< i }x|D ]}g ||< qW || j_	| jjf ddi| dS )a  
        Parameters
        ----------
        infields : list of str
            Indicates the input fields to be dynamically created

        outfields: list of str
            Indicates output fields to be dynamically created

        See class examples for usage

        r   r   z&arguments that fit into query_template)rv   r;   FN)rZ   rn  rl   r   r   r=   r   r<   r   rk  r   r   r>   )rT   r   r   r   rA   rB   Zoutdict)r\   r9   r:   rl   |  s(    


zXNATSource.__init__c             C   s   t |t| jjj S )zd

        Using traits.Any instead out OutputMultiPath till add_trait bug
        is fixed.
        )rD   r   r   rk  r   )rT   r@   r9   r9   r:   rY     s    zXNATSource._add_output_traitsc             C   s*  dd l }| jjptj }| jjr2|j| jjd}n|j| jj| jj| jj	|}| j
rx:| j
D ]0}t| j|}t|s\d| jj|f }t|q\W i }xt| jjj D ]x\}}g ||< | jj}	t| jdrt| jjr|| jjkr| jj| }	|s4|j|	jd}
|
g krtd|	 tdd |
D ||< xt|D ]\}}d	}x~|D ]v}t|ttfrt| j|rt| j|}t|trT|d	krt||krtd
| t||krTt|}qTW g }x
t|D ]}g }x^|D ]V}t|ttfrt| j|rt| j|}t|tr6|j ||  n
|j | qW |r|	t!| }|j|jd}
|
g kr~td| tdd |
D }n8|j|	jd}
|
g krtd|	 tdd |
D }|| j"|| qW q@W t|| dkrd ||< qt|| d	kr|| d ||< qW |S )Nr   )r   zF%s requires a value for input '%s' because it was listed in 'infields'r   objzTemplate %s returned no filesc             S   s    g | ]}|j  rt|j qS r9   )r   r,   r   )r   file_objectr9   r9   r:   r     s   z,XNATSource._list_outputs.<locals>.<listcomp>r   z'incompatible number of arguments for %sc             S   s    g | ]}|j  rt|j qS r9   )r   r,   r   )r   rq  r9   r9   r:   r     s   c             S   s    g | ]}|j  rt|j qS r9   )r   r,   r   )r   rq  r9   r9   r:   r     s   )#ro  r   rm  tempfile
gettempdirr   	Interfaceri  re  rf  r   r?   r   r\   r]   r   r   rk  r   rj  r   r   selectr   r)   r	   r   r   r,   r   r   r   r+   r  insert)rT   ro  rm  xnatrB   rx   r  r   r/   r   Zfile_objectsr
  r  r  r  r   r  r  targetr9   r9   r:   rX     s    







zXNATSource._list_outputs)NN)r]   r^   r_   rt   rd  r   r   r   r  rl   rY   rX   r`   r9   r9   )r\   r:   rn  W  s   'rn  c                   s   e Zd Zejei ddZedddgdgdZe Zej	 Z
eddgdZed	d
ZedddZedddZedddZeddgdZeddgdZejddddZ fddZ  ZS )XNATSinkInputSpecT)rx   rw   re  rf  r   )r   rg  rh  ri  )r   rh  r   )rv   z%Project in which to store the outputs)rv   r   zSet to subject idzSet to workflow namezaOption to customize ouputs representation in XNAT - assessor level will be used with specified idreconstruction_id)rv   rh  zgOption to customize ouputs representation in XNAT - reconstruction level will be used with specified idassessor_idFzOption to share the subjects from the original projectinstead of creating new ones when possible - the created experiments are then shared back to the original project)rv   rw   c                s.   || j  kr|| j|< ntt| j|| d S )N)ry   r[   rZ   ry  rz   )rT   rB   rx   )r\   r9   r:   rz   >  s    zXNATSinkInputSpec.__setattr__)r]   r^   r_   r   r   r   r[   ri  re  rl  rf  r   r   r   rm  
project_idrL  experiment_idr{  rz  r}   sharerz   r`   r9   r9   )r\   r:   ry    s(   


ry  c               @   s    e Zd ZdZeZdZdd ZdS )XNATSinkzGeneric datasink module that takes a directory containing a
    list of nifti files and provides a set of structured output
    fields.
    ro  c          	   C   s  ddl }| jjptj }| jjr2|j| jjd}n|j| jj| jj| jj	|}| jj
r| jj}|jdddgjd| }|jot|jd tr|jd }|jd| jj| jjf }|j s|jd	| jj }|j s|j  |jd
| }|j
t| jj tt| jj| jjt| jjd}	| jj
r:|d |	d< | jjrVt| jj|	d< n| jjrpt| jj|	d< xt| jjj D ]l\}
}x`t|D ]T}t|trx@t|D ]"\}}t| ||d| |
 |	 qW nt| |||
|	 qW qW dS )zExecute this module.r   N)r   zxnat:subjectDatazxnat:subjectData/PROJECTzxnat:subjectData/SUBJECT_IDz$xnat:subjectData/SUBJECT_ID = %s ANDz/project/%s/subject/%sz/project/%sz+/project/%(project)s/subject/%(subject_id)s)r|  rL  r}  projectoriginal_projectr{  rz  z%s_)ro  r   rm  rr  rs  r   rt  ri  re  rf  r~  rL  ru  wheredatar   r)  r|  r   rv  r,   quote_idr}  r{  rz  r   r[   r   r
   r   	push_file)rT   ro  rm  rw  rL  r:  sharedZshare_projectsubjecturi_template_argsrB   r   r5   r  	file_namer9   r9   r:   rX   N  sT    









zXNATSink._list_outputsN)r]   r^   r_   rt   ry  r   r  rX   r9   r9   r9   r:   r  E  s   r  c             C   s   t | jddS )NrC   z---)r,   r   )r  r9   r9   r:   r    s    r  c             C   s   t | jddS )Nz---rC   )r,   r   )r  r9   r9   r:   
unquote_id  s    r  c             C   s  dd t jj|d jt jD }ttt|dd d |dd d }g }x6t|j D ]&\}}	t	| j
j|	krZ|j||	g qZW d |d< x6dD ].}
t| j
|
r|
jd	d |d< ||
 |d
< qW |d d krd|d< t|d |d
< |r|d
  ddj| 7  < n|d
  d7  < d|d
 |jdd f |d< t jjt jjt|d |d< d}x&t|j D ]}t|| ||< qlW |j|| }|j|ddd d|krd}|j|| j|d  d S )Nc             S   sH   g | ]@}|j d dd D ](}|jd rt|j d d rt|qqS )rC   r   Nr   )r   r   r   r  )r   partr   r9   r9   r:   r     s   zpush_file.<locals>.<listcomp>r   r   r   Zcontainer_typer{  rz  _idZcontainer_idZreconstructionr}  z_results_%srC   _resultsz%s_%sr   Zresource_labelr  z/project/%(project_id)s/subject/%(subject_id)s/experiment/%(experiment_id)s/%(container_type)s/%(container_id)s/out/resource/%(resource_label)s/file/%(file_name)szxnat:imageSessionDataT)ZexperimentsZ	use_labelr  zQ/project/%(original_project)s/subject/%(subject_id)s/experiment/%(experiment_id)s)r{  rz  )r!   r&   r   r   r)  r   rB  sortedr   r,   r   rL  r.   r?   r  r   r   r   ru  rv  r~  )rT   rw  r  Zout_keyr  Zval_listZkeymapZ_labelrB   r   r|   Zuri_templateZremote_fileZexperiment_templater9   r9   r:   r    sD    &


r  c               C   s   d S )Nr9   r9   r9   r9   r:   capture_provenance  s    r  c               C   s   d S )Nr9   r9   r9   r9   r:   push_provenance  s    r  c               @   s"   e Zd ZedddZeddZdS )SQLiteSinkInputSpecT)r   r   )r   N)r]   r^   r_   r   database_filer   
table_namer9   r9   r9   r:   r    s   r  c                   s0   e Zd ZdZeZdZ fddZdd Z  Z	S )
SQLiteSinka-  
    Very simple frontend for storing values into SQLite database.

    .. warning::

        This is not a thread-safe node because it can write to a common
        shared location. It will not complain when it overwrites a file.

    Examples
    --------

    >>> sql = SQLiteSink(input_names=['subject_id', 'some_measurement'])
    >>> sql.inputs.database_file = 'my_database.db'
    >>> sql.inputs.table_name = 'experiment_results'
    >>> sql.inputs.subject_id = 's1'
    >>> sql.inputs.some_measurement = 11.4
    >>> sql.run() # doctest: +SKIP

    sqlite3c                s8   t t| jf | t|| _t| jdd | jD  d S )Nc             S   s   g | ]}|qS r9   r9   )r   r5   r9   r9   r:   r   	  s    z'SQLiteSink.__init__.<locals>.<listcomp>)rZ   r  rl   r
   _input_namesrD   r   )rT   input_namesr   )r\   r9   r:   rl   	  s    
zSQLiteSink.__init__c                s   ddl }|j jjdd}|j }|jd jj dj j d djdgt	 j  d	  fd
d jD  |j
  |j  dS )zExecute this module.r   NF)Zcheck_same_threadzINSERT OR REPLACE INTO %s (r   z
) VALUES (?)c                s   g | ]}t  j|qS r9   )r?   r   )r   r5   )rT   r9   r:   r   #	  s    z,SQLiteSink._list_outputs.<locals>.<listcomp>)r  connectr   r  cursorexecuter  r   r  r   commitclose)rT   r  r  cr9   )rT   r:   rX   	  s    4zSQLiteSink._list_outputs)
r]   r^   r_   rt   r  r   r  rl   rX   r`   r9   r9   )r\   r:   r    s
   r  c               @   sV   e Zd ZeddddgdgddZeddgdd	Zedd
dZeddZe Z	e Z
dS )MySQLSinkInputSpec	localhostTusernamepasswordr   )r   rg  rh  rw   hostz*MySQL Options File (same format as my.cnf))r   rh  rv   z"Otherwise known as the schema name)r   rv   )r   N)r]   r^   r_   r   r  r   r   database_namer  r  r  r9   r9   r9   r:   r  *	  s   
r  c                   s,   e Zd ZdZeZ fddZdd Z  ZS )	MySQLSinka  
    Very simple frontend for storing values into MySQL database.

    Examples
    --------

    >>> sql = MySQLSink(input_names=['subject_id', 'some_measurement'])
    >>> sql.inputs.database_name = 'my_database'
    >>> sql.inputs.table_name = 'experiment_results'
    >>> sql.inputs.username = 'root'
    >>> sql.inputs.password = 'secret'
    >>> sql.inputs.subject_id = 's1'
    >>> sql.inputs.some_measurement = 11.4
    >>> sql.run() # doctest: +SKIP

    c                s8   t t| jf | t|| _t| jdd | jD  d S )Nc             S   s   g | ]}|qS r9   r9   )r   r5   r9   r9   r:   r   T	  s    z&MySQLSink.__init__.<locals>.<listcomp>)rZ   r  rl   r
   r  rD   r   )rT   r  r   )r\   r9   r:   rl   O	  s    
zMySQLSink.__init__c                s   ddl }t jjr,|j jj jjd}n"|j jj jj jj jjd}|j	 }|j
d jj dj j d djdgt j  d	  fd
d jD  |j  |j  dS )zExecute this module.r   N)dbZread_default_file)r  re  passwdr  zREPLACE INTO %s (r   z
) VALUES (z%sr  c                s   g | ]}t  j|qS r9   )r?   r   )r   r5   )rT   r9   r:   r   l	  s    z+MySQLSink._list_outputs.<locals>.<listcomp>)MySQLdbr   r   r   r  r  r  r  r  r  r  r  r   r  r   r  r  )rT   r  r  r  r9   )rT   r:   rX   V	  s     4zMySQLSink._list_outputs)	r]   r^   r_   rt   r  r   rl   rX   r`   r9   r9   )r\   r:   r  ;	  s   r  c               @   sl   e Zd ZedddZeddZejddZej	ddddZ
edd	dZejd
dgdddZeddddZdS )SSHDataGrabberInputSpecTzServer hostname.)r   rv   zServer username.)rv   zServer password.z?If false it will return the file names without downloading them)rw   rv   z6Path to the base directory consisting of subject data.fnmatchregexpz1Use either fnmatch or regexp to express templatesr   z4If set SSH commands will be logged to the given fileN)r]   r^   r_   r   hostnamer  r   rl  r  r}   download_filesr{   r   template_expressionssh_log_to_filer9   r9   r9   r:   r  s	  s   

r  c                   sJ   e Zd ZdZeZeZdZdZ	d fdd	Z
dd Zd	d
 Zdd Z  ZS )SSHDataGrabbera  
    Extension of DataGrabber module that downloads the file list and
    optionally the files from a SSH server. The SSH operation must
    not need user and password so an SSH agent must be active in
    where this module is being run.


    .. attention::

       Doesn't support directories currently

    Examples
    --------
    >>> from nipype.interfaces.io import SSHDataGrabber
    >>> dg = SSHDataGrabber()
    >>> dg.inputs.hostname = 'test.rebex.net'
    >>> dg.inputs.user = 'demo'
    >>> dg.inputs.password = 'password'
    >>> dg.inputs.base_directory = 'pub/example'

    Pick all files from the base directory

    >>> dg.inputs.template = '*'

    Pick all files starting with "s" and a number from current directory

    >>> dg.inputs.template_expression = 'regexp'
    >>> dg.inputs.template = 'pop[0-9].*'

    Same thing but with dynamically created fields

    >>> dg = SSHDataGrabber(infields=['arg1','arg2'])
    >>> dg.inputs.hostname = 'test.rebex.net'
    >>> dg.inputs.user = 'demo'
    >>> dg.inputs.password = 'password'
    >>> dg.inputs.base_directory = 'pub'
    >>> dg.inputs.template = '%s/%s.txt'
    >>> dg.inputs.arg1 = 'example'
    >>> dg.inputs.arg2 = 'foo'

    however this latter form can be used with iterables and iterfield in a
    pipeline.

    Dynamically created, user-defined input and output fields

    >>> dg = SSHDataGrabber(infields=['sid'], outfields=['func','struct','ref'])
    >>> dg.inputs.hostname = 'myhost.com'
    >>> dg.inputs.base_directory = '/main_folder/my_remote_dir'
    >>> dg.inputs.template_args['func'] = [['sid',['f3','f5']]]
    >>> dg.inputs.template_args['struct'] = [['sid',['struct']]]
    >>> dg.inputs.template_args['ref'] = [['sid','ref']]
    >>> dg.inputs.sid = 's1'

    Change the template only for output field struct. The rest use the
    general template

    >>> dg.inputs.field_template = dict(struct='%s/struct.nii')
    >>> dg.inputs.template_args['struct'] = [['sid']]

    FparamikoNc                s   |s
dg}|j  }||d< ||d< tt| jf | d| jj| jjfkrPtd| jjdkr|| jj	d	 dkr|| j j	d7  _	dS )
a  
        Parameters
        ----------
        infields : list of str
            Indicates the input fields to be dynamically created

        outfields: list of str
            Indicates output fields to be dynamically created

        See class examples for usage

        r   r   r   Nz>either both username and password are provided or none of themr  r   $r   )
r   rZ   r  rl   r   r  r  r   r  r   )rT   r   r   r   )r\   r9   r:   rl   	  s    zSSHDataGrabber.__init__c                sv  | j  }|j }|j| jj tjj|}tjj|}|j	| | jj
dkrZtj |}n0| jj
dkrtj|}tt|j }ntdt|dkrd| }| jjrt|nt| d}n| jjrt|}| jjrjtj|x6D ].}	t|	dd}
 fd	d
|
D }j| qW xND ]F}y|jtjj||| W n$ tk
rb   tjd|  Y nX q W t |}|S )z7Get the files matching template over an SSH connection.r  r  z!template_expression value invalidr   z%Output template: %s returned no filesNF)Zinclude_this_filec                s    g | ]}| kr|kr|qS r9   r9   )r   ra  )every_file_in_dirfiles_to_downloadr9   r:   r   
  s   z6SSHDataGrabber._get_files_over_ssh.<locals>.<listcomp>zremote file %s not found)!_get_ssh_clientZ	open_sftpchdirr   r{   r!   r&   r   r  r"   r  r  filterr   r=  r   r   r   r   r   r)   r   r   r   r  r   r   r.   r   r   r   r   r	   )rT   r   rI   sftpZtemplate_dirZtemplate_baser   r  r  Zfile_to_downloadZrelated_to_currentZ existing_related_not_downloadingra  r9   )r  r  r:   _get_files_over_ssh	  sF    







z"SSHDataGrabber._get_files_over_sshc             C   s  dd l }t| jjdkr(|jj| jj | jrjx:| jD ]0}t| j|}t|s6d| j	j
|f }t|q6W i }xVt| jjj D ]@\}}g ||< | jj}t| jdrt| jjr|| jjkr| jj| }|s| j|||< xt|D ]x\}}	d}
x~|	D ]v}t|ttfr,t| j|r,t| j|}t|t r|
dkr\t||
kr\td| t||
k rt|}
 qW g }xt|
D ]}g }x^|	D ]V}t|ttfrt| j|rt| j|}t|tr|j||  n
|j| qW |}|rJy|t| }W n@ tk
rH } z"t| d| dt| W Y d d }~X nX || j| j| qW qW tdd	 || D rg ||< t|| dkrd ||< qt|| dkr|| d ||< qW x0t|j D ] \}}tjjtj |||< qW |S )
Nr   zF%s requires a value for input '%s' because it was listed in 'infields'r   r   z'incompatible number of arguments for %sz: Template z failed to convert with args c             S   s   g | ]}|d kqS )Nr9   )r   r   r9   r9   r:   r   j
  s    z0SSHDataGrabber._list_outputs.<locals>.<listcomp>) r  r   r   r  utilZlog_to_filer   r?   r   r\   r]   r   r   r   r   r   r   r   r  r   r   r,   r   r   r+   r  r  r  r!   r&   r   getcwd)rT   r  rB   rx   r  r   r/   r   r
  r  r  r  r   r  r  r  r  r   r%  r9   r9   r:   rX   (
  sr    


,
zSSHDataGrabber._list_outputsc             C   s   dd l }|j }|jttjjd |j| jj	}d|krf|j
tjtjd dd|d  gj }nd }|j }|j  |j|j  |j|d |d |d	 |S )
Nr   z~/.ssh/configZproxycommandSHELLz-czecho %sr  re  )r  sock)r  Z	SSHConfigr   r   r!   r&   r   lookupr   r  ZProxyCommand
subprocesscheck_outputenvironr   Z	SSHClientZload_system_host_keysZset_missing_host_key_policyZAutoAddPolicyr  )rT   r  r   r  proxyrI   r9   r9   r:   r  z
  s    "zSSHDataGrabber._get_ssh_client)NN)r]   r^   r_   rt   r  r   r   r   r   r  rl   r  rX   r  r`   r9   r9   )r\   r:   r  	  s   <>Rr  c               @   s$   e Zd ZedddZejddZdS )JSONFileGrabberInputSpecTzJSON source file)r   rv   zUJSON dictionary that sets default outputvalues, overridden by values found in in_file)rv   N)r]   r^   r_   r   in_filer   r   defaultsr9   r9   r9   r:   r  
  s   r  c               @   s$   e Zd ZdZeZeZdZdd Z	dS )JSONFileGrabbera  
    Datagrabber interface that loads a json file and generates an output for
    every first-level object

    Example
    -------

    >>> import pprint
    >>> from nipype.interfaces.io import JSONFileGrabber
    >>> jsonSource = JSONFileGrabber()
    >>> jsonSource.inputs.defaults = {'param1': 'overrideMe', 'param3': 1.0}
    >>> res = jsonSource.run()
    >>> pprint.pprint(res.outputs.get())
    {'param1': 'overrideMe', 'param3': 1.0}
    >>> jsonSource.inputs.in_file = os.path.join(datadir, 'jsongrabber.txt')
    >>> res = jsonSource.run()
    >>> pprint.pprint(res.outputs.get())  # doctest:, +ELLIPSIS
    {'param1': 'exampleStr', 'param2': 4, 'param3': 1.0}
    Tc             C   s   dd l }i }t| jjrpt| jjd}|j|}W d Q R X t|tsNtdx t	|j
 D ]\}}|||< q\W t| jjr| jj}x0t	|j
 D ] \}}|t	|j kr|||< qW |S )Nr   r   z&JSON input has no dictionary structure)
simplejsonr   r   r  r   loadr   r)  rC  r   r   r  r   )rT   r  r   ra  r  rB   rx   r  r9   r9   r:   rX   
  s    
zJSONFileGrabber._list_outputsN)
r]   r^   r_   rt   r  r   r   r   r   rX   r9   r9   r9   r:   r  
  s
   r  c                   sD   e Zd ZeddZeji dddZeji ddZ fddZ	  Z
S )	JSONFileSinkInputSpeczJSON sink file)rv   Tzinput JSON dictionary)rx   rw   rv   )rx   rw   c                s\   || j  kr2t|s&tt| j|| || j|< n&|| jkrF|| j|< tt| j|| d S )N)ry   r   rZ   r  rz   r[   )rT   rB   rx   )r\   r9   r:   rz   
  s    

z!JSONFileSinkInputSpec.__setattr__)r]   r^   r_   r   r   r   r   in_dictr[   rz   r`   r9   r9   )r\   r:   r  
  s   
r  c               @   s   e Zd ZeddZdS )JSONFileSinkOutputSpeczJSON sink file)rv   N)r]   r^   r_   r   r   r9   r9   r9   r:   r  
  s   r  c                   s>   e Zd ZdZeZeZg df fdd	Zdd Z	dd Z
  ZS )	JSONFileSinkaF  
    Very simple frontend for storing values into a JSON file.
    Entries already existing in in_dict will be overridden by matching
    entries dynamically added as inputs.

    .. warning::

        This is not a thread-safe node because it can write to a common
        shared location. It will not complain when it overwrites a file.

    Examples
    --------
    >>> jsonsink = JSONFileSink(input_names=['subject_id',
    ...                         'some_measurement'])
    >>> jsonsink.inputs.subject_id = 's1'
    >>> jsonsink.inputs.some_measurement = 11.4
    >>> jsonsink.run() # doctest: +SKIP

    Using a dictionary as input:

    >>> dictsink = JSONFileSink()
    >>> dictsink.inputs.in_dict = {'subject_id': 's1',
    ...                            'some_measurement': 11.4}
    >>> dictsink.run() # doctest: +SKIP

    Tc                sr   t t| jf | || _i }x0|D ](}| jj|tj t| jj	|< t||< q"W | jj
f ddi| |rnd| _d S )Nr;   FT)rZ   r  rl   r  r   r=   r   r<   r   r[   r>   r   )rT   r   r   r   rA   rB   )r\   r9   r:   rl   
  s    
zJSONFileSink.__init__c             C   sN   d|krF|j d}|jd}|j |i}xt|D ]}||i}q2W |}||fS )Nr   r   )r   popreversed)rT   r5   r   ZnewkeysZnested_dictZnkr9   r9   r:   _process_name
  s    

zJSONFileSink._process_namec       	      C   s   dd l }dd lj}t| jjs*|jd}n|j| jj}| jj}xHt| jj	j
 D ]4\}}t| sR|dkrnqR| j||\}}|||< qRW t|d}|jt|j|dd W d Q R X | j j }||d< |S )Nr   zdatasink.jsonZtrait_addedwF)ensure_asciir   )r  os.pathr&   r   r   r   r   r  r   r[   r   r  r   rp   r,   dumpsr   r   )	rT   r  r,  r   Zout_dictrB   r   ra  r   r9   r9   r:   rX     s     
"zJSONFileSink._list_outputs)r]   r^   r_   rt   r  r   r  r   rl   r  rX   r`   r9   r9   )r\   r:   r  
  s   r  c               @   sp   e Zd ZeddddZejeejddZeddddZ	ej
dddd	Zej
dddd
dZejeddddZdS )BIDSDataGrabberInputSpecTzPath to BIDS Directory.)r   rv   r   zQueries for outfield outputs)r   r   rv   z&Path to load already saved Bidslayout.Fz5Generate exception if list is empty for a given field)rw   rv   z Index derivatives/ sub-directory)r   rw   rv   )r   z*Additional derivative directories to index)rv   N)r]   r^   r_   r   base_dirr   r   r   output_queryload_layoutr}   r   index_derivativesr   extra_derivativesr9   r9   r9   r:   r  0  s   r  c                   sB   e Zd ZdZeZeZdZdZ	d fdd	Z
dd Zd	d
 Z  ZS )BIDSDataGrabbera  BIDS datagrabber module that wraps around pybids to allow arbitrary
    querying of BIDS datasets.

    Examples
    --------

    .. setup::

        >>> try:
        ...     import bids
        ... except ImportError:
        ...     pytest.skip()

    By default, the BIDSDataGrabber fetches anatomical and functional images
    from a project, and makes BIDS entities (e.g. subject) available for
    filtering outputs.

    >>> bg = BIDSDataGrabber()
    >>> bg.inputs.base_dir = 'ds005/'
    >>> bg.inputs.subject = '01'
    >>> results = bg.run() # doctest: +SKIP


    Dynamically created, user-defined output fields can also be defined to
    return different types of outputs from the same project. All outputs
    are filtered on common entities, which can be explicitly defined as
    infields.

    >>> bg = BIDSDataGrabber(infields = ['subject'])
    >>> bg.inputs.base_dir = 'ds005/'
    >>> bg.inputs.subject = '01'
    >>> bg.inputs.output_query['dwi'] = dict(datatype='dwi')
    >>> results = bg.run() # doctest: +SKIP

    TbidsNc                s   t t| jf | t| jjsDddddgdddddgdd| j_|d	krd
dlm} tt	|j
dd}tjt|d}dd |d D }|pg | _i }x6| jD ],}| jj|tj ||kr|| nt||< qW | jjf ddi| d	S )z
        Parameters
        ----------
        infields : list of str
            Indicates the input fields to be dynamically created
        funcboldZniiz.nii.gz)datatypesuffix	extensionZanatT1w)r  r  Nr   )layoutr   z	bids.jsonr   c             S   s   g | ]}|d  qS )r5   r9   )r   r  r9   r9   r:   r     s    z,BIDSDataGrabber.__init__.<locals>.<listcomp>entitiesr;   F)rZ   r  rl   r   r   r  r  r  r   r   __file__jsonr  r   r   r=   r   r<   r   r>   )rT   r   r   Z
bidslayoutZbids_configrA   rB   )r\   r9   r:   rl   o  s&    

zBIDSDataGrabber.__init__c             C   s
  ddl m} t| jjr(|j| jj}n|| jj| jjd}t| jjrV|j	| jj i }x*| j
D ] }t| j|}t|rb|||< qbW i }xz| jjj D ]j\}}|j }|j| |jf ddi|}	t|	dkrd| }
| jjrt|
ntj|
 t}	|	||< qW |S )Nr   )
BIDSLayout)Zderivativesreturn_typefilez Output key: %s returned no files)r  r  r   r   r  r  r  r  r  Zadd_derivativesr   r?   r  r   r   rH  r   r   r   r)   r   warningr   )rT   r  r  filtersrB   rx   r   queryr/   r	  r  r9   r9   r:   rX     s2    


zBIDSDataGrabber._list_outputsc             C   s   t |t| jjj S )N)rD   r   r   r  r   )rT   r@   r9   r9   r:   rY     s    z"BIDSDataGrabber._add_output_traits)N)r]   r^   r_   rt   r  r   r   r   r   r  rl   rX   rY   r`   r9   r9   )r\   r:   r  E  s   #)%r  c               @   sB   e Zd ZeddddZedddZejddddZejdd	Z	d
S )ExportFileInputSpecTzInput file name)r   r   rv   zOutput file name)r   rv   z6Ensure that the input and output file extensions match)rw   rv   z!Permit overwriting existing files)rv   N)
r]   r^   r_   r   r  r   r   r}   check_extensionclobberr9   r9   r9   r:   r    s   r  c               @   s   e Zd ZedddZdS )ExportFileOutputSpecTzOutput file name)r   rv   N)r]   r^   r_   r   r   r9   r9   r9   r:   r    s   r  c               @   s    e Zd ZdZeZeZdd ZdS )
ExportFileaJ  Export a file to an absolute path.

    This interface copies an input file to a named output file.
    This is useful to save individual files to a specific location,
    instead of more flexible interfaces like DataSink.

    Examples
    --------
    >>> from nipype.interfaces.io import ExportFile
    >>> import os.path as op
    >>> ef = ExportFile()
    >>> ef.inputs.in_file = "T1.nii.gz"
    >>> os.mkdir("output_folder")
    >>> ef.inputs.out_file = op.abspath("output_folder/sub1_out.nii.gz")
    >>> res = ef.run()
    >>> os.path.exists(res.outputs.out_file)
    True

    c             C   s   | j j r$tj| j jr$t| j jtj| j js:td| j jrzt	| j j
d t	| j jd krztd| j j
| j jf tjt| j j
t| j j | j j| jd< |S )Nz"Out_file must be an absolute path.r   z#%s and %s have different extensionsr   )r   r  r,  r   r   FileExistsErrorisabsr   r  r   r  rC  r   r   r,   r  )rT   rU   r9   r9   r:   rV     s    zExportFile._run_interfaceN)	r]   r^   r_   rt   r  r   r  r   rV   r9   r9   r9   r:   r    s   r  )F)N)\rt   r  r  r  r  r!   r  r&   r,  r   r  r   r   rr  r   r   warningsr   r   r   r   Zutils.filemanipr   r	   r
   r   r   Z
utils.miscr   r   r@   r   r   r   r   r   r   r   r   r   r   r   r   r   r   	getLoggerr   r(   rD   rR   rS   objectra   ru   r   r   r   r   r  r  r  r  r/  r6  rI  rN  r_  rd  rn  ry  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r9   r9   r9   r:   <module>   s   
@

)
"+=    % q S ~
 ? =2SK28  
0S|