Backend: matplotlib
The matplotlib
library is a - if not the - classic plotting package in the Python ecosystem. For further details, please consult the documentation of matplotlib. A good basic introduction can also be found in the Python Data Science Handbook (2016), chapter 4, by Jake VanderPlas. The author has made the manuscript freely available in the form of Jupyter notebooks on Github.
from bewegung import Video
v = Video(width = 480, height = 270, seconds = 1.0)
@v.sequence()
class Foo:
@v.layer(
canvas = v.canvas(
backend = 'matplotlib',
facecolor = '#FFFFFFFF',
dpi = 150,
)
)
def bar(self, canvas): # a matplotlib figure object
ax = canvas.subplots()
ax.plot([1, 2, 3], [5, 4, 7])
return canvas
v.reset()
v.render_frame(v.time(0))

Similar to matplotlib.pyplot.figure
, the function call v.canvas(backend = 'matplotlib')
accepts the following additional keyword arguments, among others (see documentation of matplotlib.pyplot.figure and matplotlib.figure.Figure):
dpi
, resolution or dots per inch. 300 by default.figsize
, a tuple of width and height in inches. Width and height of the video by default, converted to inches based on the value ofdpi
.width
, width in pixels. Mapped tofigsize
if provided together withheight
. Converted to inches based on the value ofdpi
.height
, height in pixels. Mapped tofigsize
if provided together withwidth
. Converted to inches based on the value ofdpi
.tight_layout
, by defaultTrue
.facecolor
, a background color.background_color
, mapped tofacecolor
. Acceptsbewegung.Color
objects.managed
, a boolean, by defaultTrue
. This value indicates whether the thematplotlib.figure.Figure
object is “managed” bybewegung
. IfTrue
,bewegung
will close, i.e. destroy, a figure that is returned by a layer method.
Layer methods are expected to return matplotlib.figure.Figure
objects.
Warning
By default, bewegung
will “manage” matplotlib.figure.Figure
objects for saving resources, i.e. the returned matplotlib.figure.Figure
objects are automatically closed once returned. This can be avoided by setting managed
to False
.
Accelerating matplotlib
Aside from its rich set of features, matplotlib
is known for its mediocre performance. Not to be confused with bewegung
’s backends, matplotlib
also has different backends for rendering. Within bewegung
, matplotlib
is automatically configured to use mplcairo, “A (new) cairo backend for Matplotlib”. Compared to matplotlib
’s own built-in backends, its output quality is significantly better while the rendering speed is also higher. Unfortunately, mplcairo
is just “half” of the story of matplotlib
performance.
Warning
If mplcairo
can not be installed or is not present for whatever reason, bewegung
will show a warning and fall back to matplotlib
’s internal cairo
backend.
In animation frameworks for matplotlib
, such as the “official” matplotlib.animation sub-package, it is common practice to re-use and update existing figure and subplot / axes objects. This speeds up the rendering process considerably. This strategy is also supported by bewegung
.
Warning
For optimal results, the suggested approach requires some deeper understanding of matplotlib
’s facilities.
The following code illustrates the approach.
from bewegung import Video
v = Video(width = 480, height = 270, seconds = 1.0)
@v.sequence()
class Foo:
def __init__(self):
self._fig = v.canvas(
backend = 'matplotlib',
facecolor = '#FFFFFFFF',
dpi = 150,
managed = False, # ensure that bewegung does not close figure
)() # calls the factory once, generates a single figure
self._ax = self._fig.subplots() # generates a single subplot
@v.layer() # no backend configuration required
def bar(self): # no canvas requested
self._ax.clear() # optional: update content directly instead
self._ax.plot([1, 2, 3], [5, 4, 7]) # draw new content or change old content
return self._fig
v.reset()
image0 = v.render_frame(v.time(0))
image1 = v.render_frame(v.time(1))
The less a figure changes, the faster the above code becomes. Depending on the degree of complexity and optimization, anything from a few percent to an order of magnitude of performance gain can be achieved.