Skip to content

Commit eb3dd25

Browse files
committed
Add SubplotSpec.add_subplot.
Now that the preferred(?) method of creating GridSpecs attaches the GridSpec to a given figure (figure.add_gridspec), calling `fig.add_subplot(gs[...])` effectively specifies the figure information twice. Hence, allow one to do ``` gs = fig.add_gridspec(2, 2) gs[0, 0].add_subplot() ``` as a synonym for ``` gs = fig.add_gridspec(2, 2) fig.add_subplot(gs[0, 0]) ``` Ideally, this should ultimately allow one to deprecate the somewhat unwieldy subplot2grid, replacing ``` plt.subplot2grid((3, 3), (0, 0)) plt.subplot2grid((3, 3), (1, 1), rowspan=2, colspan=2) ``` by ``` plt.figure().add_grispec(3, 3)[0, 0].add_subplot() plt.figure().add_grispec(3, 3)[1:, 1:].add_subplot() ``` or, after implementing a plt.add_gridspec() that operates on gcf(), ``` gs = plt.add_gridspec(3, 3) gs[0, 0].add_subplot() gs[1:, 1:].add_subplot() ``` A similar API change would be to make GridSpec.tight_layout() lose its `figure` argument (or rather, it could become optional).
1 parent 2660901 commit eb3dd25

File tree

4 files changed

+63
-32
lines changed

4 files changed

