Structure of matplotlib
In this section, we provide an overview of the logical structure of matplotlib. This will help you better understand the matplotlib syntax.
matplotlib is a Python module for generating graphical output to your computer screen or to a computer file. Fundamentally, its job is to translate Python scripts into graphical instructions that your computer can understand. It does this using two different layers of software, the backend layer and the artist layer. To these two layers it adds a scripting layer, PyPlot, which we have met already (import matplotlib.pyplot as plt). PyPlot is a convenience layer, and not really necessary, but it facilitates rapid scripting, and aids with portability. As you shall see, for most programming we advocate using a hybrid of the scripting and artist layers. Figure below portrays the matplotlib software hierarchy.
The backend layer
For the sake of being concrete, we’ll start by considering the task of creating a figure on your computer screen. matplotlib must be able to generate graphics using different computer platforms: Linux, Microsoft Windows, and macOS. Of course, we want matplotlib to do this in a way that is transportable from one platform to another and transparent to you the user. Ideally, the Python matplotlib code you write on your PC should work without modification on your friend’s Mac or Linux computer.To accomplish this, matplotlib uses open source cross-platform software toolkits written by third parties.
There are a number of different toolkits available. Most of these toolkits can write graphics to computer screens on different platforms, includingWindows, macOS, and Linux. They are written mostly in C++, and are very efficient and powerful. To harness their power and versatility, matplotlib provides a number of Python “wrappers”—Python functions—that call the C++ functions of these toolkits to send graphics instructions to your computer,matplotlib calls these wrappers backends.
Several backends have been written for matplotlib. They fall into two categories: those written for output to files—hardcopy backends—and those for output to a computer screen—user interface backends, also known as interactive backends. For output to a computer screen, the qt5Agg backend is among the most versatile and widely used, so we will use it as an example of what an interactive backend does. The qt5Agg backend is made from two C++ toolkits: Qt7 and Agg. Qt can define windows on your computer screen, create buttons, scrollbars, and other widgets, that is to say, elements of a GUI. It can also process events, actions like clicking a mouse, pressing a keyboard key, moving a scroll bar, or pressing a button. This includes processing events generated by the computer, rather than the user, like an alarm clock going off or a process finishing. The Agg toolkit is a rendering program that produces pixel images in memory from vectorial data. For example, you provide Agg with the equation for a circle and it determines which pixels to activate on the computer screen. It employs advanced rendering techniques like anti-aliasing to produce faithful high-resolution graphics.
The job of a matplotlib backend is to provide a Python interface to the functionality of the underlying C++ (or other language) toolkits, which for qt5Agg are qt5 and Agg. The Python-facing parts of all matplotlib backends have three basic classes:
FigureCanvas defines the canvas—a figure window or a graphics file—and transfers the output from the Renderer onto this canvas.It also translates Qt events into the matplotlib Event framework (see below).
Renderer does the drawing. Basically, it connects matplotlib to the Agg library described above.
Event handles user inputs such as keyboard and mouse events for matplotlib.
Besides the qt5Agg backend, there are several other commonly used interactive backends: TkAgg, GTK3Agg, GTK3Cairo, WXAgg, and macOSX to name a few. Why all the different backends? Part of the reason is historical. Early on in the development of matplotlib, many toolkits worked on only one platform, meaning that a separate backend had to be developed for each one. As time has passed, most toolkits became cross-platform. As better cross-platform graphical tools, generally written in C++, were developed, programmers in the Python world wanted access to their functionality. Hence the different backends.
As mentioned earlier, there are also hardcopy backends that only produce graphical output to files. These include Agg (which we already met as part of qt5Agg), PDF (to produce the Adobe portable document format), SVG (scalable vector graphics), and Cairo (png,ps, pdf, and svg). In the end, the idea of a matplotlib backend is to provide the software machinery for setting up a canvas to draw on and the low-level tools for creating graphical output: plots and images. The drawing tools of the backend layer, while sufficient for producing any output you might want, work at too low of a level to be useful for everyday programming. For this, matplotlib provides another layer, the artist layer, which provides the software tools you will use for creating and managing graphical output.
The artist layer
The artist layer consists of a hierarchy of Python classes that facilitate creating a figure and embellishing it with any and all of the features we might desire: axes, data points, curves, axes labels, legends, titles, annotations, and everything else. The first step is to create a figure and place it on a canvas (figure window, whether on a computer screen or a computer file). To the figure, we add axes, data, labels, etc. When we have everything the way we want it, we send it to the screen to display and/or save it to a file.
First, we import the FigureCanvas from the qt5Agg backend.Then we import Figure from matplotlib.figure. After finishing our imports, the first step is to define and name (fig) the Figure object that will serve as a container for our plot. The next step is to attach the figure to an instance of FigureCanvas, whichwe name canvas, from the qt5Agg backend. This places the canvas on the screen and connects all the matplotlib routines to the Qt and Agg C++ routines that write to the screen.Next,we create a set of axes on our figure, making a single subplot that takes up the entire frame of the figure. Finally, we write the plot to a file and to the screen from the canvas, which makes sense, because that’s what connects the matplotlib routines to the hardware.
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
fig = Figure(figsize=(6, 4))
canvas = FigureCanvas(fig)
ax = fig.add_subplot(111)
ax.plot([1, 2, 3, 2, 3, 4, 3, 4, 5])
ax.set_title('A simple plot')
ax.grid(True)
ax.set_xlabel('time')
ax.set_ylabel('volts')
canvas.print_figure('figures.pdf')
canvas.show()
The code in this example is native matplotlib object-oriented (OO) code. In its purest form, it’s the way matplotlib code is supposed to be written. The code is entirely transportable from one computer to another irrespective of the operating system, so long as the qt5Agg backend has been included in the local machine’s Python installation. In this case, the output should look the same, whether it’s on the screen or in a file, on Microsoft Windows, macOS, or any of the different flavors of Linux. By the way, if another machine does not have the qt5Agg backend installed, you can simply change lines 1 and 2 to a different backend that is installed, and the program should work as expected, with no discernible differences.
All of the routines called in lines 5 and 7–12 are part of the Artist module and the eponymous Artist class of matplotlib. Collectively and individually, all the routines that get attached to fig and its descendant ax are known as Artists: add_subplot, plot, title, grid, xlabel, etc. Artists are those matplotlib objects that draw on the canvas, including figure.
The PyPlot (scripting) layer
For newcomers to Python, learning about backends and the OOP syntax can create a barrier to code development, particularly engineers and scientists who come to Python after having first been exposed to MATLAB. This is why the PyPlot module was developed, to provide a simpler and more familiar interface to those coming from software packages like MATLAB, or simply for those who are new to Python programming.
Consider, for example, plotting script of a sine function,
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 4.*np.pi, 33)
y = np.sin(x)
plt.plot(x, y)
plt.show()
After importing NumPy and PyPlot, we simply define the x-y arrays in two lines, make a plot in the next line, and then display it in the last line: the epitome of simplicity.
PyPlot and backends
There is no mention of a backend in this syntax. Nevertheless, one must be used so that matplotlib can communicate with the computer.So how does a backend get loaded using PyPlot? And which backend? First, a backend is loaded when PyPlot is imported. Second, which backend is loaded is determined by how you launch IPython. If you launch it from a terminal or from a Jupyter notebook, the default backend is set by a matplotlib configuration file named matplotlibrc on your computer. The file was put on your computer, perhaps without your knowledge, when matplotlib was installed, for example using the Anaconda or Enthought installations of Python. You can find out where this file is from an IPython prompt by typing
In [1]: import matplotlib
In [2]: matplotlib.matplotlib_fname()
Alternatively, if you are using a Python IDE like Spyder, the backend that is used is set in a Preferences menu and loaded when the IDE is launched. In any case, you can find out which backend was installed in your IPython shell using a IPython magic command
In [3]: %matplotlib
Out[3]: Using matplotlib backend: Qt5Agg
Thus, using PyPlot frees you up from thinking about the backend—how matplotlib is connected to your computer’s hardware—when writing matplotlib routines. That’s a good thing.
PyPlot’s “state-machine” environment
For very simple plots, you can proceed using the syntax introduced before. In this syntax, the only matplotlib prefix used is plt.You can do most of the things you want to do with matplotlib working in this way. You can make single plots or plots with multiple subplots, as demonstrated.When working in this mode with PyPlot, we are working in a “state-machine” environment, meaning that where on a canvas Py-Plot adds features (i.e., Artists) depends on the state of the program.
For example, in the program which used subplot, you make first subplot by including plt.subplot(2,1, 1) in the program. Everything that comes after that statement affects that subplot, until the program comes to the line plt.subplot(2,1, 2), which opens up a second subplot. After that statement, everything affects the second subplot. You’ve changed the “state” of the “machine” (i.e., the FigureCanvas object). Which subplot is affected by commands in the program depends on which state the machine is in.
Comments
Post a Comment