3
d                 @   sH  d Z ddlZddljZddlmZ ddlmZ ddl	Z
ddlZddlmZ ddlmZmZ ddlmZ dd	lmZmZmZmZmZmZmZmZmZ dd
lmZ ej dZ!dQddZ"G dd deZ#G dd deZ$G dd deZ%G dd deZ&G dd deZ'G dd deZ(G dd deZ)G dd deZ*G dd  d eZ+G d!d" d"e+Z,G d#d$ d$e)Z-G d%d& d&e*Z.G d'd( d(e+Z/G d)d* d*eZ0G d+d, d,eZ1G d-d. d.eZ2G d/d0 d0eZ3G d1d2 d2eZ4G d3d4 d4eZ5dRd7d8Z6dSd9d:Z7dTd<d=Z8dVd@dAZ9dXdBdCZ:dYdDdEZ;dZdHdIZ<d[dJdKZ=dLdM Z>d\dOdPZ?dS )]zB
Algorithms to compute confounds in :abbr:`fMRI (functional MRI)`
    N)OrderedDict)chain)Legendre   )configlogging)BibTeX)	traitsTraitedSpecBaseInterfaceBaseInterfaceInputSpecFile	isdefinedInputMultiPathOutputMultiPathSimpleInterface)normalize_mc_paramsznipype.interfaceTc             C   sH   yt jj| ||dS  t jjk
r*   Y nX ddlm} || ||ddS )N)full_matrices
compute_uvr   )svdZgesvd)r   r   Zlapack_driver)nplinalgr   LinAlgErrorZscipy.linalg)ar   r   r    r   =/tmp/pip-build-7vycvbft/nipype/nipype/algorithms/confounds.pyfallback_svd"   s    r   c               @   s   e Zd ZeddddZeddddZejddddZejddddZ	ejddd	dZ
ejddd
dZejddddZejddZejddddZejddddZejejdejddddZejddddddZejddddZdS )ComputeDVARSInputSpecTzfunctional data, after HMC)exists	mandatorydescza brain maskz remove voxels with zero variance)
usedefaultr    zsave standardized DVARSFzsave non-standardized DVARSz"save voxel-wise standardized DVARSzoutput all DVARSzrepetition time in sec.)r    zwrite DVARS plotd   zoutput dpi for the plotgffffff'@gffffff@zoutput figure sizeZpngZpdfsvgzoutput format for figuresg     @@aj  Divide value in each voxel at each timepoint by the median calculated across all voxelsand timepoints within the mask (if specified)and then multiply by the value specified bythis parameter. By using the default (1000)output DVARS will be expressed in x10 % BOLD units compatible with Power et al.2012. Set this to 0 to disable intensitynormalization altogether.N)__name__
__module____qualname__r   in_filein_maskr	   Boolremove_zerovariancesave_std	save_nstd
save_vxstdsave_allFloat	series_tr	save_plotIntfigdpiTuplefigsizeEnum	figformatintensity_normalizationr   r   r   r   r   /   s.   r   c               @   sx   e Zd ZedddZedddZedddZedddZej	 Z
ej	 Zej	 ZedddZedddZedddZdS )ComputeDVARSOutputSpecTzoutput text file)r   r    zoutput DVARS plotN)r$   r%   r&   r   out_stdout_nstd	out_vxstdout_allr	   r/   avg_stdavg_nstd	avg_vxstdfig_stdfig_nstd	fig_vxstdr   r   r   r   r9   W   s   r9   c                   sb   e Zd ZdZeZeZeddgdeddgdgZ	 fddZ
dd	d
Zdd Zdd Z  ZS )ComputeDVARSz
    Computes the DVARS.
    a}  @techreport{nichols_notes_2013,
    address = {Coventry, UK},
    title = {Notes on {Creating} a {Standardized} {Version} of {DVARS}},
    url = {http://www2.warwick.ac.uk/fac/sci/statistics/staff/academic-research/nichols/scripts/fsl/standardizeddvars.pdf},
    urldate = {2016-08-16},
    institution = {University of Warwick},
    author = {Nichols, Thomas},
    year = {2013}
}method)entrytagsa  @article{power_spurious_2012,
    title = {Spurious but systematic correlations in functional connectivity {MRI} networks arise from subject motion},
    volume = {59},
    doi = {10.1016/j.neuroimage.2011.10.018},
    number = {3},
    urldate = {2016-08-16},
    journal = {NeuroImage},
    author = {Power, Jonathan D. and Barnes, Kelly A. and Snyder, Abraham Z. and Schlaggar, Bradley L. and Petersen, Steven E.},
    year = {2012},
    pages = {2142--2154},
}
c                s   i | _ tt| jf | d S )N)_resultssuperrD   __init__)selfinputs)	__class__r   r   rJ      s    zComputeDVARS.__init__Nc             C   sl   t jt j| jj\}}|dkr6t j|\}}|| }|d krB|}|jdrX|dd  }t jdj|||S )Nz.gz.   z{}_{}.{})opsplitextbasenamerL   r'   
startswithabspathformat)rK   suffixextfnameZin_extZin_ext2r   r   r   
_gen_fname   s    
zComputeDVARS._gen_fnamec             C   sx  t | jj| jj| jj| jjd}tj|ddjt	\| j
d< | j
d< | j
d< d }t| jjrd| jj}| jjr| jddd	}tj||d
 dd || j
