3
ƽhUB                 @   sZ  d Z ddlZddlZddlZddlm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ZddlmZ ddlZddlmZ ddlmZ dd	gZd
d Zdd Zd.ddZejddd ZejdjZdd ZG dd de Z!G dd dZ"G dd de"Z#G dd de"Z$d d! Z%i Z&e%  d"d	 Z'd#d$ Z(d%d& Z)d'd( Z*d/d*dZ+d+d, Z,dS )0z(
Utilities for comparing image results.
    N)Path)TemporaryDirectoryTemporaryFile)Image)cbook)ImageComparisonFailurecompare_imagescomparable_formatsc             C   s   t jj| \}}d|||f S )zQ
    Make a new filename by inserting *purpose* before the file's extension.
    z%s-%s%s)ospathsplitext)fnamepurposebaseext r   @/tmp/pip-build-7iwl8md4/matplotlib/matplotlib/testing/compare.pymake_test_filename   s    r   c              C   s$   t tj d} | jddd t| S )NZ
test_cacheT)parentsexist_ok)r   mplZget_cachedirmkdirstr)	cache_dirr   r   r   get_cache_dir!   s    r         c             C   s   t j }t| d&}x|j|}|s&P |j| qW W d Q R X t| jdkrj|jttj	dj
jd n*t| jdkr|jttj	dj
jd |j S )Nrbz.pdfgszutf-8z.svginkscape)hashlibmd5openreadupdater   suffixr   r   _get_executable_infoversionencode	hexdigest)r   
block_sizer!   fddatar   r   r   get_file_hash'   s    

r-   z3.3c                s    fdd}|S )Nc                s    | |}t j|dt jt jd}|j \}}|j }tjj| sF|r|ddj| }|rd|d| 7 }|rt|d| 7 }t	|d S )NT)universal_newlinesstdoutstderrzConversion command failed:
%s
 zStandard output:
%s
zStandard error:
%s
)

subprocessPopenPIPEcommunicatewaitr
   r   existsjoinIOError)oldnewZcmdlinepiper/   r0   errcodemsg)cmdr   r   convert<   s    
z1make_external_conversion_command.<locals>.convertr   )r?   r@   r   )r?   r    make_external_conversion_command:   s    rA   s   [^a-zA-Z0-9_@%+=:,./-]c             C   s$   t | d kr| S d| jdd d S )N   's   '"'"')_find_unsafe_bytesreplace)br   r   r   _shlex_quote_bytesQ   s    rF   c               @   s   e Zd ZdS )_ConverterErrorN)__name__
__module____qualname__r   r   r   r   rG   V   s   rG   c               @   s$   e Zd Zdd Zdd Zdd ZdS )
_Converterc             C   s   d | _ tj| j d S )N)_procatexitregister__del__)selfr   r   r   __init__[   s    z_Converter.__init__c             C   sR   | j rN| j j  | j j  x,td | j j| j j| j jgD ]}|j  q8W d | _ d S )N)rL   killr6   filterstdinr/   r0   close)rP   streamr   r   r   rO   c   s    

z_Converter.__del__c             C   sP   t  }xD| jjjd}|st|j| |j|rt|dt|  S qW dS )z!Read until the prompt is reached.   N)		bytearrayrL   r/   r#   rG   extendendswithbyteslen)rP   
terminatorbufcr   r   r   _read_untilm   s    

z_Converter._read_untilN)rH   rI   rJ   rQ   rO   r`   r   r   r   r   rK   Z   s   
rK   c               @   s   e Zd Zdd ZdS )_GSConverterc             C   s  | j shtjtjdjdddgtjtjd| _ y| jd W n, tk
rf } zt	d|W Y d d }~X nX dd	 }| j j
jd
|| d || d  | j j
j  | jd}| jd}|stjj| r|rt|dd  nd}| j j
jd|  t|d | d jtj dd S )Nr   z	-dNOSAFERz	-dNOPAUSEz-sDEVICE=png16m)rT   r/   s   
GSzFailed to start Ghostscriptc             S   s"   t j| jddjddjddS )N   \s   \\   (s   \(   )s   \))r
   fsencoderD   )namer   r   r   encode_and_escape   s    
z0_GSConverter.__call__.<locals>.encode_and_escapes   << /OutputFile (s   ) >> setpagedevice (s   ) run flush
s   GS   >rW   r   s   pop
rD   )rL   r2   r3   r   r&   
executabler4   r`   rG   OSErrorrT   writeflushr
   r   r7   intr   decodesysgetfilesystemencoding)rP   origdesterrrg   stack
