gridspec.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. r"""
  2. :mod:`~matplotlib.gridspec` contains classes that help to layout multiple
  3. `~axes.Axes` in a grid-like pattern within a figure.
  4. The `GridSpec` specifies the overall grid structure. Individual cells within
  5. the grid are referenced by `SubplotSpec`\s.
  6. See the tutorial :ref:`sphx_glr_tutorials_intermediate_gridspec.py` for a
  7. comprehensive usage guide.
  8. """
  9. import copy
  10. import logging
  11. import numpy as np
  12. import matplotlib as mpl
  13. from matplotlib import _pylab_helpers, cbook, tight_layout, rcParams
  14. from matplotlib.transforms import Bbox
  15. import matplotlib._layoutbox as layoutbox
  16. _log = logging.getLogger(__name__)
  17. class GridSpecBase:
  18. """
  19. A base class of GridSpec that specifies the geometry of the grid
  20. that a subplot will be placed.
  21. """
  22. def __init__(self, nrows, ncols, height_ratios=None, width_ratios=None):
  23. """
  24. Parameters
  25. ----------
  26. nrows, ncols : int
  27. The number of rows and columns of the grid.
  28. width_ratios : array-like of length *ncols*, optional
  29. Defines the relative widths of the columns. Each column gets a
  30. relative width of ``width_ratios[i] / sum(width_ratios)``.
  31. If not given, all columns will have the same width.
  32. height_ratios : array-like of length *nrows*, optional
  33. Defines the relative heights of the rows. Each column gets a
  34. relative height of ``height_ratios[i] / sum(height_ratios)``.
  35. If not given, all rows will have the same height.
  36. """
  37. self._nrows, self._ncols = nrows, ncols
  38. self.set_height_ratios(height_ratios)
  39. self.set_width_ratios(width_ratios)
  40. def __repr__(self):
  41. height_arg = (', height_ratios=%r' % self._row_height_ratios
  42. if self._row_height_ratios is not None else '')
  43. width_arg = (', width_ratios=%r' % self._col_width_ratios
  44. if self._col_width_ratios is not None else '')
  45. return '{clsname}({nrows}, {ncols}{optionals})'.format(
  46. clsname=self.__class__.__name__,
  47. nrows=self._nrows,
  48. ncols=self._ncols,
  49. optionals=height_arg + width_arg,
  50. )
  51. nrows = property(lambda self: self._nrows,
  52. doc="The number of rows in the grid.")
  53. ncols = property(lambda self: self._ncols,
  54. doc="The number of columns in the grid.")
  55. def get_geometry(self):
  56. """
  57. Return a tuple containing the number of rows and columns in the grid.
  58. """
  59. return self._nrows, self._ncols
  60. def get_subplot_params(self, figure=None):
  61. # Must be implemented in subclasses
  62. pass
  63. def new_subplotspec(self, loc, rowspan=1, colspan=1):
  64. """
  65. Create and return a `.SubplotSpec` instance.
  66. Parameters
  67. ----------
  68. loc : (int, int)
  69. The position of the subplot in the grid as
  70. ``(row_index, column_index)``.
  71. rowspan, colspan : int, default: 1
  72. The number of rows and columns the subplot should span in the grid.
  73. """
  74. loc1, loc2 = loc
  75. subplotspec = self[loc1:loc1+rowspan, loc2:loc2+colspan]
  76. return subplotspec
  77. def set_width_ratios(self, width_ratios):
  78. """
  79. Set the relative widths of the columns.
  80. *width_ratios* must be of length *ncols*. Each column gets a relative
  81. width of ``width_ratios[i] / sum(width_ratios)``.
  82. """
  83. if width_ratios is not None and len(width_ratios) != self._ncols:
  84. raise ValueError('Expected the given number of width ratios to '
  85. 'match the number of columns of the grid')
  86. self._col_width_ratios = width_ratios
  87. def get_width_ratios(self):
  88. """
  89. Return the width ratios.
  90. This is *None* if no width ratios have been set explicitly.
  91. """
  92. return self._col_width_ratios
  93. def set_height_ratios(self, height_ratios):
  94. """
  95. Set the relative heights of the rows.
  96. *height_ratios* must be of length *nrows*. Each row gets a relative
  97. height of ``height_ratios[i] / sum(height_ratios)``.
  98. """
  99. if height_ratios is not None and len(height_ratios) != self._nrows:
  100. raise ValueError('Expected the given number of height ratios to '
  101. 'match the number of rows of the grid')
  102. self._row_height_ratios = height_ratios
  103. def get_height_ratios(self):
  104. """
  105. Return the height ratios.
  106. This is *None* if no height ratios have been set explicitly.
  107. """
  108. return self._row_height_ratios
  109. def get_grid_positions(self, fig, raw=False):
  110. """
  111. Return the positions of the grid cells in figure coordinates.
  112. Parameters
  113. ----------
  114. fig : `~matplotlib.figure.Figure`
  115. The figure the grid should be applied to. The subplot parameters
  116. (margins and spacing between subplots) are taken from *fig*.
  117. raw : bool, default: False
  118. If *True*, the subplot parameters of the figure are not taken
  119. into account. The grid spans the range [0, 1] in both directions
  120. without margins and there is no space between grid cells. This is
  121. used for constrained_layout.
  122. Returns
  123. -------
  124. bottoms, tops, lefts, rights : array
  125. The bottom, top, left, right positions of the grid cells in
  126. figure coordinates.
  127. """
  128. nrows, ncols = self.get_geometry()
  129. if raw:
  130. left = 0.
  131. right = 1.
  132. bottom = 0.
  133. top = 1.
  134. wspace = 0.
  135. hspace = 0.
  136. else:
  137. subplot_params = self.get_subplot_params(fig)
  138. left = subplot_params.left
  139. right = subplot_params.right
  140. bottom = subplot_params.bottom
  141. top = subplot_params.top
  142. wspace = subplot_params.wspace
  143. hspace = subplot_params.hspace
  144. tot_width = right - left
  145. tot_height = top - bottom
  146. # calculate accumulated heights of columns
  147. cell_h = tot_height / (nrows + hspace*(nrows-1))
  148. sep_h = hspace * cell_h
  149. if self._row_height_ratios is not None:
  150. norm = cell_h * nrows / sum(self._row_height_ratios)
  151. cell_heights = [r * norm for r in self._row_height_ratios]
  152. else:
  153. cell_heights = [cell_h] * nrows
  154. sep_heights = [0] + ([sep_h] * (nrows-1))
  155. cell_hs = np.cumsum(np.column_stack([sep_heights, cell_heights]).flat)
  156. # calculate accumulated widths of rows
  157. cell_w = tot_width / (ncols + wspace*(ncols-1))
  158. sep_w = wspace * cell_w
  159. if self._col_width_ratios is not None:
  160. norm = cell_w * ncols / sum(self._col_width_ratios)
  161. cell_widths = [r * norm for r in self._col_width_ratios]
  162. else:
  163. cell_widths = [cell_w] * ncols
  164. sep_widths = [0] + ([sep_w] * (ncols-1))
  165. cell_ws = np.cumsum(np.column_stack([sep_widths, cell_widths]).flat)
  166. fig_tops, fig_bottoms = (top - cell_hs).reshape((-1, 2)).T
  167. fig_lefts, fig_rights = (left + cell_ws).reshape((-1, 2)).T
  168. return fig_bottoms, fig_tops, fig_lefts, fig_rights
  169. def __getitem__(self, key):
  170. """Create and return a `.SubplotSpec` instance."""
  171. nrows, ncols = self.get_geometry()
  172. def _normalize(key, size, axis): # Includes last index.
  173. orig_key = key
  174. if isinstance(key, slice):
  175. start, stop, _ = key.indices(size)
  176. if stop > start:
  177. return start, stop - 1
  178. raise IndexError("GridSpec slice would result in no space "
  179. "allocated for subplot")
  180. else:
  181. if key < 0:
  182. key = key + size
  183. if 0 <= key < size:
  184. return key, key
  185. elif axis is not None:
  186. raise IndexError(f"index {orig_key} is out of bounds for "
  187. f"axis {axis} with size {size}")
  188. else: # flat index
  189. raise IndexError(f"index {orig_key} is out of bounds for "
  190. f"GridSpec with size {size}")
  191. if isinstance(key, tuple):
  192. try:
  193. k1, k2 = key
  194. except ValueError:
  195. raise ValueError("unrecognized subplot spec")
  196. num1, num2 = np.ravel_multi_index(
  197. [_normalize(k1, nrows, 0), _normalize(k2, ncols, 1)],
  198. (nrows, ncols))
  199. else: # Single key
  200. num1, num2 = _normalize(key, nrows * ncols, None)
  201. return SubplotSpec(self, num1, num2)
  202. class GridSpec(GridSpecBase):
  203. """
  204. A grid layout to place subplots within a figure.
  205. The location of the grid cells is determined in a similar way to
  206. `~.figure.SubplotParams` using *left*, *right*, *top*, *bottom*, *wspace*
  207. and *hspace*.
  208. """
  209. def __init__(self, nrows, ncols, figure=None,
  210. left=None, bottom=None, right=None, top=None,
  211. wspace=None, hspace=None,
  212. width_ratios=None, height_ratios=None):
  213. """
  214. Parameters
  215. ----------
  216. nrows, ncols : int
  217. The number of rows and columns of the grid.
  218. figure : `~.figure.Figure`, optional
  219. Only used for constrained layout to create a proper layoutbox.
  220. left, right, top, bottom : float, optional
  221. Extent of the subplots as a fraction of figure width or height.
  222. Left cannot be larger than right, and bottom cannot be larger than
  223. top. If not given, the values will be inferred from a figure or
  224. rcParams at draw time. See also `GridSpec.get_subplot_params`.
  225. wspace : float, optional
  226. The amount of width reserved for space between subplots,
  227. expressed as a fraction of the average axis width.
  228. If not given, the values will be inferred from a figure or
  229. rcParams when necessary. See also `GridSpec.get_subplot_params`.
  230. hspace : float, optional
  231. The amount of height reserved for space between subplots,
  232. expressed as a fraction of the average axis height.
  233. If not given, the values will be inferred from a figure or
  234. rcParams when necessary. See also `GridSpec.get_subplot_params`.
  235. width_ratios : array-like of length *ncols*, optional
  236. Defines the relative widths of the columns. Each column gets a
  237. relative width of ``width_ratios[i] / sum(width_ratios)``.
  238. If not given, all columns will have the same width.
  239. height_ratios : array-like of length *nrows*, optional
  240. Defines the relative heights of the rows. Each column gets a
  241. relative height of ``height_ratios[i] / sum(height_ratios)``.
  242. If not given, all rows will have the same height.
  243. """
  244. self.left = left
  245. self.bottom = bottom
  246. self.right = right
  247. self.top = top
  248. self.wspace = wspace
  249. self.hspace = hspace
  250. self.figure = figure
  251. GridSpecBase.__init__(self, nrows, ncols,
  252. width_ratios=width_ratios,
  253. height_ratios=height_ratios)
  254. if self.figure is None or not self.figure.get_constrained_layout():
  255. self._layoutbox = None
  256. else:
  257. self.figure.init_layoutbox()
  258. self._layoutbox = layoutbox.LayoutBox(
  259. parent=self.figure._layoutbox,
  260. name='gridspec' + layoutbox.seq_id(),
  261. artist=self)
  262. # by default the layoutbox for a gridspec will fill a figure.
  263. # but this can change below if the gridspec is created from a
  264. # subplotspec. (GridSpecFromSubplotSpec)
  265. _AllowedKeys = ["left", "bottom", "right", "top", "wspace", "hspace"]
  266. def __getstate__(self):
  267. state = self.__dict__
  268. try:
  269. state.pop('_layoutbox')
  270. except KeyError:
  271. pass
  272. return state
  273. def __setstate__(self, state):
  274. self.__dict__ = state
  275. # layoutboxes don't survive pickling...
  276. self._layoutbox = None
  277. def update(self, **kwargs):
  278. """
  279. Update the subplot parameters of the grid.
  280. Parameters that are not explicitly given are not changed. Setting a
  281. parameter to *None* resets it to :rc:`figure.subplot.*`.
  282. Parameters
  283. ----------
  284. left, right, top, bottom : float or None, optional
  285. Extent of the subplots as a fraction of figure width or height.
  286. wspace, hspace : float, optional
  287. Spacing between the subplots as a fraction of the average subplot
  288. width / height.
  289. """
  290. for k, v in kwargs.items():
  291. if k in self._AllowedKeys:
  292. setattr(self, k, v)
  293. else:
  294. raise AttributeError(f"{k} is an unknown keyword")
  295. for figmanager in _pylab_helpers.Gcf.figs.values():
  296. for ax in figmanager.canvas.figure.axes:
  297. # copied from Figure.subplots_adjust
  298. if not isinstance(ax, mpl.axes.SubplotBase):
  299. # Check if sharing a subplots axis
  300. if isinstance(ax._sharex, mpl.axes.SubplotBase):
  301. if ax._sharex.get_subplotspec().get_gridspec() == self:
  302. ax._sharex.update_params()
  303. ax._set_position(ax._sharex.figbox)
  304. elif isinstance(ax._sharey, mpl.axes.SubplotBase):
  305. if ax._sharey.get_subplotspec().get_gridspec() == self:
  306. ax._sharey.update_params()
  307. ax._set_position(ax._sharey.figbox)
  308. else:
  309. ss = ax.get_subplotspec().get_topmost_subplotspec()
  310. if ss.get_gridspec() == self:
  311. ax.update_params()
  312. ax._set_position(ax.figbox)
  313. def get_subplot_params(self, figure=None):
  314. """
  315. Return the `~.SubplotParams` for the GridSpec.
  316. In order of precedence the values are taken from
  317. - non-*None* attributes of the GridSpec
  318. - the provided *figure*
  319. - :rc:`figure.subplot.*`
  320. """
  321. if figure is None:
  322. kw = {k: rcParams["figure.subplot."+k] for k in self._AllowedKeys}
  323. subplotpars = mpl.figure.SubplotParams(**kw)
  324. else:
  325. subplotpars = copy.copy(figure.subplotpars)
  326. subplotpars.update(**{k: getattr(self, k) for k in self._AllowedKeys})
  327. return subplotpars
  328. def locally_modified_subplot_params(self):
  329. """
  330. Return a list of the names of the subplot parameters explicitly set
  331. in the GridSpec.
  332. This is a subset of the attributes of `.SubplotParams`.
  333. """
  334. return [k for k in self._AllowedKeys if getattr(self, k)]
  335. def tight_layout(self, figure, renderer=None,
  336. pad=1.08, h_pad=None, w_pad=None, rect=None):
  337. """
  338. Adjust subplot parameters to give specified padding.
  339. Parameters
  340. ----------
  341. pad : float
  342. Padding between the figure edge and the edges of subplots, as a
  343. fraction of the font-size.
  344. h_pad, w_pad : float, optional
  345. Padding (height/width) between edges of adjacent subplots.
  346. Defaults to *pad*.
  347. rect : tuple of 4 floats, optional
  348. (left, bottom, right, top) rectangle in normalized figure
  349. coordinates that the whole subplots area (including labels) will
  350. fit into. Default is (0, 0, 1, 1).
  351. """
  352. subplotspec_list = tight_layout.get_subplotspec_list(
  353. figure.axes, grid_spec=self)
  354. if None in subplotspec_list:
  355. cbook._warn_external("This figure includes Axes that are not "
  356. "compatible with tight_layout, so results "
  357. "might be incorrect.")
  358. if renderer is None:
  359. renderer = tight_layout.get_renderer(figure)
  360. kwargs = tight_layout.get_tight_layout_figure(
  361. figure, figure.axes, subplotspec_list, renderer,
  362. pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
  363. if kwargs:
  364. self.update(**kwargs)
  365. class GridSpecFromSubplotSpec(GridSpecBase):
  366. """
  367. GridSpec whose subplot layout parameters are inherited from the
  368. location specified by a given SubplotSpec.
  369. """
  370. def __init__(self, nrows, ncols,
  371. subplot_spec,
  372. wspace=None, hspace=None,
  373. height_ratios=None, width_ratios=None):
  374. """
  375. The number of rows and number of columns of the grid need to
  376. be set. An instance of SubplotSpec is also needed to be set
  377. from which the layout parameters will be inherited. The wspace
  378. and hspace of the layout can be optionally specified or the
  379. default values (from the figure or rcParams) will be used.
  380. """
  381. self._wspace = wspace
  382. self._hspace = hspace
  383. self._subplot_spec = subplot_spec
  384. GridSpecBase.__init__(self, nrows, ncols,
  385. width_ratios=width_ratios,
  386. height_ratios=height_ratios)
  387. # do the layoutboxes
  388. subspeclb = subplot_spec._layoutbox
  389. if subspeclb is None:
  390. self._layoutbox = None
  391. else:
  392. # OK, this is needed to divide the figure.
  393. self._layoutbox = subspeclb.layout_from_subplotspec(
  394. subplot_spec,
  395. name=subspeclb.name + '.gridspec' + layoutbox.seq_id(),
  396. artist=self)
  397. def get_subplot_params(self, figure=None):
  398. """Return a dictionary of subplot layout parameters.
  399. """
  400. hspace = (self._hspace if self._hspace is not None
  401. else figure.subplotpars.hspace if figure is not None
  402. else rcParams["figure.subplot.hspace"])
  403. wspace = (self._wspace if self._wspace is not None
  404. else figure.subplotpars.wspace if figure is not None
  405. else rcParams["figure.subplot.wspace"])
  406. figbox = self._subplot_spec.get_position(figure)
  407. left, bottom, right, top = figbox.extents
  408. return mpl.figure.SubplotParams(left=left, right=right,
  409. bottom=bottom, top=top,
  410. wspace=wspace, hspace=hspace)
  411. def get_topmost_subplotspec(self):
  412. """
  413. Return the topmost `.SubplotSpec` instance associated with the subplot.
  414. """
  415. return self._subplot_spec.get_topmost_subplotspec()
  416. class SubplotSpec:
  417. """
  418. Specifies the location of a subplot in a `GridSpec`.
  419. .. note::
  420. Likely, you'll never instantiate a `SubplotSpec` yourself. Instead you
  421. will typically obtain one from a `GridSpec` using item-access.
  422. Parameters
  423. ----------
  424. gridspec : `~matplotlib.gridspec.GridSpec`
  425. The GridSpec, which the subplot is referencing.
  426. num1, num2 : int
  427. The subplot will occupy the num1-th cell of the given
  428. gridspec. If num2 is provided, the subplot will span between
  429. num1-th cell and num2-th cell *inclusive*.
  430. The index starts from 0.
  431. """
  432. def __init__(self, gridspec, num1, num2=None):
  433. self._gridspec = gridspec
  434. self.num1 = num1
  435. self.num2 = num2
  436. if gridspec._layoutbox is not None:
  437. glb = gridspec._layoutbox
  438. # So note that here we don't assign any layout yet,
  439. # just make the layoutbox that will contain all items
  440. # associated w/ this axis. This can include other axes like
  441. # a colorbar or a legend.
  442. self._layoutbox = layoutbox.LayoutBox(
  443. parent=glb,
  444. name=glb.name + '.ss' + layoutbox.seq_id(),
  445. artist=self)
  446. else:
  447. self._layoutbox = None
  448. # num2 is a property only to handle the case where it is None and someone
  449. # mutates num1.
  450. @property
  451. def num2(self):
  452. return self.num1 if self._num2 is None else self._num2
  453. @num2.setter
  454. def num2(self, value):
  455. self._num2 = value
  456. def __getstate__(self):
  457. state = self.__dict__
  458. try:
  459. state.pop('_layoutbox')
  460. except KeyError:
  461. pass
  462. return state
  463. def __setstate__(self, state):
  464. self.__dict__ = state
  465. # layoutboxes don't survive pickling...
  466. self._layoutbox = None
  467. def get_gridspec(self):
  468. return self._gridspec
  469. def get_geometry(self):
  470. """
  471. Return the subplot geometry as tuple ``(n_rows, n_cols, start, stop)``.
  472. The indices *start* and *stop* define the range of the subplot within
  473. the `GridSpec`. *stop* is inclusive (i.e. for a single cell
  474. ``start == stop``).
  475. """
  476. rows, cols = self.get_gridspec().get_geometry()
  477. return rows, cols, self.num1, self.num2
  478. def get_rows_columns(self):
  479. """
  480. Return the subplot row and column numbers as a tuple
  481. ``(n_rows, n_cols, row_start, row_stop, col_start, col_stop)``.
  482. """
  483. gridspec = self.get_gridspec()
  484. nrows, ncols = gridspec.get_geometry()
  485. row_start, col_start = divmod(self.num1, ncols)
  486. row_stop, col_stop = divmod(self.num2, ncols)
  487. return nrows, ncols, row_start, row_stop, col_start, col_stop
  488. @property
  489. def rowspan(self):
  490. """The rows spanned by this subplot, as a `range` object."""
  491. ncols = self.get_gridspec().ncols
  492. return range(self.num1 // ncols, self.num2 // ncols + 1)
  493. @property
  494. def colspan(self):
  495. """The columns spanned by this subplot, as a `range` object."""
  496. ncols = self.get_gridspec().ncols
  497. return range(self.num1 % ncols, self.num2 % ncols + 1)
  498. def get_position(self, figure, return_all=False):
  499. """
  500. Update the subplot position from ``figure.subplotpars``.
  501. """
  502. gridspec = self.get_gridspec()
  503. nrows, ncols = gridspec.get_geometry()
  504. rows, cols = np.unravel_index([self.num1, self.num2], (nrows, ncols))
  505. fig_bottoms, fig_tops, fig_lefts, fig_rights = \
  506. gridspec.get_grid_positions(figure)
  507. fig_bottom = fig_bottoms[rows].min()
  508. fig_top = fig_tops[rows].max()
  509. fig_left = fig_lefts[cols].min()
  510. fig_right = fig_rights[cols].max()
  511. figbox = Bbox.from_extents(fig_left, fig_bottom, fig_right, fig_top)
  512. if return_all:
  513. return figbox, rows[0], cols[0], nrows, ncols
  514. else:
  515. return figbox
  516. def get_topmost_subplotspec(self):
  517. """
  518. Return the topmost `SubplotSpec` instance associated with the subplot.
  519. """
  520. gridspec = self.get_gridspec()
  521. if hasattr(gridspec, "get_topmost_subplotspec"):
  522. return gridspec.get_topmost_subplotspec()
  523. else:
  524. return self
  525. def __eq__(self, other):
  526. """
  527. Two SubplotSpecs are considered equal if they refer to the same
  528. position(s) in the same `GridSpec`.
  529. """
  530. # other may not even have the attributes we are checking.
  531. return ((self._gridspec, self.num1, self.num2)
  532. == (getattr(other, "_gridspec", object()),
  533. getattr(other, "num1", object()),
  534. getattr(other, "num2", object())))
  535. def __hash__(self):
  536. return hash((self._gridspec, self.num1, self.num2))
  537. def subgridspec(self, nrows, ncols, **kwargs):
  538. """
  539. Create a GridSpec within this subplot.
  540. The created `.GridSpecFromSubplotSpec` will have this `SubplotSpec` as
  541. a parent.
  542. Parameters
  543. ----------
  544. nrows : int
  545. Number of rows in grid.
  546. ncols : int
  547. Number or columns in grid.
  548. Returns
  549. -------
  550. gridspec : `.GridSpecFromSubplotSpec`
  551. Other Parameters
  552. ----------------
  553. **kwargs
  554. All other parameters are passed to `.GridSpecFromSubplotSpec`.
  555. See Also
  556. --------
  557. matplotlib.pyplot.subplots
  558. Examples
  559. --------
  560. Adding three subplots in the space occupied by a single subplot::
  561. fig = plt.figure()
  562. gs0 = fig.add_gridspec(3, 1)
  563. ax1 = fig.add_subplot(gs0[0])
  564. ax2 = fig.add_subplot(gs0[1])
  565. gssub = gs0[2].subgridspec(1, 3)
  566. for i in range(3):
  567. fig.add_subplot(gssub[0, i])
  568. """
  569. return GridSpecFromSubplotSpec(nrows, ncols, self, **kwargs)