B
    ]t\`                @   s  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m	Z	 d dl
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mZmZmZ d dlmZmZmZmZ eeZe
 dkrd Z Z!nd Z d	d
 Z"G dd de#Z$e$ Z%G dd de j&Z'G dd de'Z(G dd de(Z)e%*dG dd de(Z+G dd de#Z,e%*dG dd de,e(Z-e%*dG dd de,e)Z.G dd de,Z/e%*d G d!d" d"e/e-Z0e%*d#G d$d% d%e/e.Z1G d&d' d'e#Z2e%*d(G d)d* d*e2e(Z3e%*d+G d,d- d-e2e)Z4d.d/ Z5d0d1 Z6e%*d2G d3d4 d4e)Z7G d5d6 d6e#Z8G d7d8 d8e8Z9G d9d: d:e9Z:G d;d< d<e9Z;dS )=    N)BytesIO)Path)TemporaryDirectory)DISPLAY_TEMPLATEINCLUDED_FRAMES
JS_INCLUDE)cbookrcParamsrcParamsDefault
rc_contextZWindowsi   c             C   sP   dd }t | | | | | }t || | | | }||||||||fS )a#  Compute figure size so that pixels are a multiple of n

    Parameters
    ----------
    w, h : float
        Size in inches

    dpi : float
        The dpi

    n : int
        The target multiple

    Returns
    -------
    wnew, hnew : float
        The new figure size in inches.
    c             S   sv   t | | | dkrrt t| tj| | dkrBt| tj} n0t t| tj | | dkrrt| tj } | S )Nr   )intnpZ	nextafterinf)xdpin r   3lib/python3.7/site-packages/matplotlib/animation.pycorrect_roundoffS   s     z*adjusted_figsize.<locals>.correct_roundoff)r   )whr   r   r   ZwnewZhnewr   r   r   adjusted_figsize=   s    r   c               @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )MovieWriterRegistryz<Registry of available writer classes by human readable name.c             C   s   t  | _t  | _d| _d S )NF)dictavail_registered_dirty)selfr   r   r   __init__c   s    zMovieWriterRegistry.__init__c             C   s
   d| _ dS )z$Sets a flag to re-setup the writers.TN)r   )r   r   r   r   	set_dirtyh   s    zMovieWriterRegistry.set_dirtyc                s    fdd}|S )zDecorator for registering a class under a name.

        Example use::

            @registry.register(name)
            class Foo:
                pass
        c                s    | j  < |  r| j < | S )N)r   isAvailabler   )writerClass)namer   r   r   wrapperu   s    

z-MovieWriterRegistry.register.<locals>.wrapperr   )r   r"   r#   r   )r"   r   r   registerl   s    	zMovieWriterRegistry.registerc             C   s   | j r|   dS )z2If dirty, reasks the writers if they are availableN)r   reset_available_writers)r   r   r   r   ensure_not_dirty|   s    z$MovieWriterRegistry.ensure_not_dirtyc             C   s:   i | _ x(| j D ]\}}| r|| j |< qW d| _dS )z3Reset the available state of all registered writersFN)r   r   itemsr    r   )r   r"   r!   r   r   r   r%      s
    z+MovieWriterRegistry.reset_available_writersc             C   s   |    t| jS )z%Get a list of available MovieWriters.)r&   listr   )r   r   r   r   r(      s    zMovieWriterRegistry.listc             C   s   |    || jkS )zCheck if given writer is available by name.

        Parameters
        ----------
        name : str

        Returns
        -------
        available : bool
        )r&   r   )r   r"   r   r   r   is_available   s    z MovieWriterRegistry.is_availablec             C   sH   |    | jstdy
| j| S  tk
rB   td|Y nX d S )NzNo MovieWriters available!z(Requested MovieWriter ({}) not available)r&   r   RuntimeErrorKeyErrorformat)r   r"   r   r   r   __getitem__   s    
zMovieWriterRegistry.__getitem__N)__name__
__module____qualname____doc__r   r   r$   r&   r%   r(   r)   r-   r   r   r   r   r   a   s   r   c               @   sJ   e Zd ZdZejdddZejdd Zejdd Ze	j
d	d
 ZdS )AbstractMovieWritera  
    Abstract base class for writing movies. Fundamentally, what a MovieWriter
    does is provide is a way to grab frames by calling grab_frame().

    setup() is called to start the process and finish() is called afterwards.

    This class is set up to provide for writing movie frame data to a pipe.
    saving() is provided as a context manager to facilitate this process as::

        with moviewriter.saving(fig, outfile='myfile.mp4', dpi=100):
            # Iterate over frames
            moviewriter.grab_frame(**savefig_kwargs)

    The use of the context manager ensures that setup() and finish() are
    performed as necessary.

    An instance of a concrete subclass of this class can be given as the
    ``writer`` argument of `Animation.save()`.
    Nc             C   s   dS )a  
        Perform setup for writing the movie file.

        Parameters
        ----------
        fig: `matplotlib.figure.Figure` instance
            The figure object that contains the information for frames
        outfile: string
            The filename of the resulting movie file
        dpi: int, optional
            The DPI (or resolution) for the file.  This controls the size
            in pixels of the resulting movie file. Default is ``fig.dpi``.
        Nr   )r   figoutfiler   r   r   r   setup   s    zAbstractMovieWriter.setupc             K   s   dS )z
        Grab the image information from the figure and save as a movie frame.

        All keyword arguments in savefig_kwargs are passed on to the `savefig`
        command that saves the figure.
        Nr   )r   savefig_kwargsr   r   r   
grab_frame   s    zAbstractMovieWriter.grab_framec             C   s   dS )z,Finish any processing for writing the movie.Nr   )r   r   r   r   finish   s    zAbstractMovieWriter.finishc             o   s0   | j |||f|| z
| V  W d|   X dS )z
        Context manager to facilitate writing the movie file.

        ``*args, **kw`` are any parameters that should be passed to `setup`.
        N)r5   r8   )r   r3   r4   r   argskwargsr   r   r   saving   s    
zAbstractMovieWriter.saving)N)r.   r/   r0   r1   abcabstractmethodr5   r7   r8   
contextlibcontextmanagerr;   r   r   r   r   r2      s   	r2   c               @   s   e Zd ZdZdddZedd Zdd	 Zdd
dZdd Z	dd Z
dd Zdd Zdd Zdd Zedd Zedd ZdS )MovieWritera  Base class for writing movies.

    This class is set up to provide for writing movie frame data to a pipe.
    See examples for how to use these classes.

    Attributes
    ----------
    frame_format : str
        The format used in writing frame data, defaults to 'rgba'
    fig : `~matplotlib.figure.Figure`
        The figure to capture data from.
        This must be provided by the sub-classes.

       Nc             C   s|   || _ d| _|dkr td | _n|| _|dkr:td | _n|| _|dkrZtt| j | _n|| _|dkrrt | _	n|| _	dS )a  MovieWriter

        Parameters
        ----------
        fps: int
            Framerate for movie.
        codec: string or None, optional
            The codec to use. If ``None`` (the default) the ``animation.codec``
            rcParam is used.
        bitrate: int or None, optional
            The bitrate for the saved movie file, which is one way to control
            the output file size and quality. The default value is ``None``,
            which uses the ``animation.bitrate`` rcParam.  A value of -1
            implies that the bitrate should be determined automatically by the
            underlying utility.
        extra_args: list of strings or None, optional
            A list of extra string arguments to be passed to the underlying
            movie utility. The default is ``None``, which passes the additional
            arguments in the ``animation.extra_args`` rcParam.
        metadata: Dict[str, str] or None
            A dictionary of keys and values for metadata to include in the
            output file. Some keys that may be of use include:
            title, artist, genre, subject, copyright, srcform, comment.
        rgbaNzanimation.codeczanimation.bitrate)
fpsframe_formatr	   codecbitrater(   args_key
extra_argsr   metadata)r   rC   rE   rF   rH   rI   r   r   r   r      s    
zMovieWriter.__init__c             C   s*   | j  \}}t|| j t|| j fS )z7A tuple ``(width, height)`` in pixels of a movie frame.)r3   get_size_inchesr   r   )r   r   r   r   r   r   
frame_size,  s    zMovieWriter.frame_sizec             C   s   | j dkrb| j \}}t||| jd\}}||f||fksp| jj||dd td|||| n| j \}}tjd| j	  ||fS )Nh264   T)Zforwardz>figure size (inches) has been adjusted from %s x %s to %s x %sframe size in pixels is %s x %s)rN   )
rE   r3   rJ   r   r   set_size_inches_loginfodebugrK   )r   ZwoZhor   r   r   r   r   _adjust_frame_size2  s    
zMovieWriter._adjust_frame_sizec             C   s>   || _ || _|dkr| jj}|| _|  \| _| _|   dS )a  
        Perform setup for writing the movie file.

        Parameters
        ----------
        fig : matplotlib.figure.Figure
            The figure object that contains the information for frames
        outfile : string
            The filename of the resulting movie file
        dpi : int, optional
            The DPI (or resolution) for the file.  This controls the size
            in pixels of the resulting movie file. Default is fig.dpi.
        N)r4   r3   r   rS   _w_h_run)r   r3   r4   r   r   r   r   r5   ?  s    zMovieWriter.setupc             C   s8   |   }tj}td| tj|d||tjtd| _d S )Nz$MovieWriter.run: running command: %sF)shellstdoutstderrstdincreationflags)_args
subprocessPIPErP   rQ   Popensubprocess_creation_flags_proc)r   Zcommandoutputr   r   r   rV   X  s    zMovieWriter._runc             C   s   |    dS )z,Finish any processing for writing the movie.N)cleanup)r   r   r   r   r8   d  s    zMovieWriter.finishc          
   K   s   t d y8| j| j| j | jj|  f| j| j	d| W nT t
tfk
r } z2| j \}}t d|| td|||W dd}~X Y nX dS )z
        Grab the image information from the figure and save as a movie frame.

        All keyword arguments in savefig_kwargs are passed on to the `savefig`
        command that saves the figure.
        z'MovieWriter.grab_frame: Grabbing frame.)r,   r   z(MovieWriter -- Error running proc:
%s
%sz}Error saving animation to file (cause: {0}) Stdout: {1} StdError: {2}. It may help to re-run with logging level set to DEBUG.N)rP   rR   r3   rO   rT   rU   savefig_frame_sinkrD   r   r*   IOErrorra   communicaterQ   r,   )r   r6   eouterrr   r   r   r7   h  s    
zMovieWriter.grab_framec             C   s   | j jS )z4Returns the place to which frames should be written.)ra   rZ   )r   r   r   r   re     s    zMovieWriter._frame_sinkc             C   s   t dS )z9Assemble list of utility-specific command-line arguments.z)args needs to be implemented by subclass.)NotImplementedError)r   r   r   r   r\     s    zMovieWriter._argsc             C   s6   | j  \}}|    td| td| dS )z>Clean-up and collect the process used to write the movie file.z!MovieWriter -- Command stdout:
%sz!MovieWriter -- Command stderr:
%sN)ra   rg   re   closerP   rR   )r   ri   rj   r   r   r   rc     s    zMovieWriter.cleanupc             C   s   t t| j S )z
        Returns the binary path to the commandline tool used by a specific
        subclass. This is a class method so that the tool can be looked for
        before making a particular MovieWriter subclass available.
        )strr	   exec_key)clsr   r   r   bin_path  s    zMovieWriter.bin_pathc             C   s   t |  dk	S )zO
        Check to see if a MovieWriter subclass is actually available.
        N)shutilZwhichrp   )ro   r   r   r   r      s    zMovieWriter.isAvailable)rA   NNNN)N)r.   r/   r0   r1   r   propertyrK   rS   r5   rV   r8   r7   re   r\   rc   classmethodrp   r    r   r   r   r   r@      s    
0
	r@   c               @   sd   e Zd ZdZdd ZdddZed	d
 Zejdd
 Zdd Z	dd Z
dd Zdd Zdd ZdS )FileMovieWriterzx`MovieWriter` for writing to individual files and stitching at the end.

    This must be sub-classed to be useful.
    c             O   s    t j| f|| td | _d S )Nzanimation.frame_format)r@   r   r	   rD   )r   r9   r:   r   r   r   r     s    zFileMovieWriter.__init__N_tmpTc             C   sN   || _ || _|dkr| j j}|| _|   || _|| _d| _t | _d| _	dS )a6  Perform setup for writing the movie file.

        Parameters
        ----------
        fig : matplotlib.figure.Figure
            The figure to grab the rendered frames from.
        outfile : str
            The filename of the resulting movie file.
        dpi : number, optional
            The dpi of the output file. This, with the figure size,
            controls the size in pixels of the resulting movie file.
            Default is fig.dpi.
        frame_prefix : str, optional
            The filename prefix to use for temporary files.  Defaults to
            ``'_tmp'``.
        clear_temp : bool, optional
            If the temporary files should be deleted after stitching
            the final result.  Setting this to ``False`` can be useful for
            debugging.  Defaults to ``True``.

        Nr   z
%s%%07d.%s)
r3   r4   r   rS   
clear_temptemp_prefix_frame_counterr(   _temp_namesfname_format_str)r   r3   r4   r   frame_prefixrv   r   r   r   r5     s    zFileMovieWriter.setupc             C   s   | j S )z
        Format (png, jpeg, etc.) to use for saving the frames, which can be
        decided by the individual subclasses.
        )_frame_format)r   r   r   r   rD     s    zFileMovieWriter.frame_formatc             C   s"   || j kr|| _n| j d | _d S )Nr   )supported_formatsr|   )r   rD   r   r   r   rD     s    
c             C   s   | j | j| jf S )N)rz   rw   rD   )r   r   r   r   _base_temp_name  s    zFileMovieWriter._base_temp_namec             C   sB   |   | j }| j| td| j| |  jd7  _t|dS )Nz7FileMovieWriter.frame_sink: saving frame %d to fname=%s   wb)r~   rx   ry   appendrP   rR   open)r   fnamer   r   r   re     s    
zFileMovieWriter._frame_sinkc          	   K   sx   t d y6|  $}| jj|f| j| jd| W dQ R X W n2 tk
rr   | j	 \}}t 
d||  Y nX dS )z
        Grab the image information from the figure and save as a movie frame.
        All keyword arguments in savefig_kwargs are passed on to the `savefig`
        command that saves the figure.
        z'MovieWriter.grab_frame: Grabbing frame.)r,   r   Nz(MovieWriter -- Error running proc:
%s
%s)rP   rR   re   r3   rd   rD   r   r*   ra   rg   rQ   )r   r6   Zmyframesinkri   rj   r   r   r   r7     s    

zFileMovieWriter.grab_framec          
   C   s   |    t|  | jjry@dd | jjD }dd | jjD }td| td| W n" t	k
r| } zW d d }~X Y nX t
d| jjd S )Nc             S   s   g | ]}|  qS r   )decode).0sr   r   r   
<listcomp>  s    z*FileMovieWriter.finish.<locals>.<listcomp>c             S   s   g | ]}|  qS r   )r   )r   r   r   r   r   r     s    zMovieWriter.finish: stdout: %szMovieWriter.finish: stderr: %sz%Error creating movie, return code: {})rV   r@   r8   ra   
returncodeZ_stdout_buffZ_stderr_buffrP   rQ   	Exceptionr*   r,   )r   rX   rY   rh   r   r   r   r8     s    
zFileMovieWriter.finishc             C   s<   t |  | jr8td| j x| jD ]}t| q&W d S )Nz)MovieWriter: clearing temporary fnames=%s)r@   rc   rv   rP   rR   ry   osremove)r   r   r   r   r   rc     s    
zFileMovieWriter.cleanup)Nru   T)r.   r/   r0   r1   r   r5   rr   rD   setterr~   re   r7   r8   rc   r   r   r   r   rt     s    
#rt   Zpillowc                   sB   e Zd Zedd Z fddZdddZdd	 Zd
d Z  Z	S )PillowWriterc             C   s&   ydd l }W n tk
r    dS X dS )Nr   FT)PILImportError)ro   r   r   r   r   r    %  s
    zPillowWriter.isAvailablec                s(   | dd krd|d< t j|| d S )NrH   r   )getsuperr   )r   r9   r:   )	__class__r   r   r   -  s    zPillowWriter.__init__Nc             C   s   g | _ || _|| _|| _d S )N)_frames_outfileZ_dpi_fig)r   r3   r4   r   r   r   r   r5   2  s    zPillowWriter.setupc             K   sd   ddl m} t }| jj|ft|dd | jj }| j	|
dt|jt|jf|  d S )Nr   )ImagerB   )r,   ZRGBA)r   r   r   r   rd   r   canvasZget_rendererr   r   Z	frombytesr   widthZheightgetvalue)r   r6   r   ZbufZrendererr   r   r   r7   8  s    
zPillowWriter.grab_framec             C   s2   | j d j| jd| j dd  td| j d d S )Nr   Tr   i  )Zsave_allZappend_imagesZduration)r   saver   r   rC   )r   r   r   r   r8   D  s    
zPillowWriter.finish)N)
r.   r/   r0   rs   r    r   r5   r7   r8   __classcell__r   r   )r   r   r   #  s
   
r   c                   s8   e Zd ZdZdZdZedd Ze fddZ	  Z
S )
FFMpegBasezMixin class for FFMpeg output.

    To be useful this must be multiply-inherited from with a
    `MovieWriterBase` sub-class.
    zanimation.ffmpeg_pathzanimation.ffmpeg_argsc             C   s   d| j g}| j dkr,d| jkr,|ddg | jdkrJ|dd| j g | jr\|| j x,| j D ]\}}|dd	||f g qhW |d
| jg S )Nz-vcodecrL   z-pix_fmtZyuv420pr   z-bz%dkz	-metadataz%s=%sz-y)rE   rH   extendrF   rI   r'   r4   )r   r9   kvr   r   r   output_argsV  s    

zFFMpegBase.output_argsc                s,   t   o*dtj|  gttjtjdjkS )Ns   LibAv)r[   rX   rY   )	r   r    r]   runrp   r`   ZDEVNULLr^   rY   )ro   )r   r   r   r    j  s    