d< | jjr| jd| jjd	| j
d< t|d
 | jjd|d}|j| j
d t	| jj| jjdd |j  | jjr| jddd	}tj||d dd || j
d< | jjr| jd| jjd	| j
d< t|d | jjd|d}|j| j
d t	| jj| jjdd |j  | jjr4| jddd	}tj||d dd || j
d< | jjr4| jd| jjd	| j
d< t|d | jjd|d}|j| j
d t	| jj| jjdd |j  | jjrt| jddd	}tj|tj|jdddd d! || j
d"< |S )#N)r*   r8   rO   )axisr>   r?   r@   Z	dvars_stdZtsv)rW   r   s   %0.6f)fmtr:   rA   zStandardized DVARS)r0   tight)dpirU   bbox_inches
dvars_nstdr;   rB   ZDVARSZdvars_vxstdr   r<   rC   zVoxelwise std DVARSdvarss   %0.8f   	z)std DVARS	non-std DVARS	vx-wise std DVARS )r[   	delimiterheadercommentsr=   )compute_dvarsrL   r'   r(   r*   r8   r   meanastypefloatrH   r   r0   r+   rY   savetxtr1   r7   plot_confoundr5   savefigr3   clfr,   r-   r.   ZvstackT)rK   runtimer`   trout_filefigr   r   r   _run_interface   s    ,












zComputeDVARS._run_interfacec             C   s   | j S )N)rH   )rK   r   r   r   _list_outputs  s    zComputeDVARS._list_outputs)N)r$   r%   r&   __doc__r   
input_specr9   output_specr   _referencesrJ   rY   rs   rt   __classcell__r   r   )rM   r   rD   d   s   
\rD   c            	   @   s   e Zd ZeddddZejdddddd	dd
ZejddddZ	eddddZ
eddddZejddZejddddZejddddZejddddZejejdejddddZdS )FramewiseDisplacementInputSpecTzmotion parameters)r   r   r    ZFSLZAFNIZSPMZFSFASTZNIPYzSource of movement parameters)r    r   2   z`radius in mm to calculate angular FDs, 50mm is the default since it is used in Power et al. 2012)r!   r    zfd_power_2012.txtzoutput file namezfd_power_2012.pdfzoutput figure namezrepetition time in sec.)r    Fzwrite FD plotzcalculate FD in mm/sr"   zoutput dpi for the FD plotgffffff'@gffffff@zoutput figure sizeN)r$   r%   r&   r   r'   r	   r6   parameter_sourcer/   radiusrq   
out_figurer0   r)   r1   	normalizer2   r3   r4   r5   r   r   r   r   rz     s0   rz   c               @   s,   e Zd ZeddZeddZejddZdS )FramewiseDisplacementOutputSpeczcalculated FD per timestep)r    zoutput image filez
average FDN)	r$   r%   r&   r   rq   r~   r	   r/   
fd_averager   r   r   r   r   $  s   

r   c               @   s:   e Zd ZdZeZeZeddgdgZ	dd Z
dd Zd	S )
FramewiseDisplacementa  
    Calculate the :abbr:`FD (framewise displacement)` as in [Power2012]_.
    This implementation reproduces the calculation in fsl_motion_outliers

    .. [Power2012] Power et al., Spurious but systematic correlations in functional
         connectivity MRI networks arise from subject motion, NeuroImage 59(3),
         2012. doi:`10.1016/j.neuroimage.2011.10.018
         <https://doi.org/10.1016/j.neuroimage.2011.10.018>`_.


    a  @article{power_spurious_2012,
    title = {Spurious but systematic correlations in functional connectivity {MRI} networks arise from subject motion},
    volume = {59},
    doi = {10.1016/j.neuroimage.2011.10.018},
    number = {3},
    urldate = {2016-08-16},
    journal = {NeuroImage},
    author = {Power, Jonathan D. and Barnes, Kelly A. and Snyder, Abraham Z. and Schlaggar, Bradley L. and Petersen, Steven E.},
    year = {2012},
    pages = {2142--2154},
}
rE   )rF   rG   c             C   sV  t j| jj}t jtd|| jjd}|d dd df |dd d df  }|d d ddf  | jj9  < t j|j	dd}t
j| jjt|j d| _t j| jj|ddd	 | jjrRd }t| jjr| jj}| jjr|d krtjd
 t
j| jj| jd< t|| jjdd|| jjd}|j| jd t| jj| jjdd  dd |j  |S )NrO   )Zfunc1drZ   Zarrsource      )rZ   )rq   r   r   rb   )rd   re   z-FD plot cannot be normalized if TR is not setr~   ZFDmm)unitsr0   r   r\   )r]   rU   r^   )r   ZloadtxtrL   r'   apply_along_axisr   r|   r}   abssumrP   rT   rq   ri   rg   rH   rj   r1   r   r0   r   IFLOGGERwarningr~   rk   r5   rl   r3   rm   )rK   ro   ZmparsdiffZfd_resrp   rr   r   r   r   rs   Q  sD    ( 