stack_sizer   r   r   __call__z   s*    


z_GSConverter.__call__N)rH   rI   rJ   rv   r   r   r   r   ra   y   s   ra   c                   s$   e Zd Zdd Z fddZ  ZS )_SVGConverterc       
   '   C   s  t jdjdk }|rdnd}t| ds.t | _| j sD| jj d k	rtj	dtj
d}t }tj|rnddd	gndd	gtjtj||| jjd
| _|| j_y| j| W n, tk
r } ztd|W Y d d }~X nX t| jjtjd}t| jjtjd}	y|jt|j  W n" tk
r2   tj|| Y nX | jjj|rFdnd | jjj  y| j| W nP tk
r } z2| jjjd t| jjj j t!j" d|W Y d d }~X nX tj#| tj$|	| d S )Nr   1s   
>s   > _tmpdir )ZDISPLAYZINKSCAPE_PROFILE_DIRz--without-guiz--shell)rT   r/   r0   envcwdz,Failed to start Inkscape in interactive modes   f.svgs   f.pngs   f.svg --export-png=f.png
s;   file-open:f.svg;export-filename:f.png;export-do;file-close
r   rD   )%r   r&   r'   hasattrr   ry   rL   pollr
   environdevnullr   r2   r3   r4   rf   r0   r`   rG   rj   r   fsdecodeZ
symlink_toresolveshutilcopyfilerT   rk   rl   seekr   r#   rn   ro   rp   removemove)
rP   rq   rr   Zold_inkscaper]   r{   r0   rs   Zinkscape_origZinkscape_destr   r   r   rv      sP    


"
z_SVGConverter.__call__c                s"   t  j  t| dr| jj  d S )Nry   )superrO   r}   ry   cleanup)rP   )	__class__r   r   rO      s    

z_SVGConverter.__del__)rH   rI   rJ   rv   rO   __classcell__r   r   )r   r   rw      s   >rw   c               C   sl   yt jd W n t jk
r$   Y nX t  td< td< yt jd W n t jk
r\   Y nX t td< d S )Nr   pdfepsr   svg)r   r&   ZExecutableNotFoundErrorra   	converterrw   r   r   r   r   _update_converter   s    r   c               C   s   dt S )z
    Return the list of file formats that `.compare_images` can compare
    on this system.

    Returns
    -------
    list of str
        E.g. ``['png', 'pdf', 'svg', 'eps']``.

    png)r   )r   r   r   r   r   r	      s    c             C   s  t | }|j st| d|jdd tkrLddl}|jd|j d |j|j d|jdd  d }|j  s|j	 j
|j	 j
k r|rt t nd}|dk	rt|}|||j  }|j rtj|| t|S t|jdd  || |dk	rtj|| t|S )	at  
    Convert the named file to png; return the name of the created file.

    If *cache* is True, the result of the conversion is cached in
    `matplotlib.get_cachedir() + '/test_cache/'`.  The caching is based on a
    hash of the exact contents of the input file.  There is no limit on the
    size of the cache, so it may need to be manually cleared periodically.
    z does not existrW   Nr   zDon't know how to convert z files to png_z.png)r   r7   r9   r%   r   pytestskipparentZstemstatst_mtimer   r-   r   r   r   )filenamecacher   r   newpathr   Z
hash_valueZcached_pathr   r   r   r@   	  s&    	" 
r@   c       
      C   s   | dd dkr|dd	 dkr|j \}}}|j \}}}	|t|d |d  t|d |d  t|d |d  t|d |d  f }||fS )
N      r   r   r   iir   )shaperm   )
Zactual_pathactual_imageZexpected_pathexpected_imageZawZahadewehZedr   r   r   crop_to_same.  s     >r   c             C   s<   | j |j kr tdj| j |j tj| | jtd j S )zR
    Calculate the per-pixel errors, then compute the root mean square error.
    z9Image sizes do not match expected size: {} actual size {}r   )r   r   formatnpsqrtastypefloatZmean)r   r   r   r   r   calculate_rms9  s
    r   Fc       
         sz  t j|}t jj|s"td| t j|jdkr>td| t j| } t jj| s`td|  | jdd }|dkrt	|dd	}t	| d