zFFMpegBase.isAvailable)r.   r/   r0   r1   rn   rG   rr   r   rs   r    r   r   r   )r   r   r   L  s
   r   Zffmpegc               @   s   e Zd ZdZdd ZdS )FFMpegWriterzwPipe-based ffmpeg writer.

    Frames are streamed directly to ffmpeg via a pipe and written in a single
    pass.
    c             C   s\   |   dddddd| j d| jdt| jg}t tjkrF|dd	g7 }|d
dg| j	 7 }|S )Nz-fZrawvideoz-vcodecz-sz%dx%dz-pix_fmtz-rz	-loglevelquietz-izpipe:)
rp   rK   rD   rm   rC   rP   ZgetEffectiveLevelloggingDEBUGr   )r   r9   r   r   r   r\   }  s    zFFMpegWriter._argsN)r.   r/   r0   r1   r\   r   r   r   r   r   v  s   r   Zffmpeg_filec            	   @   s.   e Zd ZdZdddddddd	d
g	Zdd ZdS )FFMpegFileWriterz}File-based ffmpeg writer.

    Frames are written to temporary files on disk and then stitched
    together at the end.

    pngjpegppmtiffsgibmppbmrawrB   c             C   s,   |   dt| jd|  dt| jg| j S )Nz-rz-iz-vframes)rp   rm   rC   r~   rx   r   )r   r   r   r   r\     s    zFFMpegFileWriter._argsN)r.   r/   r0   r1   r}   r\   r   r   r   r   r     s   
