Thanks to visit codestin.com
Credit goes to github.com

Skip to content

DOC: Constrained layout tutorial improvements #11388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 68 additions & 51 deletions tutorials/intermediate/constrainedlayout_guide.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,24 @@
legends and colorbars so that they fit in the figure window while still
preserving, as best they can, the logical layout requested by the user.

*constrained_layout* is similar to *tight_layout*, but uses a constraint
solver to determine the size of axes that allows them to fit.
*constrained_layout* is similar to
:doc:`tight_layout</tutorials/intermediate/tight_layout_guide>`,
but uses a constraint solver to determine the size of axes that allows
them to fit.

*constrained_layout* needs to be activated before any axes are added to
a figure. Two ways of doing so are

* using the respective argument to :func:`~.pyplot.subplots` or
:func:`~.pyplot.figure`, e.g.::

plt.subplots(contrained_layout=True)

* activate it via :ref:`rcParams<matplotlib-rcparams>`, like::

plt.rcParams['figure.constrained_layout.use'] = True

Those are described in detail throughout the following sections.

.. warning::

Expand Down Expand Up @@ -83,7 +99,7 @@ def example_plot(ax, fontsize=12, nodec=False):
example_plot(ax)

###############################################################################
# Specifying `constrained_layout=True` in the call to `plt.subplots`
# Specifying ``constrained_layout=True`` in the call to ``plt.subplots``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using plt.subplots(..., constrained_layout=True) causes ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentence wasn't written by me, but I actually like it as it is. Otherwise it's too much doubled

Using __code__ cause x to happen: __code__

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, then leave it. The sentence feels quite verbose to me, but I won't start a discussion here.

# causes the layout to be properly constrained.

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

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

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

fig, axs = plt.subplots(2, 2, figsize=(4, 4), constrained_layout=True)
for ax in axs.flatten():
Expand Down Expand Up @@ -153,7 +170,7 @@ def example_plot(ax, fontsize=12, nodec=False):
# Suptitle
# =========
#
# ``constrained_layout`` can also make room for ``suptitle``.
# ``constrained_layout`` can also make room for `~.figure.Figure.suptitle`.

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

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

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

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

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

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

##########################################
# rcParams
# --------
# ========
#
# There are five `rcParams` that can be set, either in a script
# or in the `matplotlibrc` file. They all have the prefix
# `figure.constrained_layout`:
# There are five :ref:`rcParams<matplotlib-rcparams>` that can be set,
# either in a script or in the `matplotlibrc` file.
# They all have the prefix ``figure.constrained_layout``:
#
# - `use`: Whether to use constrained_layout. Default is False
# - `w_pad`, `h_pad` Padding around axes objects.
# - ``use``: Whether to use constrained_layout. Default is False
# - ``w_pad``, ``h_pad``: Padding around axes objects.
# Float representing inches. Default is 3./72. inches (3 pts)
# - `wspace`, `hspace` Space between subplot groups.
# - ``wspace``, ``hspace``: Space between subplot groups.
# Float representing a fraction of the subplot widths being separated.
# Default is 0.02.

Expand Down Expand Up @@ -296,7 +313,7 @@ def example_plot(ax, fontsize=12, nodec=False):
example_plot(ax2)

###############################################################################
# More complicated gridspec layouts are possible...
# More complicated gridspec layouts are possible.

fig = plt.figure(constrained_layout=True)

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

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

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

