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

Skip to content

Commit e919e9b

Browse files
committed
add tight_layout_guide.rst
1 parent 7b3bb97 commit e919e9b

1 file changed

Lines changed: 307 additions & 0 deletions

File tree

doc/users/tight_layout_guide.rst

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
.. _plotting-guide-tight-layout:
2+
3+
******************
4+
Tight Layout guide
5+
******************
6+
7+
*tight_layout* automatically adjusts subplot params so that the
8+
subplot(s) fits in to the figure area. This is an experimental
9+
feature and may not work for some cases. It only checks the extents
10+
of ticklabels, axis labels, and titles.
11+
12+
13+
Simple Example
14+
==============
15+
16+
In matplotlib location of axes (including subplots) are specified in
17+
normalized figure coordinate. It can happen that your axis labels or
18+
titles (or sometimes even ticklabels) go outside the figure area thus
19+
clipped.
20+
21+
.. plot::
22+
:include-source:
23+
:context:
24+
25+
plt.rcParams['savefig.facecolor'] = "0.8"
26+
27+
def example_plot(ax, fontsize=12):
28+
ax.plot([1, 2])
29+
ax.locator_params(nbins=3)
30+
ax.set_xlabel('x-label', fontsize=fontsize)
31+
ax.set_ylabel('y-label', fontsize=fontsize)
32+
ax.set_title('Title', fontsize=fontsize)
33+
34+
fig, ax = plt.subplots()
35+
example_plot(ax, fontsize=24)
36+
37+
To prevent this, the location of axes need to be adjusted. For
38+
subplots, this can be done by adjusting the subplot params
39+
(:ref:`howto-subplots-adjust`). Matplotlib v1.1 introduces a new
40+
command :func:`~matplotlib.pyplot.tight_layout` that does this
41+
automatically for you.
42+
43+
.. plot::
44+
:include-source:
45+
:context:
46+
47+
plt.tight_layout()
48+
49+
When you have multiple subplots, often you see labels of different
50+
axes overlaps each other.
51+
52+
.. plot::
53+
:include-source:
54+
:context:
55+
56+
plt.close('all')
57+
fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2)
58+
example_plot(ax1)
59+
example_plot(ax2)
60+
example_plot(ax3)
61+
example_plot(ax4)
62+
63+
64+
*tight_layout* will also adjust spacing betweens subplots to minimize
65+
the overlaps.
66+
67+
.. plot::
68+
:include-source:
69+
:context:
70+
71+
plt.tight_layout()
72+
73+
:func:`~matplotlib.pyplot.tight_layout` can take kwyword arguments of
74+
*pad*, *w_pad* and *height*. These controls the extra pad around the
75+
figure border and between subplots. The pads are specified in fraction
76+
of fontsize.
77+
78+
.. plot::
79+
:include-source:
80+
:context:
81+
82+
plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
83+
84+
:func:`~matplotlib.pyplot.tight_layout` will work even if the sizes of
85+
subplot are different as far as their grid specification is
86+
compatible. In the example below, *ax1* and *ax2* are subplots of 2x2
87+
grid, while *ax3* is of 1x2 grid.
88+
89+
90+
.. plot::
91+
:include-source:
92+
:context:
93+
94+
plt.close('all')
95+
fig = plt.figure()
96+
97+
ax1 = plt.subplot(221)
98+
ax2 = plt.subplot(223)
99+
ax3 = plt.subplot(122)
100+
101+
example_plot(ax1)
102+
example_plot(ax2)
103+
example_plot(ax3)
104+
105+
plt.tight_layout()
106+
107+
108+
It works with subplots created with
109+
:func:`~matplotlib.pyplot.subplot2grid`. In general, subplots created
110+
from the gridspec (:ref:`gridspec-guide`) will work.
111+
112+
.. plot::
113+
:include-source:
114+
:context:
115+
116+
plt.close('all')
117+
fig = plt.figure()
118+
119+
ax1 = plt.subplot2grid((3, 3), (0, 0))
120+
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
121+
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
122+
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
123+
124+
example_plot(ax1)
125+
example_plot(ax2)
126+
example_plot(ax3)
127+
example_plot(ax4)
128+
129+
plt.tight_layout()
130+
131+
132+
Although not thoroughly tested, it seems to work for subplot with aspect
133+
is not "auto" (e.g., axes with images).
134+
135+
136+
.. plot::
137+
:include-source:
138+
:context:
139+
140+
arr = np.arange(100).reshape((10,10))
141+
142+
plt.close('all')
143+
fig = plt.figure(figsize=(5,4))
144+
145+
ax = plt.subplot(111)
146+
im = ax.imshow(arr, interpolation="none")
147+
148+
plt.tight_layout()
149+
150+
151+
Caveats
152+
-------
153+
154+
* *tight_layout* only considers ticklabels, axis labels, and titles. Thus, other atists may be clipped and also may overlap.
155+
156+
* It assumes that the extra space needed for ticklabels, axis labels,
157+
and titles is independent of original location of axes. This is
158+
often True, but there are rare cases it is not.
159+
160+
* pad=0 clips some of the texts by a few pixels. This may be a bug or
161+
a limitation of the current algorithm and it is not clear why it
162+
happens. Meanwhile, use of pad at least larger than 0.3 is
163+
recommended.
164+
165+
166+
167+
168+
Use with GridSpec
169+
-----------------
170+
171+
GridSpec has its own tight_layout method
172+
(the pyplot api :func:`~matplotlib.pyplot.tight_layout` also works).
173+
174+
.. plot::
175+
:include-source:
176+
:context:
177+
178+
plt.close('all')
179+
fig = plt.figure()
180+
181+
import matplotlib.gridspec as gridspec
182+
183+
gs1 = gridspec.GridSpec(2, 1)
184+
ax1 = fig.add_subplot(gs1[0])
185+
ax2 = fig.add_subplot(gs1[1])
186+
187+
example_plot(ax1)
188+
example_plot(ax2)
189+
190+
gs1.tight_layout(fig)
191+
192+
193+
You may provide an optional *rect* parameter, which specify the bbox
194+
that the subplots will be fit in. The coordinate must be in normalized
195+
figure coordinate and the default is (0, 0, 1, 1).
196+
197+
.. plot::
198+
:include-source:
199+
:context:
200+
201+
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
202+
203+
204+
For example, this can be used for a figure with multiple grid_spec's.
205+
206+
.. plot::
207+
:include-source:
208+
:context:
209+
210+
gs2 = gridspec.GridSpec(3, 1)
211+
212+
for ss in gs2:
213+
ax = fig.add_subplot(ss)
214+
example_plot(ax)
215+
ax.set_title("")
216+
ax.set_xlabel("")
217+
218+
ax.set_xlabel("x-label", fontsize=12)
219+
220+
gs2.tight_layout(fig, rect=[0.5, 0, 1, 1], h_pad=0.5)
221+
222+
223+
We may try to match the top and bottom of two grids ::
224+
225+
top = min(gs1.top, gs2.top)
226+
bottom = max(gs1.bottom, gs2.bottom)
227+
228+
gs1.update(top=top, bottom=bottom)
229+
gs2.update(top=top, bottom=bottom)
230+
231+
232+
While this should be mostly good enough, but adjusting top and bottom
233+
may requires adjustment in hspace also. To update hspace & vspace, we
234+
call tight_layout again with updated rect argument. Note the rect
235+
argument specifies area including the ticklabels etc. Thus we will
236+
increase the bottom (which is 0 in normal case) by the difference
237+
between the *bottom* from above and bottom of each gridspec. Same
238+
thing for top.
239+
240+
.. plot::
241+
:include-source:
242+
:context:
243+
244+
top = min(gs1.top, gs2.top)
245+
bottom = max(gs1.bottom, gs2.bottom)
246+
247+
gs1.tight_layout(fig, rect=[None, 0 + (bottom-gs1.bottom),
248+
0.5, 1 - (gs1.top-top)])
249+
gs2.tight_layout(fig, rect=[0.5, 0 + (bottom-gs2.bottom),
250+
None, 1 - (gs2.top-top)],
251+
h_pad=0.5)
252+
253+
254+
255+
Use with AxesGrid1
256+
------------------
257+
258+
While limited, axes_grid1 toolkit is also supported.
259+
260+
261+
.. plot::
262+
:include-source:
263+
:context:
264+
265+
plt.close('all')
266+
fig = plt.figure()
267+
268+
from mpl_toolkits.axes_grid1 import Grid
269+
grid = Grid(fig, rect=111, nrows_ncols=(2,2),
270+
axes_pad=0.25, label_mode='L',
271+
)
272+
273+
for ax in grid:
274+
example_plot(ax)
275+
ax.title.set_visible(False)
276+
277+
plt.tight_layout()
278+
279+
280+
281+
Colorbar
282+
--------
283+
284+
If you create colorbar with :func:`~matplotlib.pyplot.colorbar`
285+
command, the created colorbar is an instance of Axes not Subplot, thus
286+
tight_layout does not work. One option is to use AxesGrid1 toolkit to explicitly create an axes for colorbar.
287+
288+
.. plot::
289+
:include-source:
290+
:context:
291+
292+
plt.close('all')
293+
fig = plt.figure(figsize=(4, 4))
294+
295+
ax = plt.subplot(111)
296+
im = plt.imshow(arr, interpolation="none")
297+
298+
from mpl_toolkits.axes_grid1 import make_axes_locatable
299+
divider = make_axes_locatable(ax)
300+
cax = divider.append_axes("right", "5%", pad="3%")
301+
plt.colorbar(im, cax=cax)
302+
303+
plt.tight_layout()
304+
305+
306+
307+

0 commit comments

Comments
 (0)