r   c               @   s$   e Zd ZdZdZdZeejj	ZdS )
AVConvBasezMixin class for avconv output.

    To be useful this must be multiply-inherited from with a
    `MovieWriterBase` sub-class.
    zanimation.avconv_pathzanimation.avconv_argsN)
r.   r/   r0   r1   rn   rG   rs   r@   r    __func__r   r   r   r   r     s   r   Zavconvc               @   s   e Zd ZdZdS )AVConvWriterzwPipe-based avconv writer.

    Frames are streamed directly to avconv via a pipe and written in a single
    pass.
    N)r.   r/   r0   r1   r   r   r   r   r     s   r   Zavconv_filec               @   s   e Zd ZdZdS )AVConvFileWriterz|File-based avconv writer.

    Frames are written to temporary files on disk and then stitched
    together at the end.
    N)r.   r/   r0   r1   r   r   r   r   r     s   r   c                   sP   e Zd ZdZdZdZedd Zedd Ze	dd	 Z
e	 fd
dZ  ZS )ImageMagickBasezMixin class for ImageMagick output.

    To be useful this must be multiply-inherited from with a
    `MovieWriterBase` sub-class.
    zanimation.convert_pathzanimation.convert_argsc             C   s
   d| j  S )Ng      Y@)rC   )r   r   r   r   delay  s    zImageMagickBase.delayc             C   s   | j gS )N)r4   )r   r   r   r   r     s    zImageMagickBase.output_argsc          	   C   s   t jdkst| j dkrd S dd l}xhd|j|jfD ]V}y8||jdd|j	|B }|
