Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2The figure module provides the top-level 

3:class:`~matplotlib.artist.Artist`, the :class:`Figure`, which 

4contains all the plot elements. The following classes are defined 

5 

6:class:`SubplotParams` 

7 control the default spacing of the subplots 

8 

9:class:`Figure` 

10 Top level container for all plot elements. 

11 

12""" 

13 

14import logging 

15from numbers import Integral 

16 

17import numpy as np 

18 

19from matplotlib import rcParams 

20from matplotlib import backends, docstring, projections 

21from matplotlib import __version__ as _mpl_version 

22from matplotlib import get_backend 

23 

24import matplotlib.artist as martist 

25from matplotlib.artist import Artist, allow_rasterization 

26from matplotlib.backend_bases import FigureCanvasBase, NonGuiException 

27import matplotlib.cbook as cbook 

28import matplotlib.colorbar as cbar 

29import matplotlib.image as mimage 

30 

31from matplotlib.axes import Axes, SubplotBase, subplot_class_factory 

32from matplotlib.blocking_input import BlockingMouseInput, BlockingKeyMouseInput 

33from matplotlib.gridspec import GridSpec 

34import matplotlib.legend as mlegend 

35from matplotlib.patches import Rectangle 

36from matplotlib.projections import process_projection_requirements 

37from matplotlib.text import Text, TextWithDash 

38from matplotlib.transforms import (Affine2D, Bbox, BboxTransformTo, 

39 TransformedBbox) 

40import matplotlib._layoutbox as layoutbox 

41 

42_log = logging.getLogger(__name__) 

43 

44 

45def _stale_figure_callback(self, val): 

46 if self.figure: 

47 self.figure.stale = val 

48 

49 

50class _AxesStack(cbook.Stack): 

51 """ 

52 Specialization of the `.Stack` to handle all tracking of 

53 `~matplotlib.axes.Axes` in a `.Figure`. 

54 This stack stores ``key, (ind, axes)`` pairs, where: 

55 

56 * **key** should be a hash of the args and kwargs 

57 used in generating the Axes. 

58 * **ind** is a serial number for tracking the order 

59 in which axes were added. 

60 

61 The AxesStack is a callable, where ``ax_stack()`` returns 

62 the current axes. Alternatively the :meth:`current_key_axes` will 

63 return the current key and associated axes. 

64 

65 """ 

66 def __init__(self): 

67 super().__init__() 

68 self._ind = 0 

69 

70 def as_list(self): 

71 """ 

72 Return a list of the Axes instances that have been added to the figure. 

73 """ 

74 ia_list = [a for k, a in self._elements] 

75 ia_list.sort() 

76 return [a for i, a in ia_list] 

77 

78 def get(self, key): 

79 """ 

80 Return the Axes instance that was added with *key*. 

81 If it is not present, return *None*. 

82 """ 

83 item = dict(self._elements).get(key) 

84 if item is None: 

85 return None 

86 cbook.warn_deprecated( 

87 "2.1", 

88 message="Adding an axes using the same arguments as a previous " 

89 "axes currently reuses the earlier instance. In a future " 

90 "version, a new instance will always be created and returned. " 

91 "Meanwhile, this warning can be suppressed, and the future " 

92 "behavior ensured, by passing a unique label to each axes " 

93 "instance.") 

94 return item[1] 

95 

96 def _entry_from_axes(self, e): 

97 ind, k = {a: (ind, k) for k, (ind, a) in self._elements}[e] 

98 return (k, (ind, e)) 

99 

100 def remove(self, a): 

101 """Remove the axes from the stack.""" 

102 super().remove(self._entry_from_axes(a)) 

103 

104 def bubble(self, a): 

105 """ 

106 Move the given axes, which must already exist in the 

107 stack, to the top. 

108 """ 

109 return super().bubble(self._entry_from_axes(a)) 

110 

111 def add(self, key, a): 

112 """ 

113 Add Axes *a*, with key *key*, to the stack, and return the stack. 

114 

115 If *key* is unhashable, replace it by a unique, arbitrary object. 

116 

117 If *a* is already on the stack, don't add it again, but 

118 return *None*. 

119 """ 

120 # All the error checking may be unnecessary; but this method 

121 # is called so seldom that the overhead is negligible. 

122 cbook._check_isinstance(Axes, a=a) 

123 try: 

124 hash(key) 

125 except TypeError: 

126 key = object() 

127 

128 a_existing = self.get(key) 

129 if a_existing is not None: 

130 super().remove((key, a_existing)) 

131 cbook._warn_external( 

132 "key {!r} already existed; Axes is being replaced".format(key)) 

133 # I don't think the above should ever happen. 

134 

135 if a in self: 

136 return None 

137 self._ind += 1 

138 return super().push((key, (self._ind, a))) 

139 

140 def current_key_axes(self): 

141 """ 

142 Return a tuple of ``(key, axes)`` for the active axes. 

143 

144 If no axes exists on the stack, then returns ``(None, None)``. 

145 """ 

146 if not len(self._elements): 

147 return self._default, self._default 

148 else: 

149 key, (index, axes) = self._elements[self._pos] 

150 return key, axes 

151 

152 def __call__(self): 

153 return self.current_key_axes()[1] 

154 

155 def __contains__(self, a): 

156 return a in self.as_list() 

157 

158 

159@cbook.deprecated("3.2") 

160class AxesStack(_AxesStack): 

161 pass 

162 

163 

164class SubplotParams: 

165 """ 

166 A class to hold the parameters for a subplot. 

167 """ 

168 def __init__(self, left=None, bottom=None, right=None, top=None, 

169 wspace=None, hspace=None): 

170 """ 

171 All dimensions are fractions of the figure width or height. 

172 Defaults are given by :rc:`figure.subplot.[name]`. 

173 

174 Parameters 

175 ---------- 

176 left : float 

177 The left side of the subplots of the figure. 

178 

179 right : float 

180 The right side of the subplots of the figure. 

181 

182 bottom : float 

183 The bottom of the subplots of the figure. 

184 

185 top : float 

186 The top of the subplots of the figure. 

187 

188 wspace : float 

189 The amount of width reserved for space between subplots, 

190 expressed as a fraction of the average axis width. 

191 

192 hspace : float 

193 The amount of height reserved for space between subplots, 

194 expressed as a fraction of the average axis height. 

195 """ 

196 self.validate = True 

197 self.update(left, bottom, right, top, wspace, hspace) 

198 

199 def update(self, left=None, bottom=None, right=None, top=None, 

200 wspace=None, hspace=None): 

201 """ 

202 Update the dimensions of the passed parameters. *None* means unchanged. 

203 """ 

204 thisleft = getattr(self, 'left', None) 

205 thisright = getattr(self, 'right', None) 

206 thistop = getattr(self, 'top', None) 

207 thisbottom = getattr(self, 'bottom', None) 

208 thiswspace = getattr(self, 'wspace', None) 

209 thishspace = getattr(self, 'hspace', None) 

210 

211 self._update_this('left', left) 

212 self._update_this('right', right) 

213 self._update_this('bottom', bottom) 

214 self._update_this('top', top) 

215 self._update_this('wspace', wspace) 

216 self._update_this('hspace', hspace) 

217 

218 def reset(): 

219 self.left = thisleft 

220 self.right = thisright 

221 self.top = thistop 

222 self.bottom = thisbottom 

223 self.wspace = thiswspace 

224 self.hspace = thishspace 

225 

226 if self.validate: 

227 if self.left >= self.right: 

228 reset() 

229 raise ValueError('left cannot be >= right') 

230 

231 if self.bottom >= self.top: 

232 reset() 

233 raise ValueError('bottom cannot be >= top') 

234 

235 def _update_this(self, s, val): 

236 if val is None: 

237 val = getattr(self, s, None) 

238 if val is None: 

239 key = 'figure.subplot.' + s 

240 val = rcParams[key] 

241 

242 setattr(self, s, val) 

243 

244 

245class Figure(Artist): 

246 """ 

247 The top level container for all the plot elements. 

248 

249 The Figure instance supports callbacks through a *callbacks* attribute 

250 which is a `.CallbackRegistry` instance. The events you can connect to 

251 are 'dpi_changed', and the callback will be called with ``func(fig)`` where 

252 fig is the `Figure` instance. 

253 

254 Attributes 

255 ---------- 

256 patch 

257 The `.Rectangle` instance representing the figure background patch. 

258 

259 suppressComposite 

260 For multiple figure images, the figure will make composite images 

261 depending on the renderer option_image_nocomposite function. If 

262 *suppressComposite* is a boolean, this will override the renderer. 

263 """ 

264 

265 def __str__(self): 

266 return "Figure(%gx%g)" % tuple(self.bbox.size) 

267 

268 def __repr__(self): 

269 return "<{clsname} size {h:g}x{w:g} with {naxes} Axes>".format( 

270 clsname=self.__class__.__name__, 

271 h=self.bbox.size[0], w=self.bbox.size[1], 

272 naxes=len(self.axes), 

273 ) 

274 

275 def __init__(self, 

276 figsize=None, 

277 dpi=None, 

278 facecolor=None, 

279 edgecolor=None, 

280 linewidth=0.0, 

281 frameon=None, 

282 subplotpars=None, # default to rc 

283 tight_layout=None, # default to rc figure.autolayout 

284 constrained_layout=None, # default to rc 

285 #figure.constrained_layout.use 

286 ): 

287 """ 

288 Parameters 

289 ---------- 

290 figsize : 2-tuple of floats, default: :rc:`figure.figsize` 

291 Figure dimension ``(width, height)`` in inches. 

292 

293 dpi : float, default: :rc:`figure.dpi` 

294 Dots per inch. 

295 

296 facecolor : default: :rc:`figure.facecolor` 

297 The figure patch facecolor. 

298 

299 edgecolor : default: :rc:`figure.edgecolor` 

300 The figure patch edge color. 

301 

302 linewidth : float 

303 The linewidth of the frame (i.e. the edge linewidth of the figure 

304 patch). 

305 

306 frameon : bool, default: :rc:`figure.frameon` 

307 If ``False``, suppress drawing the figure background patch. 

308 

309 subplotpars : :class:`SubplotParams` 

310 Subplot parameters. If not given, the default subplot 

311 parameters :rc:`figure.subplot.*` are used. 

312 

313 tight_layout : bool or dict, default: :rc:`figure.autolayout` 

314 If ``False`` use *subplotpars*. If ``True`` adjust subplot 

315 parameters using `.tight_layout` with default padding. 

316 When providing a dict containing the keys ``pad``, ``w_pad``, 

317 ``h_pad``, and ``rect``, the default `.tight_layout` paddings 

318 will be overridden. 

319 

320 constrained_layout : bool 

321 If ``True`` use constrained layout to adjust positioning of plot 

322 elements. Like ``tight_layout``, but designed to be more 

323 flexible. See 

324 :doc:`/tutorials/intermediate/constrainedlayout_guide` 

325 for examples. (Note: does not work with :meth:`.subplot` or 

326 :meth:`.subplot2grid`.) 

327 Defaults to :rc:`figure.constrained_layout.use`. 

328 """ 

329 super().__init__() 

330 # remove the non-figure artist _axes property 

331 # as it makes no sense for a figure to be _in_ an axes 

332 # this is used by the property methods in the artist base class 

333 # which are over-ridden in this class 

334 del self._axes 

335 self.callbacks = cbook.CallbackRegistry() 

336 

337 if figsize is None: 

338 figsize = rcParams['figure.figsize'] 

339 if dpi is None: 

340 dpi = rcParams['figure.dpi'] 

341 if facecolor is None: 

342 facecolor = rcParams['figure.facecolor'] 

343 if edgecolor is None: 

344 edgecolor = rcParams['figure.edgecolor'] 

345 if frameon is None: 

346 frameon = rcParams['figure.frameon'] 

347 

348 if not np.isfinite(figsize).all() or (np.array(figsize) <= 0).any(): 

349 raise ValueError('figure size must be positive finite not ' 

350 f'{figsize}') 

351 self.bbox_inches = Bbox.from_bounds(0, 0, *figsize) 

352 

353 self.dpi_scale_trans = Affine2D().scale(dpi) 

354 # do not use property as it will trigger 

355 self._dpi = dpi 

356 self.bbox = TransformedBbox(self.bbox_inches, self.dpi_scale_trans) 

357 

358 self.transFigure = BboxTransformTo(self.bbox) 

359 

360 self.patch = Rectangle( 

361 xy=(0, 0), width=1, height=1, visible=frameon, 

362 facecolor=facecolor, edgecolor=edgecolor, linewidth=linewidth, 

363 # Don't let the figure patch influence bbox calculation. 

364 in_layout=False) 

365 self._set_artist_props(self.patch) 

366 self.patch.set_antialiased(False) 

367 

368 FigureCanvasBase(self) # Set self.canvas. 

369 self._suptitle = None 

370 

371 if subplotpars is None: 

372 subplotpars = SubplotParams() 

373 

374 self.subplotpars = subplotpars 

375 # constrained_layout: 

376 self._layoutbox = None 

377 # set in set_constrained_layout_pads() 

378 self.set_constrained_layout(constrained_layout) 

379 

380 self.set_tight_layout(tight_layout) 

381 

382 self._axstack = _AxesStack() # track all figure axes and current axes 

383 self.clf() 

384 self._cachedRenderer = None 

385 

386 # groupers to keep track of x and y labels we want to align. 

387 # see self.align_xlabels and self.align_ylabels and 

388 # axis._get_tick_boxes_siblings 

389 self._align_xlabel_grp = cbook.Grouper() 

390 self._align_ylabel_grp = cbook.Grouper() 

391 

392 # list of child gridspecs for this figure 

393 self._gridspecs = [] 

394 

395 # TODO: I'd like to dynamically add the _repr_html_ method 

396 # to the figure in the right context, but then IPython doesn't 

397 # use it, for some reason. 

398 

399 def _repr_html_(self): 

400 # We can't use "isinstance" here, because then we'd end up importing 

401 # webagg unconditionally. 

402 if 'WebAgg' in type(self.canvas).__name__: 

403 from matplotlib.backends import backend_webagg 

404 return backend_webagg.ipython_inline_display(self) 

405 

406 def show(self, warn=True): 

407 """ 