Expand Down Expand Up @@ -520,33 +537,33 @@ def docomplicated(suptitle=None):
#
# Figures are laid out in a hierarchy:
#
# 1. Figure: `fig = plt.figure()`
# 1. Figure: ``fig = plt.figure()``
#
# a. Gridspec `gs0 = gridspec.GridSpec(1, 2, figure=fig)`
# a. Gridspec ``gs0 = gridspec.GridSpec(1, 2, figure=fig)``
#
# i. Subplotspec: `ss = gs[0, 0]`
# i. Subplotspec: ``ss = gs[0, 0]``
#
# 1. Axes: `ax0 = fig.add_subplot(ss)`
# 1. Axes: ``ax0 = fig.add_subplot(ss)``
#
# ii. Subplotspec: `ss = gs[0, 1]`
# ii. Subplotspec: ``ss = gs[0, 1]``
#
# 1. Gridspec: `gsR = gridspec.GridSpecFromSubplotSpec(2, 1, ss)`
# 1. Gridspec: ``gsR = gridspec.GridSpecFromSubplotSpec(2, 1, ss)``
#
# - Subplotspec: ss = gsR[0, 0]
# - Subplotspec: ``ss = gsR[0, 0]``
#
# - Axes: `axR0 = fig.add_subplot(ss)`
# - Axes: ``axR0 = fig.add_subplot(ss)``
#
# - Subplotspec: ss = gsR[1, 0]
# - Subplotspec: ``ss = gsR[1, 0]``
#
# - Axes: `axR1 = fig.add_subplot(ss)`
# - Axes: ``axR1 = fig.add_subplot(ss)``
#
# Each item has a layoutbox associated with it. The nesting of gridspecs
# created with `.GridSpecFromSubplotSpec` can be arbitrarily deep.
#
# Each ``~matplotlib.axes.Axes` has *two* layoutboxes. The first one,
# Each `~matplotlib.axes.Axes` has *two* layoutboxes. The first one,
# ``ax._layoutbox`` represents the outside of the Axes and all its
# decorations (i.e. ticklabels,axis labels, etc.).
# The second layoutbox corresponds to the Axes' `ax.position`, which sets
# The second layoutbox corresponds to the Axes' ``ax.position``, which sets
# where in the figure the spines are placed.
#
# Why so many stacked containers? Ideally, all that would be needed are the
Expand All @@ -569,8 +586,8 @@ def docomplicated(suptitle=None):
# the difference between the red ``pos`` box and the green ``ax`` box
# is set by the size of the decorations around the Axes.
#
# In the code, this is accomplished by the entries in `.do_constrained_layout`
# like::
# In the code, this is accomplished by the entries in
# ``do_constrained_layout()`` like::
#
# ax._poslayoutbox.edit_left_margin_min(-bbox.x0 + pos.x0 + w_padt)
#
Expand All @@ -589,7 +606,7 @@ def docomplicated(suptitle=None):
# much smaller than the left-hand, so the right-hand layoutboxes are smaller.
#
# The Subplotspec boxes are laid out in the code in the subroutine
# `.arange_subplotspecs`, which simply checks the subplotspecs in the code
# ``arange_subplotspecs()``, which simply checks the subplotspecs in the code
# against one another and stacks them appropriately.
#
# The two ``pos`` axes are lined up. Because they have the same
Expand Down Expand Up @@ -627,10 +644,10 @@ def docomplicated(suptitle=None):
# number of columns (one in this example).
#
# The colorbar layout logic is contained in `~matplotlib.colorbar.make_axes`
# which calls `._constrained_layout.layoutcolorbarsingle`
# which calls ``_constrained_layout.layoutcolorbarsingle()``
# for cbars attached to a single axes, and
# `._constrained_layout.layoutcolorbargridspec` if the colorbar is associated
# with a gridspec.
# ``_constrained_layout.layoutcolorbargridspec()`` if the colorbar is
# associated with a gridspec.

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

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

fig = plt.figure(constrained_layout=True)
gs = gridspec.GridSpec(1, 3, figure=fig)
Expand Down
3 changes: 3 additions & 0 deletions tutorials/intermediate/tight_layout_guide.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
feature and may not work for some cases. It only checks the extents
of ticklabels, axis labels, and titles.

An alternative to *tight_layout* is
:doc:`constrained_layout</tutorials/intermediate/constrainedlayout_guide>`.


Simple Example
==============
Expand Down
2 changes: 2 additions & 0 deletions tutorials/introductory/customizing.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
plt.show()

###############################################################################
# .. _matplotlib-rcparams:
#
# matplotlib rcParams
# ===================
#
Expand Down