8000 Merge pull request #11388 from ImportanceOfBeingErnest/doc_constraine… · matplotlib/matplotlib@9d81809 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9d81809

Browse files
authored
Merge pull request #11388 from ImportanceOfBeingErnest/doc_constrained_layout_improvement
DOC: Constrained layout tutorial improvements
2 parents b841556 + 553bfab commit 9d81809

File tree

3 files changed

+73
-51
lines changed

3 files changed

+73
-51
lines changed

tutorials/intermediate/constrainedlayout_guide.py

Lines changed: 68 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,24 @@
99
legends and colorbars so that they fit in the figure window while still
1010
preserving, as best they can, the logical layout requested by the user.
1111
12-
*constrained_layout* is similar to *tight_layout*, but uses a constraint
13-
solver to determine the size of axes that allows them to fit.
12+
*constrained_layout* is similar to
13+
:doc:`tight_layout</tutorials/intermediate/tight_layout_guide>`,
14+
but uses a constraint solver to determine the size of axes that allows
15+
them to fit.
16+
17+
*constrained_layout* needs to be activated before any axes are added to
18+
a figure. Two ways of doing so are
19+
20+
* using the respective argument to :func:`~.pyplot.subplots` or
21+
:func:`~.pyplot.figure`, e.g.::
22+
23+
plt.subplots(contrained_layout=True)
24+
25+
* activate it via :ref:`rcParams<matplotlib-rcparams>`, like::
26+
27+
plt.rcParams['figure.constrained_layout.use'] = True
28+
29+
Those are described in detail throughout the following sections.
1430
1531
.. warning::
1632
@@ -83,7 +99,7 @@ def example_plot(ax, fontsize=12, nodec=False):
8399
example_plot(ax)
84100

85101
###############################################################################
86-
# Specifying `constrained_layout=True` in the call to `plt.subplots`
102+
# Specifying ``constrained_layout=True`` in the call to ``plt.subplots``
87103
# causes the layout to be properly constrained.
88104

89105
fig, axs = plt.subplots(2, 2, constrained_layout=True)
@@ -102,9 +118,9 @@ def example_plot(ax, fontsize=12, nodec=False):
102118
#
103119
# .. note::
104120
#
105-
# For the `pcolormesh` kwargs (``pc_kwargs``) we use a dictionary.
121+
# For the `~.axes.Axes.pcolormesh` kwargs (``pc_kwargs``) we use a dictionary.
106122
# Below we will assign one colorbar to a number of axes each containing
107-
# a `ScalarMappable`; specifying the norm and colormap ensures
123+
# a `~.cm.ScalarMappable`; specifying the norm and colormap ensures
108124
# the colorbar is accurate for all the axes.
109125

110126
arr = np.arange(100).reshape((10, 10))
@@ -117,7 +133,8 @@ def example_plot(ax, fontsize=12, nodec=False):
117133

118134
############################################################################
119135
# If you specify a list of axes (or other iterable container) to the
120-
# ``ax`` argument of ``colorbar``, constrained_layout will take space from all # axes that share the same gridspec.
136+
# ``ax`` argument of ``colorbar``, constrained_layout will take space from all
137+
# axes that share the same gridspec.
121138

122139
fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
123140
for ax in axs.flatten():
@@ -153,7 +170,7 @@ def example_plot(ax, fontsize=12, nodec=False):
153170
# Suptitle
154171
# =========
155172
#
156-
# ``constrained_layout`` can also make room for ``suptitle``.
173+
# ``constrained_layout`` can also make room for `~.figure.Figure.suptitle`.
157174

158175
fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
159176
for ax in axs.flatten():
@@ -165,10 +182,10 @@ def example_plot(ax, fontsize=12, nodec=False):
165182
# Legends
166183
# =======
167184
#
168-
# Legends can be placed outside
169-
# of their parent axis. Constrained-layout is designed to handle this.
185+
# Legends can be placed outside of their parent axis.
186+
# Constrained-layout is designed to handle this for :meth:`.Axes.legend`.
170187
# However, constrained-layout does *not* handle legends being created via
171-
# ``fig.legend()`` (yet).
188+
# :meth:`.Figure.legend` (yet).
172189