|dd }|| P W q4 tk
r   d}Y q4X q4W |rx0dD ]$}tj||}tj|r|}P qW d}| t| j< t| j< d S )NZwin32convertr   zSoftware\Imagemagick\CurrentZBinPath )zconvert.exez
magick.exe)sysplatformr	   rn   winregZKEY_WOW64_32KEYZKEY_WOW64_64KEYZ	OpenKeyExHKEY_LOCAL_MACHINEZKEY_QUERY_VALUEZQueryValueExZCloseKeyr   r   pathjoinexistsr
   )ro   r   flaghkeyZbinpathZexer   r   r   r   _init_from_registry  s*    

z#ImageMagickBase._init_from_registryc                s"   |   }|dkr|   t  S )z
        Check to see if a ImageMagickWriter is actually available.

        Done by first checking the windows registry (if applicable) and then
        running the commandline tool.
        r   )rp   r   r   r    )ro   rp   )r   r   r   r      s    zImageMagickBase.isAvailable)r.   r/   r0   r1   rn   rG   rr   r   r   rs   r   r    r   r   r   )r   r   r     s   r   Zimagemagickc               @   s   e Zd ZdZdd ZdS )ImageMagickWriterz|Pipe-based animated gif.

    Frames are streamed directly to ImageMagick via a pipe and written
    in a single pass.

    c             C   s4   |   dd| j dddt| jddd| j g
| j S )	Nz-sizez%ix%iz-depth8z-delayz-loop0z%s:-)rp   rK   rm   r   rD   r   )r   r   r   r   r\   	  s
    
zImageMagickWriter._argsN)r.   r/   r0   r1   r\   r   r   r   r   r     s   r   Zimagemagick_filec            	   @   s.   e Zd ZdZdddddddd	d
g	Zdd ZdS )ImageMagickFileWriterzFile-based animated gif writer.

    Frames are written to temporary files on disk and then stitched
    together at the end.

    r   r   r   r   r   r   r   r   rB   c             C   s,   |   dt| jddd| j| jf g| j S )Nz-delayz-loopr   z%s*.%s)rp   rm   r   rw   rD   r   )r   r   r   r   r\   !  s    zImageMagickFileWriter._argsN)r.   r/   r0   r1   r}   r\   r   r   r   r   r     s   
r   c             C   s    t jt| tj| d |dS )z(frame_list should be a list of filenamesr   )Nframes	frame_dirrD   )r   r,   lenr   r   dirname)
frame_listrD   r   r   r   _included_frames)  s    
r   c                s&   ddd  fddt| D  S )z7frame_list should be a list of base64-encoded png filesz,  frames[{0}] = "data:image/{1};base64,{2}"

r   c          	   3   s(   | ] \}} | |d dV  qdS )r   z\
N)r,   replace)r   iZ
frame_data)rD   templater   r   	<genexpr>4  s   z#_embedded_frames.<locals>.<genexpr>)r   	enumerate)r   rD   r   )rD   r   r   _embedded_frames0  s    r   Zhtmlc                   s\   e Zd ZddddgZdZedd Zd fdd	Zd fdd	Z fddZ	dd Z
  ZS )
