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

Skip to content

Commit 29a2bc2

Browse files
committed
Merge pull request #124 from leejjoon/matplotlib
--- This is a patch motivated by Tony Yus work (http://www.mail-archive.com/[email protected]/msg18107.html). The basic idea is same while implemented slight differently. * no drawing is necessary * support subplots that span multiple rows/columns I also worked on simple guide that demonstrate its functionality (tight_layout_guide.rst). The html copy is here (any help with the documentation will be appreciated). http://dl.dropbox.com/u/178748/Tight%20Layout%20guide%20%E2%80%94%20Matplotlib%20v1.1.0%20documentation.html
2 parents 4f5e73d + f2f212e commit 29a2bc2

File tree

14 files changed

+1210
-50
lines changed

14 files changed

+1210
-50
lines changed

doc/users/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ User's Guide
2222
image_tutorial.rst
2323
artists.rst
2424
gridspec.rst
25+
tight_layout_guide.rst
2526
legend_guide.rst
2627
event_handling.rst
2728
transforms_tutorial.rst

doc/users/tight_layout_guide.rst

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

0 commit comments

Comments
 (0)