d	} t
jtj| j	d}t
jtj|j	d}t||| |\}}t|d}|dkrt
j||rdS |jt
j}|jt
j}t||}||krdS t| || t|t| t|t||d |svddddddg}	dj fdd|	D   S )a+  
    Compare two "image" files checking differences within a tolerance.

    The two given filenames may point to files which are convertible to
    PNG via the `.converter` dictionary. The underlying RMS is calculated
    with the `.calculate_rms` function.

    Parameters
    ----------
    expected : str
        The filename of the expected image.
    actual : str
        The filename of the actual image.
    tol : float
        The tolerance (a color value difference, where 255 is the
        maximal difference).  The test fails if the average pixel
        difference is greater than this value.
    in_decorator : bool
        Determines the output format. If called from image_comparison
        decorator, this should be True. (default=False)

    Returns
    -------
    None or dict or str
        Return *None* if the images are equal within the given tolerance.

        If the images differ, the return value depends on  *in_decorator*.
        If *in_decorator* is true, a dict with the following entries is
        returned:

        - *rms*: The RMS of the image difference.
        - *expected*: The filename of the expected image.
        - *actual*: The filename of the actual image.
        - *diff_image*: The filename of the difference image.
        - *tol*: The comparison tolerance.

        Otherwise, a human-readable multi-line string representation of this
        information is returned.

    Examples
    --------
    ::

        img1 = "./baseline/plot.png"
        img2 = "./output/plot.png"
        compare_images(img1, img2, 0.001)

    zOutput image %s does not exist.r   zOutput image file %s is empty.z!Baseline image %r does not exist..rW   r   F)r   TRGBzfailed-diffN)rmsexpectedactualZdifftolz!Error: Image files did not match.zRMS Value: {rms}zExpected:  
    {expected}zActual:    
    {actual}zDifference:
    {diff}zTolerance: 
    {tol}z
  c                s   g | ]}|j f  qS r   )r   ).0line)resultsr   r   
<listcomp>  s    z"compare_images.<locals>.<listcomp>)r
   fspathr   r7   	Exceptionr   st_sizer9   splitr@   r   asarrayr   r"   r   r   Zarray_equalr   Zint16r   save_diff_imagedictr   r8   )
r   r   r   Zin_decorator	extensionr   r   Z
diff_imager   templater   )r   r   r   I  sJ    1





c             C   s   t jtj| jd}t jtj|jd}t||| |\}}t j|jt}t j|jt}|j	|j	kr~t
dj|j	|j	t j|| }|d9 }t j|ddjt j}|j	\}}}	|	dkrt j||dft jd}
||
d	d	d	d	ddf< |
}d|d	d	d	d	df< tj|j|d
d d	S )z
    Parameters
    ----------
    expected : str
        File path of expected image.
    actual : str
        File path of actual image.
    output : str
        File path to save difference image to.
    r   z9Image sizes do not match expected size: {} actual size {}   
   r      r   )ZdtypeNr   )r   i	  )r   r   r   r"   r@   r   arrayr   r   r   r   r   absZclipZuint8emptyZ	fromarraysave)r   r   outputr   r   Zabs_diff_imageZsave_image_npheightwidthdepthZ
with_alphar   r   r   r     s(    r      )r   )F)-__doc__rM   r    r
   Zpathlibr   rer   r2   ro   tempfiler   r   numpyr   ZPILr   Z
matplotlibr   r   Zmatplotlib.testing.exceptionsr   __all__r   r   r-   Z
deprecatedrA   compilesearchrC   rF   r   rG   rK   ra   rw   r   r   r	   r@   r   r   r   r   r   r   r   r   <module>   sD   
&E%
h