Skip to content

Commit

Permalink
Backport PR matplotlib#26914: DOC: add a couple more placement exampl…
Browse files Browse the repository at this point in the history
…es, crosslink axes_grid [ci doc]
  • Loading branch information
rcomer authored and meeseeksmachine committed Sep 27, 2023
1 parent bf64c03 commit a361574
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"""
.. _demo-colorbar-with-axes-divider:
=========================
Colorbar with AxesDivider
=========================
Expand All @@ -8,6 +10,10 @@
method of the `.AxesDivider` can then be used to create a new axes on a given
side ("top", "right", "bottom", or "left") of the original axes. This example
uses `.append_axes` to add colorbars next to axes.
Users should consider simply passing the main axes to the *ax* keyword argument of
`~.Figure.colorbar` instead of creating a locatable axes manually like this.
See :ref:`colorbar_placement`.
"""

import matplotlib.pyplot as plt
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
"""
.. _demo-colorbar-with-inset-locator:
==============================================================
Controlling the position and size of colorbars with Inset Axes
==============================================================
This example shows how to control the position, height, and width of
colorbars using `~mpl_toolkits.axes_grid1.inset_locator.inset_axes`.
This example shows how to control the position, height, and width of colorbars
using `~mpl_toolkits.axes_grid1.inset_locator.inset_axes`.
Inset axes placement is controlled as for legends: either by providing a *loc*
option ("upper right", "best", ...), or by providing a locator with respect to
the parent bbox. Parameters such as *bbox_to_anchor* and *borderpad* likewise
work in the same way, and are also demonstrated here.
Users should consider using `.Axes.inset_axes` instead (see
:ref:`colorbar_placement`).
"""