z$FramewiseDisplacement._run_interfacec             C   s   | j S )N)rH   )rK   r   r   r   rt     s    z#FramewiseDisplacement._list_outputsN)r$   r%   r&   ru   rz   rv   r   rw   r   rx   rs   rt   r   r   r   r   r   *  s   /r   c               @   s\  e Zd ZeddddZeeddddZejddd	d
gdgddZ	ej
ddgdgddZejejddZejddddZejdej
dddgddZej
dddddgdd Zejd!d"d#dd$dZejd%d&d'd(Zej
dddd)d*Zejd+dZejd,dd-dZejd.dZejejed#dd/d0Zejejed#dd1d0Zej
ddd2d3Zejd4d5dd6dZd7S )8CompCorInputSpecTz"already realigned brain image (4D))r   r   r    )r   zOne or more mask files that determines ROI (3D). When more that one file is provided ``merge_method`` or ``merge_index`` must be provided)r    union	intersectnone
mask_index
mask_fileszMerge method if multiple masks are present - ``union`` uses voxels included in at least one input mask, ``intersect`` uses only voxels present in all input masks, ``none`` performs CompCor on each mask individually)xorrequiresr    r   merge_methodzAPosition of mask in ``mask_files`` to use - first is the default.)lowr   r   r    zNames for provided masks (for printing into metadata). If provided, it must be as long as the final mask list (after any merge and indexing operations).zcomponents_file.txtz*Filename to store physiological components)r!   r    allrO   )r   variance_thresholdz~Number of components to return from the decomposition. If ``num_components`` is ``all``, then all components will be retained.)r   r    g        g      ?num_componentsa[  Select the number of components to be returned automatically based on their ability to explain variance in the dataset. ``variance_threshold`` is a fractional value between 0 and 1; the number of components retained will be equal to the minimum number of components necessary to explain the provided fraction of variance in the masked time series.)r   highexclude_lowexclude_highr   r    
polynomialcosineFz1Detrend time series prior to component extractionz0.15.0
pre_filterz2use polynomial regression pre-component extraction)Z
deprecatednew_namer    zthe degree polynomial to use)r   valuer!   r    z`the desired header for the output tsv file (one column). If undefined, will default to "CompCor"   z+Cutoff (in seconds) for "cosine" pre-filterzIRepetition time (TR) of series - derived from image header if unspecifiedz"Save pre-filter basis as text file)defaultr!   r    z$Save component metadata as text filez.Number of volumes at start of series to ignore)r   r!   r    errorNaNzeWhen no components are found or convergence fails, raise an error or silently return columns of NaNs.N)r$   r%   r&   r   realigned_filer   r   r	   r6   r   Ranger   ListStr
mask_namescomponents_fileZEitherr   r   r   r)   use_regress_polyregress_poly_degreeheader_prefixr/   high_pass_cutoffrepetition_timesave_pre_filtersave_metadataignore_initial_volumesfailure_moder   r   r   r   r     s   
r   c               @   s,   e Zd ZedddZeddZeddZdS )CompCorOutputSpecTz)text file containing the noise components)r   r    z+text file containing high-pass filter basis)r    z'text file containing component metadataN)r$   r%   r&   r   r   pre_filter_filemetadata_filer   r   r   r   r     s   

r   c                   sV   e Zd ZdZeZeZddgeddgZ	 fddZ
dd	 ZdddZdd Z  ZS )CompCoraf  
    Interface with core CompCor computation, used in aCompCor and tCompCor.

    CompCor provides three pre-filter options, all of which include per-voxel
    mean removal:

      - ``'polynomial'``: Legendre polynomial basis
      - ``'cosine'``: Discrete cosine basis
      - ``False``: mean-removal only

    In the case of ``polynomial`` and ``cosine`` filters, a pre-filter file may
    be saved with a row for each volume/timepoint, and a column for each
    non-constant regressor.
    If no non-constant (mean-removal) columns are used, this file may be empty.

    If ``ignore_initial_volumes`` is set, then the specified number of initial
    volumes are excluded both from pre-filtering and CompCor component
    extraction.
    Each column in the components and pre-filter files are prefixe with zeros
    for each excluded volume so that the number of rows continues to match the
    number of volumes in the input file.
    In addition, for each excluded volume, a column is added to the pre-filter
    file with a 1 in the corresponding row.

    Example
    -------
    >>> ccinterface = CompCor()
    >>> ccinterface.inputs.realigned_file = 'functional.nii'
    >>> ccinterface.inputs.mask_files = 'mask.nii'
    >>> ccinterface.inputs.num_components = 1
    >>> ccinterface.inputs.pre_filter = 'polynomial'
    >>> ccinterface.inputs.regress_poly_degree = 2

    rE   implementationa  @article{compcor_2007,
    title = {A component based noise correction method (CompCor) for BOLD and perfusion based},
    volume = {37},
    number = {1},
    doi = {10.1016/j.neuroimage.2007.04.042},
    urldate = {2016-08-13},
    journal = {NeuroImage},
    author = {Behzadi, Yashar and Restom, Khaled and Liau, Joy and Liu, Thomas T.},
    year = {2007},
    pages = {90-101}
})rG   rF   c                s   t t| j|| d| _dS )z-exactly the same as compcor except the headerr   N)rI   r   rJ   _header)rK   argskwargs)rM   r   r   rJ   C  s    zCompCor.__init__c                s  g }t | jjr(t| jj| jj| jj}| jjr8d| j_| jjdkrL| jjnd}t	j
| jj}t|jdkrtdj| j| jjt|j|jt|dkrt	jtj|jd d td|j|jd}|g}| jj}|r|j|jd|d f |j|j}| j||j}d}| jjd	krt | jjr,| jj}nhy.|jj d }|jj d
 dkrX|d }W n ttfk
rx   d}Y nX |dkrtdj| jt | jj r| jj }n&t | jj!r| jj!}nd}t"j#d t$|j%tj&d||| jj|| jj'|| jj(| jj)	\}	}
}|rH|	}||	jd  }tj*||	jd
 f|	j+d}	||	|d < t,j-j.t,j/ | jj0}| j1|	jd
 }tj2||	dddj.|dd t,j-j.|j3| jj0| j4d< d}| jjd)kr| jj5}|r|| j4d< |dkrt,j-j.|j3d| j4d< ddd| jj  |
j6dkr|
jd
 nd} fddt7|D }|r|
}tj*||| f|
j+d}
|j6dkrr||
|d d |f< tj8||
d || d f< |j9dd t7|D  tj2| j4d |
dddj.|dd | jj:}|r|| j4d< |dkr t,j-j.|j3d | j4d< tj;t|d! d"d}tj<|d# }tj<tj=|d# }|||< d$d t7t|d D ||< t>| j4d d%V}|j?dj.d&gt@|jA  d'  x,tB|f|jC  D ]}|j?d(j| qW W d Q R X |S )*Nr   r      zC{} expected a 4-D nifti file. Input {} has {} dimensions (shape {})r   )dtype)affinerd   .r   rO   Zmseci  zK{} cannot detect repetition time from image - Set the repetition_time inputr   z`num_components` and `variance_threshold` are not defined. Setting number of components to 6 for backward compatibility. Please set either `num_components` or `variance_threshold`, as this feature may be deprecated in the future.s   %.10f	rb   )r[   rc   rd   re   r   Fr   Tzpre_filter.tsvr   ZCosine)r   r   c                s   g | ]}d j  |qS )z{}{:02d})rU   ).0i)ftyper   r   
<listcomp>  s    z*CompCor._run_interface.<locals>.<listcomp>c             S   s   g | ]}d j |qS )zNonSteadyStateOutlier{:02d})rU   )r   r   r   r   r   r     s    r   zcomponent_metadata.tsvmaskZobject_retainedc             S   s   g | ]}d j |qS )z	dropped{})rU   )r   r   r   r   r   r     s    w	component
z9{0[0]}	{0[1]}	{0[2]:.10f}	{0[3]:.10f}	{0[4]:.10f}	{0[5]}
)r   r   )Dr   rL   r   combine_mask_filesr   r   r   r   r   nbloadr   lenshape
ValueErrorrU   r   Nifti1Imager   onesboolr   rd   r   rM   dataobj_process_masksr   Z	get_zoomsZget_xyzt_unitsAttributeError
IndexErrorr   r   r   r   compute_noise_components	get_fdatafloat32r   r   r   zerosr   ospathjoingetcwdr   _make_headersrj   cwdrH   r   sizerangeZeyeextendr   emptywhereZlogical_notopenwritelistkeyszipvalues)rK   ro   mask_imagesdegree	imgseriesimgZ	skip_volsZTRcomponents_criterion
componentsZfilter_basismetadataZold_compZnrowsr   Zcomponents_headerr   Zncolsrd   Z	old_basisr   Zcomponents_namesr   Znot_retainedfr   r   )r   r   rs   H  s    












"zCompCor._run_interfaceNc             C   s   |S )Nr   )rK   r   
timeseriesr   r   r   r     s    zCompCor._process_masksc                s4   t | jjr| jjn| j  fddt|D }|S )Nc                s   g | ]}d j  |qS )z{}{:02d})rU   )r   r   )rd   r   r   r     s    z)CompCor._make_headers.<locals>.<listcomp>)r   rL   r   r   r   )rK   Znum_colheadersr   )rd   r   r     s    zCompCor._make_headers)N)r$   r%   r&   ru   r   rv   r   rw   r   rx   rJ   rs   r   r   ry   r   r   )rM   r   r   	  s   " -
r   c                   s    e Zd ZdZ fddZ  ZS )ACompCorz
    Anatomical compcor: for inputs and outputs, see CompCor.
    When the mask provided is an anatomical mask, then CompCor
    is equivalent to ACompCor.
    c                s   t t| j|| d| _dS )z-exactly the same as compcor except the headerZaCompCorN)rI   r   rJ   r   )rK   r   r   )rM   r   r   rJ     s    zACompCor.__init__)r$   r%   r&   ru   rJ   ry   r   r   )rM   r   r     s   r   c            	   @   s$   e Zd ZejddddddddZdS )TCompCorInputSpecg        g      ?g{Gz?Tzthe percentile used to select highest-variance voxels, represented by a number between 0 and 1, exclusive. By default, this value is set to .02. That is, the 2% of voxels with the highest variance are used.)r   r   r   r   r   r!   r    N)r$   r%   r&   r	   r   percentile_thresholdr   r   r   r   r     s   r   c               @   s   e Zd ZeeddddZdS )TCompCorOutputSpecT)r   z'voxels exceeding the variance threshold)r    N)r$   r%   r&   r   r   high_variance_masksr   r   r   r   r   !  s   r   c                   s>   e Zd ZdZeZeZ fddZd	ddZ	 fddZ
  ZS )
TCompCora  
    Interface for tCompCor. Computes a ROI mask based on variance of voxels.

    Example
    -------
    >>> ccinterface = TCompCor()
    >>> ccinterface.inputs.realigned_file = 'functional.nii'
    >>> ccinterface.inputs.mask_files = 'mask.nii'
    >>> ccinterface.inputs.num_components = 1
    >>> ccinterface.inputs.pre_filter = 'polynomial'
    >>> ccinterface.inputs.regress_poly_degree = 2
    >>> ccinterface.inputs.percentile_threshold = .03

    c                s"   t t| j|| d| _g | _dS )z-exactly the same as compcor except the headerZtCompCorN)rI   r   rJ   r   _mask_files)rK   r   r   )rM   r   r   rJ   ;  s    zTCompCor.__init__Nc             C   s  g }g | _ tj|}xt|D ]\}}tj|jjt}||d d f }td|d }t|dd
d}tj	|tj
dd| jj  jt}	tj|}
||	k|
|dk< tj|
|j|jd}tjjdj|}|j| tjd	t|j| | j j| |j| qW |S )Nr   r   rO   )rZ   g      Y@g      ?)r   rd   zmask_{:03d}.nii.gzz<tCompcor computed and saved mask of shape %s to mask_file %sr   )r   r   
asanyarray	enumerater   rh   r   regress_poly_compute_tSTD
percentileroundrL   r   int
zeros_liker   r   r   rd   r   r   rT   rU   to_filenamer   debugstrr   append)rK   r   r   Z
out_imagesr   r   r   r   ZtSTDZthreshold_stdZ	mask_dataZ	out_imageZ	mask_filer   r   r   r   A  s.    


zTCompCor._process_masksc                s   t t| j }| j|d< |S )Nr   )rI   r   rt   r   )rK   outputs)rM   r   r   rt   ^  s    
zTCompCor._list_outputs)N)r$   r%   r&   ru   r   rv   r   rw   rJ   r   rt   ry   r   r   )rM   r   r   (  s   
r   c               @   sn   e Zd ZeedddddZejdddZeddd	d
dZ	eddd	ddZ
eddd	d
dZeddd	ddZdS )TSNRInputSpecT)r   z'realigned 4D file or a list of 3D files)r   r    rO   zRemove polynomials)r   r    ztsnr.nii.gzFzoutput tSNR file)r!   Z
hash_filesr    zmean.nii.gzzoutput mean filezstdev.nii.gzzdetrend.nii.gzzinput file after detrendingN)r$   r%   r&   r   r   r'   r	   r   r  	tsnr_file	mean_filestddev_filedetrended_filer   r   r   r   r  d  s    r  c               @   s:   e Zd ZedddZedddZedddZeddZdS )	TSNROutputSpecTztsnr image file)r   r    zmean image filezstd dev image filezdetrended input file)r    N)r$   r%   r&   r   r  r  r  r  r   r   r   r   r  |  s   r  c               @   s(   e Zd ZdZeZeZdd Zdd Z	dS )TSNRa  
    Computes the time-course SNR for a time series

    Typically you want to run this on a realigned time-series.

    Example
    -------
    >>> tsnr = TSNR()
    >>> tsnr.inputs.in_file = 'functional.nii'
    >>> res = tsnr.run() # doctest: +SKIP

    c       
      C   st  t j| jjd }|jj }dd | jjD }tjdd |D dd}tj|}|j	j
dkrt|jtj |jtj}t| jjrt| jj|dd	d }t j||j|}t j|tj| jj tj|dd}tj|dd}tj|}|d
k}	||	 ||	  ||	< t j||j|}t j|tj| jj t j||j|}t j|tj| jj t j||j|}t j|tj| jj |S )Nr   c             S   s   g | ]}t j|qS r   )r   r   )r   filenamer   r   r   r     s    z'TSNR._run_interface.<locals>.<listcomp>c             S   s.   g | ]&}|j tjd j|jdd d qS ))r   Nr   rO   r   )r   )r   r   r   reshaper   )r   Zvolr   r   r   r     s   r   )rZ   r   F)remove_meangMbP?)r   r   rL   r'   rd   copyr   ZconcatenateZ
nan_to_numr   kindZset_data_dtyper   rh   r   r  r   r   saverP   rT   r  rg   stdr  r  r  r  )
rK   ro   r   rd   ZvollistdataZmeanimgZ	stddevimgZtsnrZstddevimg_nonzeror   r   r   rs     s6    


zTSNR._run_interfacec             C   sR   | j  j }x"dD ]}tjt| j|||< qW t| jjrNtj| jj|d< |S )Nr  r  r  r  )r  r  r  )	Z_outputsgetrP   rT   getattrrL   r   r  r  )rK   r  kr   r   r   rt     s    
zTSNR._list_outputsN)
r$   r%   r&   ru   r  rv   r  rw   rs   rt   r   r   r   r   r    s
   %r  c               @   s   e Zd ZeddddZdS )NonSteadyStateDetectorInputSpecTz4D NIFTI EPI file)r   r   r    N)r$   r%   r&   r   r'   r   r   r   r   r    s   r  c               @   s   e Zd ZejddZdS ) NonSteadyStateDetectorOutputSpeczHNumber of non-steady state volumesdetected in the beginning of the scan.)r    N)r$   r%   r&   r	   r2   n_volumes_to_discardr   r   r   r   r     s   r   c               @   s(   e Zd ZdZeZeZdd Zdd Z	dS )NonSteadyStateDetectorzc
    Returns the number of non-steady state volumes detected at the beginning
    of the scan.
    c             C   sZ   t j| jj}|jd d d d d d d df jddjddjdd}dt|i| _|S )Nr{   r   )rZ   r!  )r   r   rL   r'   r   rg   
is_outlierrH   )rK   ro   Zin_niiZglobal_signalr   r   r   rs     s    :z%NonSteadyStateDetector._run_interfacec             C   s   | j S )N)rH   )rK   r   r   r   rt     s    z$NonSteadyStateDetector._list_outputsN)
r$   r%   r&   ru   r  rv   r   rw   rs   rt   r   r   r   r   r"    s
   
r"  F  c             C   s  ddl }ddl}ddlm} ddl}|j| j|jd}|j|j|j	j
|j}	t|jdkrhtd|j|	dk}
||
d |
d |
d ddf }|dkr||j| | }|j|d	dd
d|j|ddd
d d }|r||dkddf }||dk }|j|dtd|ddd j
|jddddf }|j|jd| d j | }|j }|j|dd}|j|j|jdd}|| }|j D |jd |j||j|g|jd  j }|j|jdd}W dQ R X |||fS )a  
    Compute the :abbr:`DVARS (D referring to temporal
    derivative of timecourses, VARS referring to RMS variance over voxels)`
    [Power2012]_.

    Particularly, the *standardized* :abbr:`DVARS (D referring to temporal
    derivative of timecourses, VARS referring to RMS variance over voxels)`
    [Nichols2013]_ are computed.

    .. [Nichols2013] Nichols T, `Notes on creating a standardized version of
         DVARS <http://www2.warwick.ac.uk/fac/sci/statistics/staff/academic-research/nichols/scripts/fsl/standardizeddvars.pdf>`_, 2013.

    .. note:: Implementation details

      Uses the implementation of the `Yule-Walker equations
      from nitime
      <http://nipy.org/nitime/api/generated/nitime.algorithms.autoregressive.html#nitime.algorithms.autoregressive.AR_est_YW>`_
      for the :abbr:`AR (auto-regressive)` filtering of the fMRI signal.

    :param numpy.ndarray func: functional data, after head-motion-correction.
    :param numpy.ndarray mask: a 3D mask of the brain
    :param bool output_all: write out all dvars
    :param str out_file: a path to which the standardized dvars should be saved.
    :return: the standardized DVARS

    r   N)	AR_est_YW)r   r   z*Input fMRI dataset should be 4-dimensionalrO   r   K   lower)rZ   interpolation   g/$?T)r  )rZ   r   r   )numpynibabelZnitime.algorithmsr%  warningsr   r   r   r   r   rh   Zuint8r   r   RuntimeErrorr   medianr  r   r  Zsqueezesqrttolistrg   r   Zsquarecatch_warningsfilterwarningsarrayrn   )r'   r(   r*   r8   r   r   r%  r,  funcr   idxZmfuncZfunc_sdZar1Z
