Chapter 3. matplotlib APIs and Integrations

In the previous chapter, we examined the architecture of matplotlib by using the library itself to visualize some aspects of the structure of module imports, particularly the ones related to the scripting, artist, and backend layers of the matplotlib architecture. In this chapter, we are going to examine the developer interfaces against the backdrop of this architectural discussion.

The matplotlib module comes with what are essentially three different application programming interfaces:

  • The pylab interface, a MATLAB analog (deprecated)
  • The pyplot interface, which is synonymous with the scripting layer from the last chapter
  • The matplotlib object-oriented interface

We will define these and talk more about them in the following sections. Since they are covered in great detail elsewhere, we won't spend much time going over each of the functions that is available in the API. Rather we will demonstrate typical good usage for each API type and the circumstances under which their use would be recommended. Afterwards we will take a look at how matplotlib is integrated with the other scientific computing and visualization libraries.

To follow along with this chapter's code, clone the notebook's repository and start up IPython by using the following commands:

$ git clone https://github.com/masteringmatplotlib/apis.git
$ cd apis
$ make

We're going to create some more libraries in this chapter, and we will use a custom color palette for our results. So, let's set them up now in the following way:

In [1]: import matplotlib 
        matplotlib.use('nbagg')
        %matplotlib inline
In [2]: import numpy as np
        import matplotlib.pyplot as plt
        import matplotlib as mpl
        from matplotlib.backends import backend_agg
        from matplotlib.colors import LinearSegmentedColormap
        from matplotlib.gridspec import GridSpec
        import seaborn as sns
        from IPython.display import Image 
In [3]: pallete_name = "husl"
        colors = sns.color_palette(pallete_name, 8)
        colors.reverse()
        cmap = mpl.colors.LinearSegmentedColormap.from_list(
            pallete_name, colors)

The procedural pylab API

The pylab API is a procedural interface to matplotlib's underlying object-oriented Python API. As mentioned in the previous chapter and stated in the matplotlib FAQ, the pylab module has been deprecated. The pyplot module is the preferred API for scripting. The original vision of pylab—to provide MATLAB users a nearly one-to-one mapping of the software they knew with that of an open source platform—has been accomplished. In the 12 years since its inception, matplotlib has become a household name in scientific computing circles, and as a result the need for pylab has decreased greatly.