408 If using a GUI backend with pyplot, display the figure window. 

409 

410 If the figure was not created using 

411 :func:`~matplotlib.pyplot.figure`, it will lack a 

412 :class:`~matplotlib.backend_bases.FigureManagerBase`, and 

413 will raise an AttributeError. 

414 

415 .. warning:: 

416 This does not manage an GUI event loop. Consequently, the figure 

417 may only be shown briefly or not shown at all if you or your 

418 environment are not managing an event loop. 

419 

420 Proper use cases for `.Figure.show` include running this from a 

421 GUI application or an IPython shell. 

422 

423 If you're running a pure python shell or executing a non-GUI 

424 python script, you should use `matplotlib.pyplot.show` instead, 

425 which takes care of managing the event loop for you. 

426 

427 Parameters 

428 ---------- 

429 warn : bool 

430 If ``True`` and we are not running headless (i.e. on Linux with an 

431 unset DISPLAY), issue warning when called on a non-GUI backend. 

432 """ 

433 try: 

434 manager = getattr(self.canvas, 'manager') 

435 except AttributeError as err: 

436 raise AttributeError("%s\n" 

437 "Figure.show works only " 

438 "for figures managed by pyplot, normally " 

439 "created by pyplot.figure()." % err) 

440 

441 if manager is not None: 

442 try: 

443 manager.show() 

444 return 

445 except NonGuiException: 

446 pass 

447 if (backends._get_running_interactive_framework() != "headless" 

448 and warn): 

449 cbook._warn_external('Matplotlib is currently using %s, which is ' 

450 'a non-GUI backend, so cannot show the ' 

451 'figure.' % get_backend()) 

452 

453 def _get_axes(self): 

454 return self._axstack.as_list() 

455 

456 axes = property(fget=_get_axes, 

457 doc="List of axes in the Figure. You can access the " 

458 "axes in the Figure through this list. " 

459 "Do not modify the list itself. Instead, use " 

460 "`~Figure.add_axes`, `~.Figure.subplot` or " 

461 "`~.Figure.delaxes` to add or remove an axes.") 

462 

463 def _get_dpi(self): 

464 return self._dpi 

465 

466 def _set_dpi(self, dpi, forward=True): 

467 """ 

468 Parameters 

469 ---------- 

470 dpi : float 

471 

472 forward : bool 

473 Passed on to `~.Figure.set_size_inches` 

474 """ 

475 self._dpi = dpi 

476 self.dpi_scale_trans.clear().scale(dpi) 

477 w, h = self.get_size_inches() 

478 self.set_size_inches(w, h, forward=forward) 

479 self.callbacks.process('dpi_changed', self) 

480 

481 dpi = property(_get_dpi, _set_dpi, doc="The resolution in dots per inch.") 

482 

483 def get_tight_layout(self): 

484 """Return whether `.tight_layout` is called when drawing.""" 

485 return self._tight 

486 

487 def set_tight_layout(self, tight): 

488 """ 

489 Set whether and how `.tight_layout` is called when drawing. 

490 

491 Parameters 

492 ---------- 

493 tight : bool or dict with keys "pad", "w_pad", "h_pad", "rect" or None 

494 If a bool, sets whether to call `.tight_layout` upon drawing. 

495 If ``None``, use the ``figure.autolayout`` rcparam instead. 

496 If a dict, pass it as kwargs to `.tight_layout`, overriding the 

497 default paddings. 

498 """ 

499 if tight is None: 

500 tight = rcParams['figure.autolayout'] 

501 self._tight = bool(tight) 

502 self._tight_parameters = tight if isinstance(tight, dict) else {} 

503 self.stale = True 

504 

505 def get_constrained_layout(self): 

506 """ 

507 Return a boolean: True means constrained layout is being used. 

508 

509 See :doc:`/tutorials/intermediate/constrainedlayout_guide`. 

510 """ 

511 return self._constrained 

512 

513 def set_constrained_layout(self, constrained): 

514 """ 

515 Set whether ``constrained_layout`` is used upon drawing. If None, 

516 the rcParams['figure.constrained_layout.use'] value will be used. 

517 

518 When providing a dict containing the keys `w_pad`, `h_pad` 

519 the default ``constrained_layout`` paddings will be 

520 overridden. These pads are in inches and default to 3.0/72.0. 

521 ``w_pad`` is the width padding and ``h_pad`` is the height padding. 

522 

523 See :doc:`/tutorials/intermediate/constrainedlayout_guide`. 

524 

525 Parameters 

526 ---------- 

527 constrained : bool or dict or None 

528 """ 

529 self._constrained_layout_pads = dict() 

530 self._constrained_layout_pads['w_pad'] = None 

531 self._constrained_layout_pads['h_pad'] = None 

532 self._constrained_layout_pads['wspace'] = None 

533 self._constrained_layout_pads['hspace'] = None 

534 if constrained is None: 

535 constrained = rcParams['figure.constrained_layout.use'] 

536 self._constrained = bool(constrained) 

537 if isinstance(constrained, dict): 

538 self.set_constrained_layout_pads(**constrained) 

539 else: 

540 self.set_constrained_layout_pads() 

541 

542 self.stale = True 

543 

544 def set_constrained_layout_pads(self, **kwargs): 

545 """ 

546 Set padding for ``constrained_layout``. Note the kwargs can be passed 

547 as a dictionary ``fig.set_constrained_layout(**paddict)``. 

548 

549 See :doc:`/tutorials/intermediate/constrainedlayout_guide`. 

550 

551 Parameters 

552 ---------- 

553 w_pad : scalar 

554 Width padding in inches. This is the pad around axes 

555 and is meant to make sure there is enough room for fonts to 

556 look good. Defaults to 3 pts = 0.04167 inches 

557 

558 h_pad : scalar 

559 Height padding in inches. Defaults to 3 pts. 

560 

561 wspace : scalar 

562 Width padding between subplots, expressed as a fraction of the 

563 subplot width. The total padding ends up being w_pad + wspace. 

564 

565 hspace : scalar 

566 Height padding between subplots, expressed as a fraction of the 

567 subplot width. The total padding ends up being h_pad + hspace. 

568 

569 """ 

570 

571 todo = ['w_pad', 'h_pad', 'wspace', 'hspace'] 

572 for td in todo: 

573 if td in kwargs and kwargs[td] is not None: 

574 self._constrained_layout_pads[td] = kwargs[td] 

575 else: 

576 self._constrained_layout_pads[td] = ( 

577 rcParams['figure.constrained_layout.' + td]) 

578 

579 def get_constrained_layout_pads(self, relative=False): 

580 """ 

581 Get padding for ``constrained_layout``. 

582 

583 Returns a list of `w_pad, h_pad` in inches and 

584 `wspace` and `hspace` as fractions of the subplot. 

585 

586 See :doc:`/tutorials/intermediate/constrainedlayout_guide`. 

587 

588 Parameters 

589 ---------- 

590 relative : boolean 

591 If `True`, then convert from inches to figure relative. 

592 """ 

593 w_pad = self._constrained_layout_pads['w_pad'] 

594 h_pad = self._constrained_layout_pads['h_pad'] 

595 wspace = self._constrained_layout_pads['wspace'] 

596 hspace = self._constrained_layout_pads['hspace'] 

597 

598 if relative and (w_pad is not None or h_pad is not None): 

599 renderer0 = layoutbox.get_renderer(self) 

600 dpi = renderer0.dpi 

601 w_pad = w_pad * dpi / renderer0.width 

602 h_pad = h_pad * dpi / renderer0.height 

603 

604 return w_pad, h_pad, wspace, hspace 

605 

606 def autofmt_xdate(self, bottom=0.2, rotation=30, ha='right', which=None): 

607 """ 

608 Date ticklabels often overlap, so it is useful to rotate them 

609 and right align them. Also, a common use case is a number of 

610 subplots with shared xaxes where the x-axis is date data. The 

611 ticklabels are often long, and it helps to rotate them on the 

612 bottom subplot and turn them off on other subplots, as well as 

613 turn off xlabels. 

614 

615 Parameters 

616 ---------- 

617 bottom : scalar 

618 The bottom of the subplots for :meth:`subplots_adjust`. 

619 

620 rotation : angle in degrees 

621 The rotation of the xtick labels. 

622 

623 ha : str 

624 The horizontal alignment of the xticklabels. 

625 

626 which : {None, 'major', 'minor', 'both'} 

627 Selects which ticklabels to rotate. Default is None which works 

628 the same as major. 

629 """ 

630 allsubplots = all(hasattr(ax, 'is_last_row') for ax in self.axes) 

631 if len(self.axes) == 1: 

632 for label in self.axes[0].get_xticklabels(which=which): 

633 label.set_ha(ha) 

634 label.set_rotation(rotation) 

635 else: 

636 if allsubplots: 

637 for ax in self.get_axes(): 

638 if ax.is_last_row(): 

639 for label in ax.get_xticklabels(which=which): 

640 label.set_ha(ha) 

641 label.set_rotation(rotation) 

642 else: 

643 for label in ax.get_xticklabels(which=which): 

644 label.set_visible(False) 

645 ax.set_xlabel('') 

646 

647 if allsubplots: 

648 self.subplots_adjust(bottom=bottom) 

649 self.stale = True 

650 

651 def get_children(self): 

652 """Get a list of artists contained in the figure.""" 

653 return [self.patch, 

654 *self.artists, 

655 *self.axes, 

656 *self.lines, 

657 *self.patches, 

658 *self.texts, 

659 *self.images, 

660 *self.legends] 

661 

662 def contains(self, mouseevent): 

663 """ 

664 Test whether the mouse event occurred on the figure. 

665 

666 Returns 

667 ------- 

668 bool, {} 

669 """ 

670 inside, info = self._default_contains(mouseevent, figure=self) 

671 if inside is not None: 

672 return inside, info 

673 inside = self.bbox.contains(mouseevent.x, mouseevent.y) 

674 return inside, {} 

675 

676 def get_window_extent(self, *args, **kwargs): 

677 """ 

678 Return the figure bounding box in display space. Arguments are ignored. 

679 """ 

680 return self.bbox 

681 

682 def suptitle(self, t, **kwargs): 

683 """ 

684 Add a centered title to the figure. 

685 

686 Parameters 

687 ---------- 

688 t : str 

689 The title text. 

690 

691 x : float, default 0.5 

692 The x location of the text in figure coordinates. 

693 

694 y : float, default 0.98 

695 The y location of the text in figure coordinates. 

696 