diff_sdhatZdiff_sd_meanZ	func_diffr_   Z
dvars_stdzZdiff_vx_stdzZdvars_vx_stdzr   r   r   rf     s@     & 

rf   c             C   sZ  ddl }|jtjdd ddlj}ddlm} ddlm	}	 ddl
}
|j|d}|	| |dd	d
dgdd}|jddddd |j|dddf }|r|dk	r| | } |j|  |jdt| f |}|dk	r||rdndj|7 }|j| d}|dk	rdj|}|j| |j }|j|d }|
j| d|d |jd |j| |jg  |S )zM
    A helper function to plot :abbr:`fMRI (functional MRI)` confounds.

    r   NZ	executionZmatplotlib_backend)GridSpec)FigureCanvasPdf)r5   rO   r   r   g?)Zwidth_ratiosZwspaceg      ?gffffff?g?g?)ZhspacerightleftZbottomz speed [{}/s]z [{}]zFrame #zFrame # ({} sec TR)T)ZverticalaxZFramesr   r   )r   r   )
matplotlibZuser   r  Zmatplotlib.pyplotZpyplotZmatplotlib.gridspecr6  Zmatplotlib.backends.backend_pdfr7  ZseabornZFigureupdateZadd_subplotZplotZset_xlimr   rU   Z
set_ylabelZ
set_xlabelZget_ylimZdistplotZset_ylimZset_yticklabels)Ztseriesr5   namer   r0   r   r;  Zpltr6  ZFigureCanvasZsnsrr   Zgridr:  ZylabelZxlabelZylimr   r   r   rk   >  s<    








