The backend layer

Seasoned computer scientists, engineers, and software developers all know that one of the subtler and trickier problems that arise in our industry is naming. It sounds a bit silly and it is repeatedly the subject of jokes, but the difficulty remains—how do you speak or write explicitly on a subject whose very nature requires exquisite precision and yet has great ambiguity that arises in different contexts?

We have the same problem with the term backend. Here, as in so many other instances, the context is everything. Our context is matplotlib, a set of tools, and a framework where everything is done in support of the visualizing of data and their relationships. The term backend has to be viewed from this perspective to support the generation of plots. The matplotlib backend has nothing to do with other noteworthy backends such as databases, servers, messaging systems, or dispatchers of various sorts. The backend of matplotlib is an abstraction layer over various components that are capable of rendering a Figure. Such plots appear in desktop applications that are embedded in widgets or web pages; other plots are images in publications (digital and print). They can be generated with code, through user interfaces, or by deploying a combination of both. These plots might be the creation of a single user tweaking a widget or a batch processing job on a high-performance computing grid. All are supported by and require a matplotlib backend.

As you might have been able to deduce from the examples given in the previous sections, the backends in matplotlib can be divided into two functional categories:

  • User interface backends (interactive)
  • Hardcopy backends (noninteractive)

User interface backends include the following:

  • GTK 2.x and GTK 3.x
  • wxWidgets
  • Tk
  • Qt4 and Qt5
  • Mac OS X Cocoa

The hardcopy backends comprise of the following:

  • PS
  • PDF
  • SVG
  • PNG

Hardcopy backends can be further divided based on the support of raster graphics, vector graphics, or both of these.

Furthermore, the user-interface and hardcopy backends are built upon some core abstractions. The base classes for these are as follows:

  • FigureCanvasBase and FigureManagerBase
  • RendererBase and GraphicsContextBase
  • Event, ShowBase, and Timer

Examining these base classes brings us to the nuts and bolts of the matplotlib backend architecture.

FigureCanvasBase

The FigureCanvasBase class is a base class that is used by the user interface and hardcopy backends. It represents the canvas in which the Figure will render. Its responsibilities include the following:

  • Holding a reference to the Figure
  • Updating the Figure with a reference to the canvas
  • Defining event methods that run registered
  • Translating native toolkit events into the matplotlib event abstraction framework
  • Defining draw methods to render the Figure
  • Methods to start and stop non-GUI event loops

When used by hardcopy backends, the FigureCanvasBase classes can register the file types supported by hardcopy backends (for example, .tiff and .jpg). When used by the user interface backends, the FigureCanvasBase classes provide the means by which the matplotlib canvas is inserted into the native toolkit window (even when it is GTK, Mac OS X Cocoa, Qt, or Tk).

Additionally, there is a FigureManagerBase class that is used by matplotlib when running in pyplot mode. This class wraps FigureCanvasBase as well as various GUI toolkit methods for the easier rendering of figures and interfaces.

RendererBase

In matplotlib, the renderer handles the drawing operations. RendererBase was originally inspired by the GIMP drawing toolkit's Drawable class, and this is evident when one examines its drawing methods to render paths, images, Gouraud triangles, text, markers, path collections, and quad meshes.

Note that many of the render operations are handed off to an additional abstraction—GraphicsContextBase. This abstraction provides a clean separation for code that handles color, line styles, hatching styles, blending properties, and antialiasing options, among others.

Event

There are several aspects of the matplotlib backend that have to do with events, event loops, and timing. These responsibilities are divided across three base classes:

  • Event: This is the base class for DrawEvent, MouseEvent, and KeyEvent, among others
  • ShowBase: This is subclassed at the module level in the GUI backends
  • TimerBase: This is the base class for TimerQT, TimerGTK3, and TimerWx, to name a few

As mentioned in a previous section, FigureCanvasBase defines event methods that are used when translating to and from native GUI toolkit events. These methods instantiate the Event classes and are connected to the callbacks stored in CallbackRegistry, which is itself stored as an attribute on FigureCanvasBase.

Depending on the nature of the event, it may need to track the data in the artist layer, work with renderers, and so on. As such, some of the Event classes carry references to more than just their event properties, allowing callback functions to easily access this data.

At the core of every GUI toolkit is an event loop. Every user interface backend that integrates with a toolkit needs to define a module-level Show class, subclassing ShowBase. Its mainloop method is what pyplot uses to start up the given toolkit's main loop. However, in order for this to work, matplotlib needs something to connect to the native toolkit's timer.

This is what implementations such as TimerQT, TimerGTK3, and TimerTornado provide. These classes have a callbacks attribute that is a simple list of (function, args, and kwards) tuples that get called upon by timer events. The TimerQT and TimerGTK3 classes integrate the GUI main loops, while the TimerTornado class integrates the I/O or event loop of the Tornado asynchronous networking library.

A practical example of how these can work together will include things such as a key press, a mouse click, or the picking of events. Key presses can be used to develop custom keyboard commands that change a plot based on the interactive input from the user. The ability to pick events allows the developers to support the interactive panning and zooming of their plots. All of these events are intercepted by the matplotlib event system and then forwarded to the native toolkits after the backend does the appropriate translation.

Visualizing the backend layer

The matplotlib backend components work together in order to provide a seamless experience regardless of:

  • The GUI toolkit being used (if any)
  • The type of output being produced (raster, vector, file type, and so on)
  • Whether the events are being handled
  • Whether the images are static or animated

We now have the information needed to visually summarize the backend layer. This information is portrayed in the following image:

Visualizing the backend layer

Note that in reality, the backend layer and its components are more complex than this graphic portrays. There are multiple relationships, as is exemplified by RendererBase and FigureCanvasBase appearing twice. The intent is to show the main backend base classes. The FigureManagerBase function has one of the other backend base classes as a supporting component (its canvas attribute).

This concludes our overview of matplotlib's backend layer. In the next section, we will move higher up the stack.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset