3
d*                 @   s   d Z ddlZddlZddlZddlmZ ddlmZ ddlm	Z	 ddl
ZddlZdd Zddd	Zd
d Zdd Zdd Zdde	eefddZdd Zdd Zdd Zdd Zd ddZd!ddZdS )"z Miscellaneous utility functions
    N)Iterator)warn)LooseVersionc                s    dd   fdd}t | |dS )zASorts string in human order (i.e. 'stat10' will go after 'stat2')c             S   s   | j  rt| S | S )N)isdigitint)text r   3/tmp/pip-build-7vycvbft/nipype/nipype/utils/misc.pyatoi   s    z human_order_sorted.<locals>.atoic                s,   t | tr| d }  fddtjd| D S )Nr   c                s   g | ]} |qS r   r   ).0c)r
   r   r	   
<listcomp>   s    z<human_order_sorted.<locals>.natural_keys.<locals>.<listcomp>z(\d+))
isinstancetupleresplit)r   )r
   r   r	   natural_keys   s    
z(human_order_sorted.<locals>.natural_keys)key)sorted)lr   r   )r
   r	   human_order_sorted   s    r   c                sF  t | trt| d} | sdS | j j }tj}x6|dd  D ]&}|j   r<t|t	|t	  }q<W |d j
 g}|tjk rxx|dd  D ]h}|j j
 j  |d k	rވ rt fdd D rވ d d	kr|j d |}|j||d  j  qW x|r|d
  r|j  qW x"|r:|d  r:|jd qW dj|S )Nzutf-8    r   c                s   g | ]}| d  kqS )r   r   )r   s)strippedr   r	   r   9   s    ztrim.<locals>.<listcomp>:
)r   )r   bytesstr
expandtabs
splitlinessysmaxsizelstripminlenstriprstripallreplaceappendpopjoin)Z	docstringmarkerlinesindentlineZtrimmedr   )r   r	   trim!   s2    


r2   c             C   s   t jt j| \}|S )z1Return the indices where ravel(condition) is true)npZnonzeroZravel)	conditionresr   r   r	   find_indicesG   s    r6   c             C   s$   t | trdS t| drdS dS dS )zChecks if item is a container (list, tuple, dict, set)

    Parameters
    ----------
    item : object
        object to check for .__iter__

    Returns
    -------
    output : Boolean
        True if container
        False if not (eg string)
    F__iter__TN)r   r   hasattr)itemr   r   r	   is_containerM   s
    

r:   c             C   s(   t | dr t| t r dj| } t| S )a  Convert a container to a command line string.

    Elements of the container are joined with a space between them,
    suitable for a command line parameter.

    If the container `cont` is only a sequence, like a string and not a
    container, it is returned unmodified.

    Parameters
    ----------
    cont : container
       A container object like a list, tuple, dict, or a set.

    Returns
    -------
    cont_str : string
        Container elements joined into a string.

    r7    )r8   r   r   r-   )Zcontr   r   r	   container_to_stringc   s    
r<   c       
      C   s   |rd|| f }nd|  }|r,|d|f 7 }yt | }W n, tk
rd } z|||W Y dd}~X nX |sndS y
|j}	W n0 tk
r } z|d|  |W Y dd}~X nX ||	||k r||dS )a  Check that the minimal version of the required package is installed.

    Parameters
    ----------
    pkg_name : string
        Name of the required package.
    version : string, optional
        Minimal version number for required package.
    app : string, optional
        Application that is performing the check.  For instance, the
        name of the tutorial being executed that depends on specific
        packages.  Default is *Nipype*.
    checker : object, optional
        The class that will perform the version checking.  Default is
        distutils.version.LooseVersion.
    exc_failed_import : Exception, optional
        Class of the exception to be thrown if import failed.
    exc_failed_check : Exception, optional
        Class of the exception to be thrown if version check failed.

    Examples
    --------
    package_check('numpy', '1.3')
    package_check('scipy', '0.7', 'tutorial1')

    z%s requires %szNipype requires %sz with version >= %sNzCannot find version for %s)
__import__ImportError__version__AttributeError)
pkg_nameversionZappcheckerZexc_failed_importZexc_failed_checkmsgmodeZhave_versionr   r   r	   package_check~   s"    #
 rG   c             C   s\   t | tr| S t | tr"| jd} t | trL| j }|dkr@dS |dkrLdS td|  dS )a  
    Convert strings (and bytearrays) to boolean values

    >>> all([str2bool(v) for v in (True, "yes", "true",
    ...      "y", "t", "Yes", "True", "1", "on", "On")])
    True
    >>> all([str2bool(v.encode('utf-8'))
    ...      for v in ("yes", "true", "y", "t", "1", "Yes", "on", "On")])
    True
    >>> any([str2bool(v) for v in (False, "no", "false", "n", "f",
    ...      "False", "0", "off", "Off")])
    False
    >>> any([str2bool(v.encode('utf-8'))
    ...      for v in ("no", "false", "n", "f", "0", "off", "Off")])
    False
    >>> str2bool(None)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...
    >>> str2bool('/some/path')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...
    >>> str2bool('Agg')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...
    >>> str2bool('INFO')  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...
    >>> str2bool('/some/bytes/path'.encode('utf-8'))  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ValueError: ...

    zutf-8yestrueyt1onTnofalsenf0offFz%r cannot be converted to boolN)rH   rI   rJ   rK   rL   rM   )rN   rO   rP   rQ   rR   rS   )r   boolr   decoder   lower