rk         @c             C   s   t | jdkr| dddf } tj| dd}tj| | d dd}tj|}tj|}d| | }d}x,tt |D ]}|| |krP qt|d7 }qtW |S )a  
    Returns a boolean array with True if points are outliers and False
    otherwise.

    :param nparray points: an numobservations by numdimensions numpy array of observations
    :param float thresh: the modified z-score to use as a threshold. Observations with
        a modified z-score (based on the median absolute deviation) greater
        than this value will be classified as outliers.

    :return: A bolean mask, of size numobservations-length array.

    .. note:: References

        Boris Iglewicz and David Hoaglin (1993), "Volume 16: How to Detect and
        Handle Outliers", The ASQC Basic References in Quality Control:
        Statistical Techniques, Edward F. Mykytka, Ph.D., Editor.

    rO   Nr   )rZ   r   g/$?r   )r   r   r   r.  r   r/  r   )ZpointsZthreshr.  r   Zmed_abs_deviationZmodified_z_scoreZtimepoints_to_discardr   r   r   r   r#  i  s    

r#  rO   r   c             C   s   | j }|| }|d dkr0|dkr0| tjg fS | jd|f} |tj| }tt||d }	|	j d dkr|	d d d df ntjg }
tjj|	| j	d }|s|	d d d df }	|d d }| |	j
|j	 }|j||
fS )Nr   r   rO   r   r   r   r   )r   r   r3  r  arange
_full_rank_cosine_driftr   Zlstsqrn   dot)r  Ztimestep
period_cutr  rZ   r   	datashape
timepoints
frametimesXnon_constant_regressorsbetasZ	residualsr   r   r   cosine_filter  s    ,rJ  c             C   s>  t jdt|j |j}|| }|d dkrB|dkrB|tjg fS |jd|f}tj|df}xLt| D ]@}t	j
|d }	tjdd|}
tj||	|
ddtjf f}qhW |jd dkr|dddd	f ntjg }tjj|j|j}|r |j|j}n(|ddddf j|dddf j}|| }|j||fS )
z
    Returns data with degree polynomial regressed out.

    :param bool remove_mean: whether or not demean data (i.e. degree 0),
    :param int axis: numpy array axes along which regression is performed

    z4Performing polynomial regression on data of shape %sr   r   rO   N.r   r   r   )r   r	  r
  r   r   r3  r  r   r   r   basisZlinspacehstackZnewaxisr   ZpinvrB  rn   )r   r  r  rZ   r   rD  rE  rG  r   Zpolynomial_funcZvalue_arrayrH  rI  ZdatahatZregressed_datar   r   r   r    s&    $,(r  c             C   s~  t |st | rht |s4t| dkr,d}ntd|t| k rTtj| | }|gS tdj|t| g }|dkrx| D ]}|jtj| qzW |S |dkrd}xF| D ]>}tj|}tj|j	j