+63
-32
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
GridSpec items can now add subplots to their parent Figure directly
2+
```````````````````````````````````````````````````````````````````
3+
4+
`SubplotSpec` gained an ``add_subplot`` method, which allows one to write ::
5+
6+
fig = plt.figure()
7+
gs = fig.add_gridspec(2, 2)
8+
gs[0, 0].add_subplot() # instead of `fig.add_subplot(gs[0, 0])`

lib/matplotlib/gridspec.py

+24
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ def __init__(self, nrows, ncols,
371371
name=subspeclb.name + '.gridspec' + layoutbox.seq_id(),
372372
artist=self)
373373

374+
@property
375+
def figure(self):
376+
return self.get_topmost_subplotspec().gridspec.figure
377+
374378
def get_subplot_params(self, figure=None):
375379
"""Return a dictionary of subplot layout parameters.
376380
"""
@@ -542,3 +546,23 @@ def subgridspec(self, nrows, ncols, **kwargs):
542546
"""
543547

544548
return GridSpecFromSubplotSpec(nrows, ncols, self, **kwargs)
549+
550+
def add_subplot(self, **kwargs):
551+
"""
552+
Add the subplot specified by *self* to the parent figure.
553+
554+
Note that the parent `GridSpec` must have its ``.parent`` attribute set
555+
for this method to work; otherwise, a ValueError is raised.
556+
557+
Keyword arguments are forwarded to `Figure.add_subplot`.
558+
559+
Example
560+
-------
561+
562+
gs = plt.figure().add_gridspec(2, 2)
563+
ax = gs[0, 0].add_subplot()
564+
"""
565+
if self._gridspec.figure is None:
566+
raise ValueError("add_subplot() only works for GridSpecs created "
567+
"with a parent Figure")
568+
self._gridspec.figure.add_subplot(self, **kwargs)

lib/matplotlib/tests/test_tightlayout.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ def test_tight_layout6():
107107

108108
gs1.tight_layout(fig, rect=[0, 0, 0.5, 1])
109109

110-
gs2 = gridspec.GridSpec(3, 1)
110+
gs2 = fig.add_gridspec(3, 1)
111111

112112
for ss in gs2:
113-
ax = fig.add_subplot(ss)
113+
ax = ss.add_subplot()
114114
example_plot(ax)
115115
ax.set_title("")
116116
ax.set_xlabel("")

tutorials/intermediate/gridspec.py

+29-30
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,17 @@
4949
# For a simple use case such as this, :mod:`~matplotlib.gridspec` is
5050
# perhaps overly verbose.
5151
# You have to create the figure and :class:`~matplotlib.gridspec.GridSpec`
52-
# instance separately, then pass elements of gridspec instance to the
53-
# :func:`~matplotlib.figure.Figure.add_subplot` method to create the axes
54-
# objects.
52+
# instance separately, then call the `~SubplotSpec.add_subplot` method of
53+
# elements of gridspec instance to create the axes objects.
5554
# The elements of the gridspec are accessed in generally the same manner as
5655
# numpy arrays.
5756

5857
fig2 = plt.figure(constrained_layout=True)
5958
spec2 = gridspec.GridSpec(ncols=2, nrows=2, figure=fig2)
60-
f2_ax1 = fig2.add_subplot(spec2[0, 0])
61-
f2_ax2 = fig2.add_subplot(spec2[0, 1])
62-
f2_ax3 = fig2.add_subplot(spec2[1, 0])
63-
f2_ax4 = fig2.add_subplot(spec2[1, 1])
59+
f2_ax1 = spec2[0, 0].add_subplot()
60+
f2_ax2 = spec2[0, 1].add_subplot()
61+
f2_ax3 = spec2[1, 0].add_subplot()
62+
f2_ax4 = spec2[1, 1].add_subplot()
6463

6564
#############################################################################
6665
# The power of gridspec comes in being able to create subplots that span
@@ -74,15 +73,15 @@
7473

7574
fig3 = plt.figure(constrained_layout=True)
7675
gs = fig3.add_gridspec(3, 3)
77-
f3_ax1 = fig3.add_subplot(gs[0, :])
76+
f3_ax1 = gs[0, :].add_subplot()
7877
f3_ax1.set_title('gs[0, :]')
79-
f3_ax2 = fig3.add_subplot(gs[1, :-1])
78+
f3_ax2 = gs[1, :-1].add_subplot()
8079
f3_ax2.set_title('gs[1, :-1]')
81-
f3_ax3 = fig3.add_subplot(gs[1:, -1])
80+
f3_ax3 = gs[1:, -1].add_subplot()
8281
f3_ax3.set_title('gs[1:, -1]')
83-
f3_ax4 = fig3.add_subplot(gs[-1, 0])
82+
f3_ax4 = gs[-1, 0].add_subplot()
8483
f3_ax4.set_title('gs[-1, 0]')
85-
f3_ax5 = fig3.add_subplot(gs[-1, -2])
84+
f3_ax5 = gs[-1, -2].add_subplot()
8685
f3_ax5.set_title('gs[-1, -2]')
8786

8887
#############################################################################
@@ -99,11 +98,11 @@
9998
anno_opts = dict(xy=(0.5, 0.5), xycoords='axes fraction',
10099
va='center', ha='center')
101100

102-
f4_ax1 = fig4.add_subplot(spec4[0, 0])
101+
f4_ax1 = spec4[0, 0].add_subplot()
103102
f4_ax1.annotate('GridSpec[0, 0]', **anno_opts)
104-
fig4.add_subplot(spec4[0, 1]).annotate('GridSpec[0, 1:]', **anno_opts)
105-
fig4.add_subplot(spec4[1, 0]).annotate('GridSpec[1:, 0]', **anno_opts)
106-
fig4.add_subplot(spec4[1, 1]).annotate('GridSpec[1:, 1:]', **anno_opts)
103+
spec4[0, 1].add_subplot().annotate('GridSpec[0, 1:]', **anno_opts)
104+
spec4[1, 0].add_subplot().annotate('GridSpec[1:, 0]', **anno_opts)
105+
spec4[1, 1].add_subplot().annotate('GridSpec[1:, 1:]', **anno_opts)
107106

108107
############################################################################
109108
# Another option is to use the ``width_ratios`` and ``height_ratios``
@@ -121,7 +120,7 @@
121120
height_ratios=heights)
122121
for row in range(3):
123122
for col in range(3):
124-
ax = fig5.add_subplot(spec5[row, col])
123+
ax = spec5[row, col].add_subplot()
125124
label = 'Width: {}\nHeight: {}'.format(widths[col], heights[row])
126125
ax.annotate(label, (0.1, 0.5), xycoords='axes fraction', va='center')
127126

@@ -154,7 +153,7 @@
154153
# remove the underlying axes
155154
for ax in f7_axs[1:, -1]:
156155
ax.remove()
157-
axbig = fig7.add_subplot(gs[1:, -1])
156+
axbig = gs[1:, -1].add_subplot()
158157
axbig.annotate('Big Axes \nGridSpec[1:, -1]', (0.1, 0.5),
159158
xycoords='axes fraction', va='center')
160159

@@ -172,9 +171,9 @@
172171

173172
fig8 = plt.figure(constrained_layout=False)
174173
gs1 = fig8.add_gridspec(nrows=3, ncols=3, left=0.05, right=0.48, wspace=0.05)
175-
f8_ax1 = fig8.add_subplot(gs1[:-1, :])
176-
f8_ax2 = fig8.add_subplot(gs1[-1, :-1])
177-
f8_ax3 = fig8.add_subplot(gs1[-1, -1])
174+
f8_ax1 = gs1[:-1, :].add_subplot()
175+
f8_ax2 = gs1[-1, :-1].add_subplot()
176+
f8_ax3 = gs1[-1, -1].add_subplot()
178177

179178
###############################################################################
180179
# This is similar to :func:`~matplotlib.pyplot.subplots_adjust`, but it only
@@ -185,15 +184,15 @@
185184
fig9 = plt.figure(constrained_layout=False)
186185
gs1 = fig9.add_gridspec(nrows=3, ncols=3, left=0.05, right=0.48,
187186
wspace=0.05)
188-
f9_ax1 = fig9.add_subplot(gs1[:-1, :])
189-
f9_ax2 = fig9.add_subplot(gs1[-1, :-1])
190-
f9_ax3 = fig9.add_subplot(gs1[-1, -1])
187+
f9_ax1 = gs1[:-1, :].add_subplot()
188+
f9_ax2 = gs1[-1, :-1].add_subplot()
189+
f9_ax3 = gs1[-1, -1].add_subplot()
191190

192191
gs2 = fig9.add_gridspec(nrows=3, ncols=3, left=0.55, right=0.98,
193192
hspace=0.05)
194-
f9_ax4 = fig9.add_subplot(gs2[:, :-1])
195-
f9_ax5 = fig9.add_subplot(gs2[:-1, -1])
196-
f9_ax6 = fig9.add_subplot(gs2[-1, -1])
193+
f9_ax4 = gs2[:, :-1].add_subplot()
194+
f9_ax5 = gs2[:-1, -1].add_subplot()
195+
f9_ax6 = gs2[-1, -1].add_subplot()
197196

198197
###############################################################################
199198
# GridSpec using SubplotSpec
@@ -214,8 +213,8 @@
214213

215214
for a in range(2):
216215
for b in range(3):
217-
fig10.add_subplot(gs00[a, b])
218-
fig10.add_subplot(gs01[b, a])
216+
gs00[a, b].add_subplot()
217+
gs01[b, a].add_subplot()
219218

220219
###############################################################################
221220
# A Complex Nested GridSpec using SubplotSpec
@@ -276,7 +275,7 @@ def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
276275

277276
matplotlib.pyplot.subplots
278277
matplotlib.figure.Figure.add_gridspec
279-
matplotlib.figure.Figure.add_subplot
280278
matplotlib.gridspec.GridSpec
279+
matplotlib.gridspec.SubplotSpec.add_subplot
281280
matplotlib.gridspec.SubplotSpec.subgridspec
282281
matplotlib.gridspec.GridSpecFromSubplotSpec

0 commit comments

Comments
 (0)