Nearly all introductory matplotlib texts and a large portion of intermediate matplotlib material focuses on the pyplot scripting layer in matplotlib. The pyplot interface offers a highly flexible and convenient means to get data into the plots with no hassles. The simple-line.py
script from the last chapter highlighted this. However, this can lead one to make an incorrect assessment of pyplot.
The pyplot API is not simply a tool for beginners, especially with the advanced use of data taking place in the object-oriented API. Rather, in pyplot's simplicity rests its power. It is the right tool to use when you need the following:
Let's explore the pyplot API a bit with a real-world example that matches several of the use cases described in the preceding sections. The example is pertaining to the plotting of magnetic fields.
The following vector equation describes the magnetic field along an infinite wire by using cylindrical coordinates:
This states that the magnetic vector is defined as the product of the magnetic constant and the current I in the wire divided by 2π and the distance from s to a point. This gives us the magnitude of the magnetic field. The direction off the cylindrical axis is indicated by the component, thus giving us a cylindrical vector.
To convert this to the Cartesian coordinates ( and components instead of a component) that can be used in this example, we can use trigonometry to make the following substitution:
In the preceding equation, s2 = x2 + y2. Due to the defined value of the magnetic s
constant, we can reduce our equation to the following:
In the preceding equation, the value of μ is 2x10-7 volt seconds per ampere meters. For this problem, we're interested in looking at an x-y plane cross-section of a wire in the z axis carrying a current of 50 A (positive direction). We will calculate the numerical solutions for an area of 4 square meters.
Let's set our initial values:
In [10]: u = 2.0e-7 I = 50 (xmin, xmax, _) = xrange = (-2.0, 2.0, 30) (ymin, ymax, _) = yrange = (-2.0, 2.0, 30)
The last value of each tuple represents the number of points that we want to define along each axis. We won't use these values individually (only as a part of the xrange
and yrange
variables). So, we will assign them to the ignore variable, the underscore. We can now create a 30 × 30 grid (evenly spaced throughout the 4 square meters) and from this grid, we can calculate the squared distance values in the following way:
In [11]: x, y = np.meshgrid( np.linspace(*xrange), np.linspace(*yrange)) s2 = (x ** 2) + (y ** 2)
Since we are not using pylab anymore, we will need to access NumPy functions from their own namespace. We've imported and aliased these functions to np
according to the community convention. In this case, we've used the linspace
function to provide us with a range of values which take as arguments a minimum for the range, a maximum, and the total number of values to generate between these two. The resulting arrays are then given as an input for the meshgrid
function. The meshgrid
function returns the coordinate matrices, which are used for the evaluations of vector fields over a grid defined by the inputs. In other words, this is how we perform n-dimensional vector field computations in NumPy.
Lastly, we will create another grid that represents the squared values for each coordinate in our grid.
Now that we have the x and y components for the coordinates over the given range as well as the squared distance s2, we can obtain the vector components of the magnetic field and use each of these to create the final equation for the complete magnetic field for the chosen values, that is, the vector components sum:
In [12]: Bx = u * I * (-y / s2) By = u * I * (x / s2) B = Bx + By
Step by step, we have converted the magnetic field equation in Cartesian coordinates to a set of numerical values that can be accepted by matplotlib. In this section, we will use the scripting layer. So, all the calls will be through the pyplot
module, which is imported as plt
.
Let's feed pyplot:
In [13]: plt.figure(figsize=(12,10)) plt.quiver(x, y, Bx, By, B, cmap=cmap) plt.axis(ranges=1, aspect=1) plt.title('Magnetic Field of a Wire with I=50 A', fontsize=20) plt.xlabel('$x mathrm{(m)}$', fontsize=16) plt.ylabel('$y mathrm{(m)}$', fontsize=16) plt.colorbar(orientation='vertical') plt.show()
The following plot is the result of the preceding command:
Most of the preceding plt.*
calls should be familiar to you owing to your experience with matplotlib. The one thing that may be new for you is the use of the in-lined LaTeX for the x and y labels.
Let's zoom in on the magnetic field and overlay our vectors on an image generated from the continuous values in our previously defined range:
In [14]: figure, axes = plt.subplots(figsize=(12,10)) im = axes.imshow(B, extent=ranges, cmap=sns.dark_palette("#666666", as_cmap=True)) q = axes.quiver(x, y, Bx, By, B, cmap=cmap) figure.colorbar(q, shrink=0.96) plt.axis([-0.5, 0.5, -0.5, 0.5], aspect=1) plt.title('Magnetic Field of a Wire with I=50 A', fontsize=20) plt.xlabel('$x mathrm{(m)}$', fontsize=16) plt.ylabel('$y mathrm{(m)}$', fontsize=16) plt.show()
The following plot is the result of the preceding command:
As you know, the zooming of the magnetic field plot is accomplished by defining new limits on the axes. With this plot, we are able to see not only the vectors (the magnitude and direction) of the selected grid and the evenly distributed coordinates, but also the smooth and continuous magnitude of the magnetic field, which appears in shades of grey.
We have seen some use cases that are a good fit for the pyplot API, and we have gone through an example. The next question that you may naturally ask is: when should we not use pyplot? All the examples in the bullet list at the beginning of this section have one thing in common—they imply that one or more individuals are working on problems in a simple, manual workflow. There are other workflows.
If you're going to generate huge numbers of plots, process vast quantities of data, or have particular needs for highly customized plots, you'll want to skip the scripting layer and work directly with the artist or backend layers.