ValueError)vrV   r   r   r	   str2bool   s    &



rY   c             C   sR   | g kr| S t | d tr6t| d t| dd   S | d d t| dd   S )Nr   r   )r   listflatten)Sr   r   r	   r[      s
    r[   c             C   sJ   t | tst| } t |ts$t| S g }x|D ]}|jt| | q.W |S )N)r   r   iterrZ   nextr+   	unflatten)Zin_listZprev_structureoutr9   r   r   r	   r_      s    


r_   c             C   s   |j  dkr"| ddddddg } n|j  dkrt| tjddddddgt| d
k  } | dd tj d | dd< nX|j  dkrddlm}m} || }tjd
} |dddf | dd< ||| ddd< | S )aN  
    Normalize a single row of motion parameters to the SPM format.

    SPM saves motion parameters as:
        x   Right-Left          (mm)
        y   Anterior-Posterior  (mm)
        z   Superior-Inferior   (mm)
        rx  Pitch               (rad)
        ry  Roll                (rad)
        rz  Yaw                 (rad)
    ZFSL         r   r      AFNIFSFAST   Ng     f@ZNIPY)to_matrix44	aff2euler)re   rf   r   r   )	upperr3   Zasarrayr&   piZnipy.algorithms.registrationrh   ri   zeros)paramssourcerh   ri   Zmatrixr   r   r	   normalize_mc_params   s    & 
ro   c                s@  yt |t |  }} W n, tk
rB   tjd|  d| d| S X t|j }t| j }g }|| rz|d||  g7 }|| r|d||  g7 }|r|jdd t|}dd	 } fd
d xN|j|D ]@} || }	 | | }
|	|
kr|d|||	||
f g7 }qW t||kr*|j|d tjdj	|d| S )zHelper to log what actually changed from old to new values of
    dictionaries.

    typical use -- log difference for hashed_inputs
    z4Diff between nipype inputs failed:
* Cached inputs: z
* New inputs: r;   z   * keys not previously seen: %sz  * keys not presently seen: %sr   z Dictionaries had differing keys:c             S   s|   t | tr4t| dkr4| d d  d| dd   S t | ttfrxt| dkrxtt| d d dg t| dd   S | S )N2   
   z...rd   i)r   r   r&   r   rZ   )valuer   r   r	   _shorten?  s
    *zdict_diff.<locals>._shortenc                sH   t | tr  fdd| j D S t | ttfrDt fdd| D S | S )Nc                s   i | ]\}} ||qS r   r   )r   krX   )_uniformizer   r	   
<dictcomp>H  s    z2dict_diff.<locals>._uniformize.<locals>.<dictcomp>c             3   s   | ]} |V  qd S )Nr   )r   el)rv   r   r	   	<genexpr>J  s    z1dict_diff.<locals>._uniformize.<locals>.<genexpr>)r   dictitemsrZ   r   )val)rv   r   r	   rv   F  s
    
zdict_diff.<locals>._uniformizez  * %s: %r != %rz-Some dictionary entries had differing values:r   )
rz   	Exceptiontextwrapr0   setkeysinsertr&   intersectionr-   )ZdoldZdnewr0   Znew_keysZold_keysZdiffZdiffkeysrt   ru   newoldr   )rv   r	   	dict_diff  s4    	 r   Tc             C   sl   | rt j S yt j }W nN tk
rf } z2t jd}|dkrJt|jdftd|  W Y dd}~X nX |S )zz
    Robust replacement for getcwd when folders get removed
    If error==True, this is just an alias for os.getcwd()
    ZPWDNzbCurrent directory does not exist anymore, and nipype was not able to guess it from the environmentz;Current folder does not exist, replacing with "%s" instead.)osgetcwdOSErrorgetenverrnor   )errorcwdexcr   r   r	   rgetcwd_  s    
r   )N)r   )T)__doc__r   r"   r   collections.abcr   warningsr   distutils.versionr   numpyr3   r~   r   r2   r6   r:   r<   r>   RuntimeErrorrG   rY   r[   r_   ro   r   r   r   r   r   r	   <module>   s0   
&16
C