173190
fig, ax = plt.subplots(constrained_layout=True)
174191
ax.plot(np.arange(10), label='This is a plot')
@@ -190,8 +207,8 @@ def example_plot(ax, fontsize=12, nodec=False):
190207
# For constrained_layout, we have implemented a padding around the edge of
191208
# each axes. This padding sets the distance from the edge of the plot,
192209
# and the minimum distance between adjacent plots. It is specified in
193-
# inches by the keyword arguments `w_pad` and `h_pad` to the function
194-
# `fig.set_constrained_layout_pads`:
210+
# inches by the keyword arguments ``w_pad`` and ``h_pad`` to the function
211+
# `~.figure.Figure.set_constrained_layout_pads`:
195212

196213
fig, axs = plt.subplots(2, 2, constrained_layout=True)
197214
for ax in axs.flatten():
@@ -210,7 +227,7 @@ def example_plot(ax, fontsize=12, nodec=False):
210227
hspace=0., wspace=0.)
211228

212229
##########################################
213-
# Spacing between subplots is set by `wspace` and `hspace`. There are
230+
# Spacing between subplots is set by ``wspace`` and ``hspace``. There are
214231
# specified as a fraction of the size of the subplot group as a whole.
215232
# If the size of the figure is changed, then these spaces change in
216233
# proportion. Note in the blow how the space at the edges doesn't change from
@@ -229,10 +246,10 @@ def example_plot(ax, fontsize=12, nodec=False):
229246
# Spacing with colorbars
230247
# -----------------------
231248
#
232-
# Colorbars still respect the `w_pad` and `h_pad` values. However they will
233-
# be `wspace` and `hsapce` apart from other subplots. Note the use of a `pad`
234-
# kwarg here in the `colorbar` call. It defaults to 0.02 of the size of the
235-
# axis it is attached to.
249+
# Colorbars still respect the ``w_pad`` and ``h_pad`` values. However they will
250+
# be ``wspace`` and ``hsapce`` apart from other subplots. Note the use of a
251+
# ``pad`` kwarg here in the ``colorbar`` call. It defaults to 0.02 of the size
252+
# of the axis it is attached to.
236253

237254
fig, axs = plt.subplots(2, 2, constrained_layout=True)
238255
for ax in axs.flatten():
@@ -246,7 +263,7 @@ def example_plot(ax, fontsize=12, nodec=False):
246263
##########################################
247264
# In the above example, the colorbar will not ever be closer than 2 pts to
248265
# the plot, but if we want it a bit further away, we can specify its value
249-
# for `pad` to be non-zero.
266+
# for ``pad`` to be non-zero.
250267

251268
fig, axs = plt.subplots(2, 2, constrained_layout=True)
252269
for ax in axs.flatten():
@@ -259,16 +276,16 @@ def example_plot(ax, fontsize=12, nodec=False):
259276

260277
##########################################
261278
# rcParams
262-
# --------
279+
# ========
263280
#
264-
# There are five `rcParams` that can be set, either in a script
265-
# or in the `matplotlibrc` file. They all have the prefix
266-
# `figure.constrained_layout`:
281+
# There are five :ref:`rcParams<matplotlib-rcparams>` that can be set,
282+
# either in a script or in the `matplotlibrc` file.
283+
# They all have the prefix ``figure.constrained_layout``:
267284
#
268-
# - `use`: Whether to use constrained_layout. Default is False
269-
# - `w_pad`, `h_pad` Padding around axes objects.
285+
# - ``use``: Whether to use constrained_layout. Default is False
286+
# - ``w_pad``, ``h_pad``: Padding around axes objects.
270287
# Float representing inches. Default is 3./72. inches (3 pts)
271-
# - `wspace`, `hspace` Space between subplot groups.
288+
# - ``wspace``, ``hspace``: Space between subplot groups.
272289
# Float representing a fraction of the subplot widths being separated.
273290
# Default is 0.02.
274291