import matplotlib.pyplot as plt
Expand Down
113 changes: 102 additions & 11 deletions galleries/users_explain/axes/colorbar_placement.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
Colorbars indicate the quantitative extent of image data. Placing in
a figure is non-trivial because room needs to be made for them.
The simplest case is just attaching a colorbar to each axes:
Automatic placement of colorbars
================================
The simplest case is just attaching a colorbar to each axes. Note in this
example that the colorbars steal some space from the parent axes.
"""
import matplotlib.pyplot as plt
import numpy as np
Expand All @@ -28,9 +32,9 @@
fig.colorbar(pcm, ax=ax)

# %%
# The first column has the same type of data in both rows, so it may
# be desirable to combine the colorbar which we do by calling
# `.Figure.colorbar` with a list of axes instead of a single axes.
# The first column has the same type of data in both rows, so it may be
# desirable to have just one colorbar. We do this by passing `.Figure.colorbar`
# a list of axes with the *ax* kwarg.

fig, axs = plt.subplots(2, 2)
cmaps = ['RdBu_r', 'viridis']
Expand All @@ -41,6 +45,27 @@
cmap=cmaps[col])
fig.colorbar(pcm, ax=axs[:, col], shrink=0.6)

# %%
# The stolen space can lead to axes in the same subplot layout
# being different sizes, which is often undesired if the the
# x-axis on each plot is meant to be comparable as in the following:

fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True)
X = np.random.randn(20, 20)
axs[0].plot(np.sum(X, axis=0))
axs[1].pcolormesh(X)
fig.colorbar(pcm, ax=axs[1], shrink=0.6)

# %%
# This is usually undesired, and can be worked around in various ways, e.g.
# adding a colorbar to the other axes and then removing it. However, the most
# straightforward is to use :ref:`constrained layout <constrainedlayout_guide>`:

fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True, layout='constrained')
axs[0].plot(np.sum(X, axis=0))
axs[1].pcolormesh(X)
fig.colorbar(pcm, ax=axs[1], shrink=0.6)

# %%
# Relatively complicated colorbar layouts are possible using this
# paradigm. Note that this example works far better with
Expand All @@ -56,8 +81,67 @@
fig.colorbar(pcm, ax=[axs[2, 1]], location='left')

# %%
# Colorbars with fixed-aspect-ratio axes
# ======================================
# Adjusting the spacing between colorbars and parent axes
# =======================================================
#
# The distance a colorbar is from the parent axes can be adjusted with the
# *pad* keyword argument. This is in units of fraction of the parent axes
# width, and the default for a vertical axes is 0.05 (or 0.15 for a horizontal
# axes).

fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(5, 5))
for ax, pad in zip(axs, [0.025, 0.05, 0.1]):
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
fig.colorbar(pcm, ax=ax, pad=pad, label=f'pad: {pad}')
fig.suptitle("layout='constrained'")

# %%
# Note that if you do not use constrained layout, the pad command makes the
# parent axes shrink:

fig, axs = plt.subplots(3, 1, figsize=(5, 5))
for ax, pad in zip(axs, [0.025, 0.05, 0.1]):
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
fig.colorbar(pcm, ax=ax, pad=pad, label=f'pad: {pad}')
fig.suptitle("No layout manager")

# %%
# Manual placement of colorbars
# =============================
#
# Sometimes the automatic placement provided by ``colorbar`` does not
# give the desired effect. We can manually create an axes and tell
# ``colorbar`` to use that axes by passing the axes to the *cax* keyword
# argument.
#
# Using ``inset_axes``
# --------------------
#
# We can manually create any type of axes for the colorbar to use, but an
# `.Axes.inset_axes` is useful because it is a child of the parent axes and can
# be positioned relative to the parent. Here we add a colorbar centered near
# the bottom of the parent axes.

fig, ax = plt.subplots(layout='constrained', figsize=(4, 4))
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
ax.set_ylim([-4, 20])
cax = ax.inset_axes([0.3, 0.07, 0.4, 0.04])
fig.colorbar(pcm, cax=cax, orientation='horizontal')

# %%
# `.Axes.inset_axes` can also specify its position in data coordinates
# using the *transform* keyword argument if you want your axes at a
# certain data position on the graph:

fig, ax = plt.subplots(layout='constrained', figsize=(4, 4))
pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis')
ax.set_ylim([-4, 20])
cax = ax.inset_axes([7.5, -1.7, 5, 1.2], transform=ax.transData)
fig.colorbar(pcm, cax=cax, orientation='horizontal')

# %%
# Colorbars attached to fixed-aspect-ratio axes
# ---------------------------------------------
#
# Placing colorbars for axes with a fixed aspect ratio pose a particular
# challenge as the parent axes changes size depending on the data view.
Expand All @@ -77,9 +161,10 @@
fig.colorbar(pcm, ax=ax, shrink=0.6)

# %%
# One way around this issue is to use an `.Axes.inset_axes` to locate the
# axes in axes coordinates. Note that if you zoom in on the axes, and
# change the shape of the axes, the colorbar will also change position.
# We solve this problem using `.Axes.inset_axes` to locate the axes in "axes
# coordinates" (see :ref:`transforms_tutorial`). Note that if you zoom in on
# the parent axes, and thus change the shape of it, the colorbar will also
# change position.

fig, axs = plt.subplots(2, 2, layout='constrained')
cmaps = ['RdBu_r', 'viridis']
Expand All @@ -94,6 +179,12 @@
ax.set_aspect(1/2)
if row == 1:
cax = ax.inset_axes([1.04, 0.2, 0.05, 0.6])
fig.colorbar(pcm, ax=ax, cax=cax)
fig.colorbar(pcm, cax=cax)

plt.show()
# %%
# .. seealso::
#
# :ref:`axes_grid` has methods for manually creating colorbar axes as well:
#
# - :ref:`demo-colorbar-with-inset-locator`
# - :ref:`demo-colorbar-with-axes-divider`
4 changes: 2 additions & 2 deletions galleries/users_explain/axes/constrainedlayout_guide.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
.. _constrainedlayout_guide:
================================
========================
Constrained Layout Guide
================================
========================
Use *constrained layout* to fit plots within your figure cleanly.
Expand Down

0 comments on commit a361574

Please sign in to comment.