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

Skip to content

Commit 30a8265

Browse files
committed
ENH: Add gridspec method to figure, and subplotspecs
1 parent 0544616 commit 30a8265

File tree

7 files changed

+227
-77
lines changed

7 files changed

+227
-77
lines changed

doc/users/whats_new.rst

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ revision, see the :ref:`github-stats`.
1515
For a release, add a new section after this, then comment out the include
1616
and toctree below by indenting them. Uncomment them after the release.
1717
18-
.. include:: next_whats_new/README.rst
18+
.. include:: next_whats_new/README.rst
1919
.. toctree::
2020
:glob:
2121
:maxdepth: 1
@@ -190,6 +190,24 @@ specify a number that is close (i.e. ``ax.title.set_position(0.5, 1.01)``)
190190
and the title will not be moved via this algorithm.
191191

192192

193+
New convenience methods for GridSpec
194+
------------------------------------
195+
196+
There are new convenience methods for `.gridspec.GridSpec` and
197+
`.gridspec.GridSpecFromSubplotSpec`. Instead of the former we can
198+
now call `.Figure.add_gridspec` and for the latter `.SubplotSpec.subgridspec`.
199+
200+
.. code-block:: python
201+
202+
import matplotlib.pyplot as plt
203+
204+
fig = plt.figure()
205+
gs0 = fig.add_gridspec(3, 1)
206+
ax1 = fig.add_subplot(gs0[0])
207+
ax2 = fig.add_subplot(gs0[1])
208+
gssub = gs0[2].subgridspec(1, 3)
209+
for i in range(3):
210+
fig.add_subplot(gssub[0, i])
193211
194212
195213