@@ -296,7 +313,7 @@ def example_plot(ax, fontsize=12, nodec=False):
296313
example_plot(ax2)
297314

298315
###############################################################################
299-
# More complicated gridspec layouts are possible...
316+
# More complicated gridspec layouts are possible.
300317

301318
fig = plt.figure(constrained_layout=True)
302319

@@ -377,17 +394,17 @@ def docomplicated(suptitle=None):
377394
# ================================
378395
#
379396
# There can be good reasons to manually set an axes position. A manual call
380-
# to `ax.set_position()` will set the axes so constrained_layout has no
381-
# effect on it anymore. (Note that constrained_layout still leaves the space
382-
# for the axes that is moved).
397+
# to `~.axes.Axes.set_position` will set the axes so constrained_layout has
398+
# no effect on it anymore. (Note that constrained_layout still leaves the
399+
# space for the axes that is moved).
383400

384401
fig, axs = plt.subplots(1, 2, constrained_layout=True)
385402
example_plot(axs[0], fontsize=12)
386403
axs[1].set_position([0.2, 0.2, 0.4, 0.4])
387404

388405
###############################################################################
389406
# If you want an inset axes in data-space, you need to manually execute the
390-
# layout using `fig.execute_constrained_layout()` call. The inset figure
407+
# layout using ``fig.execute_constrained_layout()`` call. The inset figure
391408
# will then be properly positioned. However, it will not be properly
392409
# positioned if the size of the figure is subsequently changed. Similarly,
393410
# if the figure is printed to another backend, there may be slight changes
@@ -414,7 +431,7 @@ def docomplicated(suptitle=None):
414431
#
415432
# ``constrained_layout`` will not work on subplots
416433
# created via the `subplot` command. The reason is that each of these
417-
# commands creates a separate `GridSpec` instance and `constrained_layout`
434+
# commands creates a separate `GridSpec` instance and ``constrained_layout``
418435
# uses (nested) gridspecs to carry out the layout. So the following fails
419436
# to yield a nice layout:
420437

