How do I use the "object-oriented interface" without having to rely on pyplot?

I’ve used matplotlib since 2011 and came from MATLAB so I know that it began its life as python replacement for MATLAB plotting functions.

In the intervening years, the object-oriented interface has evolved and I’ve seen it recommended over pyplot in more than one place, for example here: https://matplotlib.org/stable/tutorials/introductory/lifecycle.html

It says:

A note on the Object-Oriented API vs. Pyplot

Matplotlib has two interfaces. The first is an object-oriented (OO) interface. In this case, we utilize an instance of axes.Axes in order to render visualizations on an instance of figure.Figure.

The second is based on MATLAB and uses a state-based interface. This is encapsulated in the pyplot module. See the pyplot tutorials for a more in-depth look at the pyplot interface.

Most of the terms are straightforward but the main thing to remember is that:

  • The Figure is the final image that may contain 1 or more Axes.
  • The Axes represent an individual plot (don’t confuse this with the word “axis”, which refers to the x/y axis of a plot).

We call methods that do the plotting directly from the Axes, which gives us much more flexibility and power in customizing our plot.

Note: In general, try to use the object-oriented interface over the pyplot interface.

Ok! I find working with objects natural so I prefer that. Sold!

But then the tutorial goes on to start with:

import numpy as np
import matplotlib.pyplot as plt

and

fig, ax = plt.subplots()

So what is it now? Are we using pyplot or Axes and Figure? I have yet to find an ostensibly object-oriented example that does not rely on pyplot.

This mixing of paradigms in apparent contravention of the recommendations is, at the very least, confusing.

I have tried to work without relying on pyplot. Working in a jupyter notebook, I tried creating a figure object like this:

import matplotlib as mpl

fig = mpl.figure.Figure()
ax = mpl.axis.Axes(fig, [0.1, 0.1, 0.7, 0.7])

This results in no visible output (using the inline backend). If I try and make the figure appear:

fig.show()

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-12-73d731ead0b0> in <module>
----> 1 fig.show()

/usr/lib/python3.8/site-packages/matplotlib/figure.py in show(self, warn)
    405         """
    406         if self.canvas.manager is None:
--> 407             raise AttributeError(
    408                 "Figure.show works only for figures managed by pyplot, "
    409                 "normally created by pyplot.figure()")

AttributeError: Figure.show works only for figures managed by pyplot, normally created by pyplot.figure()

tl; dr - how can I routinely create empty Axes and display them in a jupyter notebook without having to use pyplot?

You don’t. pyplot is certainly the preferred way to create a figure. After that you need not use pyplot, because once you have a figure you can create all the other objects. However, pyplot still has some useful convenience functions.

The point of the recommendation is not to slavishly disregard the pyplot module, but to not use its state-based machinery where it tries to guess what axes you are working with based on the axes you drew on previously. Hence ax.plot is preferred to plt.plot because the former is explicit.

Its possible we could move plt.figure, plt.subplots somewhere else, but the practical advantages of doing so are minimal.

Okay. It would be helpful to have that exactly this:

The point of the recommendation is not to slavishly disregard the pyplot module, but to not use its state-based machinery where it tries to guess what axes you are working with based on the axes you drew on previously. Hence ax.plot is preferred to plt.plot because the former is explicit.

included in the documentation. (Is there a repo for the website documentation on github? If so I can create a pull request.)

You wrote that pyplot is the preferred way to create a figure. But is it possible to create the figure using matplotlib.figure.Figure() (I assume it must be) and how would that work?

1 Like

You can, but its not trivial. You need to choose a backend, and then call new_figure_manager and then use that manager to access the figure.