|
10 | 10 | Colorbars indicate the quantitative extent of image data. Placing in
|
11 | 11 | a figure is non-trivial because room needs to be made for them.
|
12 | 12 |
|
13 |
| -The simplest case is just attaching a colorbar to each axes: |
| 13 | +Automatic placement of colorbars |
| 14 | +================================ |
| 15 | +
|
| 16 | +The simplest case is just attaching a colorbar to each axes. Note in this |
| 17 | +example that the colorbars steal some space from the parent axes. |
14 | 18 | """
|
15 | 19 | import matplotlib.pyplot as plt
|
16 | 20 | import numpy as np
|
|
28 | 32 | fig.colorbar(pcm, ax=ax)
|
29 | 33 |
|
30 | 34 | # %%
|
31 |
| -# The first column has the same type of data in both rows, so it may |
32 |
| -# be desirable to combine the colorbar which we do by calling |
33 |
| -# `.Figure.colorbar` with a list of axes instead of a single axes. |
| 35 | +# The first column has the same type of data in both rows, so it may be |
| 36 | +# desirable to have just one colorbar. We do this by passing `.Figure.colorbar` |
| 37 | +# a list of axes with the *ax* kwarg. |
34 | 38 |
|
35 | 39 | fig, axs = plt.subplots(2, 2)
|
36 | 40 | cmaps = ['RdBu_r', 'viridis']
|
|
41 | 45 | cmap=cmaps[col])
|
42 | 46 | fig.colorbar(pcm, ax=axs[:, col], shrink=0.6)
|
43 | 47 |
|
| 48 | +# %% |
| 49 | +# The stolen space can lead to axes in the same subplot layout |
| 50 | +# being different sizes, which is often undesired if the the |
| 51 | +# x-axis on each plot is meant to be comparable as in the following: |
| 52 | + |
| 53 | +fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True) |
| 54 | +X = np.random.randn(20, 20) |
| 55 | +axs[0].plot(np.sum(X, axis=0)) |
| 56 | +axs[1].pcolormesh(X) |
| 57 | +fig.colorbar(pcm, ax=axs[1], shrink=0.6) |
| 58 | + |
| 59 | +# %% |
| 60 | +# This is usually undesired, and can be worked around in various ways, e.g. |
| 61 | +# adding a colorbar to the other axes and then removing it. However, the most |
| 62 | +# straightforward is to use :ref:`constrained layout <constrainedlayout_guide>`: |
| 63 | + |
| 64 | +fig, axs = plt.subplots(2, 1, figsize=(4, 5), sharex=True, layout='constrained') |
| 65 | +axs[0].plot(np.sum(X, axis=0)) |
| 66 | +axs[1].pcolormesh(X) |
| 67 | +fig.colorbar(pcm, ax=axs[1], shrink=0.6) |
| 68 | + |
44 | 69 | # %%
|
45 | 70 | # Relatively complicated colorbar layouts are possible using this
|
46 | 71 | # paradigm. Note that this example works far better with
|
|
56 | 81 | fig.colorbar(pcm, ax=[axs[2, 1]], location='left')
|
57 | 82 |
|
58 | 83 | # %%
|
59 |
| -# Colorbars with fixed-aspect-ratio axes |
60 |
| -# ====================================== |
| 84 | +# Adjusting the spacing between colorbars and parent axes |
| 85 | +# ======================================================= |
| 86 | +# |
| 87 | +# The distance a colorbar is from the parent axes can be adjusted with the |
| 88 | +# *pad* keyword argument. This is in units of fraction of the parent axes |
| 89 | +# width, and the default for a vertical axes is 0.05 (or 0.15 for a horizontal |
| 90 | +# axes). |
| 91 | + |
| 92 | +fig, axs = plt.subplots(3, 1, layout='constrained', figsize=(5, 5)) |
| 93 | +for ax, pad in zip(axs, [0.025, 0.05, 0.1]): |
| 94 | + pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis') |
| 95 | + fig.colorbar(pcm, ax=ax, pad=pad, label=f'pad: {pad}') |
| 96 | +fig.suptitle("layout='constrained'") |
| 97 | + |
| 98 | +# %% |
| 99 | +# Note that if you do not use constrained layout, the pad command makes the |
| 100 | +# parent axes shrink: |
| 101 | + |
| 102 | +fig, axs = plt.subplots(3, 1, figsize=(5, 5)) |
| 103 | +for ax, pad in zip(axs, [0.025, 0.05, 0.1]): |
| 104 | + pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis') |
| 105 | + fig.colorbar(pcm, ax=ax, pad=pad, label=f'pad: {pad}') |
| 106 | +fig.suptitle("No layout manager") |
| 107 | + |
| 108 | +# %% |
| 109 | +# Manual placement of colorbars |
| 110 | +# ============================= |
| 111 | +# |
| 112 | +# Sometimes the automatic placement provided by ``colorbar`` does not |
| 113 | +# give the desired effect. We can manually create an axes and tell |
| 114 | +# ``colorbar`` to use that axes by passing the axes to the *cax* keyword |
| 115 | +# argument. |
| 116 | +# |
| 117 | +# Using ``inset_axes`` |
| 118 | +# -------------------- |
| 119 | +# |
| 120 | +# We can manually create any type of axes for the colorbar to use, but an |
| 121 | +# `.Axes.inset_axes` is useful because it is a child of the parent axes and can |
| 122 | +# be positioned relative to the parent. Here we add a colorbar centered near |
| 123 | +# the bottom of the parent axes. |
| 124 | + |
| 125 | +fig, ax = plt.subplots(layout='constrained', figsize=(4, 4)) |
| 126 | +pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis') |
| 127 | +ax.set_ylim([-4, 20]) |
| 128 | +cax = ax.inset_axes([0.3, 0.07, 0.4, 0.04]) |
| 129 | +fig.colorbar(pcm, cax=cax, orientation='horizontal') |
| 130 | + |
| 131 | +# %% |
| 132 | +# `.Axes.inset_axes` can also specify its position in data coordinates |
| 133 | +# using the *transform* keyword argument if you want your axes at a |
| 134 | +# certain data position on the graph: |
| 135 | + |
| 136 | +fig, ax = plt.subplots(layout='constrained', figsize=(4, 4)) |
| 137 | +pcm = ax.pcolormesh(np.random.randn(20, 20), cmap='viridis') |
| 138 | +ax.set_ylim([-4, 20]) |
| 139 | +cax = ax.inset_axes([7.5, -1.7, 5, 1.2], transform=ax.transData) |
| 140 | +fig.colorbar(pcm, cax=cax, orientation='horizontal') |
| 141 | + |
| 142 | +# %% |
| 143 | +# .. seealso:: |
| 144 | +# |
| 145 | +# :ref:`axes_grid` has methods for creating colorbar axes as well: |
| 146 | +# |
| 147 | +# - :ref:`demo-colorbar-with-inset-locator` |
| 148 | +# - :ref:`demo-colorbar-with-axes-divider` |
| 149 | +# |
| 150 | +# Colorbars attached to fixed-aspect-ratio axes |
| 151 | +# --------------------------------------------- |
61 | 152 | #
|
62 | 153 | # Placing colorbars for axes with a fixed aspect ratio pose a particular
|
63 | 154 | # challenge as the parent axes changes size depending on the data view.
|
|
77 | 168 | fig.colorbar(pcm, ax=ax, shrink=0.6)
|
78 | 169 |
|
79 | 170 | # %%
|
80 |
| -# One way around this issue is to use an `.Axes.inset_axes` to locate the |
81 |
| -# axes in axes coordinates. Note that if you zoom in on the axes, and |
82 |
| -# change the shape of the axes, the colorbar will also change position. |
| 171 | +# We solve this problem using `.Axes.inset_axes` to locate the axes in "axes |
| 172 | +# coordinates" (see :ref:`transforms_tutorial`). Note that if you zoom in on |
| 173 | +# the axes, and thus change the shape of the axes, the colorbar will also |
| 174 | +# change position. |
83 | 175 |
|
84 | 176 | fig, axs = plt.subplots(2, 2, layout='constrained')
|
85 | 177 | cmaps = ['RdBu_r', 'viridis']
|
|
94 | 186 | ax.set_aspect(1/2)
|
95 | 187 | if row == 1:
|
96 | 188 | cax = ax.inset_axes([1.04, 0.2, 0.05, 0.6])
|
97 |
| - fig.colorbar(pcm, ax=ax, cax=cax) |
98 |
| - |
99 |
| -plt.show() |
| 189 | + fig.colorbar(pcm, cax=cax) |
0 commit comments