lib/matplotlib/_constrained_layout.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ def do_constrained_layout(fig, renderer, h_pad, w_pad,
132132
133133
'''
134134

135+
_log.debug('Starting do_constrained_layout')
135136
invTransFig = fig.transFigure.inverted().transform_bbox
136137

137138
# list of unique gridspecs that contain child axes:

lib/matplotlib/figure.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,9 @@ def __init__(self,
394394
self._align_xlabel_grp = cbook.Grouper()
395395
self._align_ylabel_grp = cbook.Grouper()
396396

397+
# list of child gridspecs for this figure
398+
self._gridspecs = []
399+
397400
# TODO: I'd like to dynamically add the _repr_html_ method
398401
# to the figure in the right context, but then IPython doesn't
399402
# use it, for some reason.
@@ -1480,6 +1483,7 @@ def subplots(self, nrows=1, ncols=1, sharex=False, sharey=False,
14801483
else:
14811484
# this should turn constrained_layout off if we don't want it
14821485
gs = GridSpec(nrows, ncols, figure=None, **gridspec_kw)
1486+
self._gridspecs.append(gs)
14831487

14841488
# Create array to hold all axes.
14851489
axarr = np.empty((nrows, ncols), dtype=object)
@@ -2474,6 +2478,49 @@ def align_labels(self, axs=None):
24742478
self.align_xlabels(axs=axs)
24752479
self.align_ylabels(axs=axs)
24762480

2481+
def add_gridspec(self, nrows, ncols, **kwargs):
2482+
"""
2483+
Return a `.GridSpec` that has this figure as a parent. This allows
2484+
complex layout of axes in the figure.
2485+
2486+
Parameters
2487+
----------
2488+
nrows : int
2489+
Number of rows in grid.
2490+
2491+
ncols : int
2492+
Number or columns in grid.
2493+
2494+
Returns
2495+
-------
2496+
gridspec : `.GridSpec`
2497+
2498+
Other Parameters
2499+
----------------
2500+
*kwargs* are passed to `.GridSpec`.
2501+
2502+
See Also
2503+
--------
2504+
matplotlib.pyplot.subplots
2505+
2506+
Examples
2507+
--------
2508+
Adding a subplot that spans two rows::
2509+
2510+
fig = plt.figure()
2511+
gs = fig.add_gridspec(2, 2)
2512+
ax1 = fig.add_subplot(gs[0, 0])
2513+
ax2 = fig.add_subplot(gs[1, 0])
2514+
# spans two rows:
2515+
ax3 = fig.add_subplot(gs[:, 1])
2516+
2517+
"""
2518+
2519+
_ = kwargs.pop('figure', None) # pop in case user has added this...
2520+
gs = GridSpec(nrows=nrows, ncols=ncols, figure=self, **kwargs)
2521+
self._gridspecs.append(gs)
2522+
return gs
2523+
24772524

24782525
def figaspect(arg):
24792526
"""

lib/matplotlib/gridspec.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,3 +498,43 @@ def __eq__(self, other):
498498

499499
def __hash__(self):
500500
return hash((self._gridspec, self.num1, self.num2))
501+
502+
def subgridspec(self, nrows, ncols, **kwargs):
503+
"""
504+
Return a `.GridSpecFromSubplotSpec` that has this subplotspec as
505+
a parent.
506+
507+
Parameters
508+
----------
509+
nrows : int
510+
Number of rows in grid.
511+
512+
ncols : int
513+
Number or columns in grid.
514+
515+
Returns
516+
-------
517+
gridspec : `.GridSpec`
518+
519+
Other Parameters
520+
----------------
521+
*kwargs* are passed to `.GridSpec`.
522+
523+
See Also
524+
--------
525+
matplotlib.pyplot.subplots
526+
527+
Examples
528+
--------
529+
Adding three subplots in the space occupied by a single subplot::
530+
531+
fig = plt.figure()
532+
gs0 = fig.add_gridspec(3, 1)
533+
ax1 = fig.add_subplot(gs0[0])
534+
ax2 = fig.add_subplot(gs0[1])
535+
gssub = gs0[2].subgridspec(1, 3)
536+
for i in range(3):
537+
fig.add_subplot(gssub[0, i])
538+
"""
539+
540+
return GridSpecFromSubplotSpec(nrows, ncols, self, **kwargs)

lib/matplotlib/tests/test_constrainedlayout.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ def test_constrained_layout5():
9494
def test_constrained_layout6():
9595
'Test constrained_layout for nested gridspecs'
9696
fig = plt.figure(constrained_layout=True)
97-
gs = gridspec.GridSpec(1, 2, figure=fig)
98-
gsl = gridspec.GridSpecFromSubplotSpec(2, 2, gs[0])
99-
gsr = gridspec.GridSpecFromSubplotSpec(1, 2, gs[1])
97+
gs = fig.add_gridspec(1, 2, figure=fig)
98+
gsl = gs[0].subgridspec(2, 2)
99+
gsr = gs[1].subgridspec(1, 2)
100100
axsl = []
101101
for gs in gsl:
102102
ax = fig.add_subplot(gs)

tutorials/intermediate/constrainedlayout_guide.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
plt.rcParams['savefig.facecolor'] = "0.8"
6565
plt.rcParams['figure.figsize'] = 4.5, 4.
6666

67-
6867
def example_plot(ax, fontsize=12, nodec=False):
6968
ax.plot([1, 2])
7069

@@ -78,7 +77,7 @@ def example_plot(ax, fontsize=12, nodec=False):
7877
ax.set_yticklabels('')
7978

8079

81-
fig, ax = plt.subplots()
80+
fig, ax = plt.subplots(constrained_layout=False)
8281
example_plot(ax, fontsize=24)
8382

8483
###############################################################################
@@ -334,8 +333,10 @@ def example_plot(ax, fontsize=12, nodec=False):
334333
# with :func:`~matplotlib.figure.Figure.subplots` or
335334
# :func:`~matplotlib.gridspec.GridSpec` and
336335
# :func:`~matplotlib.figure.Figure.add_subplot`.
336+
#
337+
# Note that in what follows ``constrained_layout=True``
337338

338-
fig = plt.figure(constrained_layout=True)
339+
fig = plt.figure()
339340

340341
gs1 = gridspec.GridSpec(2, 1, figure=fig)
341342
ax1 = fig.add_subplot(gs1[0])
@@ -345,20 +346,21 @@ def example_plot(ax, fontsize=12, nodec=False):
345346
example_plot(ax2)
346347

347348
###############################################################################
348-
# More complicated gridspec layouts are possible.
349+
# More complicated gridspec layouts are possible. Note here we use the
350+
# convenenience functions ``add_gridspec`` and ``subgridspec``
349351

350-
fig = plt.figure(constrained_layout=True)
352+
fig = plt.figure()
351353

352-
gs0 = gridspec.GridSpec(1, 2, figure=fig)
354+
gs0 = fig.add_gridspec(1, 2)
353355

354-
gs1 = gridspec.GridSpecFromSubplotSpec(2, 1, gs0[0])
356+
gs1 = gs0[0].subgridspec(2, 1)
355357
ax1 = fig.add_subplot(gs1[0])
356358
ax2 = fig.add_subplot(gs1[1])
357359

358360
example_plot(ax1)
359361
example_plot(ax2)
360362

361-
gs2 = gridspec.GridSpecFromSubplotSpec(3, 1, gs0[1])
363+
gs2 = gs0[1].subgridspec(3, 1)
362364

363365
for ss in gs2:
364366
ax = fig.add_subplot(ss)
@@ -373,9 +375,9 @@ def example_plot(ax, fontsize=12, nodec=False):
373375
# extent. If we want the top and bottom of the two grids to line up then
374376
# they need to be in the same gridspec:
375377

376-
fig = plt.figure(constrained_layout=True)
378+
fig = plt.figure()
377379

378-
gs0 = gridspec.GridSpec(6, 2, figure=fig)
380+
gs0 = fig.add_gridspec(6, 2)
379381

380382
ax1 = fig.add_subplot(gs0[:3, 0])
381383
ax2 = fig.add_subplot(gs0[3:, 0])
@@ -398,10 +400,10 @@ def example_plot(ax, fontsize=12, nodec=False):
398400

399401

400402
def docomplicated(suptitle=None):
401-
fig = plt.figure(constrained_layout=True)
402-
gs0 = gridspec.GridSpec(1, 2, figure=fig, width_ratios=[1., 2.])
403-
gsl = gridspec.GridSpecFromSubplotSpec(2, 1, gs0[0])
404-
gsr = gridspec.GridSpecFromSubplotSpec(2, 2, gs0[1])
403+
fig = plt.figure()
404+
gs0 = fig.add_gridspec(1, 2, figure=fig, width_ratios=[1., 2.])
405+
gsl = gs0[0].subgridspec(2, 1)
406+
gsr = gs0[1].subgridspec(2, 2)
405407

406408
for gs in gsl:
407409
ax = fig.add_subplot(gs)
@@ -430,7 +432,7 @@ def docomplicated(suptitle=None):
430432
# no effect on it anymore. (Note that constrained_layout still leaves the
431433
# space for the axes that is moved).
432434

433-
fig, axs = plt.subplots(1, 2, constrained_layout=True)
435+
fig, axs = plt.subplots(1, 2)
434436
example_plot(axs[0], fontsize=12)
435437
axs[1].set_position([0.2, 0.2, 0.4, 0.4])
436438

@@ -444,7 +446,7 @@ def docomplicated(suptitle=None):
444446

445447
from matplotlib.transforms import Bbox
446448

447-
fig, axs = plt.subplots(1, 2, constrained_layout=True)
449+
fig, axs = plt.subplots(1, 2)
448450
example_plot(axs[0], fontsize=12)
449451
fig.execute_constrained_layout()
450452
# put into data-space:
@@ -468,7 +470,7 @@ def docomplicated(suptitle=None):
468470
# to yield a nice layout:
469471

470472

471-
fig = plt.figure(constrained_layout=True)
473+
fig = plt.figure()
472474

473475
ax1 = plt.subplot(221)
474476
ax2 = plt.subplot(223)
@@ -481,8 +483,8 @@ def docomplicated(suptitle=None):
481483
###############################################################################
482484
# Of course that layout is possible using a gridspec:
483485

484-
fig = plt.figure(constrained_layout=True)
485-
gs = gridspec.GridSpec(2, 2, figure=fig)
486+
fig = plt.figure()
487+
gs = fig.add_gridspec(2, 2)
486488

487489
ax1 = fig.add_subplot(gs[0, 0])
488490
ax2 = fig.add_subplot(gs[1, 0])
@@ -497,7 +499,7 @@ def docomplicated(suptitle=None):
497499
# :func:`~matplotlib.pyplot.subplot2grid` doesn't work for the same reason:
498500
# each call creates a different parent gridspec.
499501

500-
fig = plt.figure(constrained_layout=True)
502+
fig = plt.figure()
501503

502504
ax1 = plt.subplot2grid((3, 3), (0, 0))
503505
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
@@ -513,8 +515,8 @@ def docomplicated(suptitle=None):
513515
# The way to make this plot compatible with ``constrained_layout`` is again
514516
# to use ``gridspec`` directly
515517

516-
fig = plt.figure(constrained_layout=True)
517-
gs = gridspec.GridSpec(3, 3, figure=fig)
518+
fig = plt.figure()
519+
gs = fig.add_gridspec(3, 3)
518520

519521
ax1 = fig.add_subplot(gs[0, 0])
520522
ax2 = fig.add_subplot(gs[0, 1:])

0 commit comments

Comments
 (0)