Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/matplotlib/figure.py : 14%

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
6:class:`SubplotParams`
7 control the default spacing of the subplots
9:class:`Figure`
10 Top level container for all plot elements.
12"""
14import logging
15from numbers import Integral
17import numpy as np
19from matplotlib import rcParams
20from matplotlib import backends, docstring, projections
21from matplotlib import __version__ as _mpl_version
22from matplotlib import get_backend
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
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
42_log = logging.getLogger(__name__)
45def _stale_figure_callback(self, val):
46 if self.figure:
47 self.figure.stale = val
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:
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.
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.
65 """
66 def __init__(self):
67 super().__init__()
68 self._ind = 0
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]
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]
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))
100 def remove(self, a):
101 """Remove the axes from the stack."""
102 super().remove(self._entry_from_axes(a))
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))
111 def add(self, key, a):
112 """
113 Add Axes *a*, with key *key*, to the stack, and return the stack.
115 If *key* is unhashable, replace it by a unique, arbitrary object.
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()
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.
135 if a in self:
136 return None
137 self._ind += 1
138 return super().push((key, (self._ind, a)))
140 def current_key_axes(self):
141 """
142 Return a tuple of ``(key, axes)`` for the active axes.
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
152 def __call__(self):
153 return self.current_key_axes()[1]
155 def __contains__(self, a):
156 return a in self.as_list()
159@cbook.deprecated("3.2")
160class AxesStack(_AxesStack):
161 pass
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]`.
174 Parameters
175 ----------
176 left : float
177 The left side of the subplots of the figure.
179 right : float
180 The right side of the subplots of the figure.
182 bottom : float
183 The bottom of the subplots of the figure.
185 top : float
186 The top of the subplots of the figure.
188 wspace : float
189 The amount of width reserved for space between subplots,
190 expressed as a fraction of the average axis width.
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)
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)
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)
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
226 if self.validate:
227 if self.left >= self.right:
228 reset()
229 raise ValueError('left cannot be >= right')
231 if self.bottom >= self.top:
232 reset()
233 raise ValueError('bottom cannot be >= top')
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]
242 setattr(self, s, val)
245class Figure(Artist):
246 """
247 The top level container for all the plot elements.
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.
254 Attributes
255 ----------
256 patch
257 The `.Rectangle` instance representing the figure background patch.
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 """
265 def __str__(self):
266 return "Figure(%gx%g)" % tuple(self.bbox.size)
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 )
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.
293 dpi : float, default: :rc:`figure.dpi`
294 Dots per inch.
296 facecolor : default: :rc:`figure.facecolor`
297 The figure patch facecolor.
299 edgecolor : default: :rc:`figure.edgecolor`
300 The figure patch edge color.
302 linewidth : float
303 The linewidth of the frame (i.e. the edge linewidth of the figure
304 patch).
306 frameon : bool, default: :rc:`figure.frameon`
307 If ``False``, suppress drawing the figure background patch.
309 subplotpars : :class:`SubplotParams`
310 Subplot parameters. If not given, the default subplot
311 parameters :rc:`figure.subplot.*` are used.
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.
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()
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']
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)
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)
358 self.transFigure = BboxTransformTo(self.bbox)
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)
368 FigureCanvasBase(self) # Set self.canvas.
369 self._suptitle = None
371 if subplotpars is None:
372 subplotpars = SubplotParams()
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)
380 self.set_tight_layout(tight_layout)
382 self._axstack = _AxesStack() # track all figure axes and current axes
383 self.clf()
384 self._cachedRenderer = None
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()
392 # list of child gridspecs for this figure
393 self._gridspecs = []
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.
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)
406 def show(self, warn=True):
407 """
408 If using a GUI backend with pyplot, display the figure window.
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.
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.
420 Proper use cases for `.Figure.show` include running this from a
421 GUI application or an IPython shell.
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.
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)
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())
453 def _get_axes(self):
454 return self._axstack.as_list()
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.")
463 def _get_dpi(self):
464 return self._dpi
466 def _set_dpi(self, dpi, forward=True):
467 """
468 Parameters
469 ----------
470 dpi : float
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)
481 dpi = property(_get_dpi, _set_dpi, doc="The resolution in dots per inch.")
483 def get_tight_layout(self):
484 """Return whether `.tight_layout` is called when drawing."""
485 return self._tight
487 def set_tight_layout(self, tight):
488 """
489 Set whether and how `.tight_layout` is called when drawing.
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
505 def get_constrained_layout(self):
506 """
507 Return a boolean: True means constrained layout is being used.
509 See :doc:`/tutorials/intermediate/constrainedlayout_guide`.
510 """
511 return self._constrained
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.
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.
523 See :doc:`/tutorials/intermediate/constrainedlayout_guide`.
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()
542 self.stale = True
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)``.
549 See :doc:`/tutorials/intermediate/constrainedlayout_guide`.
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
558 h_pad : scalar
559 Height padding in inches. Defaults to 3 pts.
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.
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.
569 """
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])
579 def get_constrained_layout_pads(self, relative=False):
580 """
581 Get padding for ``constrained_layout``.
583 Returns a list of `w_pad, h_pad` in inches and
584 `wspace` and `hspace` as fractions of the subplot.
586 See :doc:`/tutorials/intermediate/constrainedlayout_guide`.
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']
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
604 return w_pad, h_pad, wspace, hspace
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.
615 Parameters
616 ----------
617 bottom : scalar
618 The bottom of the subplots for :meth:`subplots_adjust`.
620 rotation : angle in degrees
621 The rotation of the xtick labels.
623 ha : str
624 The horizontal alignment of the xticklabels.
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('')
647 if allsubplots:
648 self.subplots_adjust(bottom=bottom)
649 self.stale = True
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]
662 def contains(self, mouseevent):
663 """
664 Test whether the mouse event occurred on the figure.
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, {}
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
682 def suptitle(self, t, **kwargs):
683 """
684 Add a centered title to the figure.
686 Parameters
687 ----------
688 t : str
689 The title text.
691 x : float, default 0.5
692 The x location of the text in figure coordinates.
694 y : float, default 0.98
695 The y location of the text in figure coordinates.
697 horizontalalignment, ha : {'center', 'left', right'}, default: 'center'
698 The horizontal alignment of the text relative to (*x*, *y*).
700 verticalalignment, va : {'top', 'center', 'bottom', 'baseline'}, \
701default: 'top'
702 The vertical alignment of the text relative to (*x*, *y*).
704 fontsize, size : default: :rc:`figure.titlesize`
705 The font size of the text. See `.Text.set_size` for possible
706 values.
708 fontweight, weight : default: :rc:`figure.titleweight`
709 The font weight of the text. See `.Text.set_weight` for possible
710 values.
713 Returns
714 -------
715 text
716 The `.Text` instance of the title.
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.
727 **kwargs
728 Additional kwargs are :class:`matplotlib.text.Text` properties.
731 Examples
732 --------
733 >>> fig.suptitle('This is the figure title', fontsize=12)
734 """
735 manual_position = ('x' in kwargs or 'y' in kwargs)
737 x = kwargs.pop('x', 0.5)
738 y = kwargs.pop('y', 0.98)
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'
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']
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
778 def set_canvas(self, canvas):
779 """
780 Set the canvas that contains the figure
782 Parameters
783 ----------
784 canvas : FigureCanvas
785 """
786 self.canvas = canvas
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.
793 The image is attached to the lower or upper left corner depending on
794 *origin*.
796 Parameters
797 ----------
798 X
799 The image data. This is an array of one of the following shapes:
801 - MxN: luminance (grayscale) values
802 - MxNx3: RGB values
803 - MxNx4: RGBA values
805 xo, yo : int
806 The *x*/*y* image offset in pixels.
808 alpha : None or float
809 The alpha blending value.
811 norm : :class:`matplotlib.colors.Normalize`
812 A :class:`.Normalize` instance to map the luminance to the
813 interval [0, 1].
815 cmap : str or :class:`matplotlib.colors.Colormap`
816 The colormap to use. Default: :rc:`image.cmap`.
818 vmin, vmax : scalar
819 If *norm* is not given, these values set the data limits for the
820 colormap.
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`.
826 resize : bool
827 If *True*, resize the figure to match the given image size.
829 Returns
830 -------
831 :class:`matplotlib.image.FigureImage`
833 Other Parameters
834 ----------------
835 **kwargs
836 Additional kwargs are `.Artist` kwargs passed on to `.FigureImage`.
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].
847 Examples::
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()
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)
862 im = mimage.FigureImage(self, cmap, norm, xo, yo, origin, **kwargs)
863 im.stale_callback = _stale_figure_callback
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
874 def set_size_inches(self, w, h=None, forward=True):
875 """
876 Set the figure size in inches.
878 Call signatures::
880 fig.set_size_inches(w, h) # OR
881 fig.set_size_inches((w, h))
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.
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
913 def get_size_inches(self):
914 """
915 Returns the current size of the figure in inches.
917 Returns
918 -------
919 size : ndarray
920 The size (width, height) of the figure in inches.
922 See Also
923 --------
924 matplotlib.Figure.set_size_inches
925 """
926 return np.array(self.bbox_inches.p1)
928 def get_edgecolor(self):
929 """Get the edge color of the Figure rectangle."""
930 return self.patch.get_edgecolor()
932 def get_facecolor(self):
933 """Get the face color of the Figure rectangle."""
934 return self.patch.get_facecolor()
936 def get_figwidth(self):
937 """Return the figure width as a float."""
938 return self.bbox_inches.width
940 def get_figheight(self):
941 """Return the figure height as a float."""
942 return self.bbox_inches.height
944 def get_dpi(self):
945 """Return the resolution in dots per inch as a float."""
946 return self.dpi
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()
956 def set_edgecolor(self, color):
957 """
958 Set the edge color of the Figure rectangle.
960 Parameters
961 ----------
962 color : color
963 """
964 self.patch.set_edgecolor(color)
966 def set_facecolor(self, color):
967 """
968 Set the face color of the Figure rectangle.
970 Parameters
971 ----------
972 color : color
973 """
974 self.patch.set_facecolor(color)
976 def set_dpi(self, val):
977 """
978 Set the resolution of the figure in dots-per-inch.
980 Parameters
981 ----------
982 val : float
983 """
984 self.dpi = val
985 self.stale = True
987 def set_figwidth(self, val, forward=True):
988 """
989 Set the width of the figure in inches.
991 Parameters
992 ----------
993 val : float
994 forward : bool
995 """
996 self.set_size_inches(val, self.get_figheight(), forward=forward)
998 def set_figheight(self, val, forward=True):
999 """
1000 Set the height of the figure in inches.
1002 Parameters
1003 ----------
1004 val : float
1005 forward : bool
1006 """
1007 self.set_size_inches(self.get_figwidth(), val, forward=forward)
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()``.
1015 Parameters
1016 ----------
1017 b : bool
1018 """
1019 self.patch.set_visible(b)
1020 self.stale = True
1022 frameon = property(get_frameon, set_frameon)
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
1034 def add_artist(self, artist, clip=False):
1035 """
1036 Add any :class:`~matplotlib.artist.Artist` to the figure.
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.
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.
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
1061 if not artist.is_transform_set():
1062 artist.set_transform(self.transFigure)
1064 if clip:
1065 artist.set_clip_path(self.patch)
1067 self.stale = True
1068 return artist
1070 def _make_key(self, *args, **kwargs):
1071 """Make a hashable key out of args and kwargs."""
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)
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)
1097 key = fixlist(args), fixitems(kwargs.items())
1098 return key
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::
1105 (axes_proj_class, proj_class_kwargs, proj_stack_key)
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'
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)
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)
1130 return projection_class, kwargs, key
1132 @docstring.dedent_interpd
1133 def add_axes(self, *args, **kwargs):
1134 """
1135 Add an axes to the figure.
1137 Call signatures::
1139 add_axes(rect, projection=None, polar=False, **kwargs)
1140 add_axes(ax)
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.
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.
1154 polar : boolean, optional
1155 If True, equivalent to projection='polar'.
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.
1162 label : str
1163 A label for the returned axes.
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.
1175 %(Axes)s
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.
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.
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.
1200 See Also
1201 --------
1202 .Figure.add_subplot
1203 .pyplot.subplot
1204 .pyplot.axes
1205 .Figure.subplots
1206 .pyplot.subplots
1208 Examples
1209 --------
1210 Some simple examples::
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 """
1223 if not len(args):
1224 return
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
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)
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
1254 # create the new axes using the axes class given
1255 a = projection_class(self, rect, **kwargs)
1257 return self._add_axes_internal(key, a)
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.
1264 Call signatures::
1266 add_subplot(nrows, ncols, index, **kwargs)
1267 add_subplot(pos, **kwargs)
1268 add_subplot(ax)
1269 add_subplot()
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.
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.
1287 If no positional arguments are passed, defaults to (1, 1, 1).
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.
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.
1299 polar : boolean, optional
1300 If True, equivalent to projection='polar'.
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.
1307 label : str
1308 A label for the returned axes.
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.
1319 %(Axes)s
1321 Returns
1322 -------
1323 axes : `.axes.SubplotBase`, or another subclass of `~.axes.Axes`
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.
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.
1342 See Also
1343 --------
1344 .Figure.add_axes
1345 .pyplot.subplot
1346 .pyplot.axes
1347 .Figure.subplots
1348 .pyplot.subplots
1350 Examples
1351 --------
1352 ::
1354 fig = plt.figure()
1355 fig.add_subplot(221)
1357 # equivalent but more general
1358 ax1 = fig.add_subplot(2, 2, 1)
1360 # add a subplot with no frame
1361 ax2 = fig.add_subplot(222, frameon=False)
1363 # add a polar subplot
1364 fig.add_subplot(223, projection='polar')
1366 # add a red subplot that share the x-axis with ax1
1367 fig.add_subplot(224, sharex=ax1, facecolor='red')
1369 #delete x2 from the figure
1370 fig.delaxes(ax2)
1372 #add x2 to the figure again
1373 fig.add_subplot(ax2)
1374 """
1375 if not len(args):
1376 args = (1, 1, 1)
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])))
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'")
1390 if isinstance(args[0], SubplotBase):
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)
1403 # try to find the axes with this key in the stack
1404 ax = self._axstack.get(key)
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)
1419 a = subplot_class_factory(projection_class)(self, *args, **kwargs)
1421 return self._add_axes_internal(key, a)
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
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.
1437 This utility wrapper makes it convenient to create common layouts of
1438 subplots in a single call.
1440 Parameters
1441 ----------
1442 nrows, ncols : int, optional, default: 1
1443 Number of rows/columns of the subplot grid.
1445 sharex, sharey : bool or {'none', 'all', 'row', 'col'}, default: False
1446 Controls sharing of properties among x (`sharex`) or y (`sharey`)
1447 axes:
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.
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`.
1460 squeeze : bool, optional, default: True
1461 - If True, extra dimensions are squeezed out from the returned
1462 array of Axes:
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.
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.
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.
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.
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.
1492 Examples
1493 --------
1494 ::
1496 # First create some toy data:
1497 x = np.linspace(0, 2*np.pi, 400)
1498 y = np.sin(x**2)
1500 # Create a figure
1501 plt.figure()
1503 # Create a subplot
1504 ax = fig.subplots()
1505 ax.plot(x, y)
1506 ax.set_title('Simple plot')
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)
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)
1519 # Share a X axis with each column of subplots
1520 fig.subplots(2, 2, sharex='col')
1522 # Share a Y axis with each row of subplots
1523 fig.subplots(2, 2, sharey='row')
1525 # Share both X and Y axes with all subplots
1526 fig.subplots(2, 2, sharex='all', sharey='all')
1528 # Note that this is the same as
1529 fig.subplots(2, 2, sharex=True, sharey=True)
1531 See Also
1532 --------
1533 .pyplot.subplots
1534 .Figure.add_subplot
1535 .pyplot.subplot
1536 """
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()
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)
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)
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)
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
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
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
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
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
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
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)
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)
1651 def clf(self, keep_observers=False):
1652 """
1653 Clear the figure.
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()
1661 for ax in tuple(self.axes): # Iterate over the copy.
1662 ax.cla()
1663 self.delaxes(ax) # removes ax from self._axstack
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
1682 def clear(self, keep_observers=False):
1683 """
1684 Clear the figure -- synonym for :meth:`clf`.
1685 """
1686 self.clf(keep_observers=keep_observers)
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
1696 # draw the figure bounding box, perhaps none for white figure
1697 if not self.get_visible():
1698 return
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())
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()
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()
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.
1734 self.patch.draw(renderer)
1735 mimage._draw_list_compositing_images(
1736 renderer, self, artists, self.suppressComposite)
1738 renderer.close_group('figure')
1739 finally:
1740 self.stale = False
1742 self.canvas.draw_event(renderer)
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)
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.
1759 Do not modify the list itself. Instead, use `~Figure.add_axes`,
1760 `~.Figure.subplot` or `~.Figure.delaxes` to add or remove an axes.
1762 Note: This is equivalent to the property `~.Figure.axes`.
1763 """
1764 return self.axes
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.
1770 @docstring.dedent_interpd
1771 def legend(self, *args, **kwargs):
1772 """
1773 Place a legend on the figure.
1775 To make a legend from existing artists on every axes::
1777 legend()
1779 To make a legend for a list of lines and labels::
1781 legend(
1782 (line1, line2, line3),
1783 ('label1', 'label2', 'label3'),
1784 loc='upper right')
1786 These can also be specified by keyword::
1788 legend(
1789 handles=(line1, line2, line3),
1790 labels=('label1', 'label2', 'label3'),
1791 loc='upper right')
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.
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.
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.
1810 Other Parameters
1811 ----------------
1812 %(_legend_kw_doc)s
1814 Returns
1815 -------
1816 :class:`matplotlib.legend.Legend` instance
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 """
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
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.
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.
1858 s : str
1859 The text string.
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.
1866 withdash : boolean, optional, default: False
1867 Creates a `~matplotlib.text.TextWithDash` instance instead of a
1868 `~matplotlib.text.Text` instance.
1870 Other Parameters
1871 ----------------
1872 **kwargs : `~matplotlib.text.Text` properties
1873 Other miscellaneous text parameters.
1875 %(Text)s
1877 Returns
1878 -------
1879 text : `~.text.Text`
1881 See Also
1882 --------
1883 .Axes.text
1884 .pyplot.text
1885 """
1886 default = dict(transform=self.transFigure)
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)
1894 text.update(default)
1895 if fontdict is not None:
1896 text.update(fontdict)
1897 text.update(kwargs)
1899 text.set_figure(self)
1900 text.stale_callback = _stale_figure_callback
1902 self.texts.append(text)
1903 text._remove_method = self.texts.remove
1904 self.stale = True
1905 return text
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)
1913 @docstring.dedent_interpd
1914 def gca(self, **kwargs):
1915 """
1916 Get the current axes, creating one if necessary.
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:
1922 %(Axes)s
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:
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
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)
1941 # let the returned axes have any gridspec by removing it from
1942 # the key
1943 ckey = ckey[1:]
1944 key = key[1:]
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.')
1956 # no axes found, so create one which spans the figure
1957 return self.add_subplot(1, 1, 1, **kwargs)
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
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
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
1987 def __getstate__(self):
1988 state = super().__getstate__()
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)
1998 # add version information to the state
1999 state['__mpl_version__'] = _mpl_version
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
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
2014 return state
2016 def __setstate__(self, state):
2017 version = state.pop('__mpl_version__')
2018 restore_to_pylab = state.pop('_restore_to_pylab', False)
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.")
2025 self.__dict__ = state
2027 # re-initialise some of the unstored state information
2028 self._axobservers = []
2029 FigureCanvasBase(self) # Set self.canvas.
2030 self._layoutbox = None
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)
2040 # XXX The following is a copy and paste from pyplot. Consider
2041 # factoring to pylab_helpers
2043 if self.get_label():
2044 mgr.set_window_title(self.get_label())
2046 # make this figure current on button press event
2047 def make_active(event):
2048 pylab_helpers.Gcf.set_active(mgr)
2050 mgr._cidgcf = mgr.canvas.mpl_connect('button_press_event',
2051 make_active)
2053 pylab_helpers.Gcf.set_active(mgr)
2054 self.number = num
2056 plt.draw_if_interactive()
2057 self.stale = True
2059 def add_axobserver(self, func):
2060 """Whenever the axes state change, ``func(self)`` will be called."""
2061 self._axobservers.append(func)
2063 def savefig(self, fname, *, transparent=None, **kwargs):
2064 """
2065 Save the current figure.
2067 Call signature::
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)
2074 The output formats available depend on the backend being used.
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`.
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.
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.
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.
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.
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.
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.
2114 facecolor : color or None, optional
2115 The facecolor of the figure; if *None*, defaults to
2116 :rc:`savefig.facecolor`.
2118 edgecolor : color or None, optional
2119 The edgecolor of the figure; if *None*, defaults to
2120 :rc:`savefig.edgecolor`
2122 orientation : {'landscape', 'portrait'}
2123 Currently only supported by the postscript backend.
2125 papertype : str
2126 One of 'letter', 'legal', 'executive', 'ledger', 'a0' through
2127 'a10', 'b0' through 'b10'. Only supported for postscript
2128 output.
2130 format : str
2131 The file format, e.g. 'png', 'pdf', 'svg', ... The behavior when
2132 this is unset is documented under *fname*.
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.
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
2148 pad_inches : scalar, optional
2149 Amount of padding around the figure when bbox_inches is
2150 'tight'. If None, use savefig.pad_inches
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.
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:
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.
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 """
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']
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'])
2199 if frameon:
2200 original_frameon = self.patch.get_visible()
2201 self.patch.set_visible(frameon)
2203 self.canvas.print_figure(fname, **kwargs)
2205 if frameon:
2206 self.patch.set_visible(original_frameon)
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])
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*.
2218 Documentation for the pyplot thin wrapper:
2219 %(colorbar_doc)s
2220 """
2221 if ax is None:
2222 ax = self.gca()
2224 # Store the value of gca so that we can set it back later on.
2225 current_ax = self.gca()
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)
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)
2240 self.sca(current_ax)
2241 self.stale = True
2242 return cb
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.
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
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.
2278 Wait until the user clicks *n* times on the figure, and return the
2279 coordinates of each click in a list.
2281 There are three possible interactions:
2283 - Add a point.
2284 - Remove the most recently added point.
2285 - Stop the interaction and return the points added so far.
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:
2291 - 1: left mouse button
2292 - 2: middle mouse button
2293 - 3: right mouse button
2294 - None: no mouse button
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.
2313 Returns
2314 -------
2315 points : list of tuples
2316 A list of the clicked (x, y) coordinates.
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)
2333 def waitforbuttonpress(self, timeout=-1):
2334 """
2335 Blocking call to interact with the figure.
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.
2341 If *timeout* is negative, does not timeout.
2342 """
2343 blocking_input = BlockingKeyMouseInput(self)
2344 return blocking_input(timeout=timeout)
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
2354 def get_tightbbox(self, renderer, bbox_extra_artists=None):
2355 """
2356 Return a (tight) bounding box of the figure in inches.
2358 Artists that have ``artist.set_in_layout(False)`` are not included
2359 in the bbox.
2361 Parameters
2362 ----------
2363 renderer : `.RendererBase` instance
2364 renderer that will be used to draw the figures (i.e.
2365 ``fig.canvas.get_renderer()``)
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.
2372 Returns
2373 -------
2374 bbox : `.BboxBase`
2375 containing the bounding box (in figure inches).
2376 """
2378 bb = []
2379 if bbox_extra_artists is None:
2380 artists = self.get_default_bbox_extra_artists()
2381 else:
2382 artists = bbox_extra_artists
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)
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))]
2403 if len(bb) == 0:
2404 return self.bbox_inches
2406 _bbox = Bbox.union(bb)
2408 bbox_inches = TransformedBbox(_bbox, Affine2D().scale(1 / self.dpi))
2410 return bbox_inches
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.)
2420 def execute_constrained_layout(self, renderer=None):
2421 """
2422 Use ``layoutbox`` to determine pos positions within axes.
2424 See also `.set_constrained_layout_pads`.
2425 """
2427 from matplotlib._constrained_layout import do_constrained_layout
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)
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.
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.
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).
2473 See Also
2474 --------
2475 .Figure.set_tight_layout
2476 .pyplot.tight_layout
2477 """
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.")
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)
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).
2506 Alignment persists for draw events after this is called.
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.
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.
2520 See Also
2521 --------
2522 matplotlib.figure.Figure.align_ylabels
2524 matplotlib.figure.Figure.align_labels
2526 Notes
2527 -----
2528 This assumes that ``axs`` are from the same `.GridSpec`, so that
2529 their `.SubplotSpec` positions correspond to figure positions.
2531 Examples
2532 --------
2533 Example with rotated xtick labels::
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()
2542 """
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
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)
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).
2575 Alignment persists for draw events after this is called.
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.
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.
2589 See Also
2590 --------
2591 matplotlib.figure.Figure.align_xlabels
2593 matplotlib.figure.Figure.align_labels
2595 Notes
2596 -----
2597 This assumes that ``axs`` are from the same `.GridSpec`, so that
2598 their `.SubplotSpec` positions correspond to figure positions.
2600 Examples
2601 --------
2602 Example with large yticks labels::
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()
2610 """
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)
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).
2643 Alignment persists for draw events after this is called.
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.
2652 See Also
2653 --------
2654 matplotlib.figure.Figure.align_xlabels
2656 matplotlib.figure.Figure.align_ylabels
2657 """
2658 self.align_xlabels(axs=axs)
2659 self.align_ylabels(axs=axs)
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.
2666 Parameters
2667 ----------
2668 nrows : int
2669 Number of rows in grid.
2671 ncols : int
2672 Number or columns in grid.
2674 Returns
2675 -------
2676 gridspec : `.GridSpec`
2678 Other Parameters
2679 ----------------
2680 **kwargs
2681 Keyword arguments are passed to `.GridSpec`.
2683 See Also
2684 --------
2685 matplotlib.pyplot.subplots
2687 Examples
2688 --------
2689 Adding a subplot that spans two rows::
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])
2698 """
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
2706def figaspect(arg):
2707 """
2708 Calculate the width and height for a figure with a specified aspect ratio.
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.
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.
2723 Returns
2724 -------
2725 width, height
2726 The figure size in inches.
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.
2734 Thanks to Fernando Perez for this function.
2736 Examples
2737 --------
2738 Make a figure twice as tall as it is wide::
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)
2745 Make a figure with the proper aspect for an array::
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 """
2754 isarray = hasattr(arg, 'shape') and not np.isscalar(arg)
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
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
2768 # Height of user figure defaults
2769 fig_height = rcParams['figure.figsize'][1]
2771 # New size for the figure, keeping the aspect ratio of the caller
2772 newsize = np.array((fig_height / arr_ratio, fig_height))
2774 # Sanity checks, don't drop either dimension below figsize_min
2775 newsize /= min(1.0, *(newsize / figsize_min))
2777 # Avoid humongous windows as well
2778 newsize /= max(1.0, *(newsize / figsize_max))
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
2785docstring.interpd.update(Figure=martist.kwdoc(Figure))