From 80d8dd858338cee11ceb0adef3724d3d1b06a9c6 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 7 Dec 2016 17:14:49 -0500 Subject: [PATCH 1/8] DOC: partially numpydoc-ify animation module --- lib/matplotlib/animation.py | 443 +++++++++++++++++++++++++++--------- 1 file changed, 331 insertions(+), 112 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index b4f1b77bb967..1f1ad0591c41 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -68,6 +68,8 @@ def adjusted_figsize(w, h, dpi, n): # A registry for available MovieWriter classes class MovieWriterRegistry(object): + '''Registry of of available writer classes by human readable name + ''' def __init__(self): self.avail = dict() self._registered = dict() @@ -109,6 +111,15 @@ def list(self): return list(self.avail.keys()) def is_available(self, name): + '''If given writer is available + + Parameters + ---------- + name : str + + Returns + available : bool + ''' self.ensure_not_dirty() return name in self.avail @@ -122,11 +133,36 @@ def __getitem__(self, name): class MovieWriter(object): - ''' - 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. + '''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 : string + 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 + + Examples + -------- + + 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 :: + + moviewriter = MovieWriter(...) + moveiewriter.setup() + for j in range(n): + update_figure(n) + moviewriter.grab_frame() + moviewriter.finish() + + saving() is provided as a context manager to facilitate this process as:: with moviewriter.saving('myfile.mp4'): @@ -136,15 +172,13 @@ class MovieWriter(object): The use of the context manager ensures that setup and cleanup are performed as necessary. - frame_format: string - The format used in writing frame data, defaults to 'rgba' ''' def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None, metadata=None): ''' - Construct a new MovieWriter object. - + Parameters + ---------- fps: int Framerate for movie. codec: string or None, optional @@ -210,11 +244,14 @@ def setup(self, fig, outfile, dpi): ''' Perform setup for writing the movie file. - fig: `matplotlib.Figure` instance + Parameters + ---------- + + fig : `matplotlib.Figure` instance The figure object that contains the information for frames - outfile: string + outfile : string The filename of the resulting movie file - dpi: int + dpi : int The DPI (or resolution) for the file. This controls the size in pixels of the resulting movie file. ''' @@ -329,29 +366,37 @@ def isAvailable(cls): class FileMovieWriter(MovieWriter): - '`MovieWriter` subclass that handles writing to a file.' + '''`MovieWriter` for writing to individual files and stitching at the end + This must be sub-classed to be useful. + ''' def __init__(self, *args, **kwargs): - MovieWriter.__init__(self, *args, **kwargs) - self.frame_format = rcParams['animation.frame_format'] - - def setup(self, fig, outfile, dpi, frame_prefix='_tmp', clear_temp=True): ''' - Perform setup for writing the movie file. - - fig: `matplotlib.Figure` instance + Parameters + ---------- + fig : `matplotlib.Figure` instance The figure object that contains the information for frames - outfile: string + outfile : string The filename of the resulting movie file - dpi: int + dpi : int The DPI (or resolution) for the file. This controls the size in pixels of the resulting movie file. - frame_prefix: string, optional + frame_prefix : string, optional The filename prefix to use for the temporary files. Defaults to '_tmp' - clear_temp: bool + clear_temp : bool Specifies whether the temporary files should be deleted after the movie is written. (Useful for debugging.) Defaults to True. + + ''' + + MovieWriter.__init__(self, *args, **kwargs) + self.frame_format = rcParams['animation.frame_format'] + + def setup(self, fig, outfile, dpi, frame_prefix='_tmp', clear_temp=True): + ''' + Perform setup for writing the movie file. + ''' self.fig = fig self.outfile = outfile @@ -463,6 +508,12 @@ def cleanup(self): # Base class of ffmpeg information. Has the config keys and the common set # of arguments that controls the *output* side of things. class FFMpegBase(object): + '''Mixin class for FFMpeg output + + To be useful this must be multiply-inherited from with a + `MoveWriterBase` sub-class. + ''' + exec_key = 'animation.ffmpeg_path' args_key = 'animation.ffmpeg_args' @@ -490,6 +541,11 @@ def output_args(self): # Combine FFMpeg options with pipe-based writing @writers.register('ffmpeg') class FFMpegWriter(MovieWriter, FFMpegBase): + '''Pipe based ffmpeg writer. + + Frames are streamed directly to ffmpeg via a pipe and written in a single + pass. + ''' def _args(self): # Returns the command line parameters for subprocess to use # ffmpeg to create a movie using a pipe. @@ -506,6 +562,12 @@ def _args(self): # Combine FFMpeg options with temp file-based writing @writers.register('ffmpeg_file') class FFMpegFileWriter(FileMovieWriter, FFMpegBase): + '''File based ffmpeg writer + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp', 'pbm', 'raw', 'rgba'] @@ -520,6 +582,12 @@ def _args(self): # Base class of avconv information. AVConv has identical arguments to # FFMpeg class AVConvBase(FFMpegBase): + '''Mixin class for avconv output + + To be useful this must be multiply-inherited from with a + `MoveWriterBase` sub-class. + ''' + exec_key = 'animation.avconv_path' args_key = 'animation.avconv_args' @@ -527,13 +595,22 @@ class AVConvBase(FFMpegBase): # Combine AVConv options with pipe-based writing @writers.register('avconv') class AVConvWriter(AVConvBase, FFMpegWriter): - pass + '''Pipe based avconv writer. + + Frames are streamed directly to avconv via a pipe and written in a single + pass. + ''' # Combine AVConv options with file-based writing @writers.register('avconv_file') class AVConvFileWriter(AVConvBase, FFMpegFileWriter): - pass + '''File based avconv writer + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' # Base class of mencoder information. Contains configuration key information @@ -616,6 +693,12 @@ def _args(self): # Base class for animated GIFs with convert utility class ImageMagickBase(object): + '''Mixin class for ImageMagick output + + To be useful this must be multiply-inherited from with a + `MoveWriterBase` sub-class. + ''' + exec_key = 'animation.convert_path' args_key = 'animation.convert_args' @@ -667,6 +750,12 @@ def isAvailable(cls): # former. @writers.register('imagemagick') class ImageMagickWriter(ImageMagickBase, MovieWriter): + '''Pipe based animated gif + + Frames are streamed directly to ImageMagick via a pipe and written + in a single pass. + + ''' def _args(self): return ([self.bin_path(), '-size', '%ix%i' % self.frame_size, '-depth', '8', @@ -681,6 +770,13 @@ def _args(self): # former. @writers.register('imagemagick_file') class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter): + '''File based animated gif writer + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' + supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp', 'pbm', 'raw', 'rgba'] @@ -691,19 +787,34 @@ def _args(self): class Animation(object): - ''' - 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 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. - *fig* is the figure object that is used to get draw, resize, and any - other needed events. + blit : bool, optional + controls whether blitting is used to optimize drawing. Defaults + to `False`. - *event_source* is 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. + See Also + -------- + FuncAnimation, ArtistAnimation - *blit* is a boolean that controls whether blitting is used to optimize - drawing. ''' def __init__(self, fig, event_source=None, blit=False): self._fig = fig @@ -758,55 +869,72 @@ def _stop(self, *args): def save(self, filename, writer=None, fps=None, dpi=None, codec=None, bitrate=None, extra_args=None, metadata=None, extra_anim=None, savefig_kwargs=None): - ''' - Saves a movie file by drawing every frame. - - *filename* is the output filename, e.g., :file:`mymovie.mp4` - - *writer* is either an instance of :class:`MovieWriter` or a string - key that identifies a class to use, such as 'ffmpeg' or 'mencoder'. - If nothing is passed, the value of the rcparam `animation.writer` is - used. - - *dpi* controls the dots per inch for the movie frames. This combined - with the figure's size in inches controls the size of the movie. - - *savefig_kwargs* is a dictionary containing keyword arguments to be - passed on to the 'savefig' command which is called repeatedly to save - the individual frames. This can be used to set tight bounding boxes, - for example. - - *extra_anim* is a list of additional `Animation` objects that should - be included in the saved movie file. These need to be from the same - `matplotlib.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. - - These remaining arguments are used to construct a :class:`MovieWriter` - instance when necessary and are only considered valid if *writer* is - not a :class:`MovieWriter` instance. - - *fps* is the frames per second in the movie. Defaults to None, - which will use the animation's specified interval to set the frames - per second. - - *codec* is the video codec to be used. Not all codecs are supported - by a given :class:`MovieWriter`. If none is given, this defaults to the - value specified by the rcparam `animation.codec`. - - *bitrate* specifies the amount 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 no - value is given, this defaults to the value given by the rcparam - `animation.bitrate`. - - *extra_args* is 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* is 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. + '''Saves 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' or 'mencoder'. If `None`, + defaults to ``rcParams['animation.writer']`` + + 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 ``rcparam['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 ``rcParams['animation.codec']`` + + bitrate : number, optional + specifies the amount 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 + ``rcParam['animation.bitrate']`` + + extra_args : list, optional + list of extra string arguments to be passed to the + underlying movie utility. If `None`, defaults to + ``rcParams['animation.extra_args']`` + + metadata : dict, 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` 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, metadata are used are used to + construct a :class:`MovieWriter` instance and can only be + passed if `writer` is a string. If they are pass as + non-`None` and ``writer`` is a :class:`MovieWriter`, a + `RuntimeError` will be raised. + ''' # If the writer is None, use the rc param to find the name of the one # to use @@ -1081,15 +1209,31 @@ def _repr_html_(self): class TimedAnimation(Animation): - ''' - :class:`Animation` subclass that supports time-based animation, drawing - a new frame every *interval* milliseconds. + ''':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. 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* controls whether the animation should repeat when the sequence - of frames is completed. + repeat: bool, optional + controls whether the animation should repeat when the sequence + of frames is completed. + + blit : bool, optional + controls whether blitting is used to optimize drawing. Defaults + to `False`. - *repeat_delay* optionally adds a delay in milliseconds before repeating - the animation. ''' def __init__(self, fig, interval=200, repeat_delay=None, repeat=True, event_source=None, *args, **kwargs): @@ -1147,13 +1291,38 @@ def _loop_delay(self, *args): class ArtistAnimation(TimedAnimation): - ''' - Before calling this function, all plotting should have taken place + '''Animation using a fixed set of `Artist` objects. + + Before creating an instance, all plotting should have taken place and the relevant artists saved. - *artists* is a list, with each list entry a collection of artists that - represent what needs to be enabled on each frame. These will be disabled - for other frames. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that is used to get draw, resize, and any + other needed events. + + artists : list + with 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. 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. + + blit : bool, optional + controls whether blitting is used to optimize drawing. Defaults + to `False`. + ''' def __init__(self, fig, artists, *args, **kwargs): # Internal list of artists drawn in the most recent frame. @@ -1202,25 +1371,75 @@ def _draw_frame(self, artists): class FuncAnimation(TimedAnimation): - ''' - Makes an animation by repeatedly calling a function *func*, passing in - (optional) arguments in *fargs*. + '''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(fr: object, *fargs) -> iterable_of_artists: + + + 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, equivalent to passing ``range(frames)`` + + If a generator function, then must have the signature :: + + def gen_function(): + + If `None`, then equivalent to passing ``itertools.count`` + + 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. + + If blit=True, ``init_func`` must return an iterable of artists + to be re-drawn. + + The required signature is :: + + def init_func() -> iterable_of_artists: + + 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. Defaults to 200 - *frames* can be a generator, an iterable, or a number of frames. + repeat_delay : number, optional + If the animation in repeated, adds a delay in milliseconds + before repeating the animation. Defaults to None - *init_func* is 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. + repeat: bool, optional + controls whether the animation should repeat when the sequence + of frames is completed. - If blit=True, *func* and *init_func* must return an iterable of - artists to be re-drawn. + blit : bool, optional + controls whether blitting is used to optimize drawing. Defaults + to `False`. - *kwargs* include *repeat*, *repeat_delay*, and *interval*: - *interval* draws a new frame every *interval* milliseconds. - *repeat* controls whether the animation should repeat when the sequence - of frames is completed. - *repeat_delay* optionally adds a delay in milliseconds before repeating - the animation. ''' def __init__(self, fig, func, frames=None, init_func=None, fargs=None, save_count=None, **kwargs): From 24c7aad75a21840bedcc6ee6a68ece2a35a2c758 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 7 Dec 2016 22:51:35 -0500 Subject: [PATCH 2/8] DOC: use auto summary in animation_api.rst --- doc/api/animation_api.rst | 119 +++++++++++++++++++++++++++++++++++--- 1 file changed, 110 insertions(+), 9 deletions(-) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index d43dc351abae..57c248765143 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -1,12 +1,113 @@ -********* -animation -********* +====================== + ``animation`` module +====================== +.. currentmodule:: matplotlib.animation -:mod:`matplotlib.animation` -=========================== -.. automodule:: matplotlib.animation - :members: - :undoc-members: - :show-inheritance: +Animation +========= + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + FuncAnimation + ArtistAnimation + Animation.save + + +Writer Classes +============== + + + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + AVConvFileWriter + AVConvWriter + FFMpegFileWriter + FFMpegWriter + ImageMagickFileWriter + ImageMagickWriter + + +Helper Classes +============== + + +Animation Base Classes +---------------------- + + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + Animation + TimedAnimation + + +Writer Registry +--------------- + +A module-level registry is provided to map between the name of the +writer and the class to allow a string to be passed to +`Animation.save` instead of a writer instance. + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + MovieWriterRegistry + +Writer Base Classes +------------------- + +To reduce code duplication base classes + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + MovieWriter + FileMovieWriter + +and mixins are provided + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + AVConvBase + FFMpegBase + ImageMagickBase + +See the source code for how to easily implement new `MovieWriter` +classes. + + +Inheritance Diagrams +==================== + +.. inheritance-diagram:: matplotlib.animation.FuncAnimation matplotlib.animation.ArtistAnimation + :private-bases: + +.. inheritance-diagram:: matplotlib.animation.AVConvFileWriter matplotlib.animation.AVConvWriter matplotlib.animation.FFMpegFileWriter matplotlib.animation.FFMpegWriter matplotlib.animation.ImageMagickFileWriter matplotlib.animation.ImageMagickWriter + :private-bases: + + + +Deprecated +========== + + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + MencoderBase + MencoderFileWriter + MencoderWriter From e465fb71bd86c81ae2f91c3bebc80b3c84fee113 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Thu, 8 Dec 2016 00:35:23 -0500 Subject: [PATCH 3/8] DOC: start to add animation prose --- doc/api/animation_api.rst | 162 +++++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 1 deletion(-) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index 57c248765143..5d9a7c3497b5 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -2,19 +2,170 @@ ``animation`` module ====================== -.. currentmodule:: matplotlib.animation +.. automodule:: matplotlib.animation + +.. contents:: Table of Contents + :depth: 1 + :local: + :backlinks: entry Animation ========= +The easiest way to make a live animation in mpl is to use one of the +`Animation` classes. + .. autosummary:: :toctree: _as_gen :nosignatures: FuncAnimation ArtistAnimation + +In both cases it is critical to keep a reference to tho instance +object. The animation is advanced by a timer (typically from the host +GUI framework) which the `Animation` object holds the only reference +to. If you do not hold a reference to the `Animation` object, it (and +hence the timers), will be garbage collected which will stop the +animation. + +To save an animation use to disk use + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + Animation.save + Animation.to_html5_video + +See :ref:`ani_writer_classes` below for details about what movie formats are supported. + + +``FuncAnimation`` +----------------- + +The inner workings of `FuncAnimation` is more-or-less:: + + for d in frames: + arts = func(d, *fargs) + fig.canvas.draw_idle() + plt.pause(interval) + + +with details to handle 'blitting' (to dramatically improve the live +performance), to be non-blocking, handle repeats, multiple animated +axes, and easily save the animation to a movie file. + +'Blitting' is a `old technique +`__ in computer graphics. The +general gist is to take as existing bit map (in our case a mostly +rasterized figure) and then 'blit' one more artist on top. Thus, by +managing a saved 'clean' bitmap, we can only re-draw the few artists +that are changing at each frame and possibly save significant amounts of +time. When using blitting (by passing ``blit=True``) the core loop of +`FuncAnimation` gets a bit more complicated :: + + ax = fig.gca() + + def update_blit(arts): + fig.canvas.restore_region(bg_cache) + for a in arts: + a.axes.draw_artist(a) + + ax.figure.canvas.blit(ax.bbox) + + arts = init_func() + + for a in arts: + a.set_animated(True) + + fig.canvas.draw() + bg_cache = fig.canvas.copy_from_bbox(ax.bbox) + + for f in frames: + arts = func(f, *fargs) + update_blit(arts) + plt.pause(interval) + +This is of course leaving out many details (such as updating the +background when the figure is resized or fully re-drawn). However, +this hopefully minimalist example gives a sense of how ``init_func`` +and ``func`` are used inside of `FuncAnimation` and the theory of how +'blitting' works. + +The expected signature on ``func`` and ``init_func`` is very simple to +keep `FuncAnimation` out of your book keeping and plotting logic, but +this means that the callable objects you pass in must know what +artists they should be working on. There are several approaches to +handling this, of varying complexity and encapsulation. The simplest +approach, which works quite well in the case of a script, is to define the +artist at a global scope and let Python sort things out. For example :: + + import numpy as np + import matplotlib.pyplot as plt + from matplotlib.animation import FuncAnimation + + fig, ax = plt.subplots() + xdata, ydata = [], [] + ln, = plt.plot([], [], 'ro', animated=True) + + def init(): + ax.set_xlim(0, 2*np.pi) + ax.set_ylim(-1, 1) + return ln, + + def update(i): + xdata.append(i) + ydata.append(np.sin(i)) + ln.set_data(xdata, ydata) + return ln, + + ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128), + init_func=init, blit=True) + plt.show() + + +The second method is to us `functools.partial` to 'bind' artists to +function. A third method is to use closures to build up the required +artists and functions. A forth method is to create a class. + + + + +Examples +~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + ../examples/animation/animate_decay + ../examples/animation/bayes_update + ../examples/animation/double_pendulum_animated + ../examples/animation/dynamic_image + ../examples/animation/histogram + ../examples/animation/rain + ../examples/animation/random_data + ../examples/animation/simple_3danim + ../examples/animation/simple_anim + ../examples/animation/strip_chart_demo + ../examples/animation/unchained + +``ArtistAnimation`` +------------------- + + +Examples +~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + ../examples/animation/basic_example + ../examples/animation/basic_example_writer + ../examples/animation/dynamic_image2 + + Writer Classes @@ -33,6 +184,10 @@ Writer Classes ImageMagickFileWriter ImageMagickWriter +:ref:`animation-moviewriter` + + +.. _ani_writer_classes: Helper Classes ============== @@ -50,6 +205,11 @@ Animation Base Classes TimedAnimation +Custom Animation classes +------------------------ + +:ref:`animation-subplots` + Writer Registry --------------- From ff1e71e31495e0fc87858c44228cf8bce8d5cb79 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 10 Dec 2016 21:31:22 -0500 Subject: [PATCH 4/8] DOC: address comments --- doc/api/animation_api.rst | 10 ++-- lib/matplotlib/animation.py | 110 ++++++++++++++---------------------- 2 files changed, 46 insertions(+), 74 deletions(-) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index 5d9a7c3497b5..5836ff94463f 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -23,7 +23,7 @@ The easiest way to make a live animation in mpl is to use one of the FuncAnimation ArtistAnimation -In both cases it is critical to keep a reference to tho instance +In both cases it is critical to keep a reference to the instance object. The animation is advanced by a timer (typically from the host GUI framework) which the `Animation` object holds the only reference to. If you do not hold a reference to the `Animation` object, it (and @@ -115,9 +115,9 @@ artist at a global scope and let Python sort things out. For example :: ax.set_ylim(-1, 1) return ln, - def update(i): - xdata.append(i) - ydata.append(np.sin(i)) + def update(frame): + xdata.append(frame) + ydata.append(np.sin(frame)) ln.set_data(xdata, ydata) return ln, @@ -128,7 +128,7 @@ artist at a global scope and let Python sort things out. For example :: The second method is to us `functools.partial` to 'bind' artists to function. A third method is to use closures to build up the required -artists and functions. A forth method is to create a class. +artists and functions. A fourth method is to create a class. diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index 1f1ad0591c41..dc6e7a1b7e3a 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -68,7 +68,7 @@ def adjusted_figsize(w, h, dpi, n): # A registry for available MovieWriter classes class MovieWriterRegistry(object): - '''Registry of of available writer classes by human readable name + '''Registry of available writer classes by human readable name ''' def __init__(self): self.avail = dict() @@ -111,13 +111,14 @@ def list(self): return list(self.avail.keys()) def is_available(self, name): - '''If given writer is available + '''Check if given writer is available by name Parameters ---------- name : str Returns + ------- available : bool ''' self.ensure_not_dirty() @@ -141,42 +142,19 @@ class MovieWriter(object): Attributes ---------- - frame_format : string + 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 - - Examples - -------- - - 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 :: - - moviewriter = MovieWriter(...) - moveiewriter.setup() - for j in range(n): - update_figure(n) - moviewriter.grab_frame() - moviewriter.finish() - - - saving() is provided as a context manager to facilitate this process as:: - - with moviewriter.saving('myfile.mp4'): - # Iterate over frames - moviewriter.grab_frame() - - The use of the context manager ensures that setup and cleanup are - performed as necessary. + This must be provided by the sub-classes. ''' def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None, metadata=None): - ''' + '''MovieWriter + Parameters ---------- fps: int @@ -371,31 +349,28 @@ class FileMovieWriter(MovieWriter): This must be sub-classed to be useful. ''' def __init__(self, *args, **kwargs): - ''' - Parameters - ---------- - fig : `matplotlib.Figure` instance - The figure object that contains the information for frames - outfile : string - The filename of the resulting movie file - dpi : int - The DPI (or resolution) for the file. This controls the size - in pixels of the resulting movie file. - frame_prefix : string, optional - The filename prefix to use for the temporary files. Defaults - to '_tmp' - clear_temp : bool - Specifies whether the temporary files should be deleted after - the movie is written. (Useful for debugging.) Defaults to True. - - ''' - MovieWriter.__init__(self, *args, **kwargs) self.frame_format = rcParams['animation.frame_format'] def setup(self, fig, outfile, dpi, frame_prefix='_tmp', clear_temp=True): - ''' - Perform setup for writing the movie file. + '''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 + 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. 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`. ''' self.fig = fig @@ -541,7 +516,7 @@ def output_args(self): # Combine FFMpeg options with pipe-based writing @writers.register('ffmpeg') class FFMpegWriter(MovieWriter, FFMpegBase): - '''Pipe based ffmpeg writer. + '''Pipe-based ffmpeg writer. Frames are streamed directly to ffmpeg via a pipe and written in a single pass. @@ -562,7 +537,7 @@ def _args(self): # Combine FFMpeg options with temp file-based writing @writers.register('ffmpeg_file') class FFMpegFileWriter(FileMovieWriter, FFMpegBase): - '''File based ffmpeg writer + '''File-based ffmpeg writer Frames are written to temporary files on disk and then stitched together at the end. @@ -595,7 +570,7 @@ class AVConvBase(FFMpegBase): # Combine AVConv options with pipe-based writing @writers.register('avconv') class AVConvWriter(AVConvBase, FFMpegWriter): - '''Pipe based avconv writer. + '''Pipe-based avconv writer. Frames are streamed directly to avconv via a pipe and written in a single pass. @@ -605,7 +580,7 @@ class AVConvWriter(AVConvBase, FFMpegWriter): # Combine AVConv options with file-based writing @writers.register('avconv_file') class AVConvFileWriter(AVConvBase, FFMpegFileWriter): - '''File based avconv writer + '''File-based avconv writer Frames are written to temporary files on disk and then stitched together at the end. @@ -750,7 +725,7 @@ def isAvailable(cls): # former. @writers.register('imagemagick') class ImageMagickWriter(ImageMagickBase, MovieWriter): - '''Pipe based animated gif + '''Pipe-based animated gif Frames are streamed directly to ImageMagick via a pipe and written in a single pass. @@ -770,7 +745,7 @@ def _args(self): # former. @writers.register('imagemagick_file') class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter): - '''File based animated gif writer + '''File-based animated gif writer Frames are written to temporary files on disk and then stitched together at the end. @@ -895,7 +870,7 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`, codec : str, optional the video codec to be used. Not all codecs are supported by a given :class:`MovieWriter`. If `None`, - default to ``rcParams['animation.codec']`` + default to ``rcParams['animation.codec']`` bitrate : number, optional specifies the amount of bits used per second in the @@ -931,7 +906,7 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`, ----- fps, codec, bitrate, extra_args, metadata are used are used to construct a :class:`MovieWriter` instance and can only be - passed if `writer` is a string. If they are pass as + passed if `writer` is a string. If they are passed as non-`None` and ``writer`` is a :class:`MovieWriter`, a `RuntimeError` will be raised. @@ -1220,7 +1195,7 @@ class TimedAnimation(Animation): other needed events. interval : number, optional - Delay between frames. Defaults to 200 + Delay between frames in milliseconds. Defaults to 200. repeat_delay : number, optional If the animation in repeated, adds a delay in milliseconds @@ -1228,7 +1203,7 @@ class TimedAnimation(Animation): repeat: bool, optional controls whether the animation should repeat when the sequence - of frames is completed. + of frames is completed. Defaults to `True`. blit : bool, optional controls whether blitting is used to optimize drawing. Defaults @@ -1309,15 +1284,15 @@ class ArtistAnimation(TimedAnimation): be disabled for other frames. interval : number, optional - Delay between frames. Defaults to 200 + Delay between frames in miliseconds. Defaults to 200. repeat_delay : number, optional If the animation in repeated, adds a delay in milliseconds - before repeating the animation. Defaults to None + before repeating the animation. Defaults to `None`. repeat: bool, optional controls whether the animation should repeat when the sequence - of frames is completed. + of frames is completed. Defaults to `True`. blit : bool, optional controls whether blitting is used to optimize drawing. Defaults @@ -1381,7 +1356,6 @@ class FuncAnimation(TimedAnimation): 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. @@ -1390,7 +1364,6 @@ class FuncAnimation(TimedAnimation): def func(fr: object, *fargs) -> iterable_of_artists: - frames : iterable, int, generator function, or None, optional Source of data to pass ``func`` and each frame of the animation @@ -1406,7 +1379,6 @@ def gen_function(): If `None`, then equivalent to passing ``itertools.count`` 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 @@ -1426,15 +1398,15 @@ def init_func() -> iterable_of_artists: The number of values from `frames` to cache. interval : number, optional - Delay between frames. Defaults to 200 + 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 + before repeating the animation. Defaults to `None`. repeat: bool, optional controls whether the animation should repeat when the sequence - of frames is completed. + of frames is completed. Defaults to `True` blit : bool, optional controls whether blitting is used to optimize drawing. Defaults From 55017cd1aca60ac18cff4ce699909f4d32fe6756 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 10 Dec 2016 21:51:33 -0500 Subject: [PATCH 5/8] DOC: re-work MovieWriter section a bit --- doc/api/animation_api.rst | 66 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index 5836ff94463f..3b433fcf7d75 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -173,16 +173,76 @@ Writer Classes +The provided writers fall into two broad categories: pipe-based and +file-based. The pipe-based writers stream the captured frames over a +pipe to an external process. The pipe-based variants tend to be more +performant, but may not work on all systems. + .. autosummary:: :toctree: _as_gen :nosignatures: - AVConvFileWriter - AVConvWriter - FFMpegFileWriter + FFMpegWriter ImageMagickFileWriter + AVConvWriter + +Alternatively the file-based writers save temporary files for each +frame which are stitched into a single file at the end. Although +slower, these writers can be easier to debug. + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + FFMpegFileWriter ImageMagickWriter + AVConvFileWriter + + +Fundamentally, a MovieWriter does is provide is a way to grab +sequential frames from the same underlying `~matplotlib.figure.Figure` +object. The base class `MovieWriter` implements 3 methods and a +context manager. The only difference between the pipe-based and +file-based writers in the arguments to their respective ``setup`` +methods. + + +.. autosummary:: + :toctree: _as_gen + :nosignatures: + + MovieWriter.setup + FileMovieWriter.setup + MovieWriter.grab_frame + MovieWriter.finish + MovieWriter.saving + + +The ``setup()`` method is used to prepare the writer (possibly opening +a pipe), successive calls to ``grab_frame()`` capture a single frame +at a time and ``finish()`` finalizes the movie and writes the output +file to disk. For example :: + + moviewriter = MovieWriter(...) + moveiewriter.setup(fig=fig, 'my_movie.ext', dpi=100) + for j in range(n): + update_figure(n) + moviewriter.grab_frame() + moviewriter.finish() + + +If using the writer classes directly (not through `Animation.save`), it is strongly encouraged +to use the `~MovieWriter.saving` context manager :: + + with moviewriter.saving(fig, 'myfile.mp4', dpi=100): + for j in range(n): + update_figure(n) + moviewriter.grab_frame() + + +to ensures that setup and cleanup are performed as necessary. + :ref:`animation-moviewriter` From 1a6c61c8fa6215b74453e5ebebf0ec516796a609 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 10 Dec 2016 22:05:45 -0500 Subject: [PATCH 6/8] DOC: address the rest of the comments --- doc/api/animation_api.rst | 24 +++++++-------- lib/matplotlib/animation.py | 58 ++++++++++++++++++++----------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index 3b433fcf7d75..8a95b2314da6 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -13,7 +13,7 @@ Animation ========= -The easiest way to make a live animation in mpl is to use one of the +The easiest way to make a live animation in matplotlib is to use one of the `Animation` classes. .. autosummary:: @@ -30,7 +30,7 @@ to. If you do not hold a reference to the `Animation` object, it (and hence the timers), will be garbage collected which will stop the animation. -To save an animation use to disk use +To save an animation to disk use .. autosummary:: :toctree: _as_gen @@ -48,7 +48,7 @@ See :ref:`ani_writer_classes` below for details about what movie formats are sup The inner workings of `FuncAnimation` is more-or-less:: for d in frames: - arts = func(d, *fargs) + artists = func(d, *fargs) fig.canvas.draw_idle() plt.pause(interval) @@ -59,7 +59,7 @@ axes, and easily save the animation to a movie file. 'Blitting' is a `old technique `__ in computer graphics. The -general gist is to take as existing bit map (in our case a mostly +general gist is to take an existing bit map (in our case a mostly rasterized figure) and then 'blit' one more artist on top. Thus, by managing a saved 'clean' bitmap, we can only re-draw the few artists that are changing at each frame and possibly save significant amounts of @@ -68,24 +68,24 @@ time. When using blitting (by passing ``blit=True``) the core loop of ax = fig.gca() - def update_blit(arts): + def update_blit(artists): fig.canvas.restore_region(bg_cache) - for a in arts: + for a in artists: a.axes.draw_artist(a) ax.figure.canvas.blit(ax.bbox) - arts = init_func() + artists = init_func() - for a in arts: + for a in artists: a.set_animated(True) fig.canvas.draw() bg_cache = fig.canvas.copy_from_bbox(ax.bbox) for f in frames: - arts = func(f, *fargs) - update_blit(arts) + artists = func(f, *fargs) + update_blit(artists) plt.pause(interval) This is of course leaving out many details (such as updating the @@ -98,7 +98,7 @@ The expected signature on ``func`` and ``init_func`` is very simple to keep `FuncAnimation` out of your book keeping and plotting logic, but this means that the callable objects you pass in must know what artists they should be working on. There are several approaches to -handling this, of varying complexity and encapsulation. The simplest +handling this, of varying complexity and encapsulation. The simplest approach, which works quite well in the case of a script, is to define the artist at a global scope and let Python sort things out. For example :: @@ -200,7 +200,7 @@ slower, these writers can be easier to debug. AVConvFileWriter -Fundamentally, a MovieWriter does is provide is a way to grab +Fundamentally, a `MovieWriter` does is provide is a way to grab sequential frames from the same underlying `~matplotlib.figure.Figure` object. The base class `MovieWriter` implements 3 methods and a context manager. The only difference between the pipe-based and diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index dc6e7a1b7e3a..83cdbb0430f2 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -486,7 +486,7 @@ class FFMpegBase(object): '''Mixin class for FFMpeg output To be useful this must be multiply-inherited from with a - `MoveWriterBase` sub-class. + `MovieWriterBase` sub-class. ''' exec_key = 'animation.ffmpeg_path' @@ -560,7 +560,7 @@ class AVConvBase(FFMpegBase): '''Mixin class for avconv output To be useful this must be multiply-inherited from with a - `MoveWriterBase` sub-class. + `MovieWriterBase` sub-class. ''' exec_key = 'animation.avconv_path' @@ -671,7 +671,7 @@ class ImageMagickBase(object): '''Mixin class for ImageMagick output To be useful this must be multiply-inherited from with a - `MoveWriterBase` sub-class. + `MovieWriterBase` sub-class. ''' exec_key = 'animation.convert_path' @@ -850,7 +850,7 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None, ---------- filename : str - the output filename, e.g., :file:`mymovie.mp4` + 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 @@ -863,34 +863,34 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`, the frames per second. dpi : number, optional - controls the dots per inch for the movie frames. This + 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 ``rcparam['savefig.dpi']`` codec : str, optional - the video codec to be used. Not all codecs are supported by + The video codec to be used. Not all codecs are supported by a given :class:`MovieWriter`. If `None`, default to ``rcParams['animation.codec']`` bitrate : number, optional - specifies the amount of bits used per second in the + Specifies the amount 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 ``rcParam['animation.bitrate']`` extra_args : list, optional - list of extra string arguments to be passed to the + List of extra string arguments to be passed to the underlying movie utility. If `None`, defaults to ``rcParams['animation.extra_args']`` metadata : dict, optional - dictionary of keys and values for metadata to include in + 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 + Additional `Animation` objects that should be included in the saved movie file. These need to be from the same `matplotlib.Figure` instance. Also, animation frames will just be simply combined, so there should be a 1:1 @@ -898,13 +898,13 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`, animations. savefig_kwargs : dict, optional - is a dictionary containing keyword arguments to be passed + 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, metadata are used are used to + fps, codec, bitrate, extra_args, metadata are used to construct a :class:`MovieWriter` instance and can only be passed if `writer` is a string. If they are passed as non-`None` and ``writer`` is a :class:`MovieWriter`, a @@ -1201,13 +1201,13 @@ class TimedAnimation(Animation): 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 + 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`. + Controls whether blitting is used to optimize drawing. Defaults + to `False`. ''' def __init__(self, fig, interval=200, repeat_delay=None, repeat=True, @@ -1279,7 +1279,7 @@ class ArtistAnimation(TimedAnimation): other needed events. artists : list - with each list entry a collection of artists that + With each list entry a collection of artists that represent what needs to be enabled on each frame. These will be disabled for other frames. @@ -1290,13 +1290,13 @@ class ArtistAnimation(TimedAnimation): 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 + 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`. + Controls whether blitting is used to optimize drawing. Defaults + to `False`. ''' def __init__(self, fig, artists, *args, **kwargs): @@ -1374,12 +1374,16 @@ def func(fr: object, *fargs) -> iterable_of_artists: If a generator function, then must have the signature :: - def gen_function(): + def gen_function() -> obj: + + 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. - If `None`, then equivalent to passing ``itertools.count`` + If `None`, then equivalent to passing ``itertools.count``. init_func : callable, optional - a function used to draw a clear frame. If not given, the + 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. @@ -1404,12 +1408,12 @@ def init_func() -> iterable_of_artists: 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 + 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 + Controls whether blitting is used to optimize drawing. Defaults to `False`. ''' From 8e8291c46372fc01371e3900e91587a71a020092 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sat, 10 Dec 2016 23:15:24 -0500 Subject: [PATCH 7/8] DOC: Fix more typos and minor errors --- doc/api/animation_api.rst | 13 ++++++------- lib/matplotlib/animation.py | 37 +++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/doc/api/animation_api.rst b/doc/api/animation_api.rst index 8a95b2314da6..3519bca48c23 100644 --- a/doc/api/animation_api.rst +++ b/doc/api/animation_api.rst @@ -200,12 +200,11 @@ slower, these writers can be easier to debug. AVConvFileWriter -Fundamentally, a `MovieWriter` does is provide is a way to grab -sequential frames from the same underlying `~matplotlib.figure.Figure` -object. The base class `MovieWriter` implements 3 methods and a -context manager. The only difference between the pipe-based and -file-based writers in the arguments to their respective ``setup`` -methods. +Fundamentally, a `MovieWriter` provides a way to grab sequential frames +from the same underlying `~matplotlib.figure.Figure` object. The base +class `MovieWriter` implements 3 methods and a context manager. The +only difference between the pipe-based and file-based writers is in the +arguments to their respective ``setup`` methods. .. autosummary:: @@ -225,7 +224,7 @@ at a time and ``finish()`` finalizes the movie and writes the output file to disk. For example :: moviewriter = MovieWriter(...) - moveiewriter.setup(fig=fig, 'my_movie.ext', dpi=100) + moviewriter.setup(fig=fig, 'my_movie.ext', dpi=100) for j in range(n): update_figure(n) moviewriter.grab_frame() diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index 83cdbb0430f2..f18118b366e5 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -68,8 +68,7 @@ def adjusted_figsize(w, h, dpi, n): # A registry for available MovieWriter classes class MovieWriterRegistry(object): - '''Registry of available writer classes by human readable name - ''' + '''Registry of available writer classes by human readable name.''' def __init__(self): self.avail = dict() self._registered = dict() @@ -111,7 +110,7 @@ def list(self): return list(self.avail.keys()) def is_available(self, name): - '''Check if given writer is available by name + '''Check if given writer is available by name. Parameters ---------- @@ -277,6 +276,7 @@ def finish(self): def grab_frame(self, **savefig_kwargs): ''' 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. ''' @@ -344,7 +344,7 @@ def isAvailable(cls): class FileMovieWriter(MovieWriter): - '''`MovieWriter` for writing to individual files and stitching at the end + '''`MovieWriter` for writing to individual files and stitching at the end. This must be sub-classed to be useful. ''' @@ -483,7 +483,7 @@ def cleanup(self): # Base class of ffmpeg information. Has the config keys and the common set # of arguments that controls the *output* side of things. class FFMpegBase(object): - '''Mixin class for FFMpeg output + '''Mixin class for FFMpeg output. To be useful this must be multiply-inherited from with a `MovieWriterBase` sub-class. @@ -537,7 +537,7 @@ def _args(self): # Combine FFMpeg options with temp file-based writing @writers.register('ffmpeg_file') class FFMpegFileWriter(FileMovieWriter, FFMpegBase): - '''File-based ffmpeg writer + '''File-based ffmpeg writer. Frames are written to temporary files on disk and then stitched together at the end. @@ -557,7 +557,7 @@ def _args(self): # Base class of avconv information. AVConv has identical arguments to # FFMpeg class AVConvBase(FFMpegBase): - '''Mixin class for avconv output + '''Mixin class for avconv output. To be useful this must be multiply-inherited from with a `MovieWriterBase` sub-class. @@ -580,7 +580,7 @@ class AVConvWriter(AVConvBase, FFMpegWriter): # Combine AVConv options with file-based writing @writers.register('avconv_file') class AVConvFileWriter(AVConvBase, FFMpegFileWriter): - '''File-based avconv writer + '''File-based avconv writer. Frames are written to temporary files on disk and then stitched together at the end. @@ -668,7 +668,7 @@ def _args(self): # Base class for animated GIFs with convert utility class ImageMagickBase(object): - '''Mixin class for ImageMagick output + '''Mixin class for ImageMagick output. To be useful this must be multiply-inherited from with a `MovieWriterBase` sub-class. @@ -706,7 +706,7 @@ def _init_from_registry(cls): @classmethod def isAvailable(cls): ''' - Check to see if a ImageMagickWriter is actually available + Check to see if a ImageMagickWriter is actually available. Done by first checking the windows registry (if applicable) and then running the commandline tool. @@ -725,7 +725,7 @@ def isAvailable(cls): # former. @writers.register('imagemagick') class ImageMagickWriter(ImageMagickBase, MovieWriter): - '''Pipe-based animated gif + '''Pipe-based animated gif. Frames are streamed directly to ImageMagick via a pipe and written in a single pass. @@ -745,7 +745,7 @@ def _args(self): # former. @writers.register('imagemagick_file') class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter): - '''File-based animated gif writer + '''File-based animated gif writer. Frames are written to temporary files on disk and then stitched together at the end. @@ -873,7 +873,7 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`, default to ``rcParams['animation.codec']`` bitrate : number, optional - Specifies the amount of bits used per second in the + 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 @@ -1184,7 +1184,7 @@ def _repr_html_(self): class TimedAnimation(Animation): - ''':class:`Animation` subclass for time-based animation + ''':class:`Animation` subclass for time-based animation. A new frame is drawn every *interval* milliseconds. @@ -1199,7 +1199,7 @@ class TimedAnimation(Animation): repeat_delay : number, optional If the animation in repeated, adds a delay in milliseconds - before repeating the animation. Defaults to None + before repeating the animation. Defaults to `None` repeat : bool, optional Controls whether the animation should repeat when the sequence @@ -1284,7 +1284,7 @@ class ArtistAnimation(TimedAnimation): be disabled for other frames. interval : number, optional - Delay between frames in miliseconds. Defaults to 200. + Delay between frames in milliseconds. Defaults to 200. repeat_delay : number, optional If the animation in repeated, adds a delay in milliseconds @@ -1346,7 +1346,8 @@ def _draw_frame(self, artists): class FuncAnimation(TimedAnimation): - '''Makes an animation by repeatedly calling a function ``func`` + ''' + Makes an animation by repeatedly calling a function ``func``. Parameters @@ -1410,7 +1411,7 @@ def init_func() -> iterable_of_artists: repeat : bool, optional Controls whether the animation should repeat when the sequence - of frames is completed. Defaults to `True` + of frames is completed. Defaults to `True`. blit : bool, optional Controls whether blitting is used to optimize drawing. Defaults From 4c4779b3e6812b7e277debe7c8f95fbe709da5d1 Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Mon, 12 Dec 2016 14:41:51 -0500 Subject: [PATCH 8/8] DOC: minor tweaks --- lib/matplotlib/animation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py index f18118b366e5..7588dcd41ca5 100644 --- a/lib/matplotlib/animation.py +++ b/lib/matplotlib/animation.py @@ -1199,7 +1199,7 @@ class TimedAnimation(Animation): repeat_delay : number, optional If the animation in repeated, adds a delay in milliseconds - before repeating the animation. Defaults to `None` + before repeating the animation. Defaults to `None`. repeat : bool, optional Controls whether the animation should repeat when the sequence @@ -1279,9 +1279,9 @@ class ArtistAnimation(TimedAnimation): other needed events. artists : list - With each list entry a collection of artists that - represent what needs to be enabled on each frame. These will - be disabled for other frames. + 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.