HTMLWriterr   r   r   Zsvgzanimation.html_argsc             C   s   dS )NTr   )ro   r   r   r   r    =  s    zHTMLWriter.isAvailable   NFloopc	       	         sj   || _ | | _|d kr$td | _n|| _|  jd9  _| jdkrRd| _td t ||||| d S )Nzanimation.embed_limiti   )r   onceZreflectr   z'unrecognized default_mode: using 'loop')	embed_frameslowerdefault_moder	   _bytes_limitrP   warningr   r   )	r   rC   rE   rF   rH   rI   r   r   embed_limit)r   r   r   r   A  s    


zHTMLWriter.__init__c                s   t j|\}}|dkr tdg | _d| _d| _| jsn|d krH|d }t j|s^t 	| t j
|d}nd }t j||||dd d S )N)z.htmlz.htmzoutfile must be *.htm or *.htmlr   Fr   frame)rv   )r   r   splitext
ValueError_saved_frames_total_bytes
_hit_limitr   r   makedirsr   r   r5   )r   r3   r4   r   r   rootZextr{   )r   r   r   r5   V  s    
zHTMLWriter.setupc                s   | j r| jrd S t }| jj|f| j| jd| t|	 
d}|  jt|7  _| j| jkrtd| j| j d| _q| j| nt jf |S d S )N)r,   r   asciizAnimation size has reached %s bytes, exceeding the limit of %s. If you're sure you want a larger animation embedded, set the animation.embed_limit rc parameter to a larger value (in MB). This and further frames will be dropped.T)r   r   r   r3   rd   rD   r   base64encodebytesr   r   r   r   r   rP   r   r   r   r   r7   )r   r6   fZ	imgdata64)r   r   r   r7   j  s    zHTMLWriter.grab_framec          
   C   s   G dd dt }| | _| jr8t| j| j}t| j}nt| j| j}t| j}t	dddd}d|| j
d < d| j }t| jd6}|t |tjf t j|||d	| W d Q R X d S )
Nc               @   s   e Zd ZdZdd ZdS )z'HTMLWriter._run.<locals>.ProcessStandinr   c             S   s   dS )N)r   r   r   )r   r   r   r   rg     s    z3HTMLWriter._run.<locals>.ProcessStandin.communicateN)r.   r/   r0   r   rg   r   r   r   r   ProcessStandin  s   r   r   )Zonce_checkedZloop_checkedZreflect_checkedcheckedZ_checkedi  r   )idr   fill_framesinterval)objectra   r   r   r   rD   r   r   ry   r   r   rC   r   r4   writer   r   r,   uuidZuuid4hex)r   r   r   r   Z	mode_dictr   Zofr   r   r   rV     s*    


zHTMLWriter._run)r   NNNNFr   N)N)r.   r/   r0   r}   rG   rs   r    r   r5   r7   rV   r   r   r   )r   r   r   8  s     r   c            	   @   s   e Zd ZdZd-ddZdd Zdd	 Zd.d
dZdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd/d&d'Zd0d)d*Zd+d, ZdS )1	Animationa"  This class wraps the creation of an animation using matplotlib.

    It is only a base class which should be subclassed to provide
    needed behavior.

    This class is not typically used directly.

    Parameters
    ----------
    fig : matplotlib.figure.Figure
       The figure object that is used to get draw, resize, and any
       other needed events.

    event_source : object, optional
       A class that can run a callback when desired events
       are generated, as well as be stopped and started.

       Examples include timers (see :class:`TimedAnimation`) and file
       system notifications.

    blit : bool, optional
       controls whether blitting is used to optimize drawing.  Defaults
       to ``False``.

    See Also
    --------
    FuncAnimation,  ArtistAnimation

    NFc             C   s\   || _ |o|jj| _|  | _|| _|jd| j| _	| j jd| j
| _| jrX|   d S )N
draw_eventZclose_event)r   r   Zsupports_blit_blitnew_frame_seq	frame_seqevent_sourcempl_connect_start_first_draw_id_stop	_close_id_setup_blit)r   r3   r   blitr   r   r   r     s    


zAnimation.__init__c             G   s:   | j j| j d| _|   | j| j | j  dS )z
        Starts interactive animation. Adds the draw frame command to the GUI
        handler, calls show to start the event loop.
        N)	r   r   mpl_disconnectr   
_init_drawr   add_callback_stepstart)r   r9   r   r   r   r     s
    zAnimation._startc             G   s>   | j r| jj| j | jj| j | j| j d | _d S )N)	r   r   r   r   
_resize_idr   r   remove_callbackr  )r   r9   r   r   r   r     s
    zAnimation._stopc          
      s  |dkrt d }n.t|ts@tdd |||||fD r@td|
dkrLi }
 jdk	rl jj j d}nd}|dkrt	 drd	 j
 }|dkrt d
 }|dkr jj}|dkrt d }|dkrt d } g}|	dk	r| fdd|	D  t|tr~|tjkr"t| |||||d}n\td|t d  y"tt d  |||||d}W n tk
