Skip to content

Commit aa24c65

Browse files
committed
ENH: Add Axes.colorbar() method
1 parent a895fb3 commit aa24c65

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,73 @@ def legend(self, *args, **kwargs):
355355
def _remove_legend(self, legend):
356356
self.legend_ = None
357357

358+
def colorbar(self, mappable=None, *, use_gridspec=True, **kwargs):
359+
"""
360+
Add a colorbar next to the Axes.
361+
362+
Parameters
363+
----------
364+
mappable : `matplotlib.colorizer.ColorizingArtist`, optional
365+
The `matplotlib.colorizer.ColorizingArtist` (i.e., `.AxesImage`,
366+
`.ContourSet`, etc.) described by this colorbar.
367+
368+
If not given, the mappable is inferred from the Axes. If there is exactly
369+
one image or collection, this is used as mappable. Otherwise, an error is
370+
raised and you must specify the mappable explicitly.
371+
372+
Note that one can create a `.colorizer.ColorizingArtist` "on-the-fly"
373+
to generate colorbars not attached to a previously drawn artist, e.g.
374+
::
375+
376+
cr = colorizer.Colorizer(norm=norm, cmap=cmap)
377+
ax.colorbar(colorizer.ColorizingArtist(cr))
378+
379+
Returns
380+
-------
381+
colorbar : `~matplotlib.colorbar.Colorbar`
382+
383+
Other Parameters
384+
----------------
385+
use_gridspec : bool, optional
386+
If *ax* is positioned with a subplotspec and *use_gridspec*
387+
is ``True``, then *cax* is also positioned with a subplotspec.
388+
389+
%(_make_axes_kw_doc)s
390+
%(_colormap_kw_doc)s
391+
392+
Notes
393+
-----
394+
This method is a convenience shortcut for the most common case that you have
395+
one mappable in the Axes and want to create a colorbar for it, which is
396+
located right beside the Axes.
397+
398+
::
399+
ax.imshow(data)
400+
ax.colorbar()
401+
402+
is equivalent to
403+
404+
::
405+
im = ax.imshow(data)
406+
fig.colorbar(im, ax=ax)
407+
408+
Use `.Figure.colorbar` if you need more control on placing the colorbar.
409+
"""
410+
if mappable is None:
411+
# autodetect the mappable
412+
colormapped_artists = [*self.images, *self.collections]
413+
if len(colormapped_artists) != 1:
414+
raise RuntimeError(
415+
"Axes.colormap() requires exactly one colormapped Artist in the "
416+
f"Axes, but found {len(colormapped_artists)}. In ambiguous cases, "
417+
"please specify the mappable for the colorbar explicitly."
418+
)
419+
mappable = colormapped_artists[0]
420+
421+
return self.figure.colorbar(
422+
mappable, ax=self, use_gridspec=use_gridspec, **kwargs
423+
)
424+
358425
def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs):
359426
"""
360427
Add a child inset Axes to this existing Axes.

lib/matplotlib/tests/test_axes.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9329,6 +9329,24 @@ def test_automatic_legend():
93299329
assert ax.get_yticklabels()[0].get_text() == 'b'
93309330

93319331

9332+
def test_automatic_colorbar():
9333+
"""Test that Axes.colorbar() without arguments uses the only mappable."""
9334+
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)
9335+
9336+
im = ax1.imshow([[0, 1], [2, 3]])
9337+
cb = ax1.colorbar()
9338+
assert cb.mappable is im
9339+
9340+
path_collection = ax2.scatter([0, 1], [0, 1], c=[0, 1])
9341+
cb2 = ax2.colorbar()
9342+
assert cb2.mappable is path_collection
9343+
9344+
ax3.imshow([[0, 1], [2, 3]])
9345+
ax3.scatter([0, 1], [0, 1], c=[0, 1])
9346+
with pytest.raises(RuntimeError, match="requires exactly one colormapped Artist"):
9347+
ax3.colorbar()
9348+
9349+
93329350
def test_plot_errors():
93339351
with pytest.raises(TypeError, match=r"plot\(\) got an unexpected keyword"):
93349352
plt.plot([1, 2, 3], x=1)

0 commit comments

Comments
 (0)