rL iddlZddlZddlZddlmZmZddlZddlZddlm Z ddl Z ddl Z ddl Z ddl mZddlZddlZddlZddlmZddlZddlmZmZmZmZddlmZmZddlmZ ejBe"Z#e jHdk(r e jJndZ&d Z'Gd d Z(e(Z)Gd d ejTZ+Gdde+Z,Gdde,Z-e)j]dGdde+Z/GddZ0e)j]dGdde0e,Z1e)j]dGdde0e-Z2GddZ3e)j]dGd d!e3e,Z4e)j]d"Gd#d$e3e-Z5d%Z6d&Z7e)j]d'Gd(d)e-Z8Gd*d+Z9Gd,d-e9Z:Gd.d/e:Z;Gd0d1e:Z.correct_roundoff7s qu:>Q 2<<266*3./!3q8LLBFF+R\\!bffW-c12Q6!;LLRVVG,)r)whrrrwnewhnews radjusted_figsizer s_. q3w{ a # %D q3w{ a # %D D#q )+;D#q+I IIrc4eZdZdZdZdZdZdZdZdZ y) MovieWriterRegistryz.wrapperTs%/D  T " r)r'r,r-s`` rregisterzMovieWriterRegistry.registerJs rc` |j|}|jS#t$rYywxYw)z Check if given writer is available by name. Parameters ---------- name : str Returns ------- bool F)r%KeyError isAvailable)r'r,clss r is_availablez MovieWriterRegistry.is_availableYs: ""4(C    s ! --c#ZK|jD]}|j|s|yw)z-Iterate over names of available writer class.N)r%r4r'r,s r__iter__zMovieWriterRegistry.__iter__ks.$$ D  &  s!++c g|S)z%Get a list of available MovieWriters.r.r&s rlistzMovieWriterRegistry.listqs wrc`|j|r|j|Std|d)z,Get an available writer class from its name.zRequested MovieWriter (z) not available)r4r% RuntimeErrorr6s r __getitem__zMovieWriterRegistry.__getitem__us6   T "##D) )4TF/JKKrN) __name__ __module__ __qualname____doc__r(r/r4r7r9r<r.rrr!r!Ds$F" !$ Lrr!ceZdZdZd dZej d dZedZ dZ ej dZ ej dZ e jd Zy) AbstractMovieWritera Abstract base class for writing movies, providing a way to grab frames by calling `~AbstractMovieWriter.grab_frame`. `setup` is called to start the process and `finish` is called afterwards. `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||_||ni|_tj|d|_tj|d|_y)Nzanimation.codecanimation.bitrate)fpsmetadatampl _val_or_rccodecbitrate)r'rErFrIrJs rr(zAbstractMovieWriter.__init__s=$,$8b ^^E+<= ~~g/BC rct|jjd||_||_||jj }||_y)a Setup for writing the movie file. Parameters ---------- fig : `~matplotlib.figure.Figure` The figure object that contains the information for frames. outfile : str The filename of the resulting movie file. dpi : float, default: ``fig.dpi`` The DPI (or resolution) for the file. This controls the size in pixels of the resulting movie file. TstrictN)rparentresolveoutfilefigr)r'rQrPrs rsetupzAbstractMovieWriter.setupsF W $$D$1  ;((,,Crc|jj\}}t||jzt||jzfS)z7A tuple ``(width, height)`` in pixels of a movie frame.)rQget_size_inchesrr)r'rrs r frame_sizezAbstractMovieWriter.frame_sizes?xx'')11txx< #a$((l"333rcy)z Whether this writer supports transparency. Writers may consult output file type and codec to determine this at runtime. Fr.r&s r_supports_transparencyz*AbstractMovieWriter._supports_transparencys rc y)a= Grab the image information from the figure and save as a movie frame. All keyword arguments in *savefig_kwargs* are passed on to the `~.Figure.savefig` call that saves the figure. However, several keyword arguments that are supported by `~.Figure.savefig` may not be passed as they are controlled by the MovieWriter: - *dpi*, *bbox_inches*: These may not be passed because each frame of the animation much be exactly the same size in pixels. - *format*: This is controlled by the MovieWriter. Nr.r'savefig_kwargss r grab_framezAbstractMovieWriter.grab_framercy),Finish any processing for writing the movie.Nr.r&s rfinishzAbstractMovieWriter.finishr\rc/@Ktjddk(rtjd|j|||g|i|tj ddi5 ||j  dddy#|j wxYw#1swYyxYww)z Context manager to facilitate writing the movie file. ``*args, **kw`` are any parameters that should be passed to `setup`. savefig.bboxtightzkDisabling savefig.bbox = 'tight', as it may cause frame size to vary, which is inappropriate for animation.N)rGrcParams_loginforR rc_contextr_)r'rQrPrargskwargss rsavingzAbstractMovieWriter.savings << '7 2 II# $  36t6v6 ^^^T2 3         s6ABBA=#B4 B=BBBB)NNNr#)r=r>r?r@r(abcabstractmethodrRpropertyrUrWr[r_ contextlibcontextmanagerrir.rrrBrBs$D  ,44       ;;rrBcxeZdZdZdgZ d fd ZdZd fd ZdZdZ dZ d Z e d Z e d ZxZS) MovieWritera Base class for writing movies. This is a base class for MovieWriter subclasses that write a movie frame data to a pipe. You cannot instantiate this class directly. See examples for how to use its subclasses. 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 subclasses. rgbact|tur tdt||||||j d|_||_y)a@ Parameters ---------- fps : int, default: 5 Movie frame rate (per second). codec : str or None, default: :rc:`animation.codec` The codec to use. bitrate : int, default: :rc:`animation.bitrate` The bitrate of the movie, in kilobits per second. Higher values means higher quality movies, but increase the file size. A value of -1 lets the underlying movie encoder select the bitrate. extra_args : list of str or None, optional Extra command-line arguments passed to the underlying movie encoder. These arguments are passed last to the encoder, just before the filename. The default, None, means to use :rc:`animation.[name-of-encoder]_args` for the builtin writers. metadata : dict[str, str], default: {} 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. zNMovieWriter cannot be instantiated directly. Please use one of its subclasses.)rErFrIrJrN)typerq TypeErrorsuperr(supported_formats frame_format extra_args)r'rErIrJryrF __class__s rr(zMovieWriter.__init__s\. : $ %& & S85!(  * 2215$rc|jdk(ry|jj\}}t|||jd\}}||f||fk7rU|jj ||dt jd||||n|jj\}}t jdg|j||fS)Nh264T)forwardz?figure size in inches has been adjusted from %s x %s to %s x %szframe size in pixels is %s x %s) rIrQrTrrset_size_inchesrdredebugrU)r'wohorrs r_adjust_frame_sizezMovieWriter._adjust_frame_size%s :: XX--/FB#BDHHa8DAqBxAq6!((At(< 457QC88++-DAq 4GtG!t rct|||||j\|_|_|j yN)r)rvrRr_w_h_runr'rQrPrrzs rrRzMovieWriter.setup2s7  c7 ,224 rc|j}tjdtj|t j }t j||||t|_ y)Nz%MovieWriter._run: running command: %s)stdinstdoutstderr creationflags) _argsrdrer _pformat_subprocess subprocessPIPEPopensubprocess_creation_flags_proc)r'commandrs rrzMovieWriter._run:sS**, 9++G4 6%% 4T35 rc|jj\}}tt|j }tt|j }|rKt j |jjrtjntjd||rKt j |jjrtjntjd||jjr@tj|jj|jj||y)r^zMovieWriter stdout: %szMovieWriter stderr: %sN)r communicaterrreadrdlog returncodeloggingWARNINGDEBUGrCalledProcessErrorrg)r'outerrs rr_zMovieWriter.finishFs::))+SGCL)..0GCL)..0  HH#'::#8#8gmm)3 0  HH#'::#8#8gmm)3 0 :: // %%tzzSB B !rc 4t|tjd|jj |j |j |jj|jjf|j|jd|y)Nz'MovieWriter.grab_frame: Grabbing frame.formatr) _validate_grabframe_kwargsrdrrQrrrsavefigrrrxrrYs rr[zMovieWriter.grab_frameXsq">2 <=   $''2)) 9$2C2C!XX 9)7 9rctdS)z9Assemble list of encoder-specific command-line arguments.z)args needs to be implemented by subclass.NotImplementedErrorr&s rrzMovieWriter._argscs"#NOOrcNttj|jS)z Return 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. )strrGrc _exec_keyr3s rbin_pathzMovieWriter.bin_pathgs3<< .//rcLtj|jduS)zr?r@rwr(rrRrr_r[r classmethodrr2 __classcell__rzs@rrqrqsf0 CG#%J  5B$ 9P0088rrqczeZdZdZfdZd dZdZedZejdZdZ dZ fd Z xZ S) FileMovieWriterz} `MovieWriter` for writing to individual files and stitching at the end. This must be sub-classed to be useful. cTt||i|tjd|_y)Nzanimation.frame_format)rvr(rGrcrx)r'rgrhrzs rr(zFileMovieWriter.__init__|s' $)&)LL)ABrct|jjd||_||_||jj }||_|j |>t|_tt|jjd|_ nd|_||_ d|_ t|_d|_y)a 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 : float, default: ``fig.dpi`` The dpi of the output file. This, with the figure size, controls the size in pixels of the resulting movie file. frame_prefix : str, optional The filename prefix to use for temporary files. If *None* (the default), files are written to a temporary directory which is deleted by `finish`; if not *None*, no temporary files are deleted. TrLNtmprz %s%%07d.%s)rrNrOrQrPrrr_tmpdirrr, temp_prefix_frame_counterr9 _temp_pathsfname_format_str)r'rQrPr frame_prefixs rrRzFileMovieWriter.setups( W $$D$1 ;((,,C !  -/DL"4 (9(95#ABD DL+D 6 ,rclt|dr(|jr|jjyyy)Nr)hasattrrcleanupr&s r__del__zFileMovieWriter.__del__s* 4 # LL ")5 #rc|jS)z Format (png, jpeg, etc.) to use for saving the frames, which can be decided by the individual subclasses. ) _frame_formatr&s rrxzFileMovieWriter.frame_formats !!!rc ||jvr||_ytjd|dt |j d|jdd|jd|_y)NzIgnoring file format z which is not supported by z; using rz instead.)rwrr warn_externalrtr=)r'rxs rrxzFileMovieWriter.frame_formatsr 411 1!-D    ' '78 $T 3 34H))!,-Y8 9"&!7!7!:D rcL|j|j|jfzSr#)rrrxr&s r_base_temp_namezFileMovieWriter._base_temp_names&$$(8(8$:K:K'LLLrc t|t|j|jz}|jj ||xjdz c_t jd|j|t|d5}|jj|f|j|jd|dddy#1swYyxYw)Nz8FileMovieWriter.grab_frame: Grabbing frame %d to path=%swbr) rrrrrappendrdropenrQrrxr)r'rZpathsinks rr[zFileMovieWriter.grab_frames #>2D((*T-@-@@A % q  M&& . $  / DHH  T /$*;*; /- / / / /s 5C  Ccj |jt| |jr;tj d|j|jj yy#|jr;tj d|j|jj wwxYw)N'MovieWriter: clearing temporary path=%s)rrvr_rrdrr)r'rzs rr_zFileMovieWriter.finishs ' IIK GN || =t|| $$& t|| =t|| $$& s A))A B2NN)r=r>r?r@r(rRrrmrxsetterrr[r_rrs@rrrvs\ C$-L#"";;M / ' 'rrpillowcBeZdZdZedZdfd ZdZdZxZ S) PillowWritercyNTr.r&s rrWz#PillowWriter._supports_transparencysrcyrr.rs rr2zPillowWriter.isAvailablerc8t||||g|_yr)rvrR_framesrs rrRzPillowWriter.setups  c7 , rc t|t}|jj|fii|d|jdt j d|j|jdddd}|jdddkr|jj|y|jj|jd y) NrrrRGBArawrrRGB) rrrQrrr frombufferrU getbuffer getextremarrconvert)r'rZbufims rr[zPillowWriter.grab_frames">2i  JHnHtxxH J    DOOS]]_eVQK ==?1 a 3 & LL   # LL   5 1 2rc |jdj|jd|jddtd|jz dy)NrTr)save_all append_imagesdurationloop)rsaverPrrEr&s rr_zPillowWriter.finishsE Q LL4t||AB7G)  3rr#) r=r>r?rWrr2rRr[r_rrs@rrrs+ 33rrc.eZdZdZdZdZdZedZy) FFMpegBasez Mixin class for FFMpeg output. This is a base class for the concrete `FFMpegWriter` and `FFMpegFileWriter` classes. zanimation.ffmpeg_pathzanimation.ffmpeg_argscft|jj}|dvry|jdvS)N.gif.apng.avif.webm.webpT>bmpdpxgifpngapngavrpcfhdffv1tiffv408ljpegqtrletargaproresffvhuffhuffyuvutvideojpeg2000rawvideo prores_aw prores_ks)rrPsuffixrIr'rs rrWz!FFMpegBase._supports_transparency s:dll#** A A zz>> >rcg}t|jj}|dvr |dd|_n|j d|jg|j |j nt j|j}|jdk(rd|vr|j ddgnM|jdk(rd|vr|j dd gn&|jd k(rd|vr|j gd |jd kDr |j d d|jzg|jjD]\}}|j d|d|g|j ||d|jgzS)Nrr-vcodecr|-pix_fmtyuv420pr-filter_complexz1split [a][b];[a] palettegen [p];[b][p] paletteuseavif)rz.split [rgb][rgba]; [rgba] alphaextract [alpha]-mapz[rgb]rz[alpha]rz-bz%dkz -metadata=z-y) rrPrrIextendryrGrc _args_keyrJrFitems)r'rgrrykvs r output_argszFFMpegBase.output_argssjdll#** A ADJ KKDJJ/ 0)-)Ddoo<<7  :: Jj$@ KKY/ 0ZZ5 %6j%H KK*LN OZZ6 !&7z&I KK= > <r?r@rrrWrmrr.rrrrs,(I'I > + +rrffmpegceZdZdZdZy) FFMpegWriterat Pipe-based ffmpeg writer. Frames are streamed directly to ffmpeg via a pipe and written in a single pass. This effectively works as a slideshow input to ffmpeg with the fps passed as ``-framerate``, so see also `their notes on frame rates`_ for further details. .. _their notes on frame rates: https://trac.ffmpeg.org/wiki/Slideshow#Framerates c |jdddddd|jzd|jdt|jg }t j tjkDr|dd gz }|d d g|jzz }|S) N-fr rz-s%dx%dr -framerate -loglevelerror-izpipe:) rrUrxrrErdgetEffectiveLevelrrrr'rgs rrzFFMpegWriter._argsKs z9jg/T=N=Nc$((m-  ! ! #gmm 3 ['* *D w$"2"222 rN)r=r>r?r@rr.rrr!r!?s   rr! ffmpeg_fileceZdZdZgdZdZy)FFMpegFileWriteray File-based ffmpeg writer. Frames are written to temporary files on disk and then stitched together at the end. This effectively works as a slideshow input to ffmpeg with the fps passed as ``-framerate``, so see also `their notes on frame rates`_ for further details. .. _their notes on frame rates: https://trac.ffmpeg.org/wiki/Slideshow#Framerates rjpegrrrrc g}|jdvr|dddddd|jzdd gz }|d t|jd |j gz }|j s|d t|j gz }tjtjkDr|d dgz }|jg||jS)N>rrrr#image2rr z -video_sizer$z -pixel_formatrrr%r(z -frames:vr&r') rxrUrrErrrrdr)rrrrr*s rrzFFMpegFileWriter._argsis    / h :w8 D s488}dD4H4H4JKK|| [#d&9&9":; ;D  ! ! #gmm 3 ['* *D :$:)9)9::rN)r=r>r?r@rwrr.rrr-r-[s ?;rr-cTeZdZdZdZdZdZdZefdZ efdZ xZ S)ImageMagickBasea Mixin class for ImageMagick output. This is a base class for the concrete `ImageMagickWriter` and `ImageMagickFileWriter` classes, which define an ``input_names`` attribute (or property) specifying the input names passed to ImageMagick. zanimation.convert_pathzanimation.convert_argscHt|jj}|dvS)Nr)rrPrrs rrWz&ImageMagickBase._supports_transparencys"dll#**EEErc Z|jdk(rdn |j}|j |jntj|j}|j dd|j zdddtd|jz d d |d |jg ||jS) Nrrrz-sizez%ix%iz-depth8z-delaydz-loop0:) rxryrGrcrrrUrrE input_namesrP)r'fmtrys rrzImageMagickBase._argss))U2f8I8I)-)Ddoo<<7  MMO Wt. c c#.) Se1T%%& '     LL  rclt|}|dk(rtjdj}|S)Nrmagick)rvrrG_get_executable_info executable)r3binpathrzs rrzImageMagickBase.bin_paths3'"$ i ..x8CCGrc t|S#tj$r }tj d|Yd}~yd}~wwxYw)Nz"ImageMagick unavailable due to: %sF)rvr2rGExecutableNotFoundErrorrdr)r3_enfrzs rr2zImageMagickBase.isAvailables> 7&( (**  JJ;T B s A?A) r=r>r?r@rrrWrrrr2rrs@rr3r3sG)I(IF  rr3 imagemagickceZdZdZdZy)ImageMagickWriterz Pipe-based animated gif writer. Frames are streamed directly to ImageMagick via a pipe and written in a single pass. -N)r=r>r?r@r:r.rrrFrFsKrrFimagemagick_filec*eZdZdZgdZedZy)ImageMagickFileWriterz File-based animated gif writer. Frames are written to temporary files on disk and then stitched together at the end. r.c8|jd|jS)Nz*.)rrxr&s rzImageMagickFileWriter.s(()D,=,=+>?rN)r=r>r?r@rwrmr:r.rrrJrJs??AKrrJc2tj|||S)N)Nframes frame_dirrx)r r) frame_countrxrOs r_included_framesrQs  ! !+,5/; ==rcfdk(rddddjfdt|DzS)z7frame_list should be a list of base64-encoded png filessvgzsvg+xmlz, frames[{0}] = "data:image/{1};base64,{2}"  c 3jK|]*\}}j||jdd,yw)rTz\ N)rreplace).0i frame_datarxtemplates r z#_embedded_frames..s74 Az <););D&)IJ4s03)join enumerate) frame_listrxr[s `@r_embedded_framesr`s?u >H "''4&z244 44rhtmlc^eZdZdZgdZedZ dfd Zd fd ZfdZ dZ xZ S) HTMLWriterz(Writer for JavaScript-based HTML movies.)rr/rrScyrr.rs rr2zHTMLWriter.isAvailablerrc <|rtjdd}||_|j|_t j gd|jtj|d|_ |xjdzc_ t |-|||||y)NzHTMLWriter ignores 'extra_args'r.)roncereflect) default_modeanimation.embed_limit) rdwarning embed_frameslowerrhr check_in_listrGrH _bytes_limitrvr() r'rErIrJryrFrlrh embed_limitrzs rr(zHTMLWriter.__init__s  LL: ; ((..0 6(,(9(9 ; NN;8OP [( eWj(CrcLt|}tjddg|jg|_d|_d|_|js9||j|jdz}|jdd|d z }nd}t|1||||d|_ y) Nz.htmlz.htm)outfile_extensionrFrT)parentsexist_okframe)rr rnr _saved_frames _total_bytes _hit_limitrl with_namestemmkdirrvrR _clear_temp)r'rQrPrrOrrzs rrRzHTMLWriter.setupsw- GV,O   #--gllY.FG OOD4O 8$w.LL  c7C6 rc Xt||jr|jryt}|jj |f|j |jd|tj|jjd}|xjt|z c_ |j|jk\r3tj!d|j|jd|_y|j"j%|yt'|Pdi|S)NrasciizAnimation 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.Tr.)rrlrxrrQrrxrbase64 encodebytesgetvaluedecoderwlenrordrkrvrrvr[)r'rZf imgdata64rzs rr[zHTMLWriter.grab_frames">2    A DHH  Q =t'8'8!% =-; =**1::<8??HI   Y /   D$5$55 !% 1 143D3D F #'"")))47%77 7rc X|jr6t|j|j}t |j}nft |j }t ||j|j djj|jj}tddd}d||jdz<d|jz}t|jd5}|jtt z|jt#j$d t'j(j*|||d|ddd|j,r;t.j1d |j,|j,j3yy#1swYQxYw) NrrU) once_checked loop_checkedreflect_checkedchecked_checkedrr)idrN fill_framesintervalrr.)rlr`rvrxrrrQrN relative_torPr$rhrErwriter r rruuiduuid4hexrrdrr)r'rrP mode_dictrofs rr_zHTMLWriter.finish(sg   *4+=+=+/+<+<>Kd001Kd../K*T..  #**66t||7J7JKMKb&()+- 5> $##j01488# $,, $ ; HHZ-/ 0 HH%,,: 0@0@5@9D6>:09 : ; ; << JJ@$,, O LL "  ; ;s .A"F  F))NNNNFrNr) r=r>r?r@rwrr2r(rRr[r_rrs@rrcrcs@26EIAG!D&!&80"#rrcceZdZdZddZdZdZdZ ddddZd Z d Z d Z d Z d Z dZdZdZdZdZdZdZdZddZddZdZdZdZy) Animationa A base class for Animations. This class is not usable as is, and should be subclassed to provide needed behavior. .. note:: You must store the created Animation in a variable that lives as long as the animation should run. Otherwise, the Animation object will be garbage-collected and the animation stops. Parameters ---------- fig : `~matplotlib.figure.Figure` The figure object used to get needed events, such as draw or resize. 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 `TimedAnimation`) and file system notifications. blit : bool, default: False Whether blitting is used to optimize drawing. If the backend does not support blitting, then this parameter has no effect. See Also -------- FuncAnimation, ArtistAnimation Ncd|_||_|xr|jj|_|j |_||_|jjd|j|_ |jjjd|j|_ |jr|jyy)NF draw_event close_event)_draw_was_started_figcanvas supports_blit_blit new_frame_seq frame_seq event_source mpl_connect_start_first_draw_id_stop _close_id _setup_blit)r'rQrblits rr(zAnimation.__init__os!& 6cjj66 ++-("jj44\4;;O))55m6:jjB ::     rcJt|ddstjdyy)NrTzAnimation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. `anim`, that exists until you output the Animation using `plt.show()` or `anim.save()`.)getattrwarningswarnr&s rrzAnimation.__del__s%t0$7 MM! 8rcJ|jjjry|jjj|j|j |j j|j|j jy)z Starts interactive animation. Adds the draw frame command to the GUI handler, calls show to start the event loop. N) rr is_savingmpl_disconnectr _init_drawr add_callback_stepstartr*s rrzAnimation._startss 99   % % '  ''(;(;<  &&tzz2 !rc0|jr/|jjj|j|jjj|j |j j|jd|_yr#) rrrr _resize_idrrremove_callbackrr*s rrzAnimation._stopsa :: II   + +DOO < ''7 ))$**5 r)progress_callbackc  Ng} | | jfd| D| D] } d| _ |tjd}n2t |t s"t d|||||fDr td| i} n t| } |tdrdjz }tj|d }|d k(rjj}i}|||d <|||d <|||d <|||d<t |t r t|}||fi|}t j%dt'|d| vr&t j#d| j)dd}|j+j||5t-j.jj0dd5|j3sR| j5dtjd}|dk(rjj7}||| d<d| d<| D]} | j9d}| Dcgc]}t;|dd}}d|vrd}n t=|}t?| Dcgc]}|jAc}D]L}t?| |D])\} }| jC|d| | |||dz }+|jDdi| N ddddddy#t$r t}t j#d|YwxYwcc}wcc}w#1swYHxYw#1swYyxYw)a Save the animation as a movie file by drawing every frame. Parameters ---------- filename : str The output filename, e.g., :file:`mymovie.mp4`. writer : `MovieWriter` or str, default: :rc:`animation.writer` A `MovieWriter` instance to use or a key that identifies a class to use, such as 'ffmpeg'. fps : int, optional Movie frame rate (per second). If not set, the frame rate from the animation's frame interval. dpi : float, default: :rc:`savefig.dpi` Controls the dots per inch for the movie frames. Together with the figure's size in inches, this controls the size of the movie. codec : str, default: :rc:`animation.codec`. The video codec to use. Not all codecs are supported by a given `MovieWriter`. bitrate : int, default: :rc:`animation.bitrate` The bitrate of the movie, in kilobits per second. Higher values means higher quality movies, but increase the file size. A value of -1 lets the underlying movie encoder select the bitrate. extra_args : list of str or None, optional Extra command-line arguments passed to the underlying movie encoder. These arguments are passed last to the encoder, just before the output filename. The default, None, means to use :rc:`animation.[name-of-encoder]_args` for the builtin writers. metadata : dict[str, str], default: {} 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, default: [] Additional `Animation` objects that should be included in the saved movie file. These need to be from the same `.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, default: {} Keyword arguments passed to each `~.Figure.savefig` call used to save the individual frames. progress_callback : function, optional A callback function that will be called for every frame to notify the saving progress. It must have the signature :: def func(current_frame: int, total_frames: int) -> Any where *current_frame* is the current frame number and *total_frames* is the total number of frames to be saved. *total_frames* is set to None, if the total number of frames cannot be determined. Return values may exist but are ignored. Example code to write the progress to stdout:: progress_callback = lambda i, n: print(f'Saving frame {i}/{n}') 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. Nc3RK|]}|jjur| ywr#)r)rXanimr's rr\z!Animation.save..s(7T#yyDII5!7s$'Tanimation.writerc3$K|]}|du ywr#r.)rXargs rr\z!Animation.save..sJT/JszPassing 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. _interval@@z savefig.dpifigurerIrJryrFz1MovieWriter %s unavailable; using Pillow instead.zAnimation.save using %s bbox_incheszWarning: discarding the 'bbox_inches' argument in 'savefig_kwargs' as it may cause frame size to vary, which is inappropriate for animation.cxtj|\}}}}|tj|||gzdz|z S)Nr)mcolorsto_rgbararray)colorrgbas r_pre_composite_to_whitez/Animation.save.._pre_composite_to_whiteCs< /JAq!QrxxAq **Q.2 2r) _is_savingmanager facecolorzsavefig.facecolorautoF transparentr _save_count)rrr.)#rrrGrc isinstanceranyr;r$rrrHrrwritersrrdrkrertpoprir _setattr_cmrrWget get_facecolorrrsumzipnew_saved_frame_seq_draw_next_framer[)r'filenamewriterrErrIrJryrF extra_animrZrall_animr writer_kwargsr+rr frame_numberrsave_count_list total_framesdatads` rrzAnimation.saves}Z6  ! OO7Z7 7 *D%)D " * >\\"45FVS)J!5':xHJJ 78 8  !N".1N ;745$..(CnnS-0 (?))--C  %*M' "  '.M) $  !*4M, '  (0M* % fc " 1$V_  5}5F +T&\: N * LLJ K   } - 3mmDIIx5 4 0 0T4P 4002*..{/2||2O2&# "?3 xH!a335HI 4"8T2*GD!))!%)8(4), E$) * "!!3N3 4+ 4 4 47  1)  ()/1 1T2 I+ 4 4 4 4s[ K?-L,BL,LLL 4.L#$LL%LL LL LL$c t|j}|j||jy#t$rYywxYw)z Handler for getting events. By default, gets the next frame in the sequence and hands the data off to be drawn. TF)nextrrr StopIteration)r'rg framedatas rrzAnimation._stephs> T^^,I  ! !)TZZ 8  s14 AAc,t|jS)z+Return a new sequence of frame information.)iter _framedatar&s rrzAnimation.new_frame_seqwsDOO$$rc"|jS)z8Return a new sequence of saved/cached frame information.)rr&s rrzAnimation.new_saved_frame_seq|s!!##rcn|j|||j||j||yr#) _pre_draw _draw_frame _post_drawr'rrs rrzAnimation._draw_next_frames. y$' #  4(rcd|_yr)rr&s rrzAnimation._init_draws "&rc@|r|j|jyyr#) _blit_clear_drawn_artistsrs rrzAnimation._pre_draws     T00 1 rctd)NzDNeeds to be implemented by subclasses to actually make an animation.r)r'rs rrzAnimation._draw_frames!#AB Brc|r(|jr|j|jy|jjj yr#)r _blit_drawrr draw_idlers rrzAnimation._post_draws7 D'' OOD// 0 II   & & (rc|Dchc]}|j}}|D]}|j}|jj|t df\}}||k7sB||j j j|jf|j|<|D]}|jj||D]1}|j j j|j3ycc}wr#) axes _get_view _blit_cacherobjectrrcopy_from_bboxbbox draw_artistr)r'artistsr updated_axaxcur_viewviewbgs rrzAnimation._blit_draws'..aff. . HB||~H''++B40@AHD"4bii..==bggF(H  $ H "A FF  q ! " +B II   ! !"'' * +!/sC7c:|Dchc]}|j}}|D]i} |j|\}}|j|k(r&|jj j |O|jj|kycc}w#t$rY}wxYwr#)rrr1rrrrestore_regionr)r'rrrrr r s rrzAnimation._blit_clears!((1(( )B ++B/b||~%   //3  $$R( ))  sB B BBct|_g|_|jd|j|j |j jjd|j|_ y)N resize_event) r$rrrrrrrr _on_resizerr&s rrzAnimation._setup_blitsX6  djj) ))**66~7;HrcT|jjj|j|jj |j j|j|jjjd|j|_y)Nr) rrrrrstoprclearrr _end_redrawr'events rrzAnimation._on_resizesv ''8     ))**66|7;7G7GIrc$|jdd|jj|jjj |j |jjjd|j|_y)NFr) rrrrrrrrrrs rrzAnimation._end_redrawsf e$ ! ''8))**66~7;Hrc4d}t|dstj|d}|dz}t5}t |d}t tj d}|dtj dd |jz }|jt|| tj|j}d d d t}||k\rtjd ||n4|j!d|_dj$j&|_t|drYddg} t+|ddr| j-d|j%|j"|j(dj/| Sy#1swYxYw)a Convert the animation to an HTML5 ``