ddk}|dkr|}tj||| qW tj||j|jd	}|gS |d
krzd}xJ| D ]B}tj|}tj|j	j
ddk}|dkrL|}tj||| qW tj||j|jd	}|gS dS )a  Combines input mask files into a single nibabel image

    A helper function for CompCor

    Parameters
    ----------
    mask_files: a list
        one or more binary mask files
    mask_method: enum ('union', 'intersect', 'none')
        determines how to combine masks
    mask_index: an integer
        determines which file to return (mutually exclusive with mask_method)

    Returns
    -------
    masks: a list of nibabel images

    rO   r   zWWhen more than one mask file is provided, one of merge_method or mask_index must be setz9mask_index {0} must be less than number of mask files {1}r   r   NZint32)rd   r   )r   r   r   r   r   rU   r  r   r   r   rh   
logical_orr   r   rd   logical_and)r   Zmask_methodr   r   masksr  r   Zimg_as_maskr   r   r   r     sJ    







r         ?r   c	                sX  t jg }	|dkrd}|p$tt|}g }
g }g }g }g }g }xzt||D ]j\}}t jtj|jj	t
}| jdd |jkrtdj| jdd |j| |ddf }d|t jt j|ddddf< |dkr|dkrtd	t||||d
\}}	n|dkrt|||d
\}}	|j}|t|d }yt|dd\}}}W n t jjtfk
r   |dkrh t j|jd t jt jd}|dkrt j|jd |ft jt jd}nt j|jd dft jt jd}Y nX |d t j|d  }t j|}t| d|  k odk n  r&t j||d  n|dkr8t| t   dkrLP |
j|ddd f  |j|gt|  |j| |j| |j| |j fddtt|D  qLW t|
dkrt j|
}
n0|dkrtdt j|jd  ft jt jd}
tdt t!| fdt j|fdt j|fdt j|fdt t!| fg}|
|	|fS )ak	  
    Compute the noise components from the image series for each mask.

    Parameters
    ----------
    imgseries: nibabel image
        Time series data to be decomposed.
    mask_images: list
        List of nibabel images. Time series data from ``img_series`` is subset
        according to the spatial extent of each mask, and the subset data is
        then decomposed using principal component analysis. Masks should be
        coextensive with either anatomical or spatial noise ROIs.
    components_criterion: float
        Number of noise components to return. If this is a decimal value
        between 0 and 1, then ``create_noise_components`` will instead return
        the smallest number of components necessary to explain the indicated
        fraction of variance. If ``components_criterion`` is ``all``, then all
        components will be returned.
    filter_type: str
        Type of filter to apply to time series before computing noise components.

            - 'polynomial' - Legendre polynomial basis
            - 'cosine' - Discrete cosine (DCT) basis
            - False - None (mean-removal only)

    failure_mode: str
        Action to be taken in the event that any decomposition fails to
        identify any components. ``error`` indicates that the routine should
        raise an exception and exit, while any other value indicates that the
        routine should return a matrix of NaN values equal in size to the
        requested decomposition matrix.
    mask_names: list or None
        List of names for each image in ``mask_images``. This should be equal in
        length to ``mask_images``, with the ith element of ``mask_names`` naming
        the ith element of ``mask_images``.
    degree: int
        Order of polynomial used to remove trends from the timeseries
    period_cut: float
        Minimum period (in sec) for DCT high-pass filter
    repetition_time: float
        Time (in sec) between volume acquisitions. This must be defined if
        the ``filter_type`` is ``cosine``.

    Returns
    -------
    components: numpy array
        Numpy array containing the requested set of noise components
    basis: numpy array
        Numpy array containing the (non-constant) filter regressors
    metadata: OrderedDict{str: numpy array}
        Dictionary of eigenvalues, fractional explained variances, and
        cumulative explained variances.

    r   rO   Nr   zjInputs for CompCor, timeseries and mask, do not have matching spatial dimensions ({} and {}, respectively)r   )rZ   r   z2Repetition time must be provided for cosine filter)r   r   Fg      ?)r   r   )r   r   c                s   g | ]}| k qS r   r   )r   r   )r   r   r   r     s    z,compute_noise_components.<locals>.<listcomp>zNo components foundr   Zsingular_valuevariance_explainedcumulative_variance_explainedr   r   )r   Fr   )"r   r3  r   r   r   r   r   Zsqueeze_imager   rh   r   r   r   rU   isnanr   rJ  r  rn   r  r   r   r   fullnanr   Zcumsumr  Zsearchsortedr  rL  r   r   r   )r   r   r   Zfilter_typer   rC  r   r   r   rK  r   Zmd_maskZmd_svZmd_varZ	md_cumvarZmd_retainedr=  r   r   Zvoxel_timecoursesMus_rQ  rR  r   r   )r   r   r     s    A
 