r|   tdY nX tdt| d|
krtd |
d t  t d dkrtd dt d< | j||p x|D ]}|  qW xPtdd |D  D ]:}x&t||D ]\}}|j|dd q"W |jf |
 qW W dQ R X W dQ R X |r~ jjd j _dS )a
  
        Save the animation as a movie file by drawing every frame.

        Parameters
        ----------

        filename : str
            The output filename, e.g., :file:`mymovie.mp4`.

        writer : :class:`MovieWriter` or str, optional
            A `MovieWriter` instance to use or a key that identifies a
            class to use, such as 'ffmpeg'. If ``None``, defaults to
            :rc:`animation.writer` = 'ffmpeg'.

        fps : number, optional
           Frames per second in the movie. Defaults to ``None``, which will use
           the animation's specified interval to set the frames per second.

        dpi : number, optional
           Controls the dots per inch for the movie frames.  This combined with
           the figure's size in inches controls the size of the movie.  If
           ``None``, defaults to :rc:`savefig.dpi`.

        codec : str, optional
           The video codec to be used. Not all codecs are supported
           by a given :class:`MovieWriter`. If ``None``, default to
           :rc:`animation.codec` = 'h264'.

        bitrate : number, optional
           Specifies the number of bits used per second in the compressed
           movie, in kilobits per second. A higher number means a higher
           quality movie, but at the cost of increased file size. If ``None``,
           defaults to :rc:`animation.bitrate` = -1.

        extra_args : list, optional
           List of extra string arguments to be passed to the underlying movie
           utility. If ``None``, defaults to :rc:`animation.extra_args`.

        metadata : Dict[str, str], optional
           Dictionary of keys and values for metadata to include in
           the output file. Some keys that may be of use include:
           title, artist, genre, subject, copyright, srcform, comment.

        extra_anim : list, optional
           Additional `Animation` objects that should be included
           in the saved movie file. These need to be from the same
           `matplotlib.figure.Figure` instance. Also, animation frames will
           just be simply combined, so there should be a 1:1 correspondence
           between the frames from the different animations.

        savefig_kwargs : dict, optional
           Is a dictionary containing keyword arguments to be passed
           on to the `savefig` command which is called repeatedly to
           save the individual frames.

        Notes
        -----
        *fps*, *codec*, *bitrate*, *extra_args* and *metadata* are used to
        construct a `.MovieWriter` instance and can only be passed if
        *writer* is a string.  If they are passed as non-*None* and *writer*
        is a `.MovieWriter`, a `RuntimeError` will be raised.

        Nzanimation.writerc             s   s   | ]}|d k	V  qd S )Nr   )r   argr   r   r   r   =  s   z!Animation.save.<locals>.<genexpr>zPassing in values for arguments fps, codec, bitrate, extra_args, or metadata is not supported when writer is an existing MovieWriter instance. These should instead be passed as arguments when creating the MovieWriter instance.TF	_intervalg     @@zsavefig.dpifigurezanimation.codeczanimation.bitratec             3   s   | ]}|j  j kr|V  qd S )N)r   )r   anim)r   r   r   r   c  s   )rH   rI   z5MovieWriter {} unavailable. Trying to use {} instead.r   zZCannot save animation: no writers are available. Please install ffmpeg to save animations.zAnimation.save using %sZbbox_incheszWarning: discarding the 'bbox_inches' argument in 'savefig_kwargs' as it may cause frame size to vary, which is inappropriate for animation.zsavefig.bboxZtightzkDisabling savefig.bbox = 'tight', as it may cause frame size to vary, which is inappropriate for animation.c             S   s   g | ]}|  qS r   )new_saved_frame_seq)r   ar   r   r   r     s    z"Animation.save.<locals>.<listcomp>)r   r   ) r	   
isinstancerm   anyr*   r   r   r   r   hasattrr  r   r   writersr   rP   r   r,   r(   
IndexErrorr   rQ   typepopr   r;   r   zip_draw_next_framer7   r   r   )r   filenamewriterrC   r   rE   rF   rH   rI   Z
extra_animr6   Zreconnect_first_drawZall_animr  datadr   )r   r   r     sr    D










&
zAnimation.savec             G   s6   yt | j}| || j dS  tk
r0   dS X dS )z
        Handler for getting events. By default, gets the next frame in the
        sequence and hands the data off to be drawn.
        TFN)nextr   r  r   StopIteration)r   r9   	framedatar   r   r   r    s    
zAnimation._stepc             C   s
   t | jS )z+Return a new sequence of frame information.)iter
_framedata)r   r   r   r   r     s    zAnimation.new_frame_seqc             C   s   |   S )z8Return a new sequence of saved/cached frame information.)r   )r   r   r   r   r	    s    zAnimation.new_saved_frame_seqc             C   s&   |  || | | | || d S )N)	_pre_draw_draw_frame
_post_draw)r   r  r   r   r   r   r    s    
zAnimation._draw_next_framec             C   s   d S )Nr   )r   r   r   r   r     s    zAnimation._init_drawc             C   s   |r|  | j| j d S )N)_blit_clear_drawn_artists_blit_cache)r   r  r   r   r   r   r    s    zAnimation._pre_drawc             C   s   t dd S )NzDNeeds to be implemented by subclasses to actually make an animation.)rk   )r   r  r   r   r   r    s    zAnimation._draw_framec             C   s,   |r| j r| | j | j n| jj  d S )N)r!  
_blit_drawr"  r   r   	draw_idle)r   r  r   r   r   r   r    s    
zAnimation._post_drawc             C   sr   g }xF|D ]>}|j |kr0|jj|j j||j < |j | ||j  q
W x t|D ]}|jj|j qVW d S )N)	axesr  r   Zcopy_from_bboxZbboxZdraw_artistr   setr   )r   artistsbg_cacheZ
updated_axr
  Zaxr   r   r   r#    s    

zAnimation._blit_drawc             C   s:   dd |D }x&|D ]}||kr|j j||  qW d S )Nc             S   s   h | ]
}|j qS r   )r%  )r   r
  r   r   r   	<setcomp>  s    z(Animation._blit_clear.<locals>.<setcomp>)r  r   Zrestore_region)r   r'  r(  r%  r
  r   r   r   r     s    
zAnimation._blit_clearc             C   s4   t  | _g | _| jjd| j| _| d | j	 d S )Nresize_event)
r   r"  r!  r   r   r   _handle_resizer  r  r   )r   r   r   r   r     s
    

zAnimation._setup_blitc             G   sD   | j j| j | j  | j  |   | j j	d| j
| _d S )Nr   )r   r   r   r  r   stopr"  clearr   r   _end_redraw)r   r9   r   r   r   r+    s    


zAnimation._handle_resizec             C   s>   |  d d | j  | jj| j | jjd| j| _d S )NFr*  )	r  r   r  r   r   r   r  r   r+  )r   Zevtr   r   r   r.    s
    

zAnimation._end_redrawc       
   	   C   s  d}t | ds|dkrtd }|d9 }t T}t|d}ttd  }|dtd	 d