697 horizontalalignment, ha : {'center', 'left', right'}, default: 'center' 

698 The horizontal alignment of the text relative to (*x*, *y*). 

699 

700 verticalalignment, va : {'top', 'center', 'bottom', 'baseline'}, \ 

701default: 'top' 

702 The vertical alignment of the text relative to (*x*, *y*). 

703 

704 fontsize, size : default: :rc:`figure.titlesize` 

705 The font size of the text. See `.Text.set_size` for possible 

706 values. 

707 

708 fontweight, weight : default: :rc:`figure.titleweight` 

709 The font weight of the text. See `.Text.set_weight` for possible 

710 values. 

711 

712 

713 Returns 

714 ------- 

715 text 

716 The `.Text` instance of the title. 

717 

718 

719 Other Parameters 

720 ---------------- 

721 fontproperties : None or dict, optional 

722 A dict of font properties. If *fontproperties* is given the 

723 default values for font size and weight are taken from the 

724 `FontProperties` defaults. :rc:`figure.titlesize` and 

725 :rc:`figure.titleweight` are ignored in this case. 

726 

727 **kwargs 

728 Additional kwargs are :class:`matplotlib.text.Text` properties. 

729 

730 

731 Examples 

732 -------- 

733 >>> fig.suptitle('This is the figure title', fontsize=12) 

734 """ 

735 manual_position = ('x' in kwargs or 'y' in kwargs) 

736 

737 x = kwargs.pop('x', 0.5) 

738 y = kwargs.pop('y', 0.98) 

739 

740 if 'horizontalalignment' not in kwargs and 'ha' not in kwargs: 

741 kwargs['horizontalalignment'] = 'center' 

742 if 'verticalalignment' not in kwargs and 'va' not in kwargs: 

743 kwargs['verticalalignment'] = 'top' 

744 

745 if 'fontproperties' not in kwargs: 

746 if 'fontsize' not in kwargs and 'size' not in kwargs: 

747 kwargs['size'] = rcParams['figure.titlesize'] 

748 if 'fontweight' not in kwargs and 'weight' not in kwargs: 

749 kwargs['weight'] = rcParams['figure.titleweight'] 

750 

751 sup = self.text(x, y, t, **kwargs) 

752 if self._suptitle is not None: 

753 self._suptitle.set_text(t) 

754 self._suptitle.set_position((x, y)) 

755 self._suptitle.update_from(sup) 

756 sup.remove() 

757 else: 

758 self._suptitle = sup 

759 self._suptitle._layoutbox = None 

760 if self._layoutbox is not None and not manual_position: 

761 w_pad, h_pad, wspace, hspace = \ 

762 self.get_constrained_layout_pads(relative=True) 

763 figlb = self._layoutbox 

764 self._suptitle._layoutbox = layoutbox.LayoutBox( 

765 parent=figlb, artist=self._suptitle, 

766 name=figlb.name+'.suptitle') 

767 # stack the suptitle on top of all the children. 

768 # Some day this should be on top of all the children in the 

769 # gridspec only. 

770 for child in figlb.children: 

771 if child is not self._suptitle._layoutbox: 

772 layoutbox.vstack([self._suptitle._layoutbox, 

773 child], 

774 padding=h_pad*2., strength='required') 

775 self.stale = True 

776 return self._suptitle 

777 

778 def set_canvas(self, canvas): 

779 """ 

780 Set the canvas that contains the figure 

781 

782 Parameters 

783 ---------- 

784 canvas : FigureCanvas 

785 """ 

786 self.canvas = canvas 

787 

788 def figimage(self, X, xo=0, yo=0, alpha=None, norm=None, cmap=None, 

789 vmin=None, vmax=None, origin=None, resize=False, **kwargs): 

790 """ 

791 Add a non-resampled image to the figure. 

792 

793 The image is attached to the lower or upper left corner depending on 

794 *origin*. 

795 

796 Parameters 

797 ---------- 

798 X 

799 The image data. This is an array of one of the following shapes: 

800 

801 - MxN: luminance (grayscale) values 

802 - MxNx3: RGB values 

803 - MxNx4: RGBA values 

804 

805 xo, yo : int 

806 The *x*/*y* image offset in pixels. 

807 

808 alpha : None or float 

809 The alpha blending value. 

810 

811 norm : :class:`matplotlib.colors.Normalize` 

812 A :class:`.Normalize` instance to map the luminance to the 

813 interval [0, 1]. 

814 

815 cmap : str or :class:`matplotlib.colors.Colormap` 

816 The colormap to use. Default: :rc:`image.cmap`. 

817 

818 vmin, vmax : scalar 

819 If *norm* is not given, these values set the data limits for the 

820 colormap. 

821 

822 origin : {'upper', 'lower'} 

823 Indicates where the [0, 0] index of the array is in the upper left 

824 or lower left corner of the axes. Defaults to :rc:`image.origin`. 

825 

826 resize : bool 

827 If *True*, resize the figure to match the given image size. 

828 

829 Returns 

830 ------- 

831 :class:`matplotlib.image.FigureImage` 

832 

833 Other Parameters 

834 ---------------- 

835 **kwargs 

836 Additional kwargs are `.Artist` kwargs passed on to `.FigureImage`. 

837 

838 Notes 

839 ----- 

840 figimage complements the axes image 

841 (:meth:`~matplotlib.axes.Axes.imshow`) which will be resampled 

842 to fit the current axes. If you want a resampled image to 

843 fill the entire figure, you can define an 

844 :class:`~matplotlib.axes.Axes` with extent [0, 0, 1, 1]. 

845 

846 

847 Examples:: 

848 

849 f = plt.figure() 

850 nx = int(f.get_figwidth() * f.dpi) 

851 ny = int(f.get_figheight() * f.dpi) 

852 data = np.random.random((ny, nx)) 

853 f.figimage(data) 

854 plt.show() 

855 

856 """ 

857 if resize: 

858 dpi = self.get_dpi() 

859 figsize = [x / dpi for x in (X.shape[1], X.shape[0])] 

860 self.set_size_inches(figsize, forward=True) 

861 

862 im = mimage.FigureImage(self, cmap, norm, xo, yo, origin, **kwargs) 

863 im.stale_callback = _stale_figure_callback 

864 

865 im.set_array(X) 

866 im.set_alpha(alpha) 

867 if norm is None: 

868 im.set_clim(vmin, vmax) 

869 self.images.append(im) 

870 im._remove_method = self.images.remove 

871 self.stale = True 

872 return im 

873 

874 def set_size_inches(self, w, h=None, forward=True): 

875 """ 

876 Set the figure size in inches. 

877 

878 Call signatures:: 

879 

880 fig.set_size_inches(w, h) # OR 

881 fig.set_size_inches((w, h)) 

882 

883 Parameters 

884 ---------- 

885 w : (float, float) or float 

886 Width and height in inches (if height not specified as a separate 

887 argument) or width. 

888 h : float 

889 Height in inches. 

890 forward : bool, default: True 

891 If ``True``, the canvas size is automatically updated, e.g., 

892 you can resize the figure window from the shell. 

893 

894 See Also 

895 -------- 

896 matplotlib.Figure.get_size_inches 

897 """ 

898 if h is None: # Got called with a single pair as argument. 

899 w, h = w 

900 size = np.array([w, h]) 

901 if not np.isfinite(size).all() or (size <= 0).any(): 

902 raise ValueError(f'figure size must be positive finite not {size}') 

903 self.bbox_inches.p1 = size 

904 if forward: 

905 canvas = getattr(self, 'canvas') 

906 if canvas is not None: 

907 dpi_ratio = getattr(canvas, '_dpi_ratio', 1) 

908 manager = getattr(canvas, 'manager', None) 

909 if manager is not None: 

910 manager.resize(*(size * self.dpi / dpi_ratio).astype(int)) 

911 self.stale = True 

912 

913 def get_size_inches(self): 

914 """ 

915 Returns the current size of the figure in inches. 

916 

917 Returns 

918 ------- 

919 size : ndarray 

920 The size (width, height) of the figure in inches. 

921 

922 See Also 

923 -------- 

924 matplotlib.Figure.set_size_inches 

925 """ 

926 return np.array(self.bbox_inches.p1) 

927 

928 def get_edgecolor(self): 

929 """Get the edge color of the Figure rectangle.""" 

930 return self.patch.get_edgecolor() 

931 

932 def get_facecolor(self): 

933 """Get the face color of the Figure rectangle.""" 

934 return self.patch.get_facecolor() 

935 

936 def get_figwidth(self): 

937 """Return the figure width as a float.""" 

938 return self.bbox_inches.width 

939 

940 def get_figheight(self): 

941 """Return the figure height as a float.""" 

942 return self.bbox_inches.height 

943 

944 def get_dpi(self): 

945 """Return the resolution in dots per inch as a float.""" 

946 return self.dpi 

947 

948 def get_frameon(self): 

949 """ 

950 Return the figure's background patch visibility, i.e. 

951 whether the figure background will be drawn. Equivalent to 

952 ``Figure.patch.get_visible()``. 

953 """ 

954 return self.patch.get_visible() 

955 

956 def set_edgecolor(self, color): 

957 """ 

958 Set the edge color of the Figure rectangle. 

959 

960 Parameters 

961 ---------- 

962 color : color 

963 """ 

964 self.patch.set_edgecolor(color) 

965 

966 def set_facecolor(self, color): 

967 """ 

968 Set the face color of the Figure rectangle. 

969 

970 Parameters 

971 ---------- 

972 color : color 

973 """ 

974 self.patch.set_facecolor(color) 

975 

976 def set_dpi(self, val): 

977 """ 

978 Set the resolution of the figure in dots-per-inch. 

979 

980 Parameters 

981 ---------- 

982 val : float 

983 """ 

984 self.dpi = val 

985 self.stale = True 

986 

987 def set_figwidth(self, val, forward=True): 

988 """ 

989 Set the width of the figure in inches. 

990 

991 Parameters 

992 ---------- 

993 val : float 

994 forward : bool 

995 """ 

996 self.set_size_inches(val, self.get_figheight(), forward=forward) 

997 

998 def set_figheight(self, val, forward=True): 

999 """ 

1000 Set the height of the figure in inches. 

1001 

1002 Parameters 

1003 ---------- 

1004 val : float 

1005 forward : bool 

1006 """ 

1007 self.set_size_inches(self.get_figwidth(), val, forward=forward) 

1008 

1009 def set_frameon(self, b): 

1010 """ 

1011 Set the figure's background patch visibility, i.e. 

1012 whether the figure background will be drawn. Equivalent to 

1013 ``Figure.patch.set_visible()``. 

1014 

1015 Parameters 

1016 ---------- 

1017 b : bool 

1018 """ 

1019 self.patch.set_visible(b) 

1020 self.stale = True 

1021 

1022 frameon = property(get_frameon, set_frameon) 

1023 

1024 def delaxes(self, ax): 

1025 """ 

1026 Remove the `~matplotlib.axes.Axes` *ax* from the figure and update the 

1027 current axes. 

1028 """ 

1029 self._axstack.remove(ax) 

1030 for func in self._axobservers: 

1031 func(self) 

1032 self.stale = True 

1033 

1034 def add_artist(self, artist, clip=False): 

1035 """ 

1036 Add any :class:`~matplotlib.artist.Artist` to the figure. 

1037 

1038 Usually artists are added to axes objects using 

1039 :meth:`matplotlib.axes.Axes.add_artist`, but use this method in the 

1040 rare cases that adding directly to the figure is necessary. 

1041 

1042 Parameters 

1043 ---------- 

1044 artist : `~matplotlib.artist.Artist` 

1045 The artist to add to the figure. If the added artist has no 

1046 transform previously set, its transform will be set to 

1047 ``figure.transFigure``. 

1048 clip : bool, optional, default ``False`` 

1049 An optional parameter ``clip`` determines whether the added artist 

1050 should be clipped by the figure patch. Default is *False*, 

1051 i.e. no clipping. 

1052 

1053 Returns 

1054 ------- 

1055 artist : The added `~matplotlib.artist.Artist` 

1056 """ 

1057 artist.set_figure(self) 

1058 self.artists.append(artist) 

1059 artist._remove_method = self.artists.remove 

1060 

1061 if not artist.is_transform_set(): 

1062 artist.set_transform(self.transFigure) 

1063 

1064 if clip: 

1065 artist.set_clip_path(self.patch) 

1066 

1067 self.stale = True 

1068 return artist 

1069 

1070 def _make_key(self, *args, **kwargs): 

1071 """Make a hashable key out of args and kwargs.""" 

1072 

1073 def fixitems(items): 

1074 # items may have arrays and lists in them, so convert them 

1075 # to tuples for the key 

1076 ret = [] 

1077 for k, v in items: 

1078 # some objects can define __getitem__ without being 

1079 # iterable and in those cases the conversion to tuples 

1080 # will fail. So instead of using the np.iterable(v) function 

1081 # we simply try and convert to a tuple, and proceed if not. 

1082 try: 

1083 v = tuple(v) 

1084 except Exception: 

1085 pass 

1086 ret.append((k, v)) 

1087 return tuple(ret) 

1088 

1089 def fixlist(args): 

1090 ret = [] 

1091 for a in args: 

1092 if np.iterable(a): 

1093 a = tuple(a) 

1094 ret.append(a) 

1095 return tuple(ret) 

1096 

1097 key = fixlist(args), fixitems(kwargs.items()) 

1098 return key 

1099 

1100 def _process_projection_requirements( 

1101 self, *args, polar=False, projection=None, **kwargs): 

1102 """ 

1103 Handle the args/kwargs to add_axes/add_subplot/gca, returning:: 

1104 

1105 (axes_proj_class, proj_class_kwargs, proj_stack_key) 

1106 

1107 which can be used for new axes initialization/identification. 

1108 """ 

1109 if polar: 

1110 if projection is not None and projection != 'polar': 

1111 raise ValueError( 

1112 "polar=True, yet projection=%r. " 

1113 "Only one of these arguments should be supplied." % 

1114 projection) 

1115 projection = 'polar' 

1116 

1117 if isinstance(projection, str) or projection is None: 

1118 projection_class = projections.get_projection_class(projection) 

1119 elif hasattr(projection, '_as_mpl_axes'): 

1120 projection_class, extra_kwargs = projection._as_mpl_axes() 

1121 kwargs.update(**extra_kwargs) 

1122 else: 

1123 raise TypeError('projection must be a string, None or implement a ' 

1124 '_as_mpl_axes method. Got %r' % projection) 

1125 

1126 # Make the key without projection kwargs, this is used as a unique 

1127 # lookup for axes instances 

1128 key = self._make_key(*args, **kwargs) 

1129 

1130 return projection_class, kwargs, key 

1131 

1132 @docstring.dedent_interpd 

1133 def add_axes(self, *args, **kwargs): 

1134 """ 

1135 Add an axes to the figure. 

1136 

1137 Call signatures:: 

1138 

1139 add_axes(rect, projection=None, polar=False, **kwargs) 

1140 add_axes(ax) 

1141 

1142 Parameters 

1143 ---------- 

1144 rect : sequence of float 

1145 The dimensions [left, bottom, width, height] of the new axes. All 

1146 quantities are in fractions of figure width and height. 

1147 

1148 projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', \ 

1149'polar', 'rectilinear', str}, optional 

1150 The projection type of the `~.axes.Axes`. *str* is the name of 

1151 a custom projection, see `~matplotlib.projections`. The default 

1152 None results in a 'rectilinear' projection. 

1153 

1154 polar : boolean, optional 

1155 If True, equivalent to projection='polar'. 

1156 

1157 sharex, sharey : `~.axes.Axes`, optional 

1158 Share the x or y `~matplotlib.axis` with sharex and/or sharey. 

1159 The axis will have the same limits, ticks, and scale as the axis 

1160 of the shared axes. 

1161 

1162 label : str 

1163 A label for the returned axes. 

1164 

1165 Other Parameters 

1166 ---------------- 

1167 **kwargs 

1168 This method also takes the keyword arguments for 

1169 the returned axes class. The keyword arguments for the 

1170 rectilinear axes class `~.axes.Axes` can be found in 

1171 the following table but there might also be other keyword 

1172 arguments if another projection is used, see the actual axes 

1173 class. 

1174 

1175 %(Axes)s 

1176 

1177 Returns 

1178 ------- 

1179 axes : `~.axes.Axes` (or a subclass of `~.axes.Axes`) 

1180 The returned axes class depends on the projection used. It is 

1181 `~.axes.Axes` if rectilinear projection are used and 

1182 `.projections.polar.PolarAxes` if polar projection 

1183 are used. 

1184 

1185 Notes 

1186 ----- 

1187 If the figure already has an axes with key (*args*, 

1188 *kwargs*) then it will simply make that axes current and 

1189 return it. This behavior is deprecated. Meanwhile, if you do 

1190 not want this behavior (i.e., you want to force the creation of a 

1191 new axes), you must use a unique set of args and kwargs. The axes 

1192 *label* attribute has been exposed for this purpose: if you want 

1193 two axes that are otherwise identical to be added to the figure, 

1194 make sure you give them unique labels. 

1195 

1196 In rare circumstances, `.add_axes` may be called with a single 

1197 argument, a axes instance already created in the present figure but 

1198 not in the figure's list of axes. 

1199 

1200 See Also 

1201 -------- 

1202 .Figure.add_subplot 

1203 .pyplot.subplot 

1204 .pyplot.axes 

1205 .Figure.subplots 

1206 .pyplot.subplots 

1207 

1208 Examples 

1209 -------- 

1210 Some simple examples:: 

1211 

1212 rect = l, b, w, h 

1213 fig = plt.figure() 

1214 fig.add_axes(rect, label=label1) 

1215 fig.add_axes(rect, label=label2) 

1216 fig.add_axes(rect, frameon=False, facecolor='g') 

1217 fig.add_axes(rect, polar=True) 

1218 ax = fig.add_axes(rect, projection='polar') 

1219 fig.delaxes(ax) 

1220 fig.add_axes(ax) 

1221 """ 

1222 

1223 if not len(args): 

1224 return 

1225 

1226 # shortcut the projection "key" modifications later on, if an axes 

1227 # with the exact args/kwargs exists, return it immediately. 

1228 key = self._make_key(*args, **kwargs) 

1229 ax = self._axstack.get(key) 

1230 if ax is not None: 

1231 self.sca(ax) 

1232 return ax 

1233 

1234 if isinstance(args[0], Axes): 

1235 a = args[0] 

1236 if a.get_figure() is not self: 

1237 raise ValueError( 

1238 "The Axes must have been created in the present figure") 

1239 else: 

1240 rect = args[0] 

1241 if not np.isfinite(rect).all(): 

1242 raise ValueError('all entries in rect must be finite ' 

1243 'not {}'.format(rect)) 

1244 projection_class, kwargs, key = \ 

1245 self._process_projection_requirements(*args, **kwargs) 

1246 

1247 # check that an axes of this type doesn't already exist, if it 

1248 # does, set it as active and return it 

1249 ax = self._axstack.get(key) 

1250 if isinstance(ax, projection_class): 

1251 self.sca(ax) 

1252 return ax 

1253 

1254 # create the new axes using the axes class given 

1255 a = projection_class(self, rect, **kwargs) 

1256 

1257 return self._add_axes_internal(key, a) 

1258 

1259 @docstring.dedent_interpd 

1260 def add_subplot(self, *args, **kwargs): 

1261 """ 

1262 Add an `~.axes.Axes` to the figure as part of a subplot arrangement. 

1263 

1264 Call signatures:: 

1265 

1266 add_subplot(nrows, ncols, index, **kwargs) 

1267 add_subplot(pos, **kwargs) 

1268 add_subplot(ax) 

1269 add_subplot() 

1270 

1271 Parameters 

1272 ---------- 

1273 *args 

1274 Either a 3-digit integer or three separate integers 

1275 describing the position of the subplot. If the three 

1276 integers are *nrows*, *ncols*, and *index* in order, the 

1277 subplot will take the *index* position on a grid with *nrows* 

1278 rows and *ncols* columns. *index* starts at 1 in the upper left 

1279 corner and increases to the right. 

1280 

1281 *pos* is a three digit integer, where the first digit is the 

1282 number of rows, the second the number of columns, and the third 

1283 the index of the subplot. i.e. fig.add_subplot(235) is the same as 

1284 fig.add_subplot(2, 3, 5). Note that all integers must be less than 

1285 10 for this form to work. 

1286 

1287 If no positional arguments are passed, defaults to (1, 1, 1). 

1288 

1289 In rare circumstances, `.add_subplot` may be called with a single 

1290 argument, a subplot axes instance already created in the 

1291 present figure but not in the figure's list of axes. 

1292 

1293 projection : {None, 'aitoff', 'hammer', 'lambert', 'mollweide', \ 

1294'polar', 'rectilinear', str}, optional 

1295 The projection type of the subplot (`~.axes.Axes`). *str* is the 

1296 name of a custom projection, see `~matplotlib.projections`. The 

1297 default None results in a 'rectilinear' projection. 

1298 

1299 polar : boolean, optional 

1300 If True, equivalent to projection='polar'. 

1301 

1302 sharex, sharey : `~.axes.Axes`, optional 

1303 Share the x or y `~matplotlib.axis` with sharex and/or sharey. 

1304 The axis will have the same limits, ticks, and scale as the axis 

1305 of the shared axes. 

1306 

1307 label : str 

1308 A label for the returned axes. 

1309 

1310 Other Parameters 

1311 ---------------- 

1312 **kwargs 

1313 This method also takes the keyword arguments for the returned axes 

1314 base class; except for the *figure* argument. The keyword arguments 

1315 for the rectilinear base class `~.axes.Axes` can be found in 

1316 the following table but there might also be other keyword 

1317 arguments if another projection is used. 

1318 

1319 %(Axes)s 

1320 

1321 Returns 

1322 ------- 

1323 axes : `.axes.SubplotBase`, or another subclass of `~.axes.Axes` 

1324 

1325 The axes of the subplot. The returned axes base class depends on 

1326 the projection used. It is `~.axes.Axes` if rectilinear projection 

1327 are used and `.projections.polar.PolarAxes` if polar projection 

1328 are used. The returned axes is then a subplot subclass of the 

1329 base class. 

1330 

1331 Notes 

1332 ----- 

1333 If the figure already has a subplot with key (*args*, 

1334 *kwargs*) then it will simply make that subplot current and 

1335 return it. This behavior is deprecated. Meanwhile, if you do 

1336 not want this behavior (i.e., you want to force the creation of a 

1337 new subplot), you must use a unique set of args and kwargs. The axes 

1338 *label* attribute has been exposed for this purpose: if you want 

1339 two subplots that are otherwise identical to be added to the figure, 

1340 make sure you give them unique labels. 

1341 

1342 See Also 

1343 -------- 

1344 .Figure.add_axes 

1345 .pyplot.subplot 

1346 .pyplot.axes 

1347 .Figure.subplots 

1348 .pyplot.subplots 

1349 

1350 Examples 

1351 -------- 

1352 :: 

1353 

1354 fig = plt.figure() 

1355 fig.add_subplot(221) 

1356 

1357 # equivalent but more general 

1358 ax1 = fig.add_subplot(2, 2, 1) 

1359 

1360 # add a subplot with no frame 

1361 ax2 = fig.add_subplot(222, frameon=False) 

1362 

1363 # add a polar subplot 

1364 fig.add_subplot(223, projection='polar') 

1365 

1366 # add a red subplot that share the x-axis with ax1 

1367 fig.add_subplot(224, sharex=ax1, facecolor='red') 

1368 

1369 #delete x2 from the figure 

1370 fig.delaxes(ax2) 

1371 

1372 #add x2 to the figure again 

1373 fig.add_subplot(ax2) 

1374 """ 

1375 if not len(args): 

1376 args = (1, 1, 1) 

1377 

1378 if len(args) == 1 and isinstance(args[0], Integral): 

1379 if not 100 <= args[0] <= 999: 

1380 raise ValueError("Integer subplot specification must be a " 

1381 "three-digit number, not {}".format(args[0])) 

1382 args = tuple(map(int, str(args[0]))) 

1383 

1384 if 'figure' in kwargs: 

1385 # Axes itself allows for a 'figure' kwarg, but since we want to 

1386 # bind the created Axes to self, it is not allowed here. 

1387 raise TypeError( 

1388 "add_subplot() got an unexpected keyword argument 'figure'") 

1389 

1390 if isinstance(args[0], SubplotBase): 

1391 

1392 a = args[0] 

1393 if a.get_figure() is not self: 

1394 raise ValueError( 

1395 "The Subplot must have been created in the present figure") 

1396 # make a key for the subplot (which includes the axes object id 

1397 # in the hash) 

1398 key = self._make_key(*args, **kwargs) 

1399 else: 

1400 projection_class, kwargs, key = \ 

1401 self._process_projection_requirements(*args, **kwargs) 

1402 

1403 # try to find the axes with this key in the stack 

1404 ax = self._axstack.get(key) 

1405 

1406 if ax is not None: 

1407 if isinstance(ax, projection_class): 

1408 # the axes already existed, so set it as active & return 

1409 self.sca(ax) 

1410 return ax 

1411 else: 

1412 # Undocumented convenience behavior: 

1413 # subplot(111); subplot(111, projection='polar') 

1414 # will replace the first with the second. 

1415 # Without this, add_subplot would be simpler and 

1416 # more similar to add_axes. 

1417 self._axstack.remove(ax) 

1418 

1419 a = subplot_class_factory(projection_class)(self, *args, **kwargs) 

1420 

1421 return self._add_axes_internal(key, a) 

1422 

1423 def _add_axes_internal(self, key, ax): 

1424 """Private helper for `add_axes` and `add_subplot`.""" 

1425 self._axstack.add(key, ax) 

1426 self.sca(ax) 

1427 ax._remove_method = self._remove_ax 

1428 self.stale = True 

1429 ax.stale_callback = _stale_figure_callback 

1430 return ax 

1431 

1432 def subplots(self, nrows=1, ncols=1, sharex=False, sharey=False, 

1433 squeeze=True, subplot_kw=None, gridspec_kw=None): 

1434 """ 

1435 Add a set of subplots to this figure. 

1436 

1437 This utility wrapper makes it convenient to create common layouts of 

1438 subplots in a single call. 

1439 

1440 Parameters 

1441 ---------- 

1442 nrows, ncols : int, optional, default: 1 

1443 Number of rows/columns of the subplot grid. 

1444 

1445 sharex, sharey : bool or {'none', 'all', 'row', 'col'}, default: False 

1446 Controls sharing of properties among x (`sharex`) or y (`sharey`) 

1447 axes: 

1448 

1449 - True or 'all': x- or y-axis will be shared among all subplots. 

1450 - False or 'none': each subplot x- or y-axis will be independent. 

1451 - 'row': each subplot row will share an x- or y-axis. 

1452 - 'col': each subplot column will share an x- or y-axis. 

1453 

1454 When subplots have a shared x-axis along a column, only the x tick 

1455 labels of the bottom subplot are created. Similarly, when subplots 

1456 have a shared y-axis along a row, only the y tick labels of the 

1457 first column subplot are created. To later turn other subplots' 

1458 ticklabels on, use `~matplotlib.axes.Axes.tick_params`. 

1459 

1460 squeeze : bool, optional, default: True 

1461 - If True, extra dimensions are squeezed out from the returned 

1462 array of Axes: 

1463 

1464 - if only one subplot is constructed (nrows=ncols=1), the 

1465 resulting single Axes object is returned as a scalar. 

1466 - for Nx1 or 1xM subplots, the returned object is a 1D numpy 

1467 object array of Axes objects. 

1468 - for NxM, subplots with N>1 and M>1 are returned as a 2D array. 

1469 

1470 - If False, no squeezing at all is done: the returned Axes object 

1471 is always a 2D array containing Axes instances, even if it ends 

1472 up being 1x1. 

1473 

1474 subplot_kw : dict, optional 

1475 Dict with keywords passed to the 

1476 :meth:`~matplotlib.figure.Figure.add_subplot` call used to create 

1477 each subplot. 

1478 

1479 gridspec_kw : dict, optional 

1480 Dict with keywords passed to the 

1481 `~matplotlib.gridspec.GridSpec` constructor used to create 

1482 the grid the subplots are placed on. 

1483 

1484 Returns 

1485 ------- 

1486 ax : `~.axes.Axes` object or array of Axes objects. 

1487 *ax* can be either a single `~matplotlib.axes.Axes` object or 

1488 an array of Axes objects if more than one subplot was created. The 

1489 dimensions of the resulting array can be controlled with the 

1490 squeeze keyword, see above. 

1491 

1492 Examples 

1493 -------- 

1494 :: 

1495 

1496 # First create some toy data: 

1497 x = np.linspace(0, 2*np.pi, 400) 

1498 y = np.sin(x**2) 

1499 

1500 # Create a figure 

1501 plt.figure() 

1502 

1503 # Create a subplot 

1504 ax = fig.subplots() 

1505 ax.plot(x, y) 

1506 ax.set_title('Simple plot') 

1507 

1508 # Create two subplots and unpack the output array immediately 

1509 ax1, ax2 = fig.subplots(1, 2, sharey=True) 

1510 ax1.plot(x, y) 

1511 ax1.set_title('Sharing Y axis') 

1512 ax2.scatter(x, y) 

1513 

1514 # Create four polar axes and access them through the returned array 

1515 axes = fig.subplots(2, 2, subplot_kw=dict(polar=True)) 

1516 axes[0, 0].plot(x, y) 

1517 axes[1, 1].scatter(x, y) 

1518 

1519 # Share a X axis with each column of subplots 

1520 fig.subplots(2, 2, sharex='col') 

1521 

1522 # Share a Y axis with each row of subplots 

1523 fig.subplots(2, 2, sharey='row') 

1524 

1525 # Share both X and Y axes with all subplots 

1526 fig.subplots(2, 2, sharex='all', sharey='all') 

1527 

1528 # Note that this is the same as 

1529 fig.subplots(2, 2, sharex=True, sharey=True) 

1530 

1531 See Also 

1532 -------- 

1533 .pyplot.subplots 

1534 .Figure.add_subplot 

1535 .pyplot.subplot 

1536 """ 

1537 

1538 if isinstance(sharex, bool): 

1539 sharex = "all" if sharex else "none" 

1540 if isinstance(sharey, bool): 

1541 sharey = "all" if sharey else "none" 

1542 # This check was added because it is very easy to type 

1543 # `subplots(1, 2, 1)` when `subplot(1, 2, 1)` was intended. 

1544 # In most cases, no error will ever occur, but mysterious behavior 

1545 # will result because what was intended to be the subplot index is 

1546 # instead treated as a bool for sharex. 

1547 if isinstance(sharex, Integral): 

1548 cbook._warn_external( 

1549 "sharex argument to subplots() was an integer. Did you " 

1550 "intend to use subplot() (without 's')?") 

1551 cbook._check_in_list(["all", "row", "col", "none"], 

1552 sharex=sharex, sharey=sharey) 

1553 if subplot_kw is None: 

1554 subplot_kw = {} 

1555 if gridspec_kw is None: 

1556 gridspec_kw = {} 

1557 # don't mutate kwargs passed by user... 

1558 subplot_kw = subplot_kw.copy() 

1559 gridspec_kw = gridspec_kw.copy() 

1560 

1561 if self.get_constrained_layout(): 

1562 gs = GridSpec(nrows, ncols, figure=self, **gridspec_kw) 

1563 else: 

1564 # this should turn constrained_layout off if we don't want it 

1565 gs = GridSpec(nrows, ncols, figure=None, **gridspec_kw) 

1566 self._gridspecs.append(gs) 

1567 

1568 # Create array to hold all axes. 

1569 axarr = np.empty((nrows, ncols), dtype=object) 

1570 for row in range(nrows): 

1571 for col in range(ncols): 

1572 shared_with = {"none": None, "all": axarr[0, 0], 

1573 "row": axarr[row, 0], "col": axarr[0, col]} 

1574 subplot_kw["sharex"] = shared_with[sharex] 

1575 subplot_kw["sharey"] = shared_with[sharey] 

1576 axarr[row, col] = self.add_subplot(gs[row, col], **subplot_kw) 

1577 

1578 # turn off redundant tick labeling 

1579 if sharex in ["col", "all"]: 

1580 # turn off all but the bottom row 

1581 for ax in axarr[:-1, :].flat: 

1582 ax.xaxis.set_tick_params(which='both', 

1583 labelbottom=False, labeltop=False) 

1584 ax.xaxis.offsetText.set_visible(False) 

1585 if sharey in ["row", "all"]: 

1586 # turn off all but the first column 

1587 for ax in axarr[:, 1:].flat: 

1588 ax.yaxis.set_tick_params(which='both', 

1589 labelleft=False, labelright=False) 

1590 ax.yaxis.offsetText.set_visible(False) 

1591 

1592 if squeeze: 

1593 # Discarding unneeded dimensions that equal 1. If we only have one 

1594 # subplot, just return it instead of a 1-element array. 

1595 return axarr.item() if axarr.size == 1 else axarr.squeeze() 

1596 else: 

1597 # Returned axis array will be always 2-d, even if nrows=ncols=1. 

1598 return axarr 

1599 

1600 def _remove_ax(self, ax): 

1601 def _reset_locators_and_formatters(axis): 

1602 # Set the formatters and locators to be associated with axis 

1603 # (where previously they may have been associated with another 

1604 # Axis isntance) 

1605 # 

1606 # Because set_major_formatter() etc. force isDefault_* to be False, 

1607 # we have to manually check if the original formatter was a 

1608 # default and manually set isDefault_* if that was the case. 

1609 majfmt = axis.get_major_formatter() 

1610 isDefault = majfmt.axis.isDefault_majfmt 

1611 axis.set_major_formatter(majfmt) 

1612 if isDefault: 

1613 majfmt.axis.isDefault_majfmt = True 

1614 

1615 majloc = axis.get_major_locator() 

1616 isDefault = majloc.axis.isDefault_majloc 

1617 axis.set_major_locator(majloc) 

1618 if isDefault: 

1619 majloc.axis.isDefault_majloc = True 

1620 

1621 minfmt = axis.get_minor_formatter() 

1622 isDefault = majloc.axis.isDefault_minfmt 

1623 axis.set_minor_formatter(minfmt) 

1624 if isDefault: 

1625 minfmt.axis.isDefault_minfmt = True 

1626 

1627 minloc = axis.get_minor_locator() 

1628 isDefault = majloc.axis.isDefault_minloc 

1629 axis.set_minor_locator(minloc) 

1630 if isDefault: 

1631 minloc.axis.isDefault_minloc = True 

1632 

1633 def _break_share_link(ax, grouper): 

1634 siblings = grouper.get_siblings(ax) 

1635 if len(siblings) > 1: 

1636 grouper.remove(ax) 

1637 for last_ax in siblings: 

1638 if ax is not last_ax: 

1639 return last_ax 

1640 return None 

1641 

1642 self.delaxes(ax) 

1643 last_ax = _break_share_link(ax, ax._shared_y_axes) 

1644 if last_ax is not None: 

1645 _reset_locators_and_formatters(last_ax.yaxis) 

1646 

1647 last_ax = _break_share_link(ax, ax._shared_x_axes) 

1648 if last_ax is not None: 

1649 _reset_locators_and_formatters(last_ax.xaxis) 

1650 

1651 def clf(self, keep_observers=False): 

1652 """ 

1653 Clear the figure. 

1654 

1655 Set *keep_observers* to True if, for example, 

1656 a gui widget is tracking the axes in the figure. 

1657 """ 

1658 self.suppressComposite = None 

1659 self.callbacks = cbook.CallbackRegistry() 

1660 

1661 for ax in tuple(self.axes): # Iterate over the copy. 

1662 ax.cla() 

1663 self.delaxes(ax) # removes ax from self._axstack 

1664 

1665 toolbar = getattr(self.canvas, 'toolbar', None) 

1666 if toolbar is not None: 

1667 toolbar.update() 

1668 self._axstack.clear() 

1669 self.artists = [] 

1670 self.lines = [] 

1671 self.patches = [] 

1672 self.texts = [] 

1673 self.images = [] 

1674 self.legends = [] 

1675 if not keep_observers: 

1676 self._axobservers = [] 

1677 self._suptitle = None 

1678 if self.get_constrained_layout(): 

1679 layoutbox.nonetree(self._layoutbox) 

1680 self.stale = True 

1681 

1682 def clear(self, keep_observers=False): 

1683 """ 

1684 Clear the figure -- synonym for :meth:`clf`. 

1685 """ 

1686 self.clf(keep_observers=keep_observers) 

1687 

1688 @allow_rasterization 

1689 def draw(self, renderer): 

1690 """ 

1691 Render the figure using :class:`matplotlib.backend_bases.RendererBase` 

1692 instance *renderer*. 

1693 """ 

1694 self._cachedRenderer = renderer 

1695 

1696 # draw the figure bounding box, perhaps none for white figure 

1697 if not self.get_visible(): 

1698 return 

1699 

1700 artists = self.get_children() 

1701 artists.remove(self.patch) 

1702 artists = sorted( 

1703 (artist for artist in artists if not artist.get_animated()), 

1704 key=lambda artist: artist.get_zorder()) 

1705 

1706 for ax in self.axes: 

1707 locator = ax.get_axes_locator() 

1708 if locator: 

1709 pos = locator(ax, renderer) 

1710 ax.apply_aspect(pos) 

1711 else: 

1712 ax.apply_aspect() 

1713 

1714 for child in ax.get_children(): 

1715 if hasattr(child, 'apply_aspect'): 

1716 locator = child.get_axes_locator() 

1717 if locator: 

1718 pos = locator(child, renderer) 

1719 child.apply_aspect(pos) 

1720 else: 

1721 child.apply_aspect() 

1722 

1723 try: 

1724 renderer.open_group('figure', gid=self.get_gid()) 

1725 if self.get_constrained_layout() and self.axes: 

1726 self.execute_constrained_layout(renderer) 

1727 if self.get_tight_layout() and self.axes: 

1728 try: 

1729 self.tight_layout(**self._tight_parameters) 

1730 except ValueError: 

1731 pass 

1732 # ValueError can occur when resizing a window. 

1733 

1734 self.patch.draw(renderer) 

1735 mimage._draw_list_compositing_images( 

1736 renderer, self, artists, self.suppressComposite) 

1737 

1738 renderer.close_group('figure') 

1739 finally: 

1740 self.stale = False 

1741 

1742 self.canvas.draw_event(renderer) 

1743 

1744 def draw_artist(self, a): 

1745 """ 

1746 Draw :class:`matplotlib.artist.Artist` instance *a* only. 

1747 This is available only after the figure is drawn. 

1748 """ 

1749 if self._cachedRenderer is None: 

1750 raise AttributeError("draw_artist can only be used after an " 

1751 "initial draw which caches the renderer") 

1752 a.draw(self._cachedRenderer) 

1753 

1754 def get_axes(self): 

1755 """ 

1756 Return a list of axes in the Figure. You can access and modify the 

1757 axes in the Figure through this list. 

1758 

1759 Do not modify the list itself. Instead, use `~Figure.add_axes`, 

1760 `~.Figure.subplot` or `~.Figure.delaxes` to add or remove an axes. 

1761 

1762 Note: This is equivalent to the property `~.Figure.axes`. 

1763 """ 

1764 return self.axes 

1765 

1766 # Note: in the docstring below, the newlines in the examples after the 

1767 # calls to legend() allow replacing it with figlegend() to generate the 

1768 # docstring of pyplot.figlegend. 

1769 

1770 @docstring.dedent_interpd 

1771 def legend(self, *args, **kwargs): 

1772 """ 

1773 Place a legend on the figure. 

1774 

1775 To make a legend from existing artists on every axes:: 

1776 

1777 legend() 

1778 

1779 To make a legend for a list of lines and labels:: 

1780 

1781 legend( 

1782 (line1, line2, line3), 

1783 ('label1', 'label2', 'label3'), 

1784 loc='upper right') 

1785 

1786 These can also be specified by keyword:: 

1787 

1788 legend( 

1789 handles=(line1, line2, line3), 

1790 labels=('label1', 'label2', 'label3'), 

1791 loc='upper right') 

1792 

1793 Parameters 

1794 ---------- 

1795 handles : list of `.Artist`, optional 

1796 A list of Artists (lines, patches) to be added to the legend. 

1797 Use this together with *labels*, if you need full control on what 

1798 is shown in the legend and the automatic mechanism described above 

1799 is not sufficient. 

1800 

1801 The length of handles and labels should be the same in this 

1802 case. If they are not, they are truncated to the smaller length. 

1803 

1804 labels : list of str, optional 

1805 A list of labels to show next to the artists. 

1806 Use this together with *handles*, if you need full control on what 

1807 is shown in the legend and the automatic mechanism described above 

1808 is not sufficient. 

1809 

1810 Other Parameters 

1811 ---------------- 

1812 %(_legend_kw_doc)s 

1813 

1814 Returns 

1815 ------- 

1816 :class:`matplotlib.legend.Legend` instance 

1817 

1818 Notes 

1819 ----- 

1820 Not all kinds of artist are supported by the legend command. See 

1821 :doc:`/tutorials/intermediate/legend_guide` for details. 

1822 """ 

1823 

1824 handles, labels, extra_args, kwargs = mlegend._parse_legend_args( 

1825 self.axes, 

1826 *args, 

1827 **kwargs) 

1828 # check for third arg 

1829 if len(extra_args): 

1830 # cbook.warn_deprecated( 

1831 # "2.1", 

1832 # message="Figure.legend will accept no more than two " 

1833 # "positional arguments in the future. Use " 

1834 # "'fig.legend(handles, labels, loc=location)' " 

1835 # "instead.") 

1836 # kwargs['loc'] = extra_args[0] 

1837 # extra_args = extra_args[1:] 

1838 pass 

1839 l = mlegend.Legend(self, handles, labels, *extra_args, **kwargs) 

1840 self.legends.append(l) 

1841 l._remove_method = self.legends.remove 

1842 self.stale = True 

1843 return l 

1844 

1845 @cbook._delete_parameter("3.1", "withdash") 

1846 @docstring.dedent_interpd 

1847 def text(self, x, y, s, fontdict=None, withdash=False, **kwargs): 

1848 """ 

1849 Add text to figure. 

1850 

1851 Parameters 

1852 ---------- 

1853 x, y : float 

1854 The position to place the text. By default, this is in figure 

1855 coordinates, floats in [0, 1]. The coordinate system can be changed 

1856 using the *transform* keyword. 

1857 

1858 s : str 

1859 The text string. 

1860 

1861 fontdict : dictionary, optional, default: None 

1862 A dictionary to override the default text properties. If fontdict 

1863 is None, the defaults are determined by your rc parameters. A 

1864 property in *kwargs* override the same property in fontdict. 

1865 

1866 withdash : boolean, optional, default: False 

1867 Creates a `~matplotlib.text.TextWithDash` instance instead of a 

1868 `~matplotlib.text.Text` instance. 

1869 

1870 Other Parameters 

1871 ---------------- 

1872 **kwargs : `~matplotlib.text.Text` properties 

1873 Other miscellaneous text parameters. 

1874 

1875 %(Text)s 

1876 

1877 Returns 

1878 ------- 

1879 text : `~.text.Text` 

1880 

1881 See Also 

1882 -------- 

1883 .Axes.text 

1884 .pyplot.text 

1885 """ 

1886 default = dict(transform=self.transFigure) 

1887 

1888 if (withdash 

1889 and withdash is not cbook.deprecation._deprecated_parameter): 

1890 text = TextWithDash(x=x, y=y, text=s) 

1891 else: 

1892 text = Text(x=x, y=y, text=s) 

1893 

1894 text.update(default) 

1895 if fontdict is not None: 

1896 text.update(fontdict) 

1897 text.update(kwargs) 

1898 

1899 text.set_figure(self) 

1900 text.stale_callback = _stale_figure_callback 

1901 

1902 self.texts.append(text) 

1903 text._remove_method = self.texts.remove 

1904 self.stale = True 

1905 return text 

1906 

1907 def _set_artist_props(self, a): 

1908 if a != self: 

1909 a.set_figure(self) 

1910 a.stale_callback = _stale_figure_callback 

1911 a.set_transform(self.transFigure) 

1912 

1913 @docstring.dedent_interpd 

1914 def gca(self, **kwargs): 

1915 """ 

1916 Get the current axes, creating one if necessary. 

1917 

1918 The following kwargs are supported for ensuring the returned axes 

1919 adheres to the given projection etc., and for axes creation if 

1920 the active axes does not exist: 

1921 

1922 %(Axes)s 

1923 

1924 """ 

1925 ckey, cax = self._axstack.current_key_axes() 

1926 # if there exists an axes on the stack see if it matches 

1927 # the desired axes configuration 

1928 if cax is not None: 

1929 

1930 # if no kwargs are given just return the current axes 

1931 # this is a convenience for gca() on axes such as polar etc. 

1932 if not kwargs: 

1933 return cax 

1934 

1935 # if the user has specified particular projection detail 

1936 # then build up a key which can represent this 

1937 else: 

1938 projection_class, _, key = \ 

1939 self._process_projection_requirements(**kwargs) 

1940 

1941 # let the returned axes have any gridspec by removing it from 

1942 # the key 

1943 ckey = ckey[1:] 

1944 key = key[1:] 

1945 

1946 # if the cax matches this key then return the axes, otherwise 

1947 # continue and a new axes will be created 

1948 if key == ckey and isinstance(cax, projection_class): 

1949 return cax 

1950 else: 

1951 cbook._warn_external('Requested projection is different ' 

1952 'from current axis projection, ' 

1953 'creating new axis with requested ' 

1954 'projection.') 

1955 

1956 # no axes found, so create one which spans the figure 

1957 return self.add_subplot(1, 1, 1, **kwargs) 

1958 

1959 def sca(self, a): 

1960 """Set the current axes to be a and return a.""" 

1961 self._axstack.bubble(a) 

1962 for func in self._axobservers: 

1963 func(self) 

1964 return a 

1965 

1966 def _gci(self): 

1967 """ 

1968 Helper for :func:`~matplotlib.pyplot.gci`. Do not use elsewhere. 

1969 """ 

1970 # Look first for an image in the current Axes: 

1971 cax = self._axstack.current_key_axes()[1] 

1972 if cax is None: 

1973 return None 

1974 im = cax._gci() 

1975 if im is not None: 

1976 return im 

1977 

1978 # If there is no image in the current Axes, search for 

1979 # one in a previously created Axes. Whether this makes 

1980 # sense is debatable, but it is the documented behavior. 

1981 for ax in reversed(self.axes): 

1982 im = ax._gci() 

1983 if im is not None: 

1984 return im 

1985 return None 

1986 

1987 def __getstate__(self): 

1988 state = super().__getstate__() 

1989 

1990 # the axobservers cannot currently be pickled. 

1991 # Additionally, the canvas cannot currently be pickled, but this has 

1992 # the benefit of meaning that a figure can be detached from one canvas, 

1993 # and re-attached to another. 

1994 for attr_to_pop in ('_axobservers', 'show', 

1995 'canvas', '_cachedRenderer'): 

1996 state.pop(attr_to_pop, None) 

1997 

1998 # add version information to the state 

1999 state['__mpl_version__'] = _mpl_version 

2000 

2001 # check whether the figure manager (if any) is registered with pyplot 

2002 from matplotlib import _pylab_helpers 

2003 if getattr(self.canvas, 'manager', None) \ 

2004 in _pylab_helpers.Gcf.figs.values(): 

2005 state['_restore_to_pylab'] = True 

2006 

2007 # set all the layoutbox information to None. kiwisolver objects can't 

2008 # be pickled, so we lose the layout options at this point. 

2009 state.pop('_layoutbox', None) 

2010 # suptitle: 

2011 if self._suptitle is not None: 

2012 self._suptitle._layoutbox = None 

2013 

2014 return state 

2015 

2016 def __setstate__(self, state): 

2017 version = state.pop('__mpl_version__') 

2018 restore_to_pylab = state.pop('_restore_to_pylab', False) 

2019 

2020 if version != _mpl_version: 

2021 cbook._warn_external( 

2022 f"This figure was saved with matplotlib version {version} and " 

2023 f"is unlikely to function correctly.") 

2024 

2025 self.__dict__ = state 

2026 

2027 # re-initialise some of the unstored state information 

2028 self._axobservers = [] 

2029 FigureCanvasBase(self) # Set self.canvas. 

2030 self._layoutbox = None 

2031 

2032 if restore_to_pylab: 

2033 # lazy import to avoid circularity 

2034 import matplotlib.pyplot as plt 

2035 import matplotlib._pylab_helpers as pylab_helpers 

2036 allnums = plt.get_fignums() 

2037 num = max(allnums) + 1 if allnums else 1 

2038 mgr = plt._backend_mod.new_figure_manager_given_figure(num, self) 

2039 

2040 # XXX The following is a copy and paste from pyplot. Consider 

2041 # factoring to pylab_helpers 

2042 

2043 if self.get_label(): 

2044 mgr.set_window_title(self.get_label()) 

2045 

2046 # make this figure current on button press event 

2047 def make_active(event): 

2048 pylab_helpers.Gcf.set_active(mgr) 

2049 

2050 mgr._cidgcf = mgr.canvas.mpl_connect('button_press_event', 

2051 make_active) 

2052 

2053 pylab_helpers.Gcf.set_active(mgr) 

2054 self.number = num 

2055 

2056 plt.draw_if_interactive() 

2057 self.stale = True 

2058 

2059 def add_axobserver(self, func): 

2060 """Whenever the axes state change, ``func(self)`` will be called.""" 

2061 self._axobservers.append(func) 

2062 

2063 def savefig(self, fname, *, transparent=None, **kwargs): 

2064 """ 

2065 Save the current figure. 

2066 

2067 Call signature:: 

2068 

2069 savefig(fname, dpi=None, facecolor='w', edgecolor='w', 

2070 orientation='portrait', papertype=None, format=None, 

2071 transparent=False, bbox_inches=None, pad_inches=0.1, 

2072 frameon=None, metadata=None) 

2073 

2074 The output formats available depend on the backend being used. 

2075 

2076 Parameters 

2077 ---------- 

2078 fname : str or PathLike or file-like object 

2079 A path, or a Python file-like object, or 

2080 possibly some backend-dependent object such as 

2081 `matplotlib.backends.backend_pdf.PdfPages`. 

2082 

2083 If *format* is not set, then the output format is inferred from 

2084 the extension of *fname*, if any, and from :rc:`savefig.format` 

2085 otherwise. If *format* is set, it determines the output format. 

2086 

2087 Hence, if *fname* is not a path or has no extension, remember to 

2088 specify *format* to ensure that the correct backend is used. 

2089 

2090 Other Parameters 

2091 ---------------- 

2092 dpi : [ *None* | scalar > 0 | 'figure' ] 

2093 The resolution in dots per inch. If *None*, defaults to 

2094 :rc:`savefig.dpi`. If 'figure', uses the figure's dpi value. 

2095 

2096 quality : [ *None* | 1 <= scalar <= 100 ] 

2097 The image quality, on a scale from 1 (worst) to 95 (best). 

2098 Applicable only if *format* is jpg or jpeg, ignored otherwise. 

2099 If *None*, defaults to :rc:`savefig.jpeg_quality`. 

2100 Values above 95 should be avoided; 100 completely disables the 

2101 JPEG quantization stage. 

2102 

2103 optimize : bool 

2104 If *True*, indicates that the JPEG encoder should make an extra 

2105 pass over the image in order to select optimal encoder settings. 

2106 Applicable only if *format* is jpg or jpeg, ignored otherwise. 

2107 Is *False* by default. 

2108 

2109 progressive : bool 

2110 If *True*, indicates that this image should be stored as a 

2111 progressive JPEG file. Applicable only if *format* is jpg or 

2112 jpeg, ignored otherwise. Is *False* by default. 

2113 

2114 facecolor : color or None, optional 

2115 The facecolor of the figure; if *None*, defaults to 

2116 :rc:`savefig.facecolor`. 

2117 

2118 edgecolor : color or None, optional 

2119 The edgecolor of the figure; if *None*, defaults to 

2120 :rc:`savefig.edgecolor` 

2121 

2122 orientation : {'landscape', 'portrait'} 

2123 Currently only supported by the postscript backend. 

2124 

2125 papertype : str 

2126 One of 'letter', 'legal', 'executive', 'ledger', 'a0' through 

2127 'a10', 'b0' through 'b10'. Only supported for postscript 

2128 output. 

2129 

2130 format : str 

2131 The file format, e.g. 'png', 'pdf', 'svg', ... The behavior when 

2132 this is unset is documented under *fname*. 

2133 

2134 transparent : bool 

2135 If *True*, the axes patches will all be transparent; the 

2136 figure patch will also be transparent unless facecolor 

2137 and/or edgecolor are specified via kwargs. 

2138 This is useful, for example, for displaying 

2139 a plot on top of a colored background on a web page. The 

2140 transparency of these patches will be restored to their 

2141 original values upon exit of this function. 

2142 

2143 bbox_inches : str or `~matplotlib.transforms.Bbox`, optional 

2144 Bbox in inches. Only the given portion of the figure is 

2145 saved. If 'tight', try to figure out the tight bbox of 

2146 the figure. If None, use savefig.bbox 

2147 

2148 pad_inches : scalar, optional 

2149 Amount of padding around the figure when bbox_inches is 

2150 'tight'. If None, use savefig.pad_inches 

2151 

2152 bbox_extra_artists : list of `~matplotlib.artist.Artist`, optional 

2153 A list of extra artists that will be considered when the 

2154 tight bbox is calculated. 

2155 

2156 metadata : dict, optional 

2157 Key/value pairs to store in the image metadata. The supported keys 

2158 and defaults depend on the image format and backend: 

2159 

2160 - 'png' with Agg backend: See the parameter ``metadata`` of 

2161 `~.FigureCanvasAgg.print_png`. 

2162 - 'pdf' with pdf backend: See the parameter ``metadata`` of 

2163 `~.backend_pdf.PdfPages`. 

2164 - 'eps' and 'ps' with PS backend: Only 'Creator' is supported. 

2165 

2166 pil_kwargs : dict, optional 

2167 Additional keyword arguments that are passed to `PIL.Image.save` 

2168 when saving the figure. Only applicable for formats that are saved 

2169 using Pillow, i.e. JPEG, TIFF, and (if the keyword is set to a 

2170 non-None value) PNG. 

2171 """ 

2172 

2173 kwargs.setdefault('dpi', rcParams['savefig.dpi']) 

2174 if "frameon" in kwargs: 

2175 cbook.warn_deprecated("3.1", name="frameon", obj_type="kwarg", 

2176 alternative="facecolor") 

2177 frameon = kwargs.pop("frameon") 

2178 if frameon is None: 

2179 frameon = dict.__getitem__(rcParams, 'savefig.frameon') 

2180 else: 

2181 frameon = False # Won't pass "if frameon:" below. 

2182 if transparent is None: 

2183 transparent = rcParams['savefig.transparent'] 

2184 

2185 if transparent: 

2186 kwargs.setdefault('facecolor', 'none') 

2187 kwargs.setdefault('edgecolor', 'none') 

2188 original_axes_colors = [] 

2189 for ax in self.axes: 

2190 patch = ax.patch 

2191 original_axes_colors.append((patch.get_facecolor(), 

2192 patch.get_edgecolor())) 

2193 patch.set_facecolor('none') 

2194 patch.set_edgecolor('none') 

2195 else: 

2196 kwargs.setdefault('facecolor', rcParams['savefig.facecolor']) 

2197 kwargs.setdefault('edgecolor', rcParams['savefig.edgecolor']) 

2198 

2199 if frameon: 

2200 original_frameon = self.patch.get_visible() 

2201 self.patch.set_visible(frameon) 

2202 

2203 self.canvas.print_figure(fname, **kwargs) 

2204 

2205 if frameon: 

2206 self.patch.set_visible(original_frameon) 

2207 

2208 if transparent: 

2209 for ax, cc in zip(self.axes, original_axes_colors): 

2210 ax.patch.set_facecolor(cc[0]) 

2211 ax.patch.set_edgecolor(cc[1]) 

2212 

2213 @docstring.dedent_interpd 

2214 def colorbar(self, mappable, cax=None, ax=None, use_gridspec=True, **kw): 

2215 """ 

2216 Create a colorbar for a ScalarMappable instance, *mappable*. 

2217 

2218 Documentation for the pyplot thin wrapper: 

2219 %(colorbar_doc)s 

2220 """ 

2221 if ax is None: 

2222 ax = self.gca() 

2223 

2224 # Store the value of gca so that we can set it back later on. 

2225 current_ax = self.gca() 

2226 

2227 if cax is None: 

2228 if use_gridspec and isinstance(ax, SubplotBase) \ 

2229 and (not self.get_constrained_layout()): 

2230 cax, kw = cbar.make_axes_gridspec(ax, **kw) 

2231 else: 

2232 cax, kw = cbar.make_axes(ax, **kw) 

2233 

2234 # need to remove kws that cannot be passed to Colorbar 

2235 NON_COLORBAR_KEYS = ['fraction', 'pad', 'shrink', 'aspect', 'anchor', 

2236 'panchor'] 

2237 cb_kw = {k: v for k, v in kw.items() if k not in NON_COLORBAR_KEYS} 

2238 cb = cbar.colorbar_factory(cax, mappable, **cb_kw) 

2239 

2240 self.sca(current_ax) 

2241 self.stale = True 

2242 return cb 

2243 

2244 def subplots_adjust(self, left=None, bottom=None, right=None, top=None, 

2245 wspace=None, hspace=None): 

2246 """ 

2247 Update the :class:`SubplotParams` with *kwargs* (defaulting to rc when 

2248 *None*) and update the subplot locations. 

2249 

2250 """ 

2251 if self.get_constrained_layout(): 

2252 self.set_constrained_layout(False) 

2253 cbook._warn_external("This figure was using " 

2254 "constrained_layout==True, but that is " 

2255 "incompatible with subplots_adjust and or " 

2256 "tight_layout: setting " 

2257 "constrained_layout==False. ") 

2258 self.subplotpars.update(left, bottom, right, top, wspace, hspace) 

2259 for ax in self.axes: 

2260 if not isinstance(ax, SubplotBase): 

2261 # Check if sharing a subplots axis 

2262 if isinstance(ax._sharex, SubplotBase): 

2263 ax._sharex.update_params() 

2264 ax.set_position(ax._sharex.figbox) 

2265 elif isinstance(ax._sharey, SubplotBase): 

2266 ax._sharey.update_params() 

2267 ax.set_position(ax._sharey.figbox) 

2268 else: 

2269 ax.update_params() 

2270 ax.set_position(ax.figbox) 

2271 self.stale = True 

2272 

2273 def ginput(self, n=1, timeout=30, show_clicks=True, mouse_add=1, 

2274 mouse_pop=3, mouse_stop=2): 

2275 """ 

2276 Blocking call to interact with a figure. 

2277 

2278 Wait until the user clicks *n* times on the figure, and return the 

2279 coordinates of each click in a list. 

2280 

2281 There are three possible interactions: 

2282 

2283 - Add a point. 

2284 - Remove the most recently added point. 

2285 - Stop the interaction and return the points added so far. 

2286 

2287 The actions are assigned to mouse buttons via the arguments 

2288 *mouse_add*, *mouse_pop* and *mouse_stop*. Mouse buttons are defined 

2289 by the numbers: 

2290 

2291 - 1: left mouse button 

2292 - 2: middle mouse button 

2293 - 3: right mouse button 

2294 - None: no mouse button 

2295 

2296 Parameters 

2297 ---------- 

2298 n : int, optional, default: 1 

2299 Number of mouse clicks to accumulate. If negative, accumulate 

2300 clicks until the input is terminated manually. 

2301 timeout : scalar, optional, default: 30 

2302 Number of seconds to wait before timing out. If zero or negative 

2303 will never timeout. 

2304 show_clicks : bool, optional, default: True 

2305 If True, show a red cross at the location of each click. 

2306 mouse_add : {1, 2, 3, None}, optional, default: 1 (left click) 

2307 Mouse button used to add points. 

2308 mouse_pop : {1, 2, 3, None}, optional, default: 3 (right click) 

2309 Mouse button used to remove the most recently added point. 

2310 mouse_stop : {1, 2, 3, None}, optional, default: 2 (middle click) 

2311 Mouse button used to stop input. 

2312 

2313 Returns 

2314 ------- 

2315 points : list of tuples 

2316 A list of the clicked (x, y) coordinates. 

2317 

2318 Notes 

2319 ----- 

2320 The keyboard can also be used to select points in case your mouse 

2321 does not have one or more of the buttons. The delete and backspace 

2322 keys act like right clicking (i.e., remove last point), the enter key 

2323 terminates input and any other key (not already used by the window 

2324 manager) selects a point. 

2325 """ 

2326 blocking_mouse_input = BlockingMouseInput(self, 

2327 mouse_add=mouse_add, 

2328 mouse_pop=mouse_pop, 

2329 mouse_stop=mouse_stop) 

2330 return blocking_mouse_input(n=n, timeout=timeout, 

2331 show_clicks=show_clicks) 

2332 

2333 def waitforbuttonpress(self, timeout=-1): 

2334 """ 

2335 Blocking call to interact with the figure. 

2336 

2337 This will return True is a key was pressed, False if a mouse 

2338 button was pressed and None if *timeout* was reached without 

2339 either being pressed. 

2340 

2341 If *timeout* is negative, does not timeout. 

2342 """ 

2343 blocking_input = BlockingKeyMouseInput(self) 

2344 return blocking_input(timeout=timeout) 

2345 

2346 def get_default_bbox_extra_artists(self): 

2347 bbox_artists = [artist for artist in self.get_children() 

2348 if (artist.get_visible() and artist.get_in_layout())] 

2349 for ax in self.axes: 

2350 if ax.get_visible(): 

2351 bbox_artists.extend(ax.get_default_bbox_extra_artists()) 

2352 return bbox_artists 

2353 

2354 def get_tightbbox(self, renderer, bbox_extra_artists=None): 

2355 """ 

2356 Return a (tight) bounding box of the figure in inches. 

2357 

2358 Artists that have ``artist.set_in_layout(False)`` are not included 

2359 in the bbox. 

2360 

2361 Parameters 

2362 ---------- 

2363 renderer : `.RendererBase` instance 

2364 renderer that will be used to draw the figures (i.e. 

2365 ``fig.canvas.get_renderer()``) 

2366 

2367 bbox_extra_artists : list of `.Artist` or ``None`` 

2368 List of artists to include in the tight bounding box. If 

2369 ``None`` (default), then all artist children of each axes are 

2370 included in the tight bounding box. 

2371 

2372 Returns 

2373 ------- 

2374 bbox : `.BboxBase` 

2375 containing the bounding box (in figure inches). 

2376 """ 

2377 

2378 bb = [] 

2379 if bbox_extra_artists is None: 

2380 artists = self.get_default_bbox_extra_artists() 

2381 else: 

2382 artists = bbox_extra_artists 

2383 

2384 for a in artists: 

2385 bbox = a.get_tightbbox(renderer) 

2386 if bbox is not None and (bbox.width != 0 or bbox.height != 0): 

2387 bb.append(bbox) 

2388 

2389 for ax in self.axes: 

2390 if ax.get_visible(): 

2391 # some axes don't take the bbox_extra_artists kwarg so we 

2392 # need this conditional.... 

2393 try: 

2394 bbox = ax.get_tightbbox(renderer, 

2395 bbox_extra_artists=bbox_extra_artists) 

2396 except TypeError: 

2397 bbox = ax.get_tightbbox(renderer) 

2398 bb.append(bbox) 

2399 bb = [b for b in bb 

2400 if (np.isfinite(b.width) and np.isfinite(b.height) 

2401 and (b.width != 0 or b.height != 0))] 

2402 

2403 if len(bb) == 0: 

2404 return self.bbox_inches 

2405 

2406 _bbox = Bbox.union(bb) 

2407 

2408 bbox_inches = TransformedBbox(_bbox, Affine2D().scale(1 / self.dpi)) 

2409 

2410 return bbox_inches 

2411 

2412 def init_layoutbox(self): 

2413 """Initialize the layoutbox for use in constrained_layout.""" 

2414 if self._layoutbox is None: 

2415 self._layoutbox = layoutbox.LayoutBox(parent=None, 

2416 name='figlb', 

2417 artist=self) 

2418 self._layoutbox.constrain_geometry(0., 0., 1., 1.) 

2419 

2420 def execute_constrained_layout(self, renderer=None): 

2421 """ 

2422 Use ``layoutbox`` to determine pos positions within axes. 

2423 

2424 See also `.set_constrained_layout_pads`. 

2425 """ 

2426 

2427 from matplotlib._constrained_layout import do_constrained_layout 

2428 

2429 _log.debug('Executing constrainedlayout') 

2430 if self._layoutbox is None: 

2431 cbook._warn_external("Calling figure.constrained_layout, but " 

2432 "figure not setup to do constrained layout. " 

2433 " You either called GridSpec without the " 

2434 "fig keyword, you are using plt.subplot, " 

2435 "or you need to call figure or subplots " 

2436 "with the constrained_layout=True kwarg.") 

2437 return 

2438 w_pad, h_pad, wspace, hspace = self.get_constrained_layout_pads() 

2439 # convert to unit-relative lengths 

2440 fig = self 

2441 width, height = fig.get_size_inches() 

2442 w_pad = w_pad / width 

2443 h_pad = h_pad / height 

2444 if renderer is None: 

2445 renderer = layoutbox.get_renderer(fig) 

2446 do_constrained_layout(fig, renderer, h_pad, w_pad, hspace, wspace) 

2447 

2448 @cbook._delete_parameter("3.2", "renderer") 

2449 def tight_layout(self, renderer=None, pad=1.08, h_pad=None, w_pad=None, 

2450 rect=None): 

2451 """ 

2452 Automatically adjust subplot parameters to give specified padding. 

2453 

2454 To exclude an artist on the axes from the bounding box calculation 

2455 that determines the subplot parameters (i.e. legend, or annotation), 

2456 then set `a.set_in_layout(False)` for that artist. 

2457 

2458 Parameters 

2459 ---------- 

2460 renderer : subclass of `~.backend_bases.RendererBase`, optional 

2461 Defaults to the renderer for the figure. Deprecated. 

2462 pad : float, optional 

2463 Padding between the figure edge and the edges of subplots, 

2464 as a fraction of the font size. 

2465 h_pad, w_pad : float, optional 

2466 Padding (height/width) between edges of adjacent subplots, 

2467 as a fraction of the font size. Defaults to *pad*. 

2468 rect : tuple (left, bottom, right, top), optional 

2469 A rectangle (left, bottom, right, top) in the normalized 

2470 figure coordinate that the whole subplots area (including 

2471 labels) will fit into. Default is (0, 0, 1, 1). 

2472 

2473 See Also 

2474 -------- 

2475 .Figure.set_tight_layout 

2476 .pyplot.tight_layout 

2477 """ 

2478 

2479 from .tight_layout import ( 

2480 get_renderer, get_subplotspec_list, get_tight_layout_figure) 

2481 from contextlib import suppress 

2482 subplotspec_list = get_subplotspec_list(self.axes) 

2483 if None in subplotspec_list: 

2484 cbook._warn_external("This figure includes Axes that are not " 

2485 "compatible with tight_layout, so results " 

2486 "might be incorrect.") 

2487 

2488 if renderer is None: 

2489 renderer = get_renderer(self) 

2490 ctx = (renderer._draw_disabled() 

2491 if hasattr(renderer, '_draw_disabled') 

2492 else suppress()) 

2493 with ctx: 

2494 kwargs = get_tight_layout_figure( 

2495 self, self.axes, subplotspec_list, renderer, 

2496 pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect) 

2497 if kwargs: 

2498 self.subplots_adjust(**kwargs) 

2499 

2500 def align_xlabels(self, axs=None): 

2501 """ 

2502 Align the ylabels of subplots in the same subplot column if label 

2503 alignment is being done automatically (i.e. the label position is 

2504 not manually set). 

2505 

2506 Alignment persists for draw events after this is called. 

2507 

2508 If a label is on the bottom, it is aligned with labels on axes that 

2509 also have their label on the bottom and that have the same 

2510 bottom-most subplot row. If the label is on the top, 

2511 it is aligned with labels on axes with the same top-most row. 

2512 

2513 Parameters 

2514 ---------- 

2515 axs : list of `~matplotlib.axes.Axes` 

2516 Optional list of (or ndarray) `~matplotlib.axes.Axes` 

2517 to align the xlabels. 

2518 Default is to align all axes on the figure. 

2519 

2520 See Also 

2521 -------- 

2522 matplotlib.figure.Figure.align_ylabels 

2523 

2524 matplotlib.figure.Figure.align_labels 

2525 

2526 Notes 

2527 ----- 

2528 This assumes that ``axs`` are from the same `.GridSpec`, so that 

2529 their `.SubplotSpec` positions correspond to figure positions. 

2530 

2531 Examples 

2532 -------- 

2533 Example with rotated xtick labels:: 

2534 

2535 fig, axs = plt.subplots(1, 2) 

2536 for tick in axs[0].get_xticklabels(): 

2537 tick.set_rotation(55) 

2538 axs[0].set_xlabel('XLabel 0') 

2539 axs[1].set_xlabel('XLabel 1') 

2540 fig.align_xlabels() 

2541 

2542 """ 

2543 

2544 if axs is None: 

2545 axs = self.axes 

2546 axs = np.asarray(axs).ravel() 

2547 for ax in axs: 

2548 _log.debug(' Working on: %s', ax.get_xlabel()) 

2549 ss = ax.get_subplotspec() 

2550 nrows, ncols, row0, row1, col0, col1 = ss.get_rows_columns() 

2551 labpo = ax.xaxis.get_label_position() # top or bottom 

2552 

2553 # loop through other axes, and search for label positions 

2554 # that are same as this one, and that share the appropriate 

2555 # row number. 

2556 # Add to a grouper associated with each axes of sibblings. 

2557 # This list is inspected in `axis.draw` by 

2558 # `axis._update_label_position`. 

2559 for axc in axs: 

2560 if axc.xaxis.get_label_position() == labpo: 

2561 ss = axc.get_subplotspec() 

2562 nrows, ncols, rowc0, rowc1, colc, col1 = \ 

2563 ss.get_rows_columns() 

2564 if (labpo == 'bottom' and rowc1 == row1 or 

2565 labpo == 'top' and rowc0 == row0): 

2566 # grouper for groups of xlabels to align 

2567 self._align_xlabel_grp.join(ax, axc) 

2568 

2569 def align_ylabels(self, axs=None): 

2570 """ 

2571 Align the ylabels of subplots in the same subplot column if label 

2572 alignment is being done automatically (i.e. the label position is 

2573 not manually set). 

2574 

2575 Alignment persists for draw events after this is called. 

2576 

2577 If a label is on the left, it is aligned with labels on axes that 

2578 also have their label on the left and that have the same 

2579 left-most subplot column. If the label is on the right, 

2580 it is aligned with labels on axes with the same right-most column. 

2581 

2582 Parameters 

2583 ---------- 

2584 axs : list of `~matplotlib.axes.Axes` 

2585 Optional list (or ndarray) of `~matplotlib.axes.Axes` 

2586 to align the ylabels. 

2587 Default is to align all axes on the figure. 

2588 

2589 See Also 

2590 -------- 

2591 matplotlib.figure.Figure.align_xlabels 

2592 

2593 matplotlib.figure.Figure.align_labels 

2594 

2595 Notes 

2596 ----- 

2597 This assumes that ``axs`` are from the same `.GridSpec`, so that 

2598 their `.SubplotSpec` positions correspond to figure positions. 

2599 

2600 Examples 

2601 -------- 

2602 Example with large yticks labels:: 

2603 

2604 fig, axs = plt.subplots(2, 1) 

2605 axs[0].plot(np.arange(0, 1000, 50)) 

2606 axs[0].set_ylabel('YLabel 0') 

2607 axs[1].set_ylabel('YLabel 1') 

2608 fig.align_ylabels() 

2609 

2610 """ 

2611 

2612 if axs is None: 

2613 axs = self.axes 

2614 axs = np.asarray(axs).ravel() 

2615 for ax in axs: 

2616 _log.debug(' Working on: %s', ax.get_ylabel()) 

2617 ss = ax.get_subplotspec() 

2618 nrows, ncols, row0, row1, col0, col1 = ss.get_rows_columns() 

2619 labpo = ax.yaxis.get_label_position() # left or right 

2620 # loop through other axes, and search for label positions 

2621 # that are same as this one, and that share the appropriate 

2622 # column number. 

2623 # Add to a list associated with each axes of sibblings. 

2624 # This list is inspected in `axis.draw` by 

2625 # `axis._update_label_position`. 

2626 for axc in axs: 

2627 if axc != ax: 

2628 if axc.yaxis.get_label_position() == labpo: 

2629 ss = axc.get_subplotspec() 

2630 nrows, ncols, row0, row1, colc0, colc1 = \ 

2631 ss.get_rows_columns() 

2632 if (labpo == 'left' and colc0 == col0 or 

2633 labpo == 'right' and colc1 == col1): 

2634 # grouper for groups of ylabels to align 

2635 self._align_ylabel_grp.join(ax, axc) 

2636 

2637 def align_labels(self, axs=None): 

2638 """ 

2639 Align the xlabels and ylabels of subplots with the same subplots 

2640 row or column (respectively) if label alignment is being 

2641 done automatically (i.e. the label position is not manually set). 

2642 

2643 Alignment persists for draw events after this is called. 

2644 

2645 Parameters 

2646 ---------- 

2647 axs : list of `~matplotlib.axes.Axes` 

2648 Optional list (or ndarray) of `~matplotlib.axes.Axes` 

2649 to align the labels. 

2650 Default is to align all axes on the figure. 

2651 

2652 See Also 

2653 -------- 

2654 matplotlib.figure.Figure.align_xlabels 

2655 

2656 matplotlib.figure.Figure.align_ylabels 

2657 """ 

2658 self.align_xlabels(axs=axs) 

2659 self.align_ylabels(axs=axs) 

2660 

2661 def add_gridspec(self, nrows, ncols, **kwargs): 

2662 """ 

2663 Return a `.GridSpec` that has this figure as a parent. This allows 

2664 complex layout of axes in the figure. 

2665 

2666 Parameters 

2667 ---------- 

2668 nrows : int 

2669 Number of rows in grid. 

2670 

2671 ncols : int 

2672 Number or columns in grid. 

2673 

2674 Returns 

2675 ------- 

2676 gridspec : `.GridSpec` 

2677 

2678 Other Parameters 

2679 ---------------- 

2680 **kwargs 

2681 Keyword arguments are passed to `.GridSpec`. 

2682 

2683 See Also 

2684 -------- 

2685 matplotlib.pyplot.subplots 

2686 

2687 Examples 

2688 -------- 

2689 Adding a subplot that spans two rows:: 

2690 

2691 fig = plt.figure() 

2692 gs = fig.add_gridspec(2, 2) 

2693 ax1 = fig.add_subplot(gs[0, 0]) 

2694 ax2 = fig.add_subplot(gs[1, 0]) 

2695 # spans two rows: 

2696 ax3 = fig.add_subplot(gs[:, 1]) 

2697 

2698 """ 

2699 

2700 _ = kwargs.pop('figure', None) # pop in case user has added this... 

2701 gs = GridSpec(nrows=nrows, ncols=ncols, figure=self, **kwargs) 

2702 self._gridspecs.append(gs) 

2703 return gs 

2704 

2705 

2706def figaspect(arg): 

2707 """ 

2708 Calculate the width and height for a figure with a specified aspect ratio. 

2709 

2710 While the height is taken from :rc:`figure.figsize`, the width is 

2711 adjusted to match the desired aspect ratio. Additionally, it is ensured 

2712 that the width is in the range [4., 16.] and the height is in the range 

2713 [2., 16.]. If necessary, the default height is adjusted to ensure this. 

2714 

2715 Parameters 

2716 ---------- 

2717 arg : scalar or 2d array 

2718 If a scalar, this defines the aspect ratio (i.e. the ratio height / 

2719 width). 

2720 In case of an array the aspect ratio is number of rows / number of 

2721 columns, so that the array could be fitted in the figure undistorted. 

2722 

2723 Returns 

2724 ------- 

2725 width, height 

2726 The figure size in inches. 

2727 

2728 Notes 

2729 ----- 

2730 If you want to create an axes within the figure, that still preserves the 

2731 aspect ratio, be sure to create it with equal width and height. See 

2732 examples below. 

2733 

2734 Thanks to Fernando Perez for this function. 

2735 

2736 Examples 

2737 -------- 

2738 Make a figure twice as tall as it is wide:: 

2739 

2740 w, h = figaspect(2.) 

2741 fig = Figure(figsize=(w, h)) 

2742 ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

2743 ax.imshow(A, **kwargs) 

2744 

2745 Make a figure with the proper aspect for an array:: 

2746 

2747 A = rand(5, 3) 

2748 w, h = figaspect(A) 

2749 fig = Figure(figsize=(w, h)) 

2750 ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 

2751 ax.imshow(A, **kwargs) 

2752 """ 

2753 

2754 isarray = hasattr(arg, 'shape') and not np.isscalar(arg) 

2755 

2756 # min/max sizes to respect when autoscaling. If John likes the idea, they 

2757 # could become rc parameters, for now they're hardwired. 

2758 figsize_min = np.array((4.0, 2.0)) # min length for width/height 

2759 figsize_max = np.array((16.0, 16.0)) # max length for width/height 

2760 

2761 # Extract the aspect ratio of the array 

2762 if isarray: 

2763 nr, nc = arg.shape[:2] 

2764 arr_ratio = nr / nc 

2765 else: 

2766 arr_ratio = arg 

2767 

2768 # Height of user figure defaults 

2769 fig_height = rcParams['figure.figsize'][1] 

2770 

2771 # New size for the figure, keeping the aspect ratio of the caller 

2772 newsize = np.array((fig_height / arr_ratio, fig_height)) 

2773 

2774 # Sanity checks, don't drop either dimension below figsize_min 

2775 newsize /= min(1.0, *(newsize / figsize_min)) 

2776 

2777 # Avoid humongous windows as well 

2778 newsize /= max(1.0, *(newsize / figsize_max)) 

2779 

2780 # Finally, if we have a really funky aspect ratio, break it but respect 

2781 # the min/max dimensions (we don't want figures 10 feet tall!) 

2782 newsize = np.clip(newsize, figsize_min, figsize_max) 

2783 return newsize 

2784 

2785docstring.interpd.update(Figure=martist.kwdoc(Figure))