$





$
r   c             C   s,   t j| |d}|||dk< ||t j|< |S )N)rZ   r   )r   r  rS  )rV  xrZ   ZstdMr   r   r   r    s    r  c       
      C   s   t |}tj|}d|  }|d |d  }tttjd| | | d}tj||f}tjd| }xBtd|D ]4}	|tj	tj
| |d  |	  |dd|	d f< qrW d|dd|d f< |S )a  Create a cosine drift matrix with periods greater or equals to period_cut

    Parameters
    ----------
    period_cut: float
         Cut period of the low-pass filter (in sec)
    frametimes: array of shape(nscans)
         The sampling times (in sec)

    Returns
    -------
    cdrift:  array of shape(n_scans, n_drifts)
             cosin drifts plus a constant regressor at cdrift[:,0]

    Ref: http://en.wikipedia.org/wiki/Discrete_cosine_transform DCT-II
    g      ?rO   r   r   g       @g      ?N)r   r   r?  maxr  floorr   r/  r   cospi)
rC  rF  Zlen_timZn_timesZhfcutdtorderZcdriftZnfctr  r   r   r   rA    s    
 4rA    4&kCc       	      C   s   t | dd\}}}|j |j  }}|| }||k r<| |fS tjd |||  |d  }|| }tj|tjtj||} | |fS )a  
    This function possibly adds a scalar matrix to X
    to guarantee that the condition number is smaller than a given threshold.

    Parameters
    ----------
    X: array of shape(nrows, ncols)
    cmax=1.e-15, float tolerance for condition number

    Returns
    -------
    X: array of shape(nrows, ncols) after regularization
    cmax=1.e-15, float tolerance for condition number
    F)r   z8Matrix is singular at working precision, regularizing...rO   )r   r[  minr   r   r   rB  Zdiag)	rG  ZcmaxUrX  VZsmaxZsmincZldar   r   r   r@    s    
r@  )TT)Fr$  )NNF)r>  r   )Tr   r   r   )Tr   r   )NN)rP  Fr   r   Nr   N)r   )ra  )@ru   r   os.pathr   rP   collectionsr   	itertoolsr   r+  r   r*  r   Znumpy.polynomialr   rb   r   r   Zexternal.duer   Zinterfaces.baser	   r
   r   r   r   r   r   r   r   Z
utils.miscr   	getLoggerr   r   r   r9   rD   rz   r   r   r   r   r   r   r   r   r   r  r  r  r  r   r"  rf   rk   r#  rJ  r  r   r   r  rA  r@  r   r   r   r   <module>   sf   
,

( "Z} y<@
X
+
'

+
H      
 (
$