@@ -520,33 +537,33 @@ def docomplicated(suptitle=None):
520537
#
521538
# Figures are laid out in a hierarchy:
522539
#
523-
# 1. Figure: `fig = plt.figure()`
540+
# 1. Figure: ``fig = plt.figure()``
524541
#
525-
# a. Gridspec `gs0 = gridspec.GridSpec(1, 2, figure=fig)`
542+
# a. Gridspec ``gs0 = gridspec.GridSpec(1, 2, figure=fig)``
526543
#
527-
# i. Subplotspec: `ss = gs[0, 0]`
544+
# i. Subplotspec: ``ss = gs[0, 0]``
528545
#
529-
# 1. Axes: `ax0 = fig.add_subplot(ss)`
546+
# 1. Axes: ``ax0 = fig.add_subplot(ss)``
530547
#
531-
# ii. Subplotspec: `ss = gs[0, 1]`
548+
# ii. Subplotspec: ``ss = gs[0, 1]``
532549
#
533-
# 1. Gridspec: `gsR = gridspec.GridSpecFromSubplotSpec(2, 1, ss)`
550+
# 1. Gridspec: ``gsR = gridspec.GridSpecFromSubplotSpec(2, 1, ss)``
534551
#
535-
# - Subplotspec: ss = gsR[0, 0]
552+
# - Subplotspec: ``ss = gsR[0, 0]``
536553
#
537-
# - Axes: `axR0 = fig.add_subplot(ss)`
554+
# - Axes: ``axR0 = fig.add_subplot(ss)``
538555
#
539-
# - Subplotspec: ss = gsR[1, 0]
556+
# - Subplotspec: ``ss = gsR[1, 0]``
540557
#
541-
# - Axes: `axR1 = fig.add_subplot(ss)`
558+
# - Axes: ``axR1 = fig.add_subplot(ss)``
542559
#
543560
# Each item has a layoutbox associated with it. The nesting of gridspecs
544561
# created with `.GridSpecFromSubplotSpec` can be arbitrarily deep.
545562
#
546-
# Each ``~matplotlib.axes.Axes` has *two* layoutboxes. The first one,
563+
# Each `~matplotlib.axes.Axes` has *two* layoutboxes. The first one,
547564
# ``ax._layoutbox`` represents the outside of the Axes and all its
548565
# decorations (i.e. ticklabels,axis labels, etc.).
549-
# The second layoutbox corresponds to the Axes' `ax.position`, which sets
566+
# The second layoutbox corresponds to the Axes' ``ax.position``, which sets
550567
# where in the figure the spines are placed.
551568
#
552569
# Why so many stacked containers? Ideally, all that would be needed are the
@@ -569,8 +586,8 @@ def docomplicated(suptitle=None):
569586
# the difference between the red ``pos`` box and the green ``ax`` box
570587
# is set by the size of the decorations around the Axes.
571588
#
572-
# In the code, this is accomplished by the entries in `.do_constrained_layout`
573-
# like::
589+
# In the code, this is accomplished by the entries in
590+
# ``do_constrained_layout()`` like::
574591
#
575592
# ax._poslayoutbox.edit_left_margin_min(-bbox.x0 + pos.x0 + w_padt)
576593
#
@@ -589,7 +606,7 @@ def docomplicated(suptitle=None):
589606
# much smaller than the left-hand, so the right-hand layoutboxes are smaller.
590607
#
591608
# The Subplotspec boxes are laid out in the code in the subroutine
592-
# `.arange_subplotspecs`, which simply checks the subplotspecs in the code
609+
# ``arange_subplotspecs()``, which simply checks the subplotspecs in the code
593610
# against one another and stacks them appropriately.
594611
#
595612
# The two ``pos`` axes are lined up. Because they have the same
@@ -627,10 +644,10 @@ def docomplicated(suptitle=None):
627644
# number of columns (one in this example).
628645
#
629646
# The colorbar layout logic is contained in `~matplotlib.colorbar.make_axes`
630-
# which calls `._constrained_layout.layoutcolorbarsingle`
647+
# which calls ``_constrained_layout.layoutcolorbarsingle()``
631648
# for cbars attached to a single axes, and
632-
# `._constrained_layout.layoutcolorbargridspec` if the colorbar is associated
633-
# with a gridspec.
649+
# ``_constrained_layout.layoutcolorbargridspec()`` if the colorbar is
650+
# associated with a gridspec.
634651

635652
fig, ax = plt.subplots(1, 2, constrained_layout=True)
636653
im = ax[0].pcolormesh(arr, **pc_kwargs)
@@ -644,7 +661,7 @@ def docomplicated(suptitle=None):
644661
#
645662
# This example shows the Subplotspec layoutboxes being made smaller by
646663
# a colorbar layoutbox. The size of the colorbar layoutbox is
647-
# set to be *shrink* smaller than the vertical extent of the ``pos``
664+
# set to be ``shrink`` smaller than the vertical extent of the ``pos``
648665
# layoutboxes in the gridspec, and it is made to be centered between
649666
# those two points.
650667

@@ -713,7 +730,7 @@ def docomplicated(suptitle=None):
713730
# the axes position in made the same size as the occupied Axes positions.
714731
#
715732
# This is done at the start of
716-
# `~._constrained_layout.do_constrained_layout` (``hassubplotspec``).
733+
# ``_constrained_layout.do_constrained_layout()`` (``hassubplotspec``).
717734

718735
fig = plt.figure(constrained_layout=True)
719736
gs = gridspec.GridSpec(1, 3, figure=fig)

tutorials/intermediate/tight_layout_guide.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
feature and may not work for some cases. It only checks the extents
1111
of ticklabels, axis labels, and titles.
1212
13+
An alternative to *tight_layout* is
14+
:doc:`constrained_layout</tutorials/intermediate/constrainedlayout_guide>`.
15+
1316
1417
Simple Example
1518
==============

tutorials/introductory/customizing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
plt.show()
9292

9393
###############################################################################
94+
# .. _matplotlib-rcparams:
95+
#
9496
# matplotlib rcParams
9597
# ===================
9698
#

0 commit comments

Comments
 (0)
0