| j d}| jt||d t	|
 }W dQ R X t|}||krtd|| n|d| _dj|j | _t | drddg}	t | dr| jr|	d |j| j| jd|	dS dS dS )a  
        Convert the animation to an HTML5 ``<video>`` tag.

        This saves the animation as an h264 video, encoded in base64
        directly into the HTML5 video tag. This respects the rc parameters
        for the writer as well as the bitrate. This also makes use of the
        ``interval`` to control the speed, and uses the ``repeat``
        parameter to decide whether to loop.

        Parameters
        ----------
        embed_limit : float, optional
            Limit, in MB, of the returned animation. No animation is created
            if the limit is exceeded.
            Defaults to :rc:`animation.embed_limit` = 20.0.

        Returns
        -------
        video_tag : str
            An HTML5 video tag with the animation embedded as base64 encoded
            h264 video.
            If the *embed_limit* is exceeded, this returns the string
            "Video too large to embed."
        z<video {size} {options}>
  <source type="video/mp4" src="data:video/mp4;base64,{video}">
  Your browser does not support the video tag.
</video>_base64_videoNzanimation.embed_limiti   ztemp.m4vzanimation.writerrL   zanimation.bitrateg     @@)rE   rF   rC   )r  zAnimation movie is %s bytes, exceeding the limit of %s. If you're sure you want a large animation embedded, set the animation.embed_limit rc parameter to a larger value (in MB).r   zwidth="{}" height="{}"ZcontrolsZautoplayrepeatr    )ZvideosizeoptionszVideo too large to embed.)r  r	   r   r   r  r  r   rm   r   r   Z
read_bytesr   rP   r   r   r/  r,   rK   Z_video_sizer0  r   r   )
r   r   Z	VIDEO_TAGtmpdirr   Writerr  Zvid64Zvid_lenr3  r   r   r   to_html5_video  s:    




zAnimation.to_html5_videoTc          	   C   s   |dkrt | drd| j }|dkr2| jr.dnd}t | dst :}t|d}t|||d}| jt||d	 | | _	W dQ R X | j	S )
z-Generate HTML representation of the animationNr  i  r   r   _html_representationz	temp.html)rC   r   r   )r  )
r  r  r0  r   r   r   r   rm   Z	read_textr7  )r   rC   r   r   r4  r   r  r   r   r   	to_jshtml^  s    


zAnimation.to_jshtmlc             C   s,   t d }|dkr|  S |dkr(|  S dS )z#IPython display hook for rendering.zanimation.htmlZhtml5ZjshtmlN)r	   r6  r8  )r   Zfmtr   r   r   _repr_html_v  s
    zAnimation._repr_html_)NF)	NNNNNNNNN)N)NTN)r.   r/   r0   r1   r   r   r   r   r  r   r	  r  r   r  r  r  r#  r   r   r+  r.  r6  r8  r9  r   r   r   r   r     s0   
  
 &
			
O
r   c               @   s2   e Zd ZdZdddZdd Zd	d
 Zdd ZdS )TimedAnimationa1  :class:`Animation` subclass for time-based animation.

    A new frame is drawn every *interval* milliseconds.

    Parameters
    ----------
    fig : matplotlib.figure.Figure
       The figure object that is used to get draw, resize, and any
       other needed events.

    interval : number, optional
       Delay between frames in milliseconds.  Defaults to 200.

    repeat_delay : number, optional
        If the animation in repeated, adds a delay in milliseconds
        before repeating the animation.  Defaults to ``None``.

    repeat : bool, optional
        Controls whether the animation should repeat when the sequence
        of frames is completed.  Defaults to ``True``.

    blit : bool, optional
        Controls whether blitting is used to optimize drawing.  Defaults
        to ``False``.

       NTc             O   sL   || _ || _|| _|d kr,|j }| j |_tj| |f|d|i| d S )Nr   )r  _repeat_delayr0  r   Z	new_timerr   r   r   )r   r3   r   Zrepeat_delayr0  r   r9   r:   r   r   r   r     s    

zTimedAnimation.__init__c             G   sv   t j| f| }|sn| jrn|   |  | _| jr\| j| j | j	| j
 | j| j_dS t j| f| S n|S dS )z-
        Handler for getting events.
        TN)r   r  r0  r   r   r   r<  r   r  r   _loop_delayr   )r   r9   Zstill_goingr   r   r   r    s    



zTimedAnimation._stepc             G   s   | j | j t|  d S )N)r   r  r=  r   r   )r   r9   r   r   r   r     s    zTimedAnimation._stopc             G   s4   | j | j | j| j _| j | j t|  d S )N)r   r  r=  r  r   r   r  r   )r   r9   r   r   r   r=    s    
zTimedAnimation._loop_delay)r;  NTN)r.   r/   r0   r1   r   r  r   r=  r   r   r   r   r:    s    
r:  c               @   s0   e Zd ZdZdd Zdd Zdd Zdd	 Zd
S )ArtistAnimationa  Animation using a fixed set of `Artist` objects.

    Before creating an instance, all plotting should have taken place
    and the relevant artists saved.

    Parameters
    ----------
    fig : matplotlib.figure.Figure
       The figure object that is used to get draw, resize, and any
       other needed events.

    artists : list
        Each list entry a collection of artists that represent what
        needs to be enabled on each frame. These will be disabled for
        other frames.

    interval : number, optional
       Delay between frames in milliseconds.  Defaults to 200.

    repeat_delay : number, optional
        If the animation in repeated, adds a delay in milliseconds
        before repeating the animation.  Defaults to ``None``.

    repeat : bool, optional
        Controls whether the animation should repeat when the sequence
        of frames is completed. Defaults to ``True``.

    blit : bool, optional
        Controls whether blitting is used to optimize drawing.  Defaults
        to ``False``.

    c             O   s$   g | _ || _tj| |f|| d S )N)r!  r  r:  r   )r   r3   r'  r9   r:   r   r   r   r     s    zArtistAnimation.__init__c             C   sr   t  }xN|  D ]B}x<|D ]4}|d || j | |kr||  qW qW x|D ]}|j  q\W d S )NF)	r&  r   set_visibleset_animatedr   Z
