Pyplot vs Axes : setting the image to plot a colorbar

Hello everyone.

I have specific tripcolor plots I want to handle and I want to be able to :

  1. put them in specific Axes
  2. plot a colorbar attached to them without knowing too much about colorbars meaning I want to be able to use pyplot.colorbar and not the seemingly more complicated Figure.colorbar

There are at least two ways one can do that (which is why I do not want to open a bug report since it is not really a bug) but I don’t know which one is “best practice” for what I want to do.

To be a little more precise, let us say I want to create some function draw(ax) which makes some kind of tripcolor plot in the Axes ax.

First way: use pyplot.sca + pyplot.tripcolor
def draw(ax, *args):
T, c = prepare_plot(*args)
plt.sca(ax)
plt.tripcolor(T, c)

Second way: use pyplot.sci + Axes.tripcolor
def draw(ax, *args):
T, c = prepare_plot(*args)
coll = ax.tripcolor(T, c)
plt.sci(coll)

Which one is the “expected” way to write this type of code? And if anyone can explain to me why the method of Axes version of the function does not set the image itself I’d be happy to learn. Why is Axes._sci a private function and pyplot.sci a public one?

Hi @DrizztSama we have some discussion about the two interfaces and why you might want to use one over the other here:
https://matplotlib.org/stable/users/explain/figure/api_interfaces.html

Note that plt.colorbar is just a wrapper around Figure.colorbar so the latter shouldn’t be any more complicated.

I actually hadn’t heard of plt.sci before, but I suspect that whatever you are doing after plt.sci can also be done using a method on coll.

Hi @rcomer, and I guess Happy New Year to begin with :wink:

Just to clarify what I meant by plt.colorbar is “easier” than the Figure.colorbar is this (from Figure.colorbar) :

The matplotlib.cm.ScalarMappable (i.e., AxesImage, ContourSet, etc.) described by this colorbar. This argument is mandatory for the Figure.colorbar method but optional for the pyplot.colorbar function, which sets the default to the current image.

In my head most people (users of a library that I’m working on say) will be mostly familiar with the idiom plt.colorbar() to expect a colorbar to appear next to their plot but would not know necessarily what to feed to Figure.colorbar. Of course it can be overcome with a little digging or examples or whatever.

The difference between the two it this famous sci because for instance pyplot.tripcolor is just a wrapper around Axes.tripcolor but it also sets the current image.

Thanks for the link, I came across it before but I think I never took the time to read it thoroughly…

I guess the First way I proposed is kind of a fully ‘implicit API’ implementation and the Second way a mixed explicit/implicit API implementation. I guess a fully ‘explicit API’ implementation would be:

def draw(ax, *args):
    T, c = prepare_plot(*args)
    return ax.tripcolor(T, c)

and then let the user handle the colorbar. But I feel like the user is then somewhat forced to use the explicit API because the natural usage would be (from my perspective)

fig, ax = plt.subplots(...)
coll = draw(ax, ...)
fig.colorbar(coll)

and even though this feels natural to me I don’t like to impose my codestyle preferences to users if I can avoid it.

I understand that it looks very Much Ado about Nothing though… I just wanted to know what other people thought about it.

A library can act at the figure level, the axes level, or the artist level. If you are acting at the figure level, then I’d say go ahead and add the colorbar for the user. If you are acting at the artist level, then I would return the created artist, and not make the colorbar.

Note that you can mix the paradigms - calling sci on the contour artist doesn’t hurt anything and allows plt.colorbar(). You could also make mydraw() work on the current axes with def mydraw(*args, ax=None) and then not specifying ax would work as a pyplot function.