The drawbacks of pylab include the following:

  • It hides the workings (and thus, the deeper knowledge) of matplotlib, thus preventing the natural discovery of deeper feature sets that are available to the user through matplotlib objects.
  • The additional development and maintenance of pylab are a burden for the matplotlib team in its continued efforts to provide the MATLAB functionality that wraps the already-existing functions from NumPy and matplotlib.
  • The import * expression is used to pull pylab into the current namespace (thus, going against Python's philosophical tenet of explicit is better than implicit). The gains of simplicity in this are debatable. What's more, with import *, you don't know the module from which a function or an object comes.

Despite the reasons for not using pylab, there are some motivating factors for discussing this old API here:

  • Completeness; pylab is still released with matplotlib
  • A warning to the readers—don't base your new projects on it
  • Most importantly, pylab introduces the means by which users may migrate from their MATLAB-based pylab projects to the preferred matplotlib API

It is the last point in particular that we are the most interested in—providing the recent matplotlib adopters with extensive knowledge of MATLAB and ways to utilize their old skills and apply them to the supported matplotlib APIs. First, let's have a quick overview of what pylab provides.

The pylab interface is comprised of functions that are categorized into the following areas:

  • Plotting
  • Event handling
  • Matrices
  • Probability
  • Statistics
  • Time series analysis
  • Dates

It also includes a final Other category consisting of a handful of miscellaneous functions ranging from utility functions that save data to polynomial fitting. These functions are all actually defined elsewhere, though this defining is not done in the pylab module itself. Many of them are pulled from NumPy and the rest are imported from matplotlib.mlab.

To motivate notes on migration, let's start with a simple MATLAB example. Check out the following function:

The procedural pylab API

Now, let's plot the gradient for the preceding function. Here is the MATLAB code that accomplishes this:

[X,Y] = meshgrid(-2:.2:2);
Z = X.*exp(-X.^2 - Y.^2);
[DX,DY] = gradient(Z,.2,.2);
figure
contour(X,Y,Z)
hold on
quiver(X,Y,DX,DY)
hold off

Using the deprecated pylab interface, we can obtain the same result and in the process recognize the near isomorphism between MATLAB and pylab:

In [5]: from matplotlib.pylab import *

        (y, x) = mgrid[-2:2.1:0.2,-2:2.1:0.2]
        z = x * exp(-x ** 2 - y ** 2)
        (dy, dx) = gradient(z)

        quiver(x, y, dx, dy, z, cmap=cmap)
        hold(True)
        contour(x, y, z, 10, cmap=cmap)
        show()

From this, we will get the following plot, which is a nearly exact (arguably better looking) match of the graph presented in the MATLAB quiver documentation:

The procedural pylab API

In the pylab code, we saw the following calls:

  • mgrid, exp, and gradient
  • quiver, hold, contour, and show

The first set of functions that are listed are from NumPy; the second set is from matplotlib. Knowing this will allow us to migrate from pylab * to numpy.* and matplotlib.pyplot. However, if you are unfamiliar with these libraries, how does one know where to look?

If you open the pylab.py file from a git clone repository of matplotlib or look at the files online, you will see that this module consists entirely of docstrings and imports and it has no actual function definitions. Most of the code comes from the following sources:

  • matplotlib.mlab
  • matplotlib.pyplot
  • matplotlib.cbook (which is also known as a cookbook—a utility function module)
  • numpy
  • Various numpy.* modules

The following rules of thumb can be used to figure out whether you need to find your desired function in the matplotlib or NumPy code bases:

  • If the function call has to deal directly with either the plotting, axes, figures, projections, and other transformations, or other visual elements of the plot, look for the function in matplotlib
  • Likewise, if the function is concerned with the saving of images, the configuring of formats, the selecting of colors, and so on, look for it in matplotlib
  • If the function is concerned with data, data types, mathematical operations, or transformations of data, search for the function in NumPy

To give you a better sense of the last item, some of the other NumPy functions imported by pylab are from the following modules:

  • The fast Fourier transform (FFT) module
  • The linear algebra module
  • The masked array module

The other matplotlib libraries that were imported in pylab include the dates and finance modules.

All of these can represent many potential places that you can look at when trying to figure out how to use the recommended matplotlib API. Deducing the probable module from the function name should be enough most of the time. If your first guess doesn't locate the function's module, it might be a great idea to grep the source. When migrating from pylab to pyplot, you might want to keep a check on matplotlib and NumPy in the following way:

$ cd ~/lab
$ git clone https://github.com/numpy/numpy.git
$ git clone https://github.com/matplotlib/matplotlib.git

If you had assumed that gradient was in matplotlib and after a quick look in matplotlib.mlab, you didn't see it, you can then hop into the repository clone to locate the desired function by using the following commands:

$ git grep 'def gradient'
.../tests/test_triangulation.py:    def gradient_quad(x, y):
.../tri/triinterpolate.py:    def gradient(self, x, y):
.../tri/triinterpolate.py:    def gradient(self, x, y):

After taking a look at the content of these files, you'd realize that your desired gradient function wasn't present. Then you can try NumPy:

$ cd ../numpy
$ git grep 'def gradient'
numpy/lib/function_base.py:dezf gradient(f, *varargs, **kwargs):

Sure enough, this is more promising. Taking a look at numpy.__init__, which will then point you to numpy.lib.__init__, you will see that function_base gets pulled into the numpy namespace. This is the function that we were looking for. Now that we have gone through all these efforts, you should know about a shortcut that may provide you with insights when searching for the modules that house a given class or function. In an interactive Python session, you can use the help command. In addition to printing docstrings and function signatures, the help command will also indicate the module of the function or class in the very first line of the output. In our case, help(gradient) shows numpy.lib.function_base in the first line.

The place held by pylab is a venerable, even if an aging one; it has enormously helped the adoption of matplotlib, Python, and other general open source software in the world of scientific computing. Academia in many ways is the native home of open source and as such, matplotlib and Python are by now very much at home here. Now that matplotlib has secured its place in the scientific computing community along with the deprecation of pylab, it's time to use one of the two recommended methodologies to have an interface with the library.

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

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