get_figureaddr   r$  )r   Zfigsr   artistr3   r   r   r   r     s    


zArtistAnimation._init_drawc             C   s4   |r|  | j| j nx| jD ]}|d qW dS )z5
        Clears artists from the last frame.
        FN)r   r!  r"  r?  )r   r  r   rB  r   r   r   r  
  s    zArtistAnimation._pre_drawc             C   s"   || _ x|D ]}|d qW d S )NT)r!  r?  )r   r'  rB  r   r   r   r    s    
zArtistAnimation._draw_frameN)r.   r/   r0   r1   r   r   r  r  r   r   r   r   r>    s
    	r>  c               @   s:   e Zd ZdZdddZdd Zdd Zd	d
 Zdd ZdS )FuncAnimationa  
    Makes an animation by repeatedly calling a function *func*.

    Parameters
    ----------
    fig : matplotlib.figure.Figure
       The figure object that is used to get draw, resize, and any
       other needed events.

    func : callable
       The function to call at each frame.  The first argument will
       be the next value in *frames*.   Any additional positional
       arguments can be supplied via the *fargs* parameter.

       The required signature is::

          def func(frame, *fargs) -> iterable_of_artists

       If ``blit == True``, *func* must return an iterable of all artists
       that were modified or created. This information is used by the blitting
       algorithm to determine which parts of the figure have to be updated.
       The return value is unused if ``blit == False`` and may be omitted in
       that case.

    frames : iterable, int, generator function, or None, optional
        Source of data to pass *func* and each frame of the animation

        - If an iterable, then simply use the values provided.  If the
          iterable has a length, it will override the *save_count* kwarg.

        - If an integer, then equivalent to passing ``range(frames)``

        - If a generator function, then must have the signature::

             def gen_function() -> obj

        - If *None*, then equivalent to passing ``itertools.count``.

        In all of these cases, the values in *frames* is simply passed through
        to the user-supplied *func* and thus can be of any type.

    init_func : callable, optional
       A function used to draw a clear frame. If not given, the
       results of drawing from the first item in the frames sequence
       will be used. This function will be called once before the
       first frame.

       The required signature is::

          def init_func() -> iterable_of_artists

       If ``blit == True``, *init_func* must return an iterable of artists
       to be re-drawn. This information is used by the blitting
       algorithm to determine which parts of the figure have to be updated.
       The return value is unused if ``blit == False`` and may be omitted in
       that case.

    fargs : tuple or None, optional
       Additional arguments to pass to each call to *func*.

    save_count : int, optional
       The number of values from *frames* to cache.

    interval : number, optional
       Delay between frames in milliseconds.  Defaults to 200.

    repeat_delay : number, optional
       If the animation in repeated, adds a delay in milliseconds
       before repeating the animation.  Defaults to *None*.

    repeat : bool, optional
       Controls whether the animation should repeat when the sequence
       of frames is completed.  Defaults to *True*.

    blit : bool, optional
       Controls whether blitting is used to optimize drawing. Note: when using
       blitting any animated artists will be drawn according to their zorder.
       However, they will be drawn on top of any previous artists, regardless
       of their zorder.  Defaults to *False*.
    Nc                s   |r|| _ nd| _ || _|| _ d kr0tj| _nRt r@ | _nBt rn fdd| _t	 drt
 | _n fdd| _ | _| jd krd| _nt| j| _|| _g | _tj| |f| g | _d S )Nr   c                  s   t  S )N)r  r   )framesr   r   <lambda>  s    z(FuncAnimation.__init__.<locals>.<lambda>__len__c                  s   t t S )N)r  ranger   )rD  r   r   rE    s    d   )r\   _func
save_count	itertoolscount	_iter_gencallabler   iterabler  r   r   
_init_func	_save_seqr:  r   )r   r3   funcrD  Z	init_funcZfargsrJ  r:   r   )rD  r   r   r  s,    



zFuncAnimation.__init__c             C   s   |   S )N)rM  )r   r   r   r   r     s    zFuncAnimation.new_frame_seqc                sV   | j rt| j | _t| jS | jd k	r8t|  | jS |    fdd}| S d S )Nc              3   sF   y xt dD ]} t V  qW W n tk
r4   Y nX tdd d S )NrH  z2.2zFuncAnimation.save has truncated your animation to 100 frames.  In the future, no such truncation will occur; please pass 'save_count' accordingly.)rG  r  r  r   Zwarn_deprecated)_)r   r   r   gen  s    z.FuncAnimation.new_saved_frame_seq.<locals>.gen)rQ  r(   Z_old_saved_seqr  rJ  rK  islicer   )r   rT  r   )r   r   r	    s    

z!FuncAnimation.new_saved_frame_seqc             C   sf   | j d kr| t|   n>|   | _| jr\| jd kr@tdx| jD ]}|| j qHW g | _d S )Nz7The init_func must return a sequence of Artist objects.)	rP  r  r  r   r!  r   r*   r@  rQ  )r   r
  r   r   r   r     s    


zFuncAnimation._init_drawc             C   s   | j | | j | j d  | _ | j|f| j | _| jr|| jd krLtdt| jdd d| _x| jD ]}|	| j qhW d S )Nz@The animation function must return a sequence of Artist objects.c             S   s   |   S )N)Z
get_zorder)r   r   r   r   rE    s    z+FuncAnimation._draw_frame.<locals>.<lambda>)key)
rQ  r   rJ  rI  r\   r!  r   r*   sortedr@  )r   r  r
  r   r   r   r    s    
zFuncAnimation._draw_frame)NNNN)	r.   r/   r0   r1   r   r   r	  r   r  r   r   r   r   rC     s   P 
0rC  )<r<   r   r>   ior   rK  r   r   Zpathlibr   r   rq   r]   r   Ztempfiler   r   Znumpyr   Zmatplotlib._animation_datar   r   r   Z
matplotlibr   r	   r
   r   Z	getLoggerr.   rP   systemr`   ZCREATE_NO_WINDOWr   r   r   r  ABCr2   r@   rt   r$   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r:  r>  rC  r   r   r   r   <module>   sp   

$FA 7 (*


	
	=

m   \RO