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

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
1import collections.abc
2import functools
3import itertools
4import logging
5import math
6from numbers import Number
8import numpy as np
9from numpy import ma
11import matplotlib.category as _ # <-registers a category unit converter
12import matplotlib.cbook as cbook
13import matplotlib.collections as mcoll
14import matplotlib.colors as mcolors
15import matplotlib.contour as mcontour
16import matplotlib.dates as _ # <-registers a date unit converter
17import matplotlib.docstring as docstring
18import matplotlib.image as mimage
19import matplotlib.legend as mlegend
20import matplotlib.lines as mlines
21import matplotlib.markers as mmarkers
22import matplotlib.mlab as mlab
23import matplotlib.patches as mpatches
24import matplotlib.path as mpath
25import matplotlib.quiver as mquiver
26import matplotlib.stackplot as mstack
27import matplotlib.streamplot as mstream
28import matplotlib.table as mtable
29import matplotlib.text as mtext
30import matplotlib.ticker as mticker
31import matplotlib.transforms as mtransforms
32import matplotlib.tri as mtri
33from matplotlib import _preprocess_data, rcParams
34from matplotlib.axes._base import _AxesBase, _process_plot_format
35from matplotlib.axes._secondary_axes import SecondaryAxis
36from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
38try:
39 from numpy.lib.histograms import (
40 histogram_bin_edges as _histogram_bin_edges)
41except ImportError:
42 # this function is new in np 1.15
43 def _histogram_bin_edges(arr, bins, range=None, weights=None):
44 # this in True for 1D arrays, and False for None and str
45 if np.ndim(bins) == 1:
46 return bins
48 if isinstance(bins, str):
49 # rather than backporting the internals, just do the full
50 # computation. If this is too slow for users, they can
51 # update numpy, or pick a manual number of bins
52 return np.histogram(arr, bins, range, weights)[1]
53 else:
54 if bins is None:
55 # hard-code numpy's default
56 bins = 10
57 if range is None:
58 range = np.min(arr), np.max(arr)
60 return np.linspace(*range, bins + 1)
63_log = logging.getLogger(__name__)
66def _make_inset_locator(bounds, trans, parent):
67 """
68 Helper function to locate inset axes, used in
69 `.Axes.inset_axes`.
71 A locator gets used in `Axes.set_aspect` to override the default
72 locations... It is a function that takes an axes object and
73 a renderer and tells `set_aspect` where it is to be placed.
75 Here *rect* is a rectangle [l, b, w, h] that specifies the
76 location for the axes in the transform given by *trans* on the
77 *parent*.
78 """
79 _bounds = mtransforms.Bbox.from_bounds(*bounds)
80 _trans = trans
81 _parent = parent
83 def inset_locator(ax, renderer):
84 bbox = _bounds
85 bb = mtransforms.TransformedBbox(bbox, _trans)
86 tr = _parent.figure.transFigure.inverted()
87 bb = mtransforms.TransformedBbox(bb, tr)
88 return bb
90 return inset_locator
93# The axes module contains all the wrappers to plotting functions.
94# All the other methods should go in the _AxesBase class.
97class Axes(_AxesBase):
98 """
99 The `Axes` contains most of the figure elements: `~.axis.Axis`,
100 `~.axis.Tick`, `~.lines.Line2D`, `~.text.Text`, `~.patches.Polygon`, etc.,
101 and sets the coordinate system.
103 The `Axes` instance supports callbacks through a callbacks attribute which
104 is a `~.cbook.CallbackRegistry` instance. The events you can connect to
105 are 'xlim_changed' and 'ylim_changed' and the callback will be called with
106 func(*ax*) where *ax* is the `Axes` instance.
108 Attributes
109 ----------
110 dataLim : `.Bbox`
111 The bounding box enclosing all data displayed in the Axes.
112 viewLim : `.Bbox`
113 The view limits in data coordinates.
115 """
116 ### Labelling, legend and texts
118 @cbook.deprecated("3.1")
119 @property
120 def aname(self):
121 return 'Axes'
123 def get_title(self, loc="center"):
124 """
125 Get an axes title.
127 Get one of the three available axes titles. The available titles
128 are positioned above the axes in the center, flush with the left
129 edge, and flush with the right edge.
131 Parameters
132 ----------
133 loc : {'center', 'left', 'right'}, str, optional
134 Which title to get, defaults to 'center'.
136 Returns
137 -------
138 title : str
139 The title text string.
141 """
142 titles = {'left': self._left_title,
143 'center': self.title,
144 'right': self._right_title}
145 title = cbook._check_getitem(titles, loc=loc.lower())
146 return title.get_text()
148 def set_title(self, label, fontdict=None, loc=None, pad=None,
149 **kwargs):
150 """
151 Set a title for the axes.
153 Set one of the three available axes titles. The available titles
154 are positioned above the axes in the center, flush with the left
155 edge, and flush with the right edge.
157 Parameters
158 ----------
159 label : str
160 Text to use for the title
162 fontdict : dict
163 A dictionary controlling the appearance of the title text,
164 the default *fontdict* is::
166 {'fontsize': rcParams['axes.titlesize'],
167 'fontweight' : rcParams['axes.titleweight'],
168 'color' : rcParams['axes.titlecolor'],
169 'verticalalignment': 'baseline',
170 'horizontalalignment': loc}
172 loc : {'center', 'left', 'right'}, str, optional
173 Which title to set.
174 If *None*, defaults to :rc:`axes.titlelocation`.
176 pad : float
177 The offset of the title from the top of the axes, in points.
178 If *None*, defaults to :rc:`axes.titlepad`.
180 Returns
181 -------
182 text : :class:`~matplotlib.text.Text`
183 The matplotlib text instance representing the title
185 Other Parameters
186 ----------------
187 **kwargs : `~matplotlib.text.Text` properties
188 Other keyword arguments are text properties, see
189 :class:`~matplotlib.text.Text` for a list of valid text
190 properties.
191 """
192 if loc is None:
193 loc = rcParams['axes.titlelocation']
195 titles = {'left': self._left_title,
196 'center': self.title,
197 'right': self._right_title}
198 title = cbook._check_getitem(titles, loc=loc.lower())
199 default = {
200 'fontsize': rcParams['axes.titlesize'],
201 'fontweight': rcParams['axes.titleweight'],
202 'verticalalignment': 'baseline',
203 'horizontalalignment': loc.lower()}
204 titlecolor = rcParams['axes.titlecolor']
205 if not cbook._str_lower_equal(titlecolor, 'auto'):
206 default["color"] = titlecolor
207 if pad is None:
208 pad = rcParams['axes.titlepad']
209 self._set_title_offset_trans(float(pad))
210 title.set_text(label)
211 title.update(default)
212 if fontdict is not None:
213 title.update(fontdict)
214 title.update(kwargs)
215 return title
217 def get_xlabel(self):
218 """
219 Get the xlabel text string.
220 """
221 label = self.xaxis.get_label()
222 return label.get_text()
224 def set_xlabel(self, xlabel, fontdict=None, labelpad=None, **kwargs):
225 """
226 Set the label for the x-axis.
228 Parameters
229 ----------
230 xlabel : str
231 The label text.
233 labelpad : scalar, optional, default: None
234 Spacing in points from the axes bounding box including ticks
235 and tick labels.
237 Other Parameters
238 ----------------
239 **kwargs : `.Text` properties
240 `.Text` properties control the appearance of the label.
242 See also
243 --------
244 text : for information on how override and the optional args work
245 """
246 if labelpad is not None:
247 self.xaxis.labelpad = labelpad
248 return self.xaxis.set_label_text(xlabel, fontdict, **kwargs)
250 def get_ylabel(self):
251 """
252 Get the ylabel text string.
253 """
254 label = self.yaxis.get_label()
255 return label.get_text()
257 def set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs):
258 """
259 Set the label for the y-axis.
261 Parameters
262 ----------
263 ylabel : str
264 The label text.
266 labelpad : scalar, optional, default: None
267 Spacing in points from the axes bounding box including ticks
268 and tick labels.
270 Other Parameters
271 ----------------
272 **kwargs : `.Text` properties
273 `.Text` properties control the appearance of the label.
275 See also
276 --------
277 text : for information on how override and the optional args work
279 """
280 if labelpad is not None:
281 self.yaxis.labelpad = labelpad
282 return self.yaxis.set_label_text(ylabel, fontdict, **kwargs)
284 def get_legend_handles_labels(self, legend_handler_map=None):
285 """
286 Return handles and labels for legend
288 ``ax.legend()`` is equivalent to ::
290 h, l = ax.get_legend_handles_labels()
291 ax.legend(h, l)
293 """
295 # pass through to legend.
296 handles, labels = mlegend._get_legend_handles_labels([self],
297 legend_handler_map)
298 return handles, labels
300 @docstring.dedent_interpd
301 def legend(self, *args, **kwargs):
302 """
303 Place a legend on the axes.
305 Call signatures::
307 legend()
308 legend(labels)
309 legend(handles, labels)
311 The call signatures correspond to three different ways how to use
312 this method.
314 **1. Automatic detection of elements to be shown in the legend**
316 The elements to be added to the legend are automatically determined,
317 when you do not pass in any extra arguments.
319 In this case, the labels are taken from the artist. You can specify
320 them either at artist creation or by calling the
321 :meth:`~.Artist.set_label` method on the artist::
323 line, = ax.plot([1, 2, 3], label='Inline label')
324 ax.legend()
326 or::
328 line, = ax.plot([1, 2, 3])
329 line.set_label('Label via method')
330 ax.legend()
332 Specific lines can be excluded from the automatic legend element
333 selection by defining a label starting with an underscore.
334 This is default for all artists, so calling `Axes.legend` without
335 any arguments and without setting the labels manually will result in
336 no legend being drawn.
339 **2. Labeling existing plot elements**
341 To make a legend for lines which already exist on the axes
342 (via plot for instance), simply call this function with an iterable
343 of strings, one for each legend item. For example::
345 ax.plot([1, 2, 3])
346 ax.legend(['A simple line'])
348 Note: This way of using is discouraged, because the relation between
349 plot elements and labels is only implicit by their order and can
350 easily be mixed up.
353 **3. Explicitly defining the elements in the legend**
355 For full control of which artists have a legend entry, it is possible
356 to pass an iterable of legend artists followed by an iterable of
357 legend labels respectively::
359 legend((line1, line2, line3), ('label1', 'label2', 'label3'))
361 Parameters
362 ----------
363 handles : sequence of `.Artist`, optional
364 A list of Artists (lines, patches) to be added to the legend.
365 Use this together with *labels*, if you need full control on what
366 is shown in the legend and the automatic mechanism described above
367 is not sufficient.
369 The length of handles and labels should be the same in this
370 case. If they are not, they are truncated to the smaller length.
372 labels : list of str, optional
373 A list of labels to show next to the artists.
374 Use this together with *handles*, if you need full control on what
375 is shown in the legend and the automatic mechanism described above
376 is not sufficient.
378 Other Parameters
379 ----------------
380 %(_legend_kw_doc)s
382 Returns
383 -------
384 legend : `~matplotlib.legend.Legend`
386 Notes
387 -----
388 Not all kinds of artist are supported by the legend command. See
389 :doc:`/tutorials/intermediate/legend_guide` for details.
391 Examples
392 --------
393 .. plot:: gallery/text_labels_and_annotations/legend.py
394 """
395 handles, labels, extra_args, kwargs = mlegend._parse_legend_args(
396 [self],
397 *args,
398 **kwargs)
399 if len(extra_args):
400 raise TypeError('legend only accepts two non-keyword arguments')
401 self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
402 self.legend_._remove_method = self._remove_legend
403 return self.legend_
405 def _remove_legend(self, legend):
406 self.legend_ = None
408 def inset_axes(self, bounds, *, transform=None, zorder=5,
409 **kwargs):
410 """
411 Add a child inset axes to this existing axes.
413 Warnings
414 --------
415 This method is experimental as of 3.0, and the API may change.
417 Parameters
418 ----------
419 bounds : [x0, y0, width, height]
420 Lower-left corner of inset axes, and its width and height.
422 transform : `.Transform`
423 Defaults to `ax.transAxes`, i.e. the units of *rect* are in
424 axes-relative coordinates.
426 zorder : number
427 Defaults to 5 (same as `.Axes.legend`). Adjust higher or lower
428 to change whether it is above or below data plotted on the
429 parent axes.
431 **kwargs
432 Other keyword arguments are passed on to the `.Axes` child axes.
434 Returns
435 -------
436 ax
437 The created `~.axes.Axes` instance.
439 Examples
440 --------
441 This example makes two inset axes, the first is in axes-relative
442 coordinates, and the second in data-coordinates::
444 fig, ax = plt.subplots()
445 ax.plot(range(10))
446 axin1 = ax.inset_axes([0.8, 0.1, 0.15, 0.15])
447 axin2 = ax.inset_axes(
448 [5, 7, 2.3, 2.3], transform=ax.transData)
450 """
451 if transform is None:
452 transform = self.transAxes
453 label = kwargs.pop('label', 'inset_axes')
455 # This puts the rectangle into figure-relative coordinates.
456 inset_locator = _make_inset_locator(bounds, transform, self)
457 bb = inset_locator(None, None)
459 inset_ax = Axes(self.figure, bb.bounds, zorder=zorder,
460 label=label, **kwargs)
462 # this locator lets the axes move if in data coordinates.
463 # it gets called in `ax.apply_aspect() (of all places)
464 inset_ax.set_axes_locator(inset_locator)
466 self.add_child_axes(inset_ax)
468 return inset_ax
470 def indicate_inset(self, bounds, inset_ax=None, *, transform=None,
471 facecolor='none', edgecolor='0.5', alpha=0.5,
472 zorder=4.99, **kwargs):
473 """
474 Add an inset indicator to the axes. This is a rectangle on the plot
475 at the position indicated by *bounds* that optionally has lines that
476 connect the rectangle to an inset axes (`.Axes.inset_axes`).
478 Warnings
479 --------
480 This method is experimental as of 3.0, and the API may change.
483 Parameters
484 ----------
485 bounds : [x0, y0, width, height]
486 Lower-left corner of rectangle to be marked, and its width
487 and height.
489 inset_ax : `.Axes`
490 An optional inset axes to draw connecting lines to. Two lines are
491 drawn connecting the indicator box to the inset axes on corners
492 chosen so as to not overlap with the indicator box.
494 transform : `.Transform`
495 Transform for the rectangle co-ordinates. Defaults to
496 `ax.transAxes`, i.e. the units of *rect* are in axes-relative
497 coordinates.
499 facecolor : Matplotlib color
500 Facecolor of the rectangle (default 'none').
502 edgecolor : Matplotlib color
503 Color of the rectangle and color of the connecting lines. Default
504 is '0.5'.
506 alpha : float
507 Transparency of the rectangle and connector lines. Default is 0.5.
509 zorder : float
510 Drawing order of the rectangle and connector lines. Default is 4.99
511 (just below the default level of inset axes).
513 **kwargs
514 Other keyword arguments are passed on to the rectangle patch.
516 Returns
517 -------
518 rectangle_patch : `.patches.Rectangle`
519 The indicator frame.
521 connector_lines : 4-tuple of `.patches.ConnectionPatch`
522 The four connector lines connecting to (lower_left, upper_left,
523 lower_right upper_right) corners of *inset_ax*. Two lines are
524 set with visibility to *False*, but the user can set the
525 visibility to True if the automatic choice is not deemed correct.
527 """
528 # to make the axes connectors work, we need to apply the aspect to
529 # the parent axes.
530 self.apply_aspect()
532 if transform is None:
533 transform = self.transData
534 label = kwargs.pop('label', 'indicate_inset')
536 x, y, width, height = bounds
537 rectangle_patch = mpatches.Rectangle(
538 (x, y), width, height,
539 facecolor=facecolor, edgecolor=edgecolor, alpha=alpha,
540 zorder=zorder, label=label, transform=transform, **kwargs)
541 self.add_patch(rectangle_patch)
543 connects = []
545 if inset_ax is not None:
546 # connect the inset_axes to the rectangle
547 for xy_inset_ax in [(0, 0), (0, 1), (1, 0), (1, 1)]:
548 # inset_ax positions are in axes coordinates
549 # The 0, 1 values define the four edges if the inset_ax
550 # lower_left, upper_left, lower_right upper_right.
551 ex, ey = xy_inset_ax
552 if self.xaxis.get_inverted():
553 ex = 1 - ex
554 if self.yaxis.get_inverted():
555 ey = 1 - ey
556 xy_data = x + ex * width, y + ey * height
557 p = mpatches.ConnectionPatch(
558 xyA=xy_inset_ax, coordsA=inset_ax.transAxes,
559 xyB=xy_data, coordsB=self.transData,
560 arrowstyle="-", zorder=zorder,
561 edgecolor=edgecolor, alpha=alpha)
562 connects.append(p)
563 self.add_patch(p)
565 # decide which two of the lines to keep visible....
566 pos = inset_ax.get_position()
567 bboxins = pos.transformed(self.figure.transFigure)
568 rectbbox = mtransforms.Bbox.from_bounds(
569 *bounds
570 ).transformed(transform)
571 x0 = rectbbox.x0 < bboxins.x0
572 x1 = rectbbox.x1 < bboxins.x1
573 y0 = rectbbox.y0 < bboxins.y0
574 y1 = rectbbox.y1 < bboxins.y1
575 connects[0].set_visible(x0 ^ y0)
576 connects[1].set_visible(x0 == y1)
577 connects[2].set_visible(x1 == y0)
578 connects[3].set_visible(x1 ^ y1)
580 return rectangle_patch, tuple(connects) if connects else None
582 def indicate_inset_zoom(self, inset_ax, **kwargs):
583 """
584 Add an inset indicator rectangle to the axes based on the axis
585 limits for an *inset_ax* and draw connectors between *inset_ax*
586 and the rectangle.
588 Warnings
589 --------
590 This method is experimental as of 3.0, and the API may change.
592 Parameters
593 ----------
594 inset_ax : `.Axes`
595 Inset axes to draw connecting lines to. Two lines are
596 drawn connecting the indicator box to the inset axes on corners
597 chosen so as to not overlap with the indicator box.
599 **kwargs
600 Other keyword arguments are passed on to `.Axes.indicate_inset`
602 Returns
603 -------
604 rectangle_patch : `.Patches.Rectangle`
605 Rectangle artist.
607 connector_lines : 4-tuple of `.Patches.ConnectionPatch`
608 Each of four connector lines coming from the rectangle drawn on
609 this axis, in the order lower left, upper left, lower right,
610 upper right.
611 Two are set with visibility to *False*, but the user can
612 set the visibility to *True* if the automatic choice is not deemed
613 correct.
614 """
616 xlim = inset_ax.get_xlim()
617 ylim = inset_ax.get_ylim()
618 rect = (xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0])
619 return self.indicate_inset(rect, inset_ax, **kwargs)
621 @docstring.dedent_interpd
622 def secondary_xaxis(self, location, *, functions=None, **kwargs):
623 """
624 Add a second x-axis to this axes.
626 For example if we want to have a second scale for the data plotted on
627 the xaxis.
629 %(_secax_docstring)s
631 Examples
632 --------
633 The main axis shows frequency, and the secondary axis shows period.
635 .. plot::
637 fig, ax = plt.subplots()
638 ax.loglog(range(1, 360, 5), range(1, 360, 5))
639 ax.set_xlabel('frequency [Hz]')
641 def invert(x):
642 return 1 / x
644 secax = ax.secondary_xaxis('top', functions=(invert, invert))
645 secax.set_xlabel('Period [s]')
646 plt.show()
647 """
648 if (location in ['top', 'bottom'] or isinstance(location, Number)):
649 secondary_ax = SecondaryAxis(self, 'x', location, functions,
650 **kwargs)
651 self.add_child_axes(secondary_ax)
652 return secondary_ax
653 else:
654 raise ValueError('secondary_xaxis location must be either '
655 'a float or "top"/"bottom"')
657 @docstring.dedent_interpd
658 def secondary_yaxis(self, location, *, functions=None, **kwargs):
659 """
660 Add a second y-axis to this axes.
662 For example if we want to have a second scale for the data plotted on
663 the yaxis.
665 %(_secax_docstring)s
667 Examples
668 --------
669 Add a secondary axes that converts from radians to degrees
671 .. plot::
673 fig, ax = plt.subplots()
674 ax.plot(range(1, 360, 5), range(1, 360, 5))
675 ax.set_ylabel('degrees')
676 secax = ax.secondary_yaxis('right', functions=(np.deg2rad,
677 np.rad2deg))
678 secax.set_ylabel('radians')
679 """
680 if location in ['left', 'right'] or isinstance(location, Number):
681 secondary_ax = SecondaryAxis(self, 'y', location,
682 functions, **kwargs)
683 self.add_child_axes(secondary_ax)
684 return secondary_ax
685 else:
686 raise ValueError('secondary_yaxis location must be either '
687 'a float or "left"/"right"')
689 @cbook._delete_parameter("3.1", "withdash")
690 def text(self, x, y, s, fontdict=None, withdash=False, **kwargs):
691 """
692 Add text to the axes.
694 Add the text *s* to the axes at location *x*, *y* in data coordinates.
696 Parameters
697 ----------
698 x, y : scalars
699 The position to place the text. By default, this is in data
700 coordinates. The coordinate system can be changed using the
701 *transform* parameter.
703 s : str
704 The text.
706 fontdict : dictionary, optional, default: None
707 A dictionary to override the default text properties. If fontdict
708 is None, the defaults are determined by your rc parameters.
710 withdash : boolean, optional, default: False
711 Creates a `~matplotlib.text.TextWithDash` instance instead of a
712 `~matplotlib.text.Text` instance.
714 Returns
715 -------
716 text : `.Text`
717 The created `.Text` instance.
719 Other Parameters
720 ----------------
721 **kwargs : `~matplotlib.text.Text` properties.
722 Other miscellaneous text parameters.
724 Examples
725 --------
726 Individual keyword arguments can be used to override any given
727 parameter::
729 >>> text(x, y, s, fontsize=12)
731 The default transform specifies that text is in data coords,
732 alternatively, you can specify text in axis coords ((0, 0) is
733 lower-left and (1, 1) is upper-right). The example below places
734 text in the center of the axes::
736 >>> text(0.5, 0.5, 'matplotlib', horizontalalignment='center',
737 ... verticalalignment='center', transform=ax.transAxes)
739 You can put a rectangular box around the text instance (e.g., to
740 set a background color) by using the keyword *bbox*. *bbox* is
741 a dictionary of `~matplotlib.patches.Rectangle`
742 properties. For example::
744 >>> text(x, y, s, bbox=dict(facecolor='red', alpha=0.5))
745 """
746 if fontdict is None:
747 fontdict = {}
749 effective_kwargs = {
750 'verticalalignment': 'baseline',
751 'horizontalalignment': 'left',
752 'transform': self.transData,
753 'clip_on': False,
754 **fontdict,
755 **kwargs,
756 }
758 # At some point if we feel confident that TextWithDash
759 # is robust as a drop-in replacement for Text and that
760 # the performance impact of the heavier-weight class
761 # isn't too significant, it may make sense to eliminate
762 # the withdash kwarg and simply delegate whether there's
763 # a dash to TextWithDash and dashlength.
765 if (withdash
766 and withdash is not cbook.deprecation._deprecated_parameter):
767 t = mtext.TextWithDash(x, y, text=s)
768 else:
769 t = mtext.Text(x, y, text=s)
770 t.update(effective_kwargs)
772 t.set_clip_path(self.patch)
773 self._add_text(t)
774 return t
776 @docstring.dedent_interpd
777 def annotate(self, s, xy, *args, **kwargs):
778 a = mtext.Annotation(s, xy, *args, **kwargs)
779 a.set_transform(mtransforms.IdentityTransform())
780 if 'clip_on' in kwargs:
781 a.set_clip_path(self.patch)
782 self._add_text(a)
783 return a
784 annotate.__doc__ = mtext.Annotation.__init__.__doc__
785 #### Lines and spans
787 @docstring.dedent_interpd
788 def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
789 """
790 Add a horizontal line across the axis.
792 Parameters
793 ----------
794 y : scalar, optional, default: 0
795 y position in data coordinates of the horizontal line.
797 xmin : scalar, optional, default: 0
798 Should be between 0 and 1, 0 being the far left of the plot, 1 the
799 far right of the plot.
801 xmax : scalar, optional, default: 1
802 Should be between 0 and 1, 0 being the far left of the plot, 1 the
803 far right of the plot.
805 Returns
806 -------
807 line : `~matplotlib.lines.Line2D`
809 Other Parameters
810 ----------------
811 **kwargs
812 Valid keyword arguments are `.Line2D` properties, with the
813 exception of 'transform':
815 %(_Line2D_docstr)s
817 See also
818 --------
819 hlines : Add horizontal lines in data coordinates.
820 axhspan : Add a horizontal span (rectangle) across the axis.
822 Examples
823 --------
824 * draw a thick red hline at 'y' = 0 that spans the xrange::
826 >>> axhline(linewidth=4, color='r')
828 * draw a default hline at 'y' = 1 that spans the xrange::
830 >>> axhline(y=1)
832 * draw a default hline at 'y' = .5 that spans the middle half of
833 the xrange::
835 >>> axhline(y=.5, xmin=0.25, xmax=0.75)
836 """
837 if "transform" in kwargs:
838 raise ValueError(
839 "'transform' is not allowed as a kwarg;"
840 + "axhline generates its own transform.")
841 ymin, ymax = self.get_ybound()
843 # We need to strip away the units for comparison with
844 # non-unitized bounds
845 self._process_unit_info(ydata=y, kwargs=kwargs)
846 yy = self.convert_yunits(y)
847 scaley = (yy < ymin) or (yy > ymax)
849 trans = self.get_yaxis_transform(which='grid')
850 l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs)
851 self.add_line(l)
852 self._request_autoscale_view(scalex=False, scaley=scaley)
853 return l
855 @docstring.dedent_interpd
856 def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
857 """
858 Add a vertical line across the axes.
860 Parameters
861 ----------
862 x : scalar, optional, default: 0
863 x position in data coordinates of the vertical line.
865 ymin : scalar, optional, default: 0
866 Should be between 0 and 1, 0 being the bottom of the plot, 1 the
867 top of the plot.
869 ymax : scalar, optional, default: 1
870 Should be between 0 and 1, 0 being the bottom of the plot, 1 the
871 top of the plot.
873 Returns
874 -------
875 line : `~matplotlib.lines.Line2D`
877 Other Parameters
878 ----------------
879 **kwargs
880 Valid keyword arguments are `.Line2D` properties, with the
881 exception of 'transform':
883 %(_Line2D_docstr)s
885 Examples
886 --------
887 * draw a thick red vline at *x* = 0 that spans the yrange::
889 >>> axvline(linewidth=4, color='r')
891 * draw a default vline at *x* = 1 that spans the yrange::
893 >>> axvline(x=1)
895 * draw a default vline at *x* = .5 that spans the middle half of
896 the yrange::
898 >>> axvline(x=.5, ymin=0.25, ymax=0.75)
900 See also
901 --------
902 vlines : Add vertical lines in data coordinates.
903 axvspan : Add a vertical span (rectangle) across the axis.
904 """
906 if "transform" in kwargs:
907 raise ValueError(
908 "'transform' is not allowed as a kwarg;"
909 + "axvline generates its own transform.")
910 xmin, xmax = self.get_xbound()
912 # We need to strip away the units for comparison with
913 # non-unitized bounds
914 self._process_unit_info(xdata=x, kwargs=kwargs)
915 xx = self.convert_xunits(x)
916 scalex = (xx < xmin) or (xx > xmax)
918 trans = self.get_xaxis_transform(which='grid')
919 l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
920 self.add_line(l)
921 self._request_autoscale_view(scalex=scalex, scaley=False)
922 return l
924 @docstring.dedent_interpd
925 def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
926 """
927 Add a horizontal span (rectangle) across the axis.
929 Draw a horizontal span (rectangle) from *ymin* to *ymax*.
930 With the default values of *xmin* = 0 and *xmax* = 1, this
931 always spans the xrange, regardless of the xlim settings, even
932 if you change them, e.g., with the :meth:`set_xlim` command.
933 That is, the horizontal extent is in axes coords: 0=left,
934 0.5=middle, 1.0=right but the *y* location is in data
935 coordinates.
937 Parameters
938 ----------
939 ymin : float
940 Lower limit of the horizontal span in data units.
941 ymax : float
942 Upper limit of the horizontal span in data units.
943 xmin : float, optional, default: 0
944 Lower limit of the vertical span in axes (relative
945 0-1) units.
946 xmax : float, optional, default: 1
947 Upper limit of the vertical span in axes (relative
948 0-1) units.
950 Returns
951 -------
952 Polygon : `~matplotlib.patches.Polygon`
954 Other Parameters
955 ----------------
956 **kwargs : `~matplotlib.patches.Polygon` properties.
958 %(Polygon)s
960 See Also
961 --------
962 axvspan : Add a vertical span across the axes.
963 """
964 trans = self.get_yaxis_transform(which='grid')
966 # process the unit information
967 self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs)
969 # first we need to strip away the units
970 xmin, xmax = self.convert_xunits([xmin, xmax])
971 ymin, ymax = self.convert_yunits([ymin, ymax])
973 verts = (xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)
974 p = mpatches.Polygon(verts, **kwargs)
975 p.set_transform(trans)
976 self.add_patch(p)
977 self._request_autoscale_view(scalex=False)
978 return p
980 def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
981 """
982 Add a vertical span (rectangle) across the axes.
984 Draw a vertical span (rectangle) from *xmin* to *xmax*. With
985 the default values of *ymin* = 0 and *ymax* = 1. This always
986 spans the yrange, regardless of the ylim settings, even if you
987 change them, e.g., with the :meth:`set_ylim` command. That is,
988 the vertical extent is in axes coords: 0=bottom, 0.5=middle,
989 1.0=top but the x location is in data coordinates.
991 Parameters
992 ----------
993 xmin : scalar
994 Number indicating the first X-axis coordinate of the vertical
995 span rectangle in data units.
996 xmax : scalar
997 Number indicating the second X-axis coordinate of the vertical
998 span rectangle in data units.
999 ymin : scalar, optional
1000 Number indicating the first Y-axis coordinate of the vertical
1001 span rectangle in relative Y-axis units (0-1). Default to 0.
1002 ymax : scalar, optional
1003 Number indicating the second Y-axis coordinate of the vertical
1004 span rectangle in relative Y-axis units (0-1). Default to 1.
1006 Returns
1007 -------
1008 rectangle : `~matplotlib.patches.Polygon`
1009 Vertical span (rectangle) from (xmin, ymin) to (xmax, ymax).
1011 Other Parameters
1012 ----------------
1013 **kwargs
1014 Optional parameters are properties of the class `.Polygon`.
1016 See Also
1017 --------
1018 axhspan : Add a horizontal span across the axes.
1020 Examples
1021 --------
1022 Draw a vertical, green, translucent rectangle from x = 1.25 to
1023 x = 1.55 that spans the yrange of the axes.
1025 >>> axvspan(1.25, 1.55, facecolor='g', alpha=0.5)
1027 """
1028 trans = self.get_xaxis_transform(which='grid')
1030 # process the unit information
1031 self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs)
1033 # first we need to strip away the units
1034 xmin, xmax = self.convert_xunits([xmin, xmax])
1035 ymin, ymax = self.convert_yunits([ymin, ymax])
1037 verts = [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)]
1038 p = mpatches.Polygon(verts, **kwargs)
1039 p.set_transform(trans)
1040 self.add_patch(p)
1041 self._request_autoscale_view(scaley=False)
1042 return p
1044 @_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"],
1045 label_namer="y")
1046 def hlines(self, y, xmin, xmax, colors='k', linestyles='solid',
1047 label='', **kwargs):
1048 """
1049 Plot horizontal lines at each *y* from *xmin* to *xmax*.
1051 Parameters
1052 ----------
1053 y : scalar or sequence of scalar
1054 y-indexes where to plot the lines.
1056 xmin, xmax : scalar or 1D array-like
1057 Respective beginning and end of each line. If scalars are
1058 provided, all lines will have same length.
1060 colors : array-like of colors, optional, default: 'k'
1062 linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, optional
1064 label : str, optional, default: ''
1066 Returns
1067 -------
1068 lines : `~matplotlib.collections.LineCollection`
1070 Other Parameters
1071 ----------------
1072 **kwargs : `~matplotlib.collections.LineCollection` properties.
1074 See also
1075 --------
1076 vlines : vertical lines
1077 axhline: horizontal line across the axes
1078 """
1080 # We do the conversion first since not all unitized data is uniform
1081 # process the unit information
1082 self._process_unit_info([xmin, xmax], y, kwargs=kwargs)
1083 y = self.convert_yunits(y)
1084 xmin = self.convert_xunits(xmin)
1085 xmax = self.convert_xunits(xmax)
1087 if not np.iterable(y):
1088 y = [y]
1089 if not np.iterable(xmin):
1090 xmin = [xmin]
1091 if not np.iterable(xmax):
1092 xmax = [xmax]
1094 y, xmin, xmax = cbook.delete_masked_points(y, xmin, xmax)
1096 y = np.ravel(y)
1097 xmin = np.resize(xmin, y.shape)
1098 xmax = np.resize(xmax, y.shape)
1100 verts = [((thisxmin, thisy), (thisxmax, thisy))
1101 for thisxmin, thisxmax, thisy in zip(xmin, xmax, y)]
1102 lines = mcoll.LineCollection(verts, colors=colors,
1103 linestyles=linestyles, label=label)
1104 self.add_collection(lines, autolim=False)
1105 lines.update(kwargs)
1107 if len(y) > 0:
1108 minx = min(xmin.min(), xmax.min())
1109 maxx = max(xmin.max(), xmax.max())
1110 miny = y.min()
1111 maxy = y.max()
1113 corners = (minx, miny), (maxx, maxy)
1115 self.update_datalim(corners)
1116 self._request_autoscale_view()
1118 return lines
1120 @_preprocess_data(replace_names=["x", "ymin", "ymax", "colors"],
1121 label_namer="x")
1122 def vlines(self, x, ymin, ymax, colors='k', linestyles='solid',
1123 label='', **kwargs):
1124 """
1125 Plot vertical lines.
1127 Plot vertical lines at each *x* from *ymin* to *ymax*.
1129 Parameters
1130 ----------
1131 x : scalar or 1D array-like
1132 x-indexes where to plot the lines.
1134 ymin, ymax : scalar or 1D array-like
1135 Respective beginning and end of each line. If scalars are
1136 provided, all lines will have same length.
1138 colors : array-like of colors, optional, default: 'k'
1140 linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, optional
1142 label : str, optional, default: ''
1144 Returns
1145 -------
1146 lines : `~matplotlib.collections.LineCollection`
1148 Other Parameters
1149 ----------------
1150 **kwargs : `~matplotlib.collections.LineCollection` properties.
1152 See also
1153 --------
1154 hlines : horizontal lines
1155 axvline: vertical line across the axes
1156 """
1158 self._process_unit_info(xdata=x, ydata=[ymin, ymax], kwargs=kwargs)
1160 # We do the conversion first since not all unitized data is uniform
1161 x = self.convert_xunits(x)
1162 ymin = self.convert_yunits(ymin)
1163 ymax = self.convert_yunits(ymax)
1165 if not np.iterable(x):
1166 x = [x]
1167 if not np.iterable(ymin):
1168 ymin = [ymin]
1169 if not np.iterable(ymax):
1170 ymax = [ymax]
1172 x, ymin, ymax = cbook.delete_masked_points(x, ymin, ymax)
1174 x = np.ravel(x)
1175 ymin = np.resize(ymin, x.shape)
1176 ymax = np.resize(ymax, x.shape)
1178 verts = [((thisx, thisymin), (thisx, thisymax))
1179 for thisx, thisymin, thisymax in zip(x, ymin, ymax)]
1180 lines = mcoll.LineCollection(verts, colors=colors,
1181 linestyles=linestyles, label=label)
1182 self.add_collection(lines, autolim=False)
1183 lines.update(kwargs)
1185 if len(x) > 0:
1186 minx = x.min()
1187 maxx = x.max()
1188 miny = min(ymin.min(), ymax.min())
1189 maxy = max(ymin.max(), ymax.max())
1191 corners = (minx, miny), (maxx, maxy)
1192 self.update_datalim(corners)
1193 self._request_autoscale_view()
1195 return lines
1197 @_preprocess_data(replace_names=["positions", "lineoffsets",
1198 "linelengths", "linewidths",
1199 "colors", "linestyles"])
1200 @docstring.dedent_interpd
1201 def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
1202 linelengths=1, linewidths=None, colors=None,
1203 linestyles='solid', **kwargs):
1204 """
1205 Plot identical parallel lines at the given positions.
1207 *positions* should be a 1D or 2D array-like object, with each row
1208 corresponding to a row or column of lines.
1210 This type of plot is commonly used in neuroscience for representing
1211 neural events, where it is usually called a spike raster, dot raster,
1212 or raster plot.
1214 However, it is useful in any situation where you wish to show the
1215 timing or position of multiple sets of discrete events, such as the
1216 arrival times of people to a business on each day of the month or the
1217 date of hurricanes each year of the last century.
1219 Parameters
1220 ----------
1221 positions : 1D or 2D array-like object
1222 Each value is an event. If *positions* is a 2D array-like, each
1223 row corresponds to a row or a column of lines (depending on the
1224 *orientation* parameter).
1226 orientation : {'horizontal', 'vertical'}, optional
1227 Controls the direction of the event collections:
1229 - 'horizontal' : the lines are arranged horizontally in rows,
1230 and are vertical.
1231 - 'vertical' : the lines are arranged vertically in columns,
1232 and are horizontal.
1234 lineoffsets : scalar or sequence of scalars, optional, default: 1
1235 The offset of the center of the lines from the origin, in the
1236 direction orthogonal to *orientation*.
1238 linelengths : scalar or sequence of scalars, optional, default: 1
1239 The total height of the lines (i.e. the lines stretches from
1240 ``lineoffset - linelength/2`` to ``lineoffset + linelength/2``).
1242 linewidths : scalar, scalar sequence or None, optional, default: None
1243 The line width(s) of the event lines, in points. If it is None,
1244 defaults to its rcParams setting.
1246 colors : color, sequence of colors or None, optional, default: None
1247 The color(s) of the event lines. If it is None, defaults to its
1248 rcParams setting.
1250 linestyles : str or tuple or a sequence of such values, optional
1251 Default is 'solid'. Valid strings are ['solid', 'dashed',
1252 'dashdot', 'dotted', '-', '--', '-.', ':']. Dash tuples
1253 should be of the form::
1255 (offset, onoffseq),
1257 where *onoffseq* is an even length tuple of on and off ink
1258 in points.
1260 **kwargs : optional
1261 Other keyword arguments are line collection properties. See
1262 :class:`~matplotlib.collections.LineCollection` for a list of
1263 the valid properties.
1265 Returns
1266 -------
1267 list : A list of :class:`~.collections.EventCollection` objects.
1268 Contains the :class:`~.collections.EventCollection` that
1269 were added.
1271 Notes
1272 -----
1273 For *linelengths*, *linewidths*, *colors*, and *linestyles*, if only
1274 a single value is given, that value is applied to all lines. If an
1275 array-like is given, it must have the same length as *positions*, and
1276 each value will be applied to the corresponding row of the array.
1278 Examples
1279 --------
1280 .. plot:: gallery/lines_bars_and_markers/eventplot_demo.py
1281 """
1282 self._process_unit_info(xdata=positions,
1283 ydata=[lineoffsets, linelengths],
1284 kwargs=kwargs)
1286 # We do the conversion first since not all unitized data is uniform
1287 positions = self.convert_xunits(positions)
1288 lineoffsets = self.convert_yunits(lineoffsets)
1289 linelengths = self.convert_yunits(linelengths)
1291 if not np.iterable(positions):
1292 positions = [positions]
1293 elif any(np.iterable(position) for position in positions):
1294 positions = [np.asanyarray(position) for position in positions]
1295 else:
1296 positions = [np.asanyarray(positions)]
1298 if len(positions) == 0:
1299 return []
1301 # prevent 'singular' keys from **kwargs dict from overriding the effect
1302 # of 'plural' keyword arguments (e.g. 'color' overriding 'colors')
1303 colors = cbook.local_over_kwdict(colors, kwargs, 'color')
1304 linewidths = cbook.local_over_kwdict(linewidths, kwargs, 'linewidth')
1305 linestyles = cbook.local_over_kwdict(linestyles, kwargs, 'linestyle')
1307 if not np.iterable(lineoffsets):
1308 lineoffsets = [lineoffsets]
1309 if not np.iterable(linelengths):
1310 linelengths = [linelengths]
1311 if not np.iterable(linewidths):
1312 linewidths = [linewidths]
1313 if not np.iterable(colors):
1314 colors = [colors]
1315 if hasattr(linestyles, 'lower') or not np.iterable(linestyles):
1316 linestyles = [linestyles]
1318 lineoffsets = np.asarray(lineoffsets)
1319 linelengths = np.asarray(linelengths)
1320 linewidths = np.asarray(linewidths)
1322 if len(lineoffsets) == 0:
1323 lineoffsets = [None]
1324 if len(linelengths) == 0:
1325 linelengths = [None]
1326 if len(linewidths) == 0:
1327 lineoffsets = [None]
1328 if len(linewidths) == 0:
1329 lineoffsets = [None]
1330 if len(colors) == 0:
1331 colors = [None]
1332 try:
1333 # Early conversion of the colors into RGBA values to take care
1334 # of cases like colors='0.5' or colors='C1'. (Issue #8193)
1335 colors = mcolors.to_rgba_array(colors)
1336 except ValueError:
1337 # Will fail if any element of *colors* is None. But as long
1338 # as len(colors) == 1 or len(positions), the rest of the
1339 # code should process *colors* properly.
1340 pass
1342 if len(lineoffsets) == 1 and len(positions) != 1:
1343 lineoffsets = np.tile(lineoffsets, len(positions))
1344 lineoffsets[0] = 0
1345 lineoffsets = np.cumsum(lineoffsets)
1346 if len(linelengths) == 1:
1347 linelengths = np.tile(linelengths, len(positions))
1348 if len(linewidths) == 1:
1349 linewidths = np.tile(linewidths, len(positions))
1350 if len(colors) == 1:
1351 colors = list(colors)
1352 colors = colors * len(positions)
1353 if len(linestyles) == 1:
1354 linestyles = [linestyles] * len(positions)
1356 if len(lineoffsets) != len(positions):
1357 raise ValueError('lineoffsets and positions are unequal sized '
1358 'sequences')
1359 if len(linelengths) != len(positions):
1360 raise ValueError('linelengths and positions are unequal sized '
1361 'sequences')
1362 if len(linewidths) != len(positions):
1363 raise ValueError('linewidths and positions are unequal sized '
1364 'sequences')
1365 if len(colors) != len(positions):
1366 raise ValueError('colors and positions are unequal sized '
1367 'sequences')
1368 if len(linestyles) != len(positions):
1369 raise ValueError('linestyles and positions are unequal sized '
1370 'sequences')
1372 colls = []
1373 for position, lineoffset, linelength, linewidth, color, linestyle in \
1374 zip(positions, lineoffsets, linelengths, linewidths,
1375 colors, linestyles):
1376 coll = mcoll.EventCollection(position,
1377 orientation=orientation,
1378 lineoffset=lineoffset,
1379 linelength=linelength,
1380 linewidth=linewidth,
1381 color=color,
1382 linestyle=linestyle)
1383 self.add_collection(coll, autolim=False)
1384 coll.update(kwargs)
1385 colls.append(coll)
1387 if len(positions) > 0:
1388 # try to get min/max
1389 min_max = [(np.min(_p), np.max(_p)) for _p in positions
1390 if len(_p) > 0]
1391 # if we have any non-empty positions, try to autoscale
1392 if len(min_max) > 0:
1393 mins, maxes = zip(*min_max)
1394 minpos = np.min(mins)
1395 maxpos = np.max(maxes)
1397 minline = (lineoffsets - linelengths).min()
1398 maxline = (lineoffsets + linelengths).max()
1400 if (orientation is not None and
1401 orientation.lower() == "vertical"):
1402 corners = (minline, minpos), (maxline, maxpos)
1403 else: # "horizontal", None or "none" (see EventCollection)
1404 corners = (minpos, minline), (maxpos, maxline)
1405 self.update_datalim(corners)
1406 self._request_autoscale_view()
1408 return colls
1410 #### Basic plotting
1412 # Uses a custom implementation of data-kwarg handling in
1413 # _process_plot_var_args.
1414 @docstring.dedent_interpd
1415 def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs):
1416 """
1417 Plot y versus x as lines and/or markers.
1419 Call signatures::
1421 plot([x], y, [fmt], *, data=None, **kwargs)
1422 plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
1424 The coordinates of the points or line nodes are given by *x*, *y*.
1426 The optional parameter *fmt* is a convenient way for defining basic
1427 formatting like color, marker and linestyle. It's a shortcut string
1428 notation described in the *Notes* section below.
1430 >>> plot(x, y) # plot x and y using default line style and color
1431 >>> plot(x, y, 'bo') # plot x and y using blue circle markers
1432 >>> plot(y) # plot y using x as index array 0..N-1
1433 >>> plot(y, 'r+') # ditto, but with red plusses
1435 You can use `.Line2D` properties as keyword arguments for more
1436 control on the appearance. Line properties and *fmt* can be mixed.
1437 The following two calls yield identical results:
1439 >>> plot(x, y, 'go--', linewidth=2, markersize=12)
1440 >>> plot(x, y, color='green', marker='o', linestyle='dashed',
1441 ... linewidth=2, markersize=12)
1443 When conflicting with *fmt*, keyword arguments take precedence.
1446 **Plotting labelled data**
1448 There's a convenient way for plotting objects with labelled data (i.e.
1449 data that can be accessed by index ``obj['y']``). Instead of giving
1450 the data in *x* and *y*, you can provide the object in the *data*
1451 parameter and just give the labels for *x* and *y*::
1453 >>> plot('xlabel', 'ylabel', data=obj)
1455 All indexable objects are supported. This could e.g. be a `dict`, a
1456 `pandas.DataFame` or a structured numpy array.
1459 **Plotting multiple sets of data**
1461 There are various ways to plot multiple sets of data.
1463 - The most straight forward way is just to call `plot` multiple times.
1464 Example:
1466 >>> plot(x1, y1, 'bo')
1467 >>> plot(x2, y2, 'go')
1469 - Alternatively, if your data is already a 2d array, you can pass it
1470 directly to *x*, *y*. A separate data set will be drawn for every
1471 column.
1473 Example: an array ``a`` where the first column represents the *x*
1474 values and the other columns are the *y* columns::
1476 >>> plot(a[0], a[1:])
1478 - The third way is to specify multiple sets of *[x]*, *y*, *[fmt]*
1479 groups::
1481 >>> plot(x1, y1, 'g^', x2, y2, 'g-')
1483 In this case, any additional keyword argument applies to all
1484 datasets. Also this syntax cannot be combined with the *data*
1485 parameter.
1487 By default, each line is assigned a different style specified by a
1488 'style cycle'. The *fmt* and line property parameters are only
1489 necessary if you want explicit deviations from these defaults.
1490 Alternatively, you can also change the style cycle using
1491 :rc:`axes.prop_cycle`.
1494 Parameters
1495 ----------
1496 x, y : array-like or scalar
1497 The horizontal / vertical coordinates of the data points.
1498 *x* values are optional and default to `range(len(y))`.
1500 Commonly, these parameters are 1D arrays.
1502 They can also be scalars, or two-dimensional (in that case, the
1503 columns represent separate data sets).
1505 These arguments cannot be passed as keywords.
1507 fmt : str, optional
1508 A format string, e.g. 'ro' for red circles. See the *Notes*
1509 section for a full description of the format strings.
1511 Format strings are just an abbreviation for quickly setting
1512 basic line properties. All of these and more can also be
1513 controlled by keyword arguments.
1515 This argument cannot be passed as keyword.
1517 data : indexable object, optional
1518 An object with labelled data. If given, provide the label names to
1519 plot in *x* and *y*.
1521 .. note::
1522 Technically there's a slight ambiguity in calls where the
1523 second label is a valid *fmt*. `plot('n', 'o', data=obj)`
1524 could be `plt(x, y)` or `plt(y, fmt)`. In such cases,
1525 the former interpretation is chosen, but a warning is issued.
1526 You may suppress the warning by adding an empty format string
1527 `plot('n', 'o', '', data=obj)`.
1529 Other Parameters
1530 ----------------
1531 scalex, scaley : bool, optional, default: True
1532 These parameters determined if the view limits are adapted to
1533 the data limits. The values are passed on to `autoscale_view`.
1535 **kwargs : `.Line2D` properties, optional
1536 *kwargs* are used to specify properties like a line label (for
1537 auto legends), linewidth, antialiasing, marker face color.
1538 Example::
1540 >>> plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2)
1541 >>> plot([1, 2, 3], [1, 4, 9], 'rs', label='line 2')
1543 If you make multiple lines with one plot command, the kwargs
1544 apply to all those lines.
1546 Here is a list of available `.Line2D` properties:
1548 %(_Line2D_docstr)s
1550 Returns
1551 -------
1552 lines
1553 A list of `.Line2D` objects representing the plotted data.
1555 See Also
1556 --------
1557 scatter : XY scatter plot with markers of varying size and/or color (
1558 sometimes also called bubble chart).
1560 Notes
1561 -----
1562 **Format Strings**
1564 A format string consists of a part for color, marker and line::
1566 fmt = '[marker][line][color]'
1568 Each of them is optional. If not provided, the value from the style
1569 cycle is used. Exception: If ``line`` is given, but no ``marker``,
1570 the data will be a line without markers.
1572 Other combinations such as ``[color][marker][line]`` are also
1573 supported, but note that their parsing may be ambiguous.
1575 **Markers**
1577 ============= ===============================
1578 character description
1579 ============= ===============================
1580 ``'.'`` point marker
1581 ``','`` pixel marker
1582 ``'o'`` circle marker
1583 ``'v'`` triangle_down marker
1584 ``'^'`` triangle_up marker
1585 ``'<'`` triangle_left marker
1586 ``'>'`` triangle_right marker
1587 ``'1'`` tri_down marker
1588 ``'2'`` tri_up marker
1589 ``'3'`` tri_left marker
1590 ``'4'`` tri_right marker
1591 ``'s'`` square marker
1592 ``'p'`` pentagon marker
1593 ``'*'`` star marker
1594 ``'h'`` hexagon1 marker
1595 ``'H'`` hexagon2 marker
1596 ``'+'`` plus marker
1597 ``'x'`` x marker
1598 ``'D'`` diamond marker
1599 ``'d'`` thin_diamond marker
1600 ``'|'`` vline marker
1601 ``'_'`` hline marker
1602 ============= ===============================
1604 **Line Styles**
1606 ============= ===============================
1607 character description
1608 ============= ===============================
1609 ``'-'`` solid line style
1610 ``'--'`` dashed line style
1611 ``'-.'`` dash-dot line style
1612 ``':'`` dotted line style
1613 ============= ===============================
1615 Example format strings::
1617 'b' # blue markers with default shape
1618 'or' # red circles
1619 '-g' # green solid line
1620 '--' # dashed line with default color
1621 '^k:' # black triangle_up markers connected by a dotted line
1623 **Colors**
1625 The supported color abbreviations are the single letter codes
1627 ============= ===============================
1628 character color
1629 ============= ===============================
1630 ``'b'`` blue
1631 ``'g'`` green
1632 ``'r'`` red
1633 ``'c'`` cyan
1634 ``'m'`` magenta
1635 ``'y'`` yellow
1636 ``'k'`` black
1637 ``'w'`` white
1638 ============= ===============================
1640 and the ``'CN'`` colors that index into the default property cycle.
1642 If the color is the only part of the format string, you can
1643 additionally use any `matplotlib.colors` spec, e.g. full names
1644 (``'green'``) or hex strings (``'#008000'``).
1645 """
1646 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
1647 lines = [*self._get_lines(*args, data=data, **kwargs)]
1648 for line in lines:
1649 self.add_line(line)
1650 self._request_autoscale_view(scalex=scalex, scaley=scaley)
1651 return lines
1653 @_preprocess_data(replace_names=["x", "y"], label_namer="y")
1654 @docstring.dedent_interpd
1655 def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False,
1656 **kwargs):
1657 """
1658 Plot data that contains dates.
1660 Similar to `.plot`, this plots *y* vs. *x* as lines or markers.
1661 However, the axis labels are formatted as dates depending on *xdate*
1662 and *ydate*.
1664 Parameters
1665 ----------
1666 x, y : array-like
1667 The coordinates of the data points. If *xdate* or *ydate* is
1668 *True*, the respective values *x* or *y* are interpreted as
1669 :ref:`Matplotlib dates <date-format>`.
1671 fmt : str, optional
1672 The plot format string. For details, see the corresponding
1673 parameter in `.plot`.
1675 tz : timezone string or `tzinfo` or None
1676 The time zone to use in labeling dates. If *None*, defaults to
1677 :rc:`timezone`.
1679 xdate : bool, optional, default: True
1680 If *True*, the *x*-axis will be interpreted as Matplotlib dates.
1682 ydate : bool, optional, default: False
1683 If *True*, the *y*-axis will be interpreted as Matplotlib dates.
1686 Returns
1687 -------
1688 lines
1689 A list of `.Line2D` objects representing the plotted data.
1692 Other Parameters
1693 ----------------
1694 **kwargs
1695 Keyword arguments control the `.Line2D` properties:
1697 %(_Line2D_docstr)s
1699 See Also
1700 --------
1701 matplotlib.dates : Helper functions on dates.
1702 matplotlib.dates.date2num : Convert dates to num.
1703 matplotlib.dates.num2date : Convert num to dates.
1704 matplotlib.dates.drange : Create an equally spaced sequence of dates.
1706 Notes
1707 -----
1708 If you are using custom date tickers and formatters, it may be
1709 necessary to set the formatters/locators after the call to
1710 `.plot_date`. `.plot_date` will set the default tick locator to
1711 `.AutoDateLocator` (if the tick locator is not already set to a
1712 `.DateLocator` instance) and the default tick formatter to
1713 `.AutoDateFormatter` (if the tick formatter is not already set to a
1714 `.DateFormatter` instance).
1715 """
1716 if xdate:
1717 self.xaxis_date(tz)
1718 if ydate:
1719 self.yaxis_date(tz)
1721 ret = self.plot(x, y, fmt, **kwargs)
1723 self._request_autoscale_view()
1725 return ret
1727 # @_preprocess_data() # let 'plot' do the unpacking..
1728 @docstring.dedent_interpd
1729 def loglog(self, *args, **kwargs):
1730 """
1731 Make a plot with log scaling on both the x and y axis.
1733 Call signatures::
1735 loglog([x], y, [fmt], data=None, **kwargs)
1736 loglog([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
1738 This is just a thin wrapper around `.plot` which additionally changes
1739 both the x-axis and the y-axis to log scaling. All of the concepts and
1740 parameters of plot can be used here as well.
1742 The additional parameters *basex/y*, *subsx/y* and *nonposx/y* control
1743 the x/y-axis properties. They are just forwarded to `.Axes.set_xscale`
1744 and `.Axes.set_yscale`.
1746 Parameters
1747 ----------
1748 basex, basey : scalar, optional, default 10
1749 Base of the x/y logarithm.
1751 subsx, subsy : sequence, optional
1752 The location of the minor x/y ticks. If *None*, reasonable
1753 locations are automatically chosen depending on the number of
1754 decades in the plot.
1755 See `.Axes.set_xscale` / `.Axes.set_yscale` for details.
1757 nonposx, nonposy : {'mask', 'clip'}, optional, default 'mask'
1758 Non-positive values in x or y can be masked as invalid, or clipped
1759 to a very small positive number.
1761 Returns
1762 -------
1763 lines
1764 A list of `.Line2D` objects representing the plotted data.
1766 Other Parameters
1767 ----------------
1768 **kwargs
1769 All parameters supported by `.plot`.
1770 """
1771 dx = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx']
1772 if k in kwargs}
1773 dy = {k: kwargs.pop(k) for k in ['basey', 'subsy', 'nonposy']
1774 if k in kwargs}
1776 self.set_xscale('log', **dx)
1777 self.set_yscale('log', **dy)
1779 l = self.plot(*args, **kwargs)
1780 return l
1782 # @_preprocess_data() # let 'plot' do the unpacking..
1783 @docstring.dedent_interpd
1784 def semilogx(self, *args, **kwargs):
1785 """
1786 Make a plot with log scaling on the x axis.
1788 Call signatures::
1790 semilogx([x], y, [fmt], data=None, **kwargs)
1791 semilogx([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
1793 This is just a thin wrapper around `.plot` which additionally changes
1794 the x-axis to log scaling. All of the concepts and parameters of plot
1795 can be used here as well.
1797 The additional parameters *basex*, *subsx* and *nonposx* control the
1798 x-axis properties. They are just forwarded to `.Axes.set_xscale`.
1800 Parameters
1801 ----------
1802 basex : scalar, optional, default 10
1803 Base of the x logarithm.
1805 subsx : array-like, optional
1806 The location of the minor xticks. If *None*, reasonable locations
1807 are automatically chosen depending on the number of decades in the
1808 plot. See `.Axes.set_xscale` for details.
1810 nonposx : {'mask', 'clip'}, optional, default 'mask'
1811 Non-positive values in x can be masked as invalid, or clipped to a
1812 very small positive number.
1814 Returns
1815 -------
1816 lines
1817 A list of `.Line2D` objects representing the plotted data.
1819 Other Parameters
1820 ----------------
1821 **kwargs
1822 All parameters supported by `.plot`.
1823 """
1824 d = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx']
1825 if k in kwargs}
1827 self.set_xscale('log', **d)
1828 l = self.plot(*args, **kwargs)
1829 return l
1831 # @_preprocess_data() # let 'plot' do the unpacking..
1832 @docstring.dedent_interpd
1833 def semilogy(self, *args, **kwargs):
1834 """
1835 Make a plot with log scaling on the y axis.
1837 Call signatures::
1839 semilogy([x], y, [fmt], data=None, **kwargs)
1840 semilogy([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
1842 This is just a thin wrapper around `.plot` which additionally changes
1843 the y-axis to log scaling. All of the concepts and parameters of plot
1844 can be used here as well.
1846 The additional parameters *basey*, *subsy* and *nonposy* control the
1847 y-axis properties. They are just forwarded to `.Axes.set_yscale`.
1849 Parameters
1850 ----------
1851 basey : scalar, optional, default 10
1852 Base of the y logarithm.
1854 subsy : array-like, optional
1855 The location of the minor yticks. If *None*, reasonable locations
1856 are automatically chosen depending on the number of decades in the
1857 plot. See `.Axes.set_yscale` for details.
1859 nonposy : {'mask', 'clip'}, optional, default 'mask'
1860 Non-positive values in y can be masked as invalid, or clipped to a
1861 very small positive number.
1863 Returns
1864 -------
1865 lines
1866 A list of `.Line2D` objects representing the plotted data.
1868 Other Parameters
1869 ----------------
1870 **kwargs
1871 All parameters supported by `.plot`.
1872 """
1873 d = {k: kwargs.pop(k) for k in ['basey', 'subsy', 'nonposy']
1874 if k in kwargs}
1875 self.set_yscale('log', **d)
1876 l = self.plot(*args, **kwargs)
1878 return l
1880 @_preprocess_data(replace_names=["x"], label_namer="x")
1881 def acorr(self, x, **kwargs):
1882 """
1883 Plot the autocorrelation of *x*.
1885 Parameters
1886 ----------
1887 x : array-like
1889 detrend : callable, optional, default: `mlab.detrend_none`
1890 *x* is detrended by the *detrend* callable. This must be a
1891 function ``x = detrend(x)`` accepting and returning an
1892 `numpy.array`. Default is no normalization.
1894 normed : bool, optional, default: True
1895 If ``True``, input vectors are normalised to unit length.
1897 usevlines : bool, optional, default: True
1898 Determines the plot style.
1900 If ``True``, vertical lines are plotted from 0 to the acorr value
1901 using `Axes.vlines`. Additionally, a horizontal line is plotted
1902 at y=0 using `Axes.axhline`.
1904 If ``False``, markers are plotted at the acorr values using
1905 `Axes.plot`.
1907 maxlags : int, optional, default: 10
1908 Number of lags to show. If ``None``, will return all
1909 ``2 * len(x) - 1`` lags.
1911 Returns
1912 -------
1913 lags : array (length ``2*maxlags+1``)
1914 The lag vector.
1915 c : array (length ``2*maxlags+1``)
1916 The auto correlation vector.
1917 line : `.LineCollection` or `.Line2D`
1918 `.Artist` added to the axes of the correlation:
1920 - `.LineCollection` if *usevlines* is True.
1921 - `.Line2D` if *usevlines* is False.
1922 b : `.Line2D` or None
1923 Horizontal line at 0 if *usevlines* is True
1924 None *usevlines* is False.
1926 Other Parameters
1927 ----------------
1928 linestyle : `.Line2D` property, optional
1929 The linestyle for plotting the data points.
1930 Only used if *usevlines* is ``False``.
1932 marker : str, optional, default: 'o'
1933 The marker for plotting the data points.
1934 Only used if *usevlines* is ``False``.
1936 Notes
1937 -----
1938 The cross correlation is performed with :func:`numpy.correlate` with
1939 ``mode = "full"``.
1940 """
1941 return self.xcorr(x, x, **kwargs)
1943 @_preprocess_data(replace_names=["x", "y"], label_namer="y")
1944 def xcorr(self, x, y, normed=True, detrend=mlab.detrend_none,
1945 usevlines=True, maxlags=10, **kwargs):
1946 r"""
1947 Plot the cross correlation between *x* and *y*.
1949 The correlation with lag k is defined as
1950 :math:`\sum_n x[n+k] \cdot y^*[n]`, where :math:`y^*` is the complex
1951 conjugate of :math:`y`.
1953 Parameters
1954 ----------
1955 x : array-like of length n
1957 y : array-like of length n
1959 detrend : callable, optional, default: `mlab.detrend_none`
1960 *x* and *y* are detrended by the *detrend* callable. This must be a
1961 function ``x = detrend(x)`` accepting and returning an
1962 `numpy.array`. Default is no normalization.
1964 normed : bool, optional, default: True
1965 If ``True``, input vectors are normalised to unit length.
1967 usevlines : bool, optional, default: True
1968 Determines the plot style.
1970 If ``True``, vertical lines are plotted from 0 to the xcorr value
1971 using `Axes.vlines`. Additionally, a horizontal line is plotted
1972 at y=0 using `Axes.axhline`.
1974 If ``False``, markers are plotted at the xcorr values using
1975 `Axes.plot`.
1977 maxlags : int, optional, default: 10
1978 Number of lags to show. If None, will return all ``2 * len(x) - 1``
1979 lags.
1981 Returns
1982 -------
1983 lags : array (length ``2*maxlags+1``)
1984 The lag vector.
1985 c : array (length ``2*maxlags+1``)
1986 The auto correlation vector.
1987 line : `.LineCollection` or `.Line2D`
1988 `.Artist` added to the axes of the correlation:
1990 - `.LineCollection` if *usevlines* is True.
1991 - `.Line2D` if *usevlines* is False.
1992 b : `.Line2D` or None
1993 Horizontal line at 0 if *usevlines* is True
1994 None *usevlines* is False.
1996 Other Parameters
1997 ----------------
1998 linestyle : `.Line2D` property, optional
1999 The linestyle for plotting the data points.
2000 Only used if *usevlines* is ``False``.
2002 marker : str, optional, default: 'o'
2003 The marker for plotting the data points.
2004 Only used if *usevlines* is ``False``.
2006 Notes
2007 -----
2008 The cross correlation is performed with :func:`numpy.correlate` with
2009 ``mode = "full"``.
2010 """
2011 Nx = len(x)
2012 if Nx != len(y):
2013 raise ValueError('x and y must be equal length')
2015 x = detrend(np.asarray(x))
2016 y = detrend(np.asarray(y))
2018 correls = np.correlate(x, y, mode="full")
2020 if normed:
2021 correls /= np.sqrt(np.dot(x, x) * np.dot(y, y))
2023 if maxlags is None:
2024 maxlags = Nx - 1
2026 if maxlags >= Nx or maxlags < 1:
2027 raise ValueError('maxlags must be None or strictly '
2028 'positive < %d' % Nx)
2030 lags = np.arange(-maxlags, maxlags + 1)
2031 correls = correls[Nx - 1 - maxlags:Nx + maxlags]
2033 if usevlines:
2034 a = self.vlines(lags, [0], correls, **kwargs)
2035 # Make label empty so only vertical lines get a legend entry
2036 kwargs.pop('label', '')
2037 b = self.axhline(**kwargs)
2038 else:
2039 kwargs.setdefault('marker', 'o')
2040 kwargs.setdefault('linestyle', 'None')
2041 a, = self.plot(lags, correls, **kwargs)
2042 b = None
2043 return lags, correls, a, b
2045 #### Specialized plotting
2047 # @_preprocess_data() # let 'plot' do the unpacking..
2048 def step(self, x, y, *args, where='pre', data=None, **kwargs):
2049 """
2050 Make a step plot.
2052 Call signatures::
2054 step(x, y, [fmt], *, data=None, where='pre', **kwargs)
2055 step(x, y, [fmt], x2, y2, [fmt2], ..., *, where='pre', **kwargs)
2057 This is just a thin wrapper around `.plot` which changes some
2058 formatting options. Most of the concepts and parameters of plot can be
2059 used here as well.
2061 Parameters
2062 ----------
2063 x : array-like
2064 1-D sequence of x positions. It is assumed, but not checked, that
2065 it is uniformly increasing.
2067 y : array-like
2068 1-D sequence of y levels.
2070 fmt : str, optional
2071 A format string, e.g. 'g' for a green line. See `.plot` for a more
2072 detailed description.
2074 Note: While full format strings are accepted, it is recommended to
2075 only specify the color. Line styles are currently ignored (use
2076 the keyword argument *linestyle* instead). Markers are accepted
2077 and plotted on the given positions, however, this is a rarely
2078 needed feature for step plots.
2080 data : indexable object, optional
2081 An object with labelled data. If given, provide the label names to
2082 plot in *x* and *y*.
2084 where : {'pre', 'post', 'mid'}, optional, default 'pre'
2085 Define where the steps should be placed:
2087 - 'pre': The y value is continued constantly to the left from
2088 every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
2089 value ``y[i]``.
2090 - 'post': The y value is continued constantly to the right from
2091 every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
2092 value ``y[i]``.
2093 - 'mid': Steps occur half-way between the *x* positions.
2095 Returns
2096 -------
2097 lines
2098 A list of `.Line2D` objects representing the plotted data.
2100 Other Parameters
2101 ----------------
2102 **kwargs
2103 Additional parameters are the same as those for `.plot`.
2105 Notes
2106 -----
2107 .. [notes section required to get data note injection right]
2108 """
2109 cbook._check_in_list(('pre', 'post', 'mid'), where=where)
2110 kwargs['drawstyle'] = 'steps-' + where
2111 return self.plot(x, y, *args, data=data, **kwargs)
2113 @staticmethod
2114 def _convert_dx(dx, x0, xconv, convert):
2115 """
2116 Small helper to do logic of width conversion flexibly.
2118 *dx* and *x0* have units, but *xconv* has already been converted
2119 to unitless (and is an ndarray). This allows the *dx* to have units
2120 that are different from *x0*, but are still accepted by the
2121 ``__add__`` operator of *x0*.
2122 """
2124 # x should be an array...
2125 assert type(xconv) is np.ndarray
2127 if xconv.size == 0:
2128 # xconv has already been converted, but maybe empty...
2129 return convert(dx)
2131 try:
2132 # attempt to add the width to x0; this works for
2133 # datetime+timedelta, for instance
2135 # only use the first element of x and x0. This saves
2136 # having to be sure addition works across the whole
2137 # vector. This is particularly an issue if
2138 # x0 and dx are lists so x0 + dx just concatenates the lists.
2139 # We can't just cast x0 and dx to numpy arrays because that
2140 # removes the units from unit packages like `pint` that
2141 # wrap numpy arrays.
2142 try:
2143 x0 = cbook.safe_first_element(x0)
2144 except (TypeError, IndexError, KeyError):
2145 x0 = x0
2147 try:
2148 x = cbook.safe_first_element(xconv)
2149 except (TypeError, IndexError, KeyError):
2150 x = xconv
2152 delist = False
2153 if not np.iterable(dx):
2154 dx = [dx]
2155 delist = True
2156 dx = [convert(x0 + ddx) - x for ddx in dx]
2157 if delist:
2158 dx = dx[0]
2159 except (ValueError, TypeError, AttributeError):
2160 # if the above fails (for any reason) just fallback to what
2161 # we do by default and convert dx by itself.
2162 dx = convert(dx)
2163 return dx
2165 @_preprocess_data()
2166 @docstring.dedent_interpd
2167 def bar(self, x, height, width=0.8, bottom=None, *, align="center",
2168 **kwargs):
2169 r"""
2170 Make a bar plot.
2172 The bars are positioned at *x* with the given *align*\ment. Their
2173 dimensions are given by *width* and *height*. The vertical baseline
2174 is *bottom* (default 0).
2176 Each of *x*, *height*, *width*, and *bottom* may either be a scalar
2177 applying to all bars, or it may be a sequence of length N providing a
2178 separate value for each bar.
2180 Parameters
2181 ----------
2182 x : sequence of scalars
2183 The x coordinates of the bars. See also *align* for the
2184 alignment of the bars to the coordinates.
2186 height : scalar or sequence of scalars
2187 The height(s) of the bars.
2189 width : scalar or array-like, optional
2190 The width(s) of the bars (default: 0.8).
2192 bottom : scalar or array-like, optional
2193 The y coordinate(s) of the bars bases (default: 0).
2195 align : {'center', 'edge'}, optional, default: 'center'
2196 Alignment of the bars to the *x* coordinates:
2198 - 'center': Center the base on the *x* positions.
2199 - 'edge': Align the left edges of the bars with the *x* positions.
2201 To align the bars on the right edge pass a negative *width* and
2202 ``align='edge'``.
2204 Returns
2205 -------
2206 container : `.BarContainer`
2207 Container with all the bars and optionally errorbars.
2209 Other Parameters
2210 ----------------
2211 color : scalar or array-like, optional
2212 The colors of the bar faces.
2214 edgecolor : scalar or array-like, optional
2215 The colors of the bar edges.
2217 linewidth : scalar or array-like, optional
2218 Width of the bar edge(s). If 0, don't draw edges.
2220 tick_label : str or array-like, optional
2221 The tick labels of the bars.
2222 Default: None (Use default numeric labels.)
2224 xerr, yerr : scalar or array-like of shape(N,) or shape(2, N), optional
2225 If not *None*, add horizontal / vertical errorbars to the bar tips.
2226 The values are +/- sizes relative to the data:
2228 - scalar: symmetric +/- values for all bars
2229 - shape(N,): symmetric +/- values for each bar
2230 - shape(2, N): Separate - and + values for each bar. First row
2231 contains the lower errors, the second row contains the upper
2232 errors.
2233 - *None*: No errorbar. (Default)
2235 See :doc:`/gallery/statistics/errorbar_features`
2236 for an example on the usage of ``xerr`` and ``yerr``.
2238 ecolor : scalar or array-like, optional, default: 'black'
2239 The line color of the errorbars.
2241 capsize : scalar, optional
2242 The length of the error bar caps in points.
2243 Default: None, which will take the value from
2244 :rc:`errorbar.capsize`.
2246 error_kw : dict, optional
2247 Dictionary of kwargs to be passed to the `~.Axes.errorbar`
2248 method. Values of *ecolor* or *capsize* defined here take
2249 precedence over the independent kwargs.
2251 log : bool, optional, default: False
2252 If *True*, set the y-axis to be log scale.
2254 orientation : {'vertical', 'horizontal'}, optional
2255 *This is for internal use only.* Please use `barh` for
2256 horizontal bar plots. Default: 'vertical'.
2258 See also
2259 --------
2260 barh: Plot a horizontal bar plot.
2262 Notes
2263 -----
2264 The optional arguments *color*, *edgecolor*, *linewidth*,
2265 *xerr*, and *yerr* can be either scalars or sequences of
2266 length equal to the number of bars. This enables you to use
2267 bar as the basis for stacked bar charts, or candlestick plots.
2268 Detail: *xerr* and *yerr* are passed directly to
2269 :meth:`errorbar`, so they can also have shape 2xN for
2270 independent specification of lower and upper errors.
2272 Other optional kwargs:
2274 %(Rectangle)s
2275 """
2276 kwargs = cbook.normalize_kwargs(kwargs, mpatches.Patch)
2277 color = kwargs.pop('color', None)
2278 if color is None:
2279 color = self._get_patches_for_fill.get_next_color()
2280 edgecolor = kwargs.pop('edgecolor', None)
2281 linewidth = kwargs.pop('linewidth', None)
2283 # Because xerr and yerr will be passed to errorbar, most dimension
2284 # checking and processing will be left to the errorbar method.
2285 xerr = kwargs.pop('xerr', None)
2286 yerr = kwargs.pop('yerr', None)
2287 error_kw = kwargs.pop('error_kw', {})
2288 ezorder = error_kw.pop('zorder', None)
2289 if ezorder is None:
2290 ezorder = kwargs.get('zorder', None)
2291 if ezorder is not None:
2292 # If using the bar zorder, increment slightly to make sure
2293 # errorbars are drawn on top of bars
2294 ezorder += 0.01
2295 error_kw.setdefault('zorder', ezorder)
2296 ecolor = kwargs.pop('ecolor', 'k')
2297 capsize = kwargs.pop('capsize', rcParams["errorbar.capsize"])
2298 error_kw.setdefault('ecolor', ecolor)
2299 error_kw.setdefault('capsize', capsize)
2301 orientation = kwargs.pop('orientation', 'vertical')
2302 cbook._check_in_list(['vertical', 'horizontal'],
2303 orientation=orientation)
2304 log = kwargs.pop('log', False)
2305 label = kwargs.pop('label', '')
2306 tick_labels = kwargs.pop('tick_label', None)
2308 y = bottom # Matches barh call signature.
2309 if orientation == 'vertical':
2310 if y is None:
2311 y = 0
2312 elif orientation == 'horizontal':
2313 if x is None:
2314 x = 0
2316 if orientation == 'vertical':
2317 self._process_unit_info(xdata=x, ydata=height, kwargs=kwargs)
2318 if log:
2319 self.set_yscale('log', nonposy='clip')
2320 elif orientation == 'horizontal':
2321 self._process_unit_info(xdata=width, ydata=y, kwargs=kwargs)
2322 if log:
2323 self.set_xscale('log', nonposx='clip')
2325 # lets do some conversions now since some types cannot be
2326 # subtracted uniformly
2327 if self.xaxis is not None:
2328 x0 = x
2329 x = np.asarray(self.convert_xunits(x))
2330 width = self._convert_dx(width, x0, x, self.convert_xunits)
2331 if xerr is not None:
2332 xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)
2333 if self.yaxis is not None:
2334 y0 = y
2335 y = np.asarray(self.convert_yunits(y))
2336 height = self._convert_dx(height, y0, y, self.convert_yunits)
2337 if yerr is not None:
2338 yerr = self._convert_dx(yerr, y0, y, self.convert_yunits)
2340 x, height, width, y, linewidth = np.broadcast_arrays(
2341 # Make args iterable too.
2342 np.atleast_1d(x), height, width, y, linewidth)
2344 # Now that units have been converted, set the tick locations.
2345 if orientation == 'vertical':
2346 tick_label_axis = self.xaxis
2347 tick_label_position = x
2348 elif orientation == 'horizontal':
2349 tick_label_axis = self.yaxis
2350 tick_label_position = y
2352 linewidth = itertools.cycle(np.atleast_1d(linewidth))
2353 color = itertools.chain(itertools.cycle(mcolors.to_rgba_array(color)),
2354 # Fallback if color == "none".
2355 itertools.repeat('none'))
2356 if edgecolor is None:
2357 edgecolor = itertools.repeat(None)
2358 else:
2359 edgecolor = itertools.chain(
2360 itertools.cycle(mcolors.to_rgba_array(edgecolor)),
2361 # Fallback if edgecolor == "none".
2362 itertools.repeat('none'))
2364 # We will now resolve the alignment and really have
2365 # left, bottom, width, height vectors
2366 cbook._check_in_list(['center', 'edge'], align=align)
2367 if align == 'center':
2368 if orientation == 'vertical':
2369 try:
2370 left = x - width / 2
2371 except TypeError as e:
2372 raise TypeError(f'the dtypes of parameters x ({x.dtype}) '
2373 f'and width ({width.dtype}) '
2374 f'are incompatible') from e
2375 bottom = y
2376 elif orientation == 'horizontal':
2377 try:
2378 bottom = y - height / 2
2379 except TypeError as e:
2380 raise TypeError(f'the dtypes of parameters y ({y.dtype}) '
2381 f'and height ({height.dtype}) '
2382 f'are incompatible') from e
2383 left = x
2384 elif align == 'edge':
2385 left = x
2386 bottom = y
2388 patches = []
2389 args = zip(left, bottom, width, height, color, edgecolor, linewidth)
2390 for l, b, w, h, c, e, lw in args:
2391 r = mpatches.Rectangle(
2392 xy=(l, b), width=w, height=h,
2393 facecolor=c,
2394 edgecolor=e,
2395 linewidth=lw,
2396 label='_nolegend_',
2397 )
2398 r.update(kwargs)
2399 r.get_path()._interpolation_steps = 100
2400 if orientation == 'vertical':
2401 r.sticky_edges.y.append(b)
2402 elif orientation == 'horizontal':
2403 r.sticky_edges.x.append(l)
2404 self.add_patch(r)
2405 patches.append(r)
2407 if xerr is not None or yerr is not None:
2408 if orientation == 'vertical':
2409 # using list comps rather than arrays to preserve unit info
2410 ex = [l + 0.5 * w for l, w in zip(left, width)]
2411 ey = [b + h for b, h in zip(bottom, height)]
2413 elif orientation == 'horizontal':
2414 # using list comps rather than arrays to preserve unit info
2415 ex = [l + w for l, w in zip(left, width)]
2416 ey = [b + 0.5 * h for b, h in zip(bottom, height)]
2418 error_kw.setdefault("label", '_nolegend_')
2420 errorbar = self.errorbar(ex, ey,
2421 yerr=yerr, xerr=xerr,
2422 fmt='none', **error_kw)
2423 else:
2424 errorbar = None
2426 self._request_autoscale_view()
2428 bar_container = BarContainer(patches, errorbar, label=label)
2429 self.add_container(bar_container)
2431 if tick_labels is not None:
2432 tick_labels = np.broadcast_to(tick_labels, len(patches))
2433 tick_label_axis.set_ticks(tick_label_position)
2434 tick_label_axis.set_ticklabels(tick_labels)
2436 return bar_container
2438 @docstring.dedent_interpd
2439 def barh(self, y, width, height=0.8, left=None, *, align="center",
2440 **kwargs):
2441 r"""
2442 Make a horizontal bar plot.
2444 The bars are positioned at *y* with the given *align*\ment. Their
2445 dimensions are given by *width* and *height*. The horizontal baseline
2446 is *left* (default 0).
2448 Each of *y*, *width*, *height*, and *left* may either be a scalar
2449 applying to all bars, or it may be a sequence of length N providing a
2450 separate value for each bar.
2452 Parameters
2453 ----------
2454 y : scalar or array-like
2455 The y coordinates of the bars. See also *align* for the
2456 alignment of the bars to the coordinates.
2458 width : scalar or array-like
2459 The width(s) of the bars.
2461 height : sequence of scalars, optional, default: 0.8
2462 The heights of the bars.
2464 left : sequence of scalars
2465 The x coordinates of the left sides of the bars (default: 0).
2467 align : {'center', 'edge'}, optional, default: 'center'
2468 Alignment of the base to the *y* coordinates*:
2470 - 'center': Center the bars on the *y* positions.
2471 - 'edge': Align the bottom edges of the bars with the *y*
2472 positions.
2474 To align the bars on the top edge pass a negative *height* and
2475 ``align='edge'``.
2477 Returns
2478 -------
2479 container : `.BarContainer`
2480 Container with all the bars and optionally errorbars.
2482 Other Parameters
2483 ----------------
2484 color : scalar or array-like, optional
2485 The colors of the bar faces.
2487 edgecolor : scalar or array-like, optional
2488 The colors of the bar edges.
2490 linewidth : scalar or array-like, optional
2491 Width of the bar edge(s). If 0, don't draw edges.
2493 tick_label : str or array-like, optional
2494 The tick labels of the bars.
2495 Default: None (Use default numeric labels.)
2497 xerr, yerr : scalar or array-like of shape(N,) or shape(2, N), optional
2498 If not ``None``, add horizontal / vertical errorbars to the
2499 bar tips. The values are +/- sizes relative to the data:
2501 - scalar: symmetric +/- values for all bars
2502 - shape(N,): symmetric +/- values for each bar
2503 - shape(2, N): Separate - and + values for each bar. First row
2504 contains the lower errors, the second row contains the upper
2505 errors.
2506 - *None*: No errorbar. (default)
2508 See :doc:`/gallery/statistics/errorbar_features`
2509 for an example on the usage of ``xerr`` and ``yerr``.
2511 ecolor : scalar or array-like, optional, default: 'black'
2512 The line color of the errorbars.
2514 capsize : scalar, optional
2515 The length of the error bar caps in points.
2516 Default: None, which will take the value from
2517 :rc:`errorbar.capsize`.
2519 error_kw : dict, optional
2520 Dictionary of kwargs to be passed to the `~.Axes.errorbar`
2521 method. Values of *ecolor* or *capsize* defined here take
2522 precedence over the independent kwargs.
2524 log : bool, optional, default: False
2525 If ``True``, set the x-axis to be log scale.
2527 See also
2528 --------
2529 bar: Plot a vertical bar plot.
2531 Notes
2532 -----
2533 The optional arguments *color*, *edgecolor*, *linewidth*,
2534 *xerr*, and *yerr* can be either scalars or sequences of
2535 length equal to the number of bars. This enables you to use
2536 bar as the basis for stacked bar charts, or candlestick plots.
2537 Detail: *xerr* and *yerr* are passed directly to
2538 :meth:`errorbar`, so they can also have shape 2xN for
2539 independent specification of lower and upper errors.
2541 Other optional kwargs:
2543 %(Rectangle)s
2544 """
2545 kwargs.setdefault('orientation', 'horizontal')
2546 patches = self.bar(x=left, height=height, width=width, bottom=y,
2547 align=align, **kwargs)
2548 return patches
2550 @_preprocess_data()
2551 @docstring.dedent_interpd
2552 def broken_barh(self, xranges, yrange, **kwargs):
2553 """
2554 Plot a horizontal sequence of rectangles.
2556 A rectangle is drawn for each element of *xranges*. All rectangles
2557 have the same vertical position and size defined by *yrange*.
2559 This is a convenience function for instantiating a
2560 `.BrokenBarHCollection`, adding it to the axes and autoscaling the
2561 view.
2563 Parameters
2564 ----------
2565 xranges : sequence of tuples (*xmin*, *xwidth*)
2566 The x-positions and extends of the rectangles. For each tuple
2567 (*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* +
2568 *xwidth*.
2569 yrange : (*ymin*, *yheight*)
2570 The y-position and extend for all the rectangles.
2572 Other Parameters
2573 ----------------
2574 **kwargs : :class:`.BrokenBarHCollection` properties
2576 Each *kwarg* can be either a single argument applying to all
2577 rectangles, e.g.::
2579 facecolors='black'
2581 or a sequence of arguments over which is cycled, e.g.::
2583 facecolors=('black', 'blue')
2585 would create interleaving black and blue rectangles.
2587 Supported keywords:
2589 %(BrokenBarHCollection)s
2591 Returns
2592 -------
2593 collection : A :class:`~.collections.BrokenBarHCollection`
2594 """
2595 # process the unit information
2596 if len(xranges):
2597 xdata = cbook.safe_first_element(xranges)
2598 else:
2599 xdata = None
2600 if len(yrange):
2601 ydata = cbook.safe_first_element(yrange)
2602 else:
2603 ydata = None
2604 self._process_unit_info(xdata=xdata,
2605 ydata=ydata,
2606 kwargs=kwargs)
2607 xranges_conv = []
2608 for xr in xranges:
2609 if len(xr) != 2:
2610 raise ValueError('each range in xrange must be a sequence '
2611 'with two elements (i.e. an Nx2 array)')
2612 # convert the absolute values, not the x and dx...
2613 x_conv = np.asarray(self.convert_xunits(xr[0]))
2614 x1 = self._convert_dx(xr[1], xr[0], x_conv, self.convert_xunits)
2615 xranges_conv.append((x_conv, x1))
2617 yrange_conv = self.convert_yunits(yrange)
2619 col = mcoll.BrokenBarHCollection(xranges_conv, yrange_conv, **kwargs)
2620 self.add_collection(col, autolim=True)
2621 self._request_autoscale_view()
2623 return col
2625 @_preprocess_data()
2626 def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
2627 label=None, use_line_collection=False):
2628 """
2629 Create a stem plot.
2631 A stem plot plots vertical lines at each *x* location from the baseline
2632 to *y*, and places a marker there.
2634 Call signature::
2636 stem([x,] y, linefmt=None, markerfmt=None, basefmt=None)
2638 The x-positions are optional. The formats may be provided either as
2639 positional or as keyword-arguments.
2641 Parameters
2642 ----------
2643 x : array-like, optional
2644 The x-positions of the stems. Default: (0, 1, ..., len(y) - 1).
2646 y : array-like
2647 The y-values of the stem heads.
2649 linefmt : str, optional
2650 A string defining the properties of the vertical lines. Usually,
2651 this will be a color or a color and a linestyle:
2653 ========= =============
2654 Character Line Style
2655 ========= =============
2656 ``'-'`` solid line
2657 ``'--'`` dashed line
2658 ``'-.'`` dash-dot line
2659 ``':'`` dotted line
2660 ========= =============
2662 Default: 'C0-', i.e. solid line with the first color of the color
2663 cycle.
2665 Note: While it is technically possible to specify valid formats
2666 other than color or color and linestyle (e.g. 'rx' or '-.'), this
2667 is beyond the intention of the method and will most likely not
2668 result in a reasonable reasonable plot.
2670 markerfmt : str, optional
2671 A string defining the properties of the markers at the stem heads.
2672 Default: 'C0o', i.e. filled circles with the first color of the
2673 color cycle.
2675 basefmt : str, optional
2676 A format string defining the properties of the baseline.
2678 Default: 'C3-' ('C2-' in classic mode).
2680 bottom : float, optional, default: 0
2681 The y-position of the baseline.
2683 label : str, optional, default: None
2684 The label to use for the stems in legends.
2686 use_line_collection : bool, optional, default: False
2687 If ``True``, store and plot the stem lines as a
2688 `~.collections.LineCollection` instead of individual lines. This
2689 significantly increases performance, and will become the default
2690 option in Matplotlib 3.3. If ``False``, defaults to the old
2691 behavior of using a list of `.Line2D` objects.
2694 Returns
2695 -------
2696 container : :class:`~matplotlib.container.StemContainer`
2697 The container may be treated like a tuple
2698 (*markerline*, *stemlines*, *baseline*)
2701 Notes
2702 -----
2703 .. seealso::
2704 The MATLAB function
2705 `stem <http://www.mathworks.com/help/techdoc/ref/stem.html>`_
2706 which inspired this method.
2708 """
2709 if not 1 <= len(args) <= 5:
2710 raise TypeError('stem expected between 1 and 5 positional '
2711 'arguments, got {}'.format(args))
2713 if len(args) == 1:
2714 y, = args
2715 x = np.arange(len(y))
2716 args = ()
2717 else:
2718 x, y, *args = args
2720 self._process_unit_info(xdata=x, ydata=y)
2721 x = self.convert_xunits(x)
2722 y = self.convert_yunits(y)
2724 # defaults for formats
2725 if linefmt is None:
2726 try:
2727 # fallback to positional argument
2728 linefmt = args[0]
2729 except IndexError:
2730 linecolor = 'C0'
2731 linemarker = 'None'
2732 linestyle = '-'
2733 else:
2734 linestyle, linemarker, linecolor = \
2735 _process_plot_format(linefmt)
2736 else:
2737 linestyle, linemarker, linecolor = _process_plot_format(linefmt)
2739 if markerfmt is None:
2740 try:
2741 # fallback to positional argument
2742 markerfmt = args[1]
2743 except IndexError:
2744 markercolor = 'C0'
2745 markermarker = 'o'
2746 markerstyle = 'None'
2747 else:
2748 markerstyle, markermarker, markercolor = \
2749 _process_plot_format(markerfmt)
2750 else:
2751 markerstyle, markermarker, markercolor = \
2752 _process_plot_format(markerfmt)
2754 if basefmt is None:
2755 try:
2756 # fallback to positional argument
2757 basefmt = args[2]
2758 except IndexError:
2759 if rcParams['_internal.classic_mode']:
2760 basecolor = 'C2'
2761 else:
2762 basecolor = 'C3'
2763 basemarker = 'None'
2764 basestyle = '-'
2765 else:
2766 basestyle, basemarker, basecolor = \
2767 _process_plot_format(basefmt)
2768 else:
2769 basestyle, basemarker, basecolor = _process_plot_format(basefmt)
2771 # New behaviour in 3.1 is to use a LineCollection for the stemlines
2772 if use_line_collection:
2773 stemlines = [((xi, bottom), (xi, yi)) for xi, yi in zip(x, y)]
2774 if linestyle is None:
2775 linestyle = rcParams['lines.linestyle']
2776 stemlines = mcoll.LineCollection(stemlines, linestyles=linestyle,
2777 colors=linecolor,
2778 label='_nolegend_')
2779 self.add_collection(stemlines)
2780 # Old behaviour is to plot each of the lines individually
2781 else:
2782 cbook._warn_external(
2783 'In Matplotlib 3.3 individual lines on a stem plot will be '
2784 'added as a LineCollection instead of individual lines. '
2785 'This significantly improves the performance of a stem plot. '
2786 'To remove this warning and switch to the new behaviour, '
2787 'set the "use_line_collection" keyword argument to True.')
2788 stemlines = []
2789 for xi, yi in zip(x, y):
2790 l, = self.plot([xi, xi], [bottom, yi],
2791 color=linecolor, linestyle=linestyle,
2792 marker=linemarker, label="_nolegend_")
2793 stemlines.append(l)
2795 markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle,
2796 marker=markermarker, label="_nolegend_")
2798 baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom],
2799 color=basecolor, linestyle=basestyle,
2800 marker=basemarker, label="_nolegend_")
2802 stem_container = StemContainer((markerline, stemlines, baseline),
2803 label=label)
2804 self.add_container(stem_container)
2805 return stem_container
2807 @_preprocess_data(replace_names=["x", "explode", "labels", "colors"])
2808 def pie(self, x, explode=None, labels=None, colors=None,
2809 autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
2810 startangle=None, radius=None, counterclock=True,
2811 wedgeprops=None, textprops=None, center=(0, 0),
2812 frame=False, rotatelabels=False):
2813 """
2814 Plot a pie chart.
2816 Make a pie chart of array *x*. The fractional area of each wedge is
2817 given by ``x/sum(x)``. If ``sum(x) < 1``, then the values of *x* give
2818 the fractional area directly and the array will not be normalized. The
2819 resulting pie will have an empty wedge of size ``1 - sum(x)``.
2821 The wedges are plotted counterclockwise, by default starting from the
2822 x-axis.
2824 Parameters
2825 ----------
2826 x : array-like
2827 The wedge sizes.
2829 explode : array-like, optional, default: None
2830 If not *None*, is a ``len(x)`` array which specifies the fraction
2831 of the radius with which to offset each wedge.
2833 labels : list, optional, default: None
2834 A sequence of strings providing the labels for each wedge
2836 colors : array-like, optional, default: None
2837 A sequence of matplotlib color args through which the pie chart
2838 will cycle. If *None*, will use the colors in the currently
2839 active cycle.
2841 autopct : None (default), str, or function, optional
2842 If not *None*, is a string or function used to label the wedges
2843 with their numeric value. The label will be placed inside the
2844 wedge. If it is a format string, the label will be ``fmt%pct``.
2845 If it is a function, it will be called.
2847 pctdistance : float, optional, default: 0.6
2848 The ratio between the center of each pie slice and the start of
2849 the text generated by *autopct*. Ignored if *autopct* is *None*.
2851 shadow : bool, optional, default: False
2852 Draw a shadow beneath the pie.
2854 labeldistance : float or None, optional, default: 1.1
2855 The radial distance at which the pie labels are drawn.
2856 If set to ``None``, label are not drawn, but are stored for use in
2857 ``legend()``
2859 startangle : float, optional, default: None
2860 If not *None*, rotates the start of the pie chart by *angle*
2861 degrees counterclockwise from the x-axis.
2863 radius : float, optional, default: None
2864 The radius of the pie, if *radius* is *None* it will be set to 1.
2866 counterclock : bool, optional, default: True
2867 Specify fractions direction, clockwise or counterclockwise.
2869 wedgeprops : dict, optional, default: None
2870 Dict of arguments passed to the wedge objects making the pie.
2871 For example, you can pass in ``wedgeprops = {'linewidth': 3}``
2872 to set the width of the wedge border lines equal to 3.
2873 For more details, look at the doc/arguments of the wedge object.
2874 By default ``clip_on=False``.
2876 textprops : dict, optional, default: None
2877 Dict of arguments to pass to the text objects.
2879 center : list of float, optional, default: (0, 0)
2880 Center position of the chart. Takes value (0, 0) or is a sequence
2881 of 2 scalars.
2883 frame : bool, optional, default: False
2884 Plot axes frame with the chart if true.
2886 rotatelabels : bool, optional, default: False
2887 Rotate each label to the angle of the corresponding slice if true.
2889 Returns
2890 -------
2891 patches : list
2892 A sequence of :class:`matplotlib.patches.Wedge` instances
2894 texts : list
2895 A list of the label :class:`matplotlib.text.Text` instances.
2897 autotexts : list
2898 A list of :class:`~matplotlib.text.Text` instances for the numeric
2899 labels. This will only be returned if the parameter *autopct* is
2900 not *None*.
2902 Notes
2903 -----
2904 The pie chart will probably look best if the figure and axes are
2905 square, or the Axes aspect is equal.
2906 This method sets the aspect ratio of the axis to "equal".
2907 The axes aspect ratio can be controlled with `Axes.set_aspect`.
2908 """
2909 self.set_aspect('equal')
2910 # The use of float32 is "historical", but can't be changed without
2911 # regenerating the test baselines.
2912 x = np.asarray(x, np.float32)
2913 if x.ndim != 1 and x.squeeze().ndim <= 1:
2914 cbook.warn_deprecated(
2915 "3.1", message="Non-1D inputs to pie() are currently "
2916 "squeeze()d, but this behavior is deprecated since %(since)s "
2917 "and will be removed %(removal)s; pass a 1D array instead.")
2918 x = np.atleast_1d(x.squeeze())
2920 sx = x.sum()
2921 if sx > 1:
2922 x = x / sx
2924 if labels is None:
2925 labels = [''] * len(x)
2926 if explode is None:
2927 explode = [0] * len(x)
2928 if len(x) != len(labels):
2929 raise ValueError("'label' must be of length 'x'")
2930 if len(x) != len(explode):
2931 raise ValueError("'explode' must be of length 'x'")
2932 if colors is None:
2933 get_next_color = self._get_patches_for_fill.get_next_color
2934 else:
2935 color_cycle = itertools.cycle(colors)
2937 def get_next_color():
2938 return next(color_cycle)
2940 if radius is None:
2941 radius = 1
2943 # Starting theta1 is the start fraction of the circle
2944 if startangle is None:
2945 theta1 = 0
2946 else:
2947 theta1 = startangle / 360.0
2949 # set default values in wedge_prop
2950 if wedgeprops is None:
2951 wedgeprops = {}
2952 wedgeprops.setdefault('clip_on', False)
2954 if textprops is None:
2955 textprops = {}
2956 textprops.setdefault('clip_on', False)
2958 texts = []
2959 slices = []
2960 autotexts = []
2962 for frac, label, expl in zip(x, labels, explode):
2963 x, y = center
2964 theta2 = (theta1 + frac) if counterclock else (theta1 - frac)
2965 thetam = 2 * np.pi * 0.5 * (theta1 + theta2)
2966 x += expl * math.cos(thetam)
2967 y += expl * math.sin(thetam)
2969 w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2),
2970 360. * max(theta1, theta2),
2971 facecolor=get_next_color(),
2972 **wedgeprops)
2973 slices.append(w)
2974 self.add_patch(w)
2975 w.set_label(label)
2977 if shadow:
2978 # make sure to add a shadow after the call to
2979 # add_patch so the figure and transform props will be
2980 # set
2981 shad = mpatches.Shadow(w, -0.02, -0.02)
2982 shad.set_zorder(0.9 * w.get_zorder())
2983 shad.set_label('_nolegend_')
2984 self.add_patch(shad)
2986 if labeldistance is not None:
2987 xt = x + labeldistance * radius * math.cos(thetam)
2988 yt = y + labeldistance * radius * math.sin(thetam)
2989 label_alignment_h = 'left' if xt > 0 else 'right'
2990 label_alignment_v = 'center'
2991 label_rotation = 'horizontal'
2992 if rotatelabels:
2993 label_alignment_v = 'bottom' if yt > 0 else 'top'
2994 label_rotation = (np.rad2deg(thetam)
2995 + (0 if xt > 0 else 180))
2996 props = dict(horizontalalignment=label_alignment_h,
2997 verticalalignment=label_alignment_v,
2998 rotation=label_rotation,
2999 size=rcParams['xtick.labelsize'])
3000 props.update(textprops)
3002 t = self.text(xt, yt, label, **props)
3004 texts.append(t)
3006 if autopct is not None:
3007 xt = x + pctdistance * radius * math.cos(thetam)
3008 yt = y + pctdistance * radius * math.sin(thetam)
3009 if isinstance(autopct, str):
3010 s = autopct % (100. * frac)
3011 elif callable(autopct):
3012 s = autopct(100. * frac)
3013 else:
3014 raise TypeError(
3015 'autopct must be callable or a format string')
3017 props = dict(horizontalalignment='center',
3018 verticalalignment='center')
3019 props.update(textprops)
3020 t = self.text(xt, yt, s, **props)
3022 autotexts.append(t)
3024 theta1 = theta2
3026 if not frame:
3027 self.set_frame_on(False)
3029 self.set_xlim((-1.25 + center[0],
3030 1.25 + center[0]))
3031 self.set_ylim((-1.25 + center[1],
3032 1.25 + center[1]))
3033 self.set_xticks([])
3034 self.set_yticks([])
3036 if autopct is None:
3037 return slices, texts
3038 else:
3039 return slices, texts, autotexts
3041 @_preprocess_data(replace_names=["x", "y", "xerr", "yerr"],
3042 label_namer="y")
3043 @docstring.dedent_interpd
3044 def errorbar(self, x, y, yerr=None, xerr=None,
3045 fmt='', ecolor=None, elinewidth=None, capsize=None,
3046 barsabove=False, lolims=False, uplims=False,
3047 xlolims=False, xuplims=False, errorevery=1, capthick=None,
3048 **kwargs):
3049 """
3050 Plot y versus x as lines and/or markers with attached errorbars.
3052 *x*, *y* define the data locations, *xerr*, *yerr* define the errorbar
3053 sizes. By default, this draws the data markers/lines as well the
3054 errorbars. Use fmt='none' to draw errorbars without any data markers.
3056 Parameters
3057 ----------
3058 x, y : scalar or array-like
3059 The data positions.
3061 xerr, yerr : scalar or array-like, shape(N,) or shape(2, N), optional
3062 The errorbar sizes:
3064 - scalar: Symmetric +/- values for all data points.
3065 - shape(N,): Symmetric +/-values for each data point.
3066 - shape(2, N): Separate - and + values for each bar. First row
3067 contains the lower errors, the second row contains the upper
3068 errors.
3069 - *None*: No errorbar.
3071 Note that all error arrays should have *positive* values.
3073 See :doc:`/gallery/statistics/errorbar_features`
3074 for an example on the usage of ``xerr`` and ``yerr``.
3076 fmt : str, optional, default: ''
3077 The format for the data points / data lines. See `.plot` for
3078 details.
3080 Use 'none' (case insensitive) to plot errorbars without any data
3081 markers.
3083 ecolor : color, optional, default: None
3084 The color of the errorbar lines. If None, use the color of the
3085 line connecting the markers.
3087 elinewidth : scalar, optional, default: None
3088 The linewidth of the errorbar lines. If None, the linewidth of
3089 the current style is used.
3091 capsize : scalar, optional, default: None
3092 The length of the error bar caps in points. If None, it will take
3093 the value from :rc:`errorbar.capsize`.
3095 capthick : scalar, optional, default: None
3096 An alias to the keyword argument *markeredgewidth* (a.k.a. *mew*).
3097 This setting is a more sensible name for the property that
3098 controls the thickness of the error bar cap in points. For
3099 backwards compatibility, if *mew* or *markeredgewidth* are given,
3100 then they will over-ride *capthick*. This may change in future
3101 releases.
3103 barsabove : bool, optional, default: False
3104 If True, will plot the errorbars above the plot
3105 symbols. Default is below.
3107 lolims, uplims, xlolims, xuplims : bool, optional, default: False
3108 These arguments can be used to indicate that a value gives only
3109 upper/lower limits. In that case a caret symbol is used to
3110 indicate this. *lims*-arguments may be of the same type as *xerr*
3111 and *yerr*. To use limits with inverted axes, :meth:`set_xlim`
3112 or :meth:`set_ylim` must be called before :meth:`errorbar`.
3114 errorevery : int or (int, int), optional, default: 1
3115 draws error bars on a subset of the data. *errorevery* =N draws
3116 error bars on the points (x[::N], y[::N]).
3117 *errorevery* =(start, N) draws error bars on the points
3118 (x[start::N], y[start::N]). e.g. errorevery=(6, 3)
3119 adds error bars to the data at (x[6], x[9], x[12], x[15], ...).
3120 Used to avoid overlapping error bars when two series share x-axis
3121 values.
3123 Returns
3124 -------
3125 container : :class:`~.container.ErrorbarContainer`
3126 The container contains:
3128 - plotline: `.Line2D` instance of x, y plot markers and/or line.
3129 - caplines: A tuple of `.Line2D` instances of the error bar caps.
3130 - barlinecols: A tuple of
3131 :class:`~matplotlib.collections.LineCollection` with the
3132 horizontal and vertical error ranges.
3134 Other Parameters
3135 ----------------
3136 **kwargs
3137 All other keyword arguments are passed on to the plot
3138 command for the markers. For example, this code makes big red
3139 squares with thick green edges::
3141 x, y, yerr = rand(3, 10)
3142 errorbar(x, y, yerr, marker='s', mfc='red',
3143 mec='green', ms=20, mew=4)
3145 where *mfc*, *mec*, *ms* and *mew* are aliases for the longer
3146 property names, *markerfacecolor*, *markeredgecolor*, *markersize*
3147 and *markeredgewidth*.
3149 Valid kwargs for the marker properties are `.Lines2D` properties:
3151 %(_Line2D_docstr)s
3152 """
3153 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
3154 # anything that comes in as 'None', drop so the default thing
3155 # happens down stream
3156 kwargs = {k: v for k, v in kwargs.items() if v is not None}
3157 kwargs.setdefault('zorder', 2)
3159 try:
3160 offset, errorevery = errorevery
3161 except TypeError:
3162 offset = 0
3164 if errorevery < 1 or int(errorevery) != errorevery:
3165 raise ValueError(
3166 'errorevery must be positive integer or tuple of integers')
3167 if int(offset) != offset:
3168 raise ValueError("errorevery's starting index must be an integer")
3170 self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
3172 plot_line = (fmt.lower() != 'none')
3173 label = kwargs.pop("label", None)
3175 if fmt == '':
3176 fmt_style_kwargs = {}
3177 else:
3178 fmt_style_kwargs = {k: v for k, v in
3179 zip(('linestyle', 'marker', 'color'),
3180 _process_plot_format(fmt))
3181 if v is not None}
3182 if fmt == 'none':
3183 # Remove alpha=0 color that _process_plot_format returns
3184 fmt_style_kwargs.pop('color')
3186 if ('color' in kwargs or 'color' in fmt_style_kwargs or
3187 ecolor is not None):
3188 base_style = {}
3189 if 'color' in kwargs:
3190 base_style['color'] = kwargs.pop('color')
3191 else:
3192 base_style = next(self._get_lines.prop_cycler)
3194 base_style['label'] = '_nolegend_'
3195 base_style.update(fmt_style_kwargs)
3196 if 'color' not in base_style:
3197 base_style['color'] = 'C0'
3198 if ecolor is None:
3199 ecolor = base_style['color']
3200 # make sure all the args are iterable; use lists not arrays to
3201 # preserve units
3202 if not np.iterable(x):
3203 x = [x]
3205 if not np.iterable(y):
3206 y = [y]
3208 if xerr is not None:
3209 if not np.iterable(xerr):
3210 xerr = [xerr] * len(x)
3212 if yerr is not None:
3213 if not np.iterable(yerr):
3214 yerr = [yerr] * len(y)
3216 # make the style dict for the 'normal' plot line
3217 plot_line_style = {
3218 **base_style,
3219 **kwargs,
3220 'zorder': (kwargs['zorder'] - .1 if barsabove else
3221 kwargs['zorder'] + .1),
3222 }
3224 # make the style dict for the line collections (the bars)
3225 eb_lines_style = dict(base_style)
3226 eb_lines_style.pop('marker', None)
3227 eb_lines_style.pop('linestyle', None)
3228 eb_lines_style['color'] = ecolor
3230 if elinewidth:
3231 eb_lines_style['linewidth'] = elinewidth
3232 elif 'linewidth' in kwargs:
3233 eb_lines_style['linewidth'] = kwargs['linewidth']
3235 for key in ('transform', 'alpha', 'zorder', 'rasterized'):
3236 if key in kwargs:
3237 eb_lines_style[key] = kwargs[key]
3239 # set up cap style dictionary
3240 eb_cap_style = dict(base_style)
3241 # eject any marker information from format string
3242 eb_cap_style.pop('marker', None)
3243 eb_lines_style.pop('markerfacecolor', None)
3244 eb_lines_style.pop('markeredgewidth', None)
3245 eb_lines_style.pop('markeredgecolor', None)
3246 eb_cap_style.pop('ls', None)
3247 eb_cap_style['linestyle'] = 'none'
3248 if capsize is None:
3249 capsize = rcParams["errorbar.capsize"]
3250 if capsize > 0:
3251 eb_cap_style['markersize'] = 2. * capsize
3252 if capthick is not None:
3253 eb_cap_style['markeredgewidth'] = capthick
3255 # For backwards-compat, allow explicit setting of
3256 # 'markeredgewidth' to over-ride capthick.
3257 for key in ('markeredgewidth', 'transform', 'alpha',
3258 'zorder', 'rasterized'):
3259 if key in kwargs:
3260 eb_cap_style[key] = kwargs[key]
3261 eb_cap_style['color'] = ecolor
3263 data_line = None
3264 if plot_line:
3265 data_line = mlines.Line2D(x, y, **plot_line_style)
3266 self.add_line(data_line)
3268 barcols = []
3269 caplines = []
3271 # arrays fine here, they are booleans and hence not units
3272 lolims = np.broadcast_to(lolims, len(x)).astype(bool)
3273 uplims = np.broadcast_to(uplims, len(x)).astype(bool)
3274 xlolims = np.broadcast_to(xlolims, len(x)).astype(bool)
3275 xuplims = np.broadcast_to(xuplims, len(x)).astype(bool)
3277 everymask = np.zeros(len(x), bool)
3278 everymask[offset::errorevery] = True
3280 def xywhere(xs, ys, mask):
3281 """
3282 return xs[mask], ys[mask] where mask is True but xs and
3283 ys are not arrays
3284 """
3285 assert len(xs) == len(ys)
3286 assert len(xs) == len(mask)
3287 xs = [thisx for thisx, b in zip(xs, mask) if b]
3288 ys = [thisy for thisy, b in zip(ys, mask) if b]
3289 return xs, ys
3291 def extract_err(err, data):
3292 """
3293 Private function to parse *err* and subtract/add it to *data*.
3295 Both *err* and *data* are already iterables at this point.
3296 """
3297 try: # Asymmetric error: pair of 1D iterables.
3298 a, b = err
3299 iter(a)
3300 iter(b)
3301 except (TypeError, ValueError):
3302 a = b = err # Symmetric error: 1D iterable.
3303 # This could just be `np.ndim(a) > 1 and np.ndim(b) > 1`, except
3304 # for the (undocumented, but tested) support for (n, 1) arrays.
3305 a_sh = np.shape(a)
3306 b_sh = np.shape(b)
3307 if (len(a_sh) > 2 or (len(a_sh) == 2 and a_sh[1] != 1)
3308 or len(b_sh) > 2 or (len(b_sh) == 2 and b_sh[1] != 1)):
3309 raise ValueError(
3310 "err must be a scalar or a 1D or (2, n) array-like")
3311 if len(a_sh) == 2 or len(b_sh) == 2:
3312 cbook.warn_deprecated(
3313 "3.1", message="Support for passing a (n, 1)-shaped error "
3314 "array to errorbar() is deprecated since Matplotlib "
3315 "%(since)s and will be removed %(removal)s; pass a 1D "
3316 "array instead.")
3317 # Using list comprehensions rather than arrays to preserve units.
3318 for e in [a, b]:
3319 if len(data) != len(e):
3320 raise ValueError(
3321 f"The lengths of the data ({len(data)}) and the "
3322 f"error {len(e)} do not match")
3323 low = [v - e for v, e in zip(data, a)]
3324 high = [v + e for v, e in zip(data, b)]
3325 return low, high
3327 if xerr is not None:
3328 left, right = extract_err(xerr, x)
3329 # select points without upper/lower limits in x and
3330 # draw normal errorbars for these points
3331 noxlims = ~(xlolims | xuplims)
3332 if noxlims.any() or len(noxlims) == 0:
3333 yo, _ = xywhere(y, right, noxlims & everymask)
3334 lo, ro = xywhere(left, right, noxlims & everymask)
3335 barcols.append(self.hlines(yo, lo, ro, **eb_lines_style))
3336 if capsize > 0:
3337 caplines.append(mlines.Line2D(lo, yo, marker='|',
3338 **eb_cap_style))
3339 caplines.append(mlines.Line2D(ro, yo, marker='|',
3340 **eb_cap_style))
3342 if xlolims.any():
3343 yo, _ = xywhere(y, right, xlolims & everymask)
3344 lo, ro = xywhere(x, right, xlolims & everymask)
3345 barcols.append(self.hlines(yo, lo, ro, **eb_lines_style))
3346 rightup, yup = xywhere(right, y, xlolims & everymask)
3347 if self.xaxis_inverted():
3348 marker = mlines.CARETLEFTBASE
3349 else:
3350 marker = mlines.CARETRIGHTBASE
3351 caplines.append(
3352 mlines.Line2D(rightup, yup, ls='None', marker=marker,
3353 **eb_cap_style))
3354 if capsize > 0:
3355 xlo, ylo = xywhere(x, y, xlolims & everymask)
3356 caplines.append(mlines.Line2D(xlo, ylo, marker='|',
3357 **eb_cap_style))
3359 if xuplims.any():
3360 yo, _ = xywhere(y, right, xuplims & everymask)
3361 lo, ro = xywhere(left, x, xuplims & everymask)
3362 barcols.append(self.hlines(yo, lo, ro, **eb_lines_style))
3363 leftlo, ylo = xywhere(left, y, xuplims & everymask)
3364 if self.xaxis_inverted():
3365 marker = mlines.CARETRIGHTBASE
3366 else:
3367 marker = mlines.CARETLEFTBASE
3368 caplines.append(
3369 mlines.Line2D(leftlo, ylo, ls='None', marker=marker,
3370 **eb_cap_style))
3371 if capsize > 0:
3372 xup, yup = xywhere(x, y, xuplims & everymask)
3373 caplines.append(mlines.Line2D(xup, yup, marker='|',
3374 **eb_cap_style))
3376 if yerr is not None:
3377 lower, upper = extract_err(yerr, y)
3378 # select points without upper/lower limits in y and
3379 # draw normal errorbars for these points
3380 noylims = ~(lolims | uplims)
3381 if noylims.any() or len(noylims) == 0:
3382 xo, _ = xywhere(x, lower, noylims & everymask)
3383 lo, uo = xywhere(lower, upper, noylims & everymask)
3384 barcols.append(self.vlines(xo, lo, uo, **eb_lines_style))
3385 if capsize > 0:
3386 caplines.append(mlines.Line2D(xo, lo, marker='_',
3387 **eb_cap_style))
3388 caplines.append(mlines.Line2D(xo, uo, marker='_',
3389 **eb_cap_style))
3391 if lolims.any():
3392 xo, _ = xywhere(x, lower, lolims & everymask)
3393 lo, uo = xywhere(y, upper, lolims & everymask)
3394 barcols.append(self.vlines(xo, lo, uo, **eb_lines_style))
3395 xup, upperup = xywhere(x, upper, lolims & everymask)
3396 if self.yaxis_inverted():
3397 marker = mlines.CARETDOWNBASE
3398 else:
3399 marker = mlines.CARETUPBASE
3400 caplines.append(
3401 mlines.Line2D(xup, upperup, ls='None', marker=marker,
3402 **eb_cap_style))
3403 if capsize > 0:
3404 xlo, ylo = xywhere(x, y, lolims & everymask)
3405 caplines.append(mlines.Line2D(xlo, ylo, marker='_',
3406 **eb_cap_style))
3408 if uplims.any():
3409 xo, _ = xywhere(x, lower, uplims & everymask)
3410 lo, uo = xywhere(lower, y, uplims & everymask)
3411 barcols.append(self.vlines(xo, lo, uo, **eb_lines_style))
3412 xlo, lowerlo = xywhere(x, lower, uplims & everymask)
3413 if self.yaxis_inverted():
3414 marker = mlines.CARETUPBASE
3415 else:
3416 marker = mlines.CARETDOWNBASE
3417 caplines.append(
3418 mlines.Line2D(xlo, lowerlo, ls='None', marker=marker,
3419 **eb_cap_style))
3420 if capsize > 0:
3421 xup, yup = xywhere(x, y, uplims & everymask)
3422 caplines.append(mlines.Line2D(xup, yup, marker='_',
3423 **eb_cap_style))
3424 for l in caplines:
3425 self.add_line(l)
3427 self._request_autoscale_view()
3428 errorbar_container = ErrorbarContainer((data_line, tuple(caplines),
3429 tuple(barcols)),
3430 has_xerr=(xerr is not None),
3431 has_yerr=(yerr is not None),
3432 label=label)
3433 self.containers.append(errorbar_container)
3435 return errorbar_container # (l0, caplines, barcols)
3437 @cbook._rename_parameter("3.1", "manage_xticks", "manage_ticks")
3438 @_preprocess_data()
3439 def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
3440 positions=None, widths=None, patch_artist=None,
3441 bootstrap=None, usermedians=None, conf_intervals=None,
3442 meanline=None, showmeans=None, showcaps=None,
3443 showbox=None, showfliers=None, boxprops=None,
3444 labels=None, flierprops=None, medianprops=None,
3445 meanprops=None, capprops=None, whiskerprops=None,
3446 manage_ticks=True, autorange=False, zorder=None):
3447 """
3448 Make a box and whisker plot.
3450 Make a box and whisker plot for each column of ``x`` or each
3451 vector in sequence ``x``. The box extends from the lower to
3452 upper quartile values of the data, with a line at the median.
3453 The whiskers extend from the box to show the range of the
3454 data. Flier points are those past the end of the whiskers.
3456 Parameters
3457 ----------
3458 x : Array or a sequence of vectors.
3459 The input data.
3461 notch : bool, optional (False)
3462 If `True`, will produce a notched box plot. Otherwise, a
3463 rectangular boxplot is produced. The notches represent the
3464 confidence interval (CI) around the median. See the entry
3465 for the ``bootstrap`` parameter for information regarding
3466 how the locations of the notches are computed.
3468 .. note::
3470 In cases where the values of the CI are less than the
3471 lower quartile or greater than the upper quartile, the
3472 notches will extend beyond the box, giving it a
3473 distinctive "flipped" appearance. This is expected
3474 behavior and consistent with other statistical
3475 visualization packages.
3477 sym : str, optional
3478 The default symbol for flier points. Enter an empty string
3479 ('') if you don't want to show fliers. If `None`, then the
3480 fliers default to 'b+' If you want more control use the
3481 flierprops kwarg.
3483 vert : bool, optional (True)
3484 If `True` (default), makes the boxes vertical. If `False`,
3485 everything is drawn horizontally.
3487 whis : float or (float, float) (default = 1.5)
3488 The position of the whiskers.
3490 If a float, the lower whisker is at the lowest datum above
3491 ``Q1 - whis*(Q3-Q1)``, and the upper whisker at the highest datum
3492 below ``Q3 + whis*(Q3-Q1)``, where Q1 and Q3 are the first and
3493 third quartiles. The default value of ``whis = 1.5`` corresponds
3494 to Tukey's original definition of boxplots.
3496 If a pair of floats, they indicate the percentiles at which to
3497 draw the whiskers (e.g., (5, 95)). In particular, setting this to
3498 (0, 100) results in whiskers covering the whole range of the data.
3499 "range" is a deprecated synonym for (0, 100).
3501 In the edge case where ``Q1 == Q3``, *whis* is automatically set
3502 to (0, 100) (cover the whole range of the data) if *autorange* is
3503 True.
3505 Beyond the whiskers, data are considered outliers and are plotted
3506 as individual points.
3508 bootstrap : int, optional
3509 Specifies whether to bootstrap the confidence intervals
3510 around the median for notched boxplots. If ``bootstrap`` is
3511 None, no bootstrapping is performed, and notches are
3512 calculated using a Gaussian-based asymptotic approximation
3513 (see McGill, R., Tukey, J.W., and Larsen, W.A., 1978, and
3514 Kendall and Stuart, 1967). Otherwise, bootstrap specifies
3515 the number of times to bootstrap the median to determine its
3516 95% confidence intervals. Values between 1000 and 10000 are
3517 recommended.
3519 usermedians : array-like, optional
3520 An array or sequence whose first dimension (or length) is
3521 compatible with ``x``. This overrides the medians computed
3522 by matplotlib for each element of ``usermedians`` that is not
3523 `None`. When an element of ``usermedians`` is None, the median
3524 will be computed by matplotlib as normal.
3526 conf_intervals : array-like, optional
3527 Array or sequence whose first dimension (or length) is
3528 compatible with ``x`` and whose second dimension is 2. When
3529 the an element of ``conf_intervals`` is not None, the
3530 notch locations computed by matplotlib are overridden
3531 (provided ``notch`` is `True`). When an element of
3532 ``conf_intervals`` is `None`, the notches are computed by the
3533 method specified by the other kwargs (e.g., ``bootstrap``).
3535 positions : array-like, optional
3536 Sets the positions of the boxes. The ticks and limits are
3537 automatically set to match the positions. Defaults to
3538 `range(1, N+1)` where N is the number of boxes to be drawn.
3540 widths : scalar or array-like
3541 Sets the width of each box either with a scalar or a
3542 sequence. The default is 0.5, or ``0.15*(distance between
3543 extreme positions)``, if that is smaller.
3545 patch_artist : bool, optional (False)
3546 If `False` produces boxes with the Line2D artist. Otherwise,
3547 boxes and drawn with Patch artists.
3549 labels : sequence, optional
3550 Labels for each dataset. Length must be compatible with
3551 dimensions of ``x``.
3553 manage_ticks : bool, optional (True)
3554 If True, the tick locations and labels will be adjusted to match
3555 the boxplot positions.
3557 autorange : bool, optional (False)
3558 When `True` and the data are distributed such that the 25th and
3559 75th percentiles are equal, ``whis`` is set to (0, 100) such
3560 that the whisker ends are at the minimum and maximum of the data.
3562 meanline : bool, optional (False)
3563 If `True` (and ``showmeans`` is `True`), will try to render
3564 the mean as a line spanning the full width of the box
3565 according to ``meanprops`` (see below). Not recommended if
3566 ``shownotches`` is also True. Otherwise, means will be shown
3567 as points.
3569 zorder : scalar, optional (None)
3570 Sets the zorder of the boxplot.
3572 Other Parameters
3573 ----------------
3574 showcaps : bool, optional (True)
3575 Show the caps on the ends of whiskers.
3576 showbox : bool, optional (True)
3577 Show the central box.
3578 showfliers : bool, optional (True)
3579 Show the outliers beyond the caps.
3580 showmeans : bool, optional (False)
3581 Show the arithmetic means.
3582 capprops : dict, optional (None)
3583 Specifies the style of the caps.
3584 boxprops : dict, optional (None)
3585 Specifies the style of the box.
3586 whiskerprops : dict, optional (None)
3587 Specifies the style of the whiskers.
3588 flierprops : dict, optional (None)
3589 Specifies the style of the fliers.
3590 medianprops : dict, optional (None)
3591 Specifies the style of the median.
3592 meanprops : dict, optional (None)
3593 Specifies the style of the mean.
3595 Returns
3596 -------
3597 result : dict
3598 A dictionary mapping each component of the boxplot to a list
3599 of the `.Line2D` instances created. That dictionary has the
3600 following keys (assuming vertical boxplots):
3602 - ``boxes``: the main body of the boxplot showing the
3603 quartiles and the median's confidence intervals if
3604 enabled.
3606 - ``medians``: horizontal lines at the median of each box.
3608 - ``whiskers``: the vertical lines extending to the most
3609 extreme, non-outlier data points.
3611 - ``caps``: the horizontal lines at the ends of the
3612 whiskers.
3614 - ``fliers``: points representing data that extend beyond
3615 the whiskers (fliers).
3617 - ``means``: points or lines representing the means.
3619 """
3621 # Missing arguments default to rcParams.
3622 if whis is None:
3623 whis = rcParams['boxplot.whiskers']
3624 if bootstrap is None:
3625 bootstrap = rcParams['boxplot.bootstrap']
3627 bxpstats = cbook.boxplot_stats(x, whis=whis, bootstrap=bootstrap,
3628 labels=labels, autorange=autorange)
3629 if notch is None:
3630 notch = rcParams['boxplot.notch']
3631 if vert is None:
3632 vert = rcParams['boxplot.vertical']
3633 if patch_artist is None:
3634 patch_artist = rcParams['boxplot.patchartist']
3635 if meanline is None:
3636 meanline = rcParams['boxplot.meanline']
3637 if showmeans is None:
3638 showmeans = rcParams['boxplot.showmeans']
3639 if showcaps is None:
3640 showcaps = rcParams['boxplot.showcaps']
3641 if showbox is None:
3642 showbox = rcParams['boxplot.showbox']
3643 if showfliers is None:
3644 showfliers = rcParams['boxplot.showfliers']
3646 if boxprops is None:
3647 boxprops = {}
3648 if whiskerprops is None:
3649 whiskerprops = {}
3650 if capprops is None:
3651 capprops = {}
3652 if medianprops is None:
3653 medianprops = {}
3654 if meanprops is None:
3655 meanprops = {}
3656 if flierprops is None:
3657 flierprops = {}
3659 if patch_artist:
3660 boxprops['linestyle'] = 'solid' # Not consistent with bxp.
3661 if 'color' in boxprops:
3662 boxprops['edgecolor'] = boxprops.pop('color')
3664 # if non-default sym value, put it into the flier dictionary
3665 # the logic for providing the default symbol ('b+') now lives
3666 # in bxp in the initial value of final_flierprops
3667 # handle all of the *sym* related logic here so we only have to pass
3668 # on the flierprops dict.
3669 if sym is not None:
3670 # no-flier case, which should really be done with
3671 # 'showfliers=False' but none-the-less deal with it to keep back
3672 # compatibility
3673 if sym == '':
3674 # blow away existing dict and make one for invisible markers
3675 flierprops = dict(linestyle='none', marker='', color='none')
3676 # turn the fliers off just to be safe
3677 showfliers = False
3678 # now process the symbol string
3679 else:
3680 # process the symbol string
3681 # discarded linestyle
3682 _, marker, color = _process_plot_format(sym)
3683 # if we have a marker, use it
3684 if marker is not None:
3685 flierprops['marker'] = marker
3686 # if we have a color, use it
3687 if color is not None:
3688 # assume that if color is passed in the user want
3689 # filled symbol, if the users want more control use
3690 # flierprops
3691 flierprops['color'] = color
3692 flierprops['markerfacecolor'] = color
3693 flierprops['markeredgecolor'] = color
3695 # replace medians if necessary:
3696 if usermedians is not None:
3697 if (len(np.ravel(usermedians)) != len(bxpstats) or
3698 np.shape(usermedians)[0] != len(bxpstats)):
3699 raise ValueError('usermedians length not compatible with x')
3700 else:
3701 # reassign medians as necessary
3702 for stats, med in zip(bxpstats, usermedians):
3703 if med is not None:
3704 stats['med'] = med
3706 if conf_intervals is not None:
3707 if np.shape(conf_intervals)[0] != len(bxpstats):
3708 err_mess = 'conf_intervals length not compatible with x'
3709 raise ValueError(err_mess)
3710 else:
3711 for stats, ci in zip(bxpstats, conf_intervals):
3712 if ci is not None:
3713 if len(ci) != 2:
3714 raise ValueError('each confidence interval must '
3715 'have two values')
3716 else:
3717 if ci[0] is not None:
3718 stats['cilo'] = ci[0]
3719 if ci[1] is not None:
3720 stats['cihi'] = ci[1]
3722 artists = self.bxp(bxpstats, positions=positions, widths=widths,
3723 vert=vert, patch_artist=patch_artist,
3724 shownotches=notch, showmeans=showmeans,
3725 showcaps=showcaps, showbox=showbox,
3726 boxprops=boxprops, flierprops=flierprops,
3727 medianprops=medianprops, meanprops=meanprops,
3728 meanline=meanline, showfliers=showfliers,
3729 capprops=capprops, whiskerprops=whiskerprops,
3730 manage_ticks=manage_ticks, zorder=zorder)
3731 return artists
3733 @cbook._rename_parameter("3.1", "manage_xticks", "manage_ticks")
3734 def bxp(self, bxpstats, positions=None, widths=None, vert=True,
3735 patch_artist=False, shownotches=False, showmeans=False,
3736 showcaps=True, showbox=True, showfliers=True,
3737 boxprops=None, whiskerprops=None, flierprops=None,
3738 medianprops=None, capprops=None, meanprops=None,
3739 meanline=False, manage_ticks=True, zorder=None):
3740 """
3741 Drawing function for box and whisker plots.
3743 Make a box and whisker plot for each column of *x* or each
3744 vector in sequence *x*. The box extends from the lower to
3745 upper quartile values of the data, with a line at the median.
3746 The whiskers extend from the box to show the range of the
3747 data. Flier points are those past the end of the whiskers.
3749 Parameters
3750 ----------
3751 bxpstats : list of dicts
3752 A list of dictionaries containing stats for each boxplot.
3753 Required keys are:
3755 - ``med``: The median (scalar float).
3757 - ``q1``: The first quartile (25th percentile) (scalar
3758 float).
3760 - ``q3``: The third quartile (75th percentile) (scalar
3761 float).
3763 - ``whislo``: Lower bound of the lower whisker (scalar
3764 float).
3766 - ``whishi``: Upper bound of the upper whisker (scalar
3767 float).
3769 Optional keys are:
3771 - ``mean``: The mean (scalar float). Needed if
3772 ``showmeans=True``.
3774 - ``fliers``: Data beyond the whiskers (sequence of floats).
3775 Needed if ``showfliers=True``.
3777 - ``cilo`` & ``cihi``: Lower and upper confidence intervals
3778 about the median. Needed if ``shownotches=True``.
3780 - ``label``: Name of the dataset (string). If available,
3781 this will be used a tick label for the boxplot
3783 positions : array-like, default = [1, 2, ..., n]
3784 Sets the positions of the boxes. The ticks and limits
3785 are automatically set to match the positions.
3787 widths : array-like, default = None
3788 Either a scalar or a vector and sets the width of each
3789 box. The default is ``0.15*(distance between extreme
3790 positions)``, clipped to no less than 0.15 and no more than
3791 0.5.
3793 vert : bool, default = True
3794 If `True` (default), makes the boxes vertical. If `False`,
3795 makes horizontal boxes.
3797 patch_artist : bool, default = False
3798 If `False` produces boxes with the `.Line2D` artist.
3799 If `True` produces boxes with the `~matplotlib.patches.Patch` artist.
3801 shownotches : bool, default = False
3802 If `False` (default), produces a rectangular box plot.
3803 If `True`, will produce a notched box plot
3805 showmeans : bool, default = False
3806 If `True`, will toggle on the rendering of the means
3808 showcaps : bool, default = True
3809 If `True`, will toggle on the rendering of the caps
3811 showbox : bool, default = True
3812 If `True`, will toggle on the rendering of the box
3814 showfliers : bool, default = True
3815 If `True`, will toggle on the rendering of the fliers
3817 boxprops : dict or None (default)
3818 If provided, will set the plotting style of the boxes
3820 whiskerprops : dict or None (default)
3821 If provided, will set the plotting style of the whiskers
3823 capprops : dict or None (default)
3824 If provided, will set the plotting style of the caps
3826 flierprops : dict or None (default)
3827 If provided will set the plotting style of the fliers
3829 medianprops : dict or None (default)
3830 If provided, will set the plotting style of the medians
3832 meanprops : dict or None (default)
3833 If provided, will set the plotting style of the means
3835 meanline : bool, default = False
3836 If `True` (and *showmeans* is `True`), will try to render the mean
3837 as a line spanning the full width of the box according to
3838 *meanprops*. Not recommended if *shownotches* is also True.
3839 Otherwise, means will be shown as points.
3841 manage_ticks : bool, default = True
3842 If True, the tick locations and labels will be adjusted to match the
3843 boxplot positions.
3845 zorder : scalar, default = None
3846 The zorder of the resulting boxplot.
3848 Returns
3849 -------
3850 result : dict
3851 A dictionary mapping each component of the boxplot to a list
3852 of the `.Line2D` instances created. That dictionary has the
3853 following keys (assuming vertical boxplots):
3855 - ``boxes``: the main body of the boxplot showing the
3856 quartiles and the median's confidence intervals if
3857 enabled.
3859 - ``medians``: horizontal lines at the median of each box.
3861 - ``whiskers``: the vertical lines extending to the most
3862 extreme, non-outlier data points.
3864 - ``caps``: the horizontal lines at the ends of the
3865 whiskers.
3867 - ``fliers``: points representing data that extend beyond
3868 the whiskers (fliers).
3870 - ``means``: points or lines representing the means.
3872 Examples
3873 --------
3874 .. plot:: gallery/statistics/bxp.py
3876 """
3877 # lists of artists to be output
3878 whiskers = []
3879 caps = []
3880 boxes = []
3881 medians = []
3882 means = []
3883 fliers = []
3885 # empty list of xticklabels
3886 datalabels = []
3888 # Use default zorder if none specified
3889 if zorder is None:
3890 zorder = mlines.Line2D.zorder
3892 zdelta = 0.1
3894 def line_props_with_rcdefaults(subkey, explicit, zdelta=0):
3895 d = {k.split('.')[-1]: v for k, v in rcParams.items()
3896 if k.startswith(f'boxplot.{subkey}')}
3897 d['zorder'] = zorder + zdelta
3898 if explicit is not None:
3899 d.update(
3900 cbook.normalize_kwargs(explicit, mlines.Line2D._alias_map))
3901 return d
3903 # box properties
3904 if patch_artist:
3905 final_boxprops = dict(
3906 linestyle=rcParams['boxplot.boxprops.linestyle'],
3907 linewidth=rcParams['boxplot.boxprops.linewidth'],
3908 edgecolor=rcParams['boxplot.boxprops.color'],
3909 facecolor=('white' if rcParams['_internal.classic_mode'] else
3910 rcParams['patch.facecolor']),
3911 zorder=zorder,
3912 )
3913 if boxprops is not None:
3914 final_boxprops.update(
3915 cbook.normalize_kwargs(
3916 boxprops, mpatches.PathPatch._alias_map))
3917 else:
3918 final_boxprops = line_props_with_rcdefaults('boxprops', boxprops)
3919 final_whiskerprops = line_props_with_rcdefaults(
3920 'whiskerprops', whiskerprops)
3921 final_capprops = line_props_with_rcdefaults(
3922 'capprops', capprops)
3923 final_flierprops = line_props_with_rcdefaults(
3924 'flierprops', flierprops)
3925 final_medianprops = line_props_with_rcdefaults(
3926 'medianprops', medianprops, zdelta)
3927 final_meanprops = line_props_with_rcdefaults(
3928 'meanprops', meanprops, zdelta)
3929 removed_prop = 'marker' if meanline else 'linestyle'
3930 # Only remove the property if it's not set explicitly as a parameter.
3931 if meanprops is None or removed_prop not in meanprops:
3932 final_meanprops[removed_prop] = ''
3934 def to_vc(xs, ys):
3935 # convert arguments to verts and codes, append (0, 0) (ignored).
3936 verts = np.append(np.column_stack([xs, ys]), [(0, 0)], 0)
3937 codes = ([mpath.Path.MOVETO]
3938 + [mpath.Path.LINETO] * (len(verts) - 2)
3939 + [mpath.Path.CLOSEPOLY])
3940 return verts, codes
3942 def patch_list(xs, ys, **kwargs):
3943 verts, codes = to_vc(xs, ys)
3944 path = mpath.Path(verts, codes)
3945 patch = mpatches.PathPatch(path, **kwargs)
3946 self.add_artist(patch)
3947 return [patch]
3949 # vertical or horizontal plot?
3950 if vert:
3951 def doplot(*args, **kwargs):
3952 return self.plot(*args, **kwargs)
3954 def dopatch(xs, ys, **kwargs):
3955 return patch_list(xs, ys, **kwargs)
3957 else:
3958 def doplot(*args, **kwargs):
3959 shuffled = []
3960 for i in range(0, len(args), 2):
3961 shuffled.extend([args[i + 1], args[i]])
3962 return self.plot(*shuffled, **kwargs)
3964 def dopatch(xs, ys, **kwargs):
3965 xs, ys = ys, xs # flip X, Y
3966 return patch_list(xs, ys, **kwargs)
3968 # input validation
3969 N = len(bxpstats)
3970 datashape_message = ("List of boxplot statistics and `{0}` "
3971 "values must have same the length")
3972 # check position
3973 if positions is None:
3974 positions = list(range(1, N + 1))
3975 elif len(positions) != N:
3976 raise ValueError(datashape_message.format("positions"))
3978 positions = np.array(positions)
3979 if len(positions) > 0 and not isinstance(positions[0], Number):
3980 raise TypeError("positions should be an iterable of numbers")
3982 # width
3983 if widths is None:
3984 widths = [np.clip(0.15 * np.ptp(positions), 0.15, 0.5)] * N
3985 elif np.isscalar(widths):
3986 widths = [widths] * N
3987 elif len(widths) != N:
3988 raise ValueError(datashape_message.format("widths"))
3990 for pos, width, stats in zip(positions, widths, bxpstats):
3991 # try to find a new label
3992 datalabels.append(stats.get('label', pos))
3994 # whisker coords
3995 whisker_x = np.ones(2) * pos
3996 whiskerlo_y = np.array([stats['q1'], stats['whislo']])
3997 whiskerhi_y = np.array([stats['q3'], stats['whishi']])
3999 # cap coords
4000 cap_left = pos - width * 0.25
4001 cap_right = pos + width * 0.25
4002 cap_x = np.array([cap_left, cap_right])
4003 cap_lo = np.ones(2) * stats['whislo']
4004 cap_hi = np.ones(2) * stats['whishi']
4006 # box and median coords
4007 box_left = pos - width * 0.5
4008 box_right = pos + width * 0.5
4009 med_y = [stats['med'], stats['med']]
4011 # notched boxes
4012 if shownotches:
4013 box_x = [box_left, box_right, box_right, cap_right, box_right,
4014 box_right, box_left, box_left, cap_left, box_left,
4015 box_left]
4016 box_y = [stats['q1'], stats['q1'], stats['cilo'],
4017 stats['med'], stats['cihi'], stats['q3'],
4018 stats['q3'], stats['cihi'], stats['med'],
4019 stats['cilo'], stats['q1']]
4020 med_x = cap_x
4022 # plain boxes
4023 else:
4024 box_x = [box_left, box_right, box_right, box_left, box_left]
4025 box_y = [stats['q1'], stats['q1'], stats['q3'], stats['q3'],
4026 stats['q1']]
4027 med_x = [box_left, box_right]
4029 # maybe draw the box:
4030 if showbox:
4031 if patch_artist:
4032 boxes.extend(dopatch(box_x, box_y, **final_boxprops))
4033 else:
4034 boxes.extend(doplot(box_x, box_y, **final_boxprops))
4036 # draw the whiskers
4037 whiskers.extend(doplot(
4038 whisker_x, whiskerlo_y, **final_whiskerprops
4039 ))
4040 whiskers.extend(doplot(
4041 whisker_x, whiskerhi_y, **final_whiskerprops
4042 ))
4044 # maybe draw the caps:
4045 if showcaps:
4046 caps.extend(doplot(cap_x, cap_lo, **final_capprops))
4047 caps.extend(doplot(cap_x, cap_hi, **final_capprops))
4049 # draw the medians
4050 medians.extend(doplot(med_x, med_y, **final_medianprops))
4052 # maybe draw the means
4053 if showmeans:
4054 if meanline:
4055 means.extend(doplot(
4056 [box_left, box_right], [stats['mean'], stats['mean']],
4057 **final_meanprops
4058 ))
4059 else:
4060 means.extend(doplot(
4061 [pos], [stats['mean']], **final_meanprops
4062 ))
4064 # maybe draw the fliers
4065 if showfliers:
4066 # fliers coords
4067 flier_x = np.full(len(stats['fliers']), pos, dtype=np.float64)
4068 flier_y = stats['fliers']
4070 fliers.extend(doplot(
4071 flier_x, flier_y, **final_flierprops
4072 ))
4074 if manage_ticks:
4075 axis_name = "x" if vert else "y"
4076 interval = getattr(self.dataLim, f"interval{axis_name}")
4077 axis = getattr(self, f"{axis_name}axis")
4078 positions = axis.convert_units(positions)
4079 # The 0.5 additional padding ensures reasonable-looking boxes
4080 # even when drawing a single box. We set the sticky edge to
4081 # prevent margins expansion, in order to match old behavior (back
4082 # when separate calls to boxplot() would completely reset the axis
4083 # limits regardless of what was drawn before). The sticky edges
4084 # are attached to the median lines, as they are always present.
4085 interval[:] = (min(interval[0], min(positions) - .5),
4086 max(interval[1], max(positions) + .5))
4087 for median, position in zip(medians, positions):
4088 getattr(median.sticky_edges, axis_name).extend(
4089 [position - .5, position + .5])
4090 # Modified from Axis.set_ticks and Axis.set_ticklabels.
4091 locator = axis.get_major_locator()
4092 if not isinstance(axis.get_major_locator(),
4093 mticker.FixedLocator):
4094 locator = mticker.FixedLocator([])
4095 axis.set_major_locator(locator)
4096 locator.locs = np.array([*locator.locs, *positions])
4097 formatter = axis.get_major_formatter()
4098 if not isinstance(axis.get_major_formatter(),
4099 mticker.FixedFormatter):
4100 formatter = mticker.FixedFormatter([])
4101 axis.set_major_formatter(formatter)
4102 formatter.seq = [*formatter.seq, *datalabels]
4104 self._request_autoscale_view(
4105 scalex=self._autoscaleXon, scaley=self._autoscaleYon)
4107 return dict(whiskers=whiskers, caps=caps, boxes=boxes,
4108 medians=medians, fliers=fliers, means=means)
4110 @staticmethod
4111 def _parse_scatter_color_args(c, edgecolors, kwargs, xsize,
4112 get_next_color_func):
4113 """
4114 Helper function to process color related arguments of `.Axes.scatter`.
4116 Argument precedence for facecolors:
4118 - c (if not None)
4119 - kwargs['facecolors']
4120 - kwargs['facecolor']
4121 - kwargs['color'] (==kwcolor)
4122 - 'b' if in classic mode else the result of ``get_next_color_func()``
4124 Argument precedence for edgecolors:
4126 - edgecolors (is an explicit kw argument in scatter())
4127 - kwargs['edgecolor']
4128 - kwargs['color'] (==kwcolor)
4129 - 'face' if not in classic mode else None
4131 Parameters
4132 ----------
4133 c : color or sequence or sequence of color or None
4134 See argument description of `.Axes.scatter`.
4135 edgecolors : color or sequence of color or {'face', 'none'} or None
4136 See argument description of `.Axes.scatter`.
4137 kwargs : dict
4138 Additional kwargs. If these keys exist, we pop and process them:
4139 'facecolors', 'facecolor', 'edgecolor', 'color'
4140 Note: The dict is modified by this function.
4141 xsize : int
4142 The size of the x and y arrays passed to `.Axes.scatter`.
4143 get_next_color_func : callable
4144 A callable that returns a color. This color is used as facecolor
4145 if no other color is provided.
4147 Note, that this is a function rather than a fixed color value to
4148 support conditional evaluation of the next color. As of the
4149 current implementation obtaining the next color from the
4150 property cycle advances the cycle. This must only happen if we
4151 actually use the color, which will only be decided within this
4152 method.
4154 Returns
4155 -------
4156 c
4157 The input *c* if it was not *None*, else a color derived from the
4158 other inputs or defaults.
4159 colors : array(N, 4) or None
4160 The facecolors as RGBA values, or *None* if a colormap is used.
4161 edgecolors
4162 The edgecolor.
4164 """
4165 facecolors = kwargs.pop('facecolors', None)
4166 facecolors = kwargs.pop('facecolor', facecolors)
4167 edgecolors = kwargs.pop('edgecolor', edgecolors)
4169 kwcolor = kwargs.pop('color', None)
4171 if kwcolor is not None and c is not None:
4172 raise ValueError("Supply a 'c' argument or a 'color'"
4173 " kwarg but not both; they differ but"
4174 " their functionalities overlap.")
4176 if kwcolor is not None:
4177 try:
4178 mcolors.to_rgba_array(kwcolor)
4179 except ValueError:
4180 raise ValueError(
4181 "'color' kwarg must be an color or sequence of color "
4182 "specs. For a sequence of values to be color-mapped, use "
4183 "the 'c' argument instead.")
4184 if edgecolors is None:
4185 edgecolors = kwcolor
4186 if facecolors is None:
4187 facecolors = kwcolor
4189 if edgecolors is None and not rcParams['_internal.classic_mode']:
4190 edgecolors = rcParams['scatter.edgecolors']
4192 c_was_none = c is None
4193 if c is None:
4194 c = (facecolors if facecolors is not None
4195 else "b" if rcParams['_internal.classic_mode']
4196 else get_next_color_func())
4197 c_is_string_or_strings = (
4198 isinstance(c, str)
4199 or (isinstance(c, collections.abc.Iterable) and len(c) > 0
4200 and isinstance(cbook.safe_first_element(c), str)))
4202 def invalid_shape_exception(csize, xsize):
4203 return ValueError(
4204 f"'c' argument has {csize} elements, which is inconsistent "
4205 f"with 'x' and 'y' with size {xsize}.")
4207 c_is_mapped = False # Unless proven otherwise below.
4208 valid_shape = True # Unless proven otherwise below.
4209 if not c_was_none and kwcolor is None and not c_is_string_or_strings:
4210 try: # First, does 'c' look suitable for value-mapping?
4211 c = np.asanyarray(c, dtype=float)
4212 except ValueError:
4213 pass # Failed to convert to float array; must be color specs.
4214 else:
4215 # handle the documented special case of a 2D array with 1
4216 # row which as RGB(A) to broadcast.
4217 if c.shape == (1, 4) or c.shape == (1, 3):
4218 c_is_mapped = False
4219 if c.size != xsize:
4220 valid_shape = False
4221 # If c can be either mapped values or a RGB(A) color, prefer
4222 # the former if shapes match, the latter otherwise.
4223 elif c.size == xsize:
4224 c = c.ravel()
4225 c_is_mapped = True
4226 else: # Wrong size; it must not be intended for mapping.
4227 if c.shape in ((3,), (4,)):
4228 _log.warning(
4229 "*c* argument looks like a single numeric RGB or "
4230 "RGBA sequence, which should be avoided as value-"
4231 "mapping will have precedence in case its length "
4232 "matches with *x* & *y*. Please use the *color* "
4233 "keyword-argument or provide a 2-D array "
4234 "with a single row if you intend to specify "
4235 "the same RGB or RGBA value for all points.")
4236 valid_shape = False
4237 if not c_is_mapped:
4238 try: # Is 'c' acceptable as PathCollection facecolors?
4239 colors = mcolors.to_rgba_array(c)
4240 except ValueError:
4241 if not valid_shape:
4242 raise invalid_shape_exception(c.size, xsize)
4243 # Both the mapping *and* the RGBA conversion failed: pretty
4244 # severe failure => one may appreciate a verbose feedback.
4245 raise ValueError(
4246 f"'c' argument must be a color, a sequence of colors, or "
4247 f"a sequence of numbers, not {c}")
4248 else:
4249 if len(colors) not in (0, 1, xsize):
4250 # NB: remember that a single color is also acceptable.
4251 # Besides *colors* will be an empty array if c == 'none'.
4252 raise invalid_shape_exception(len(colors), xsize)
4253 else:
4254 colors = None # use cmap, norm after collection is created
4255 return c, colors, edgecolors
4257 @_preprocess_data(replace_names=["x", "y", "s", "linewidths",
4258 "edgecolors", "c", "facecolor",
4259 "facecolors", "color"],
4260 label_namer="y")
4261 @cbook._delete_parameter("3.2", "verts")
4262 def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
4263 vmin=None, vmax=None, alpha=None, linewidths=None,
4264 verts=None, edgecolors=None, *, plotnonfinite=False,
4265 **kwargs):
4266 """
4267 A scatter plot of *y* vs. *x* with varying marker size and/or color.
4269 Parameters
4270 ----------
4271 x, y : scalar or array-like, shape (n, )
4272 The data positions.
4274 s : scalar or array-like, shape (n, ), optional
4275 The marker size in points**2.
4276 Default is ``rcParams['lines.markersize'] ** 2``.
4278 c : array-like or list of colors or color, optional
4279 The marker colors. Possible values:
4281 - A scalar or sequence of n numbers to be mapped to colors using
4282 *cmap* and *norm*.
4283 - A 2-D array in which the rows are RGB or RGBA.
4284 - A sequence of colors of length n.
4285 - A single color format string.
4287 Note that *c* should not be a single numeric RGB or RGBA sequence
4288 because that is indistinguishable from an array of values to be
4289 colormapped. If you want to specify the same RGB or RGBA value for
4290 all points, use a 2-D array with a single row. Otherwise, value-
4291 matching will have precedence in case of a size matching with *x*
4292 and *y*.
4294 If you wish to specify a single color for all points
4295 prefer the *color* keyword argument.
4297 Defaults to `None`. In that case the marker color is determined
4298 by the value of *color*, *facecolor* or *facecolors*. In case
4299 those are not specified or `None`, the marker color is determined
4300 by the next color of the ``Axes``' current "shape and fill" color
4301 cycle. This cycle defaults to :rc:`axes.prop_cycle`.
4303 marker : `~matplotlib.markers.MarkerStyle`, optional
4304 The marker style. *marker* can be either an instance of the class
4305 or the text shorthand for a particular marker.
4306 Defaults to ``None``, in which case it takes the value of
4307 :rc:`scatter.marker` = 'o'.
4308 See `~matplotlib.markers` for more information about marker styles.
4310 cmap : `~matplotlib.colors.Colormap`, optional, default: None
4311 A `.Colormap` instance or registered colormap name. *cmap* is only
4312 used if *c* is an array of floats. If ``None``, defaults to rc
4313 ``image.cmap``.
4315 norm : `~matplotlib.colors.Normalize`, optional, default: None
4316 A `.Normalize` instance is used to scale luminance data to 0, 1.
4317 *norm* is only used if *c* is an array of floats. If *None*, use
4318 the default `.colors.Normalize`.
4320 vmin, vmax : scalar, optional, default: None
4321 *vmin* and *vmax* are used in conjunction with *norm* to normalize
4322 luminance data. If None, the respective min and max of the color
4323 array is used. *vmin* and *vmax* are ignored if you pass a *norm*
4324 instance.
4326 alpha : scalar, optional, default: None
4327 The alpha blending value, between 0 (transparent) and 1 (opaque).
4329 linewidths : scalar or array-like, optional, default: None
4330 The linewidth of the marker edges. Note: The default *edgecolors*
4331 is 'face'. You may want to change this as well.
4332 If *None*, defaults to :rc:`lines.linewidth`.
4334 edgecolors : {'face', 'none', *None*} or color or sequence of color, \
4335optional.
4336 The edge color of the marker. Possible values:
4338 - 'face': The edge color will always be the same as the face color.
4339 - 'none': No patch boundary will be drawn.
4340 - A Matplotlib color or sequence of color.
4342 Defaults to ``None``, in which case it takes the value of
4343 :rc:`scatter.edgecolors` = 'face'.
4345 For non-filled markers, the *edgecolors* kwarg is ignored and
4346 forced to 'face' internally.
4348 plotnonfinite : boolean, optional, default: False
4349 Set to plot points with nonfinite *c*, in conjunction with
4350 `~matplotlib.colors.Colormap.set_bad`.
4352 Returns
4353 -------
4354 paths : `~matplotlib.collections.PathCollection`
4356 Other Parameters
4357 ----------------
4358 **kwargs : `~matplotlib.collections.Collection` properties
4360 See Also
4361 --------
4362 plot : To plot scatter plots when markers are identical in size and
4363 color.
4365 Notes
4366 -----
4367 * The `.plot` function will be faster for scatterplots where markers
4368 don't vary in size or color.
4370 * Any or all of *x*, *y*, *s*, and *c* may be masked arrays, in which
4371 case all masks will be combined and only unmasked points will be
4372 plotted.
4374 * Fundamentally, scatter works with 1-D arrays; *x*, *y*, *s*, and *c*
4375 may be input as N-D arrays, but within scatter they will be
4376 flattened. The exception is *c*, which will be flattened only if its
4377 size matches the size of *x* and *y*.
4379 """
4380 # Process **kwargs to handle aliases, conflicts with explicit kwargs:
4382 self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
4383 x = self.convert_xunits(x)
4384 y = self.convert_yunits(y)
4386 # np.ma.ravel yields an ndarray, not a masked array,
4387 # unless its argument is a masked array.
4388 x = np.ma.ravel(x)
4389 y = np.ma.ravel(y)
4390 if x.size != y.size:
4391 raise ValueError("x and y must be the same size")
4393 if s is None:
4394 s = (20 if rcParams['_internal.classic_mode'] else
4395 rcParams['lines.markersize'] ** 2.0)
4396 s = np.ma.ravel(s)
4397 if len(s) not in (1, x.size):
4398 raise ValueError("s must be a scalar, or the same size as x and y")
4400 c, colors, edgecolors = \
4401 self._parse_scatter_color_args(
4402 c, edgecolors, kwargs, x.size,
4403 get_next_color_func=self._get_patches_for_fill.get_next_color)
4405 if plotnonfinite and colors is None:
4406 c = np.ma.masked_invalid(c)
4407 x, y, s, edgecolors, linewidths = \
4408 cbook._combine_masks(x, y, s, edgecolors, linewidths)
4409 else:
4410 x, y, s, c, colors, edgecolors, linewidths = \
4411 cbook._combine_masks(
4412 x, y, s, c, colors, edgecolors, linewidths)
4414 scales = s # Renamed for readability below.
4416 # load default marker from rcParams
4417 if marker is None:
4418 marker = rcParams['scatter.marker']
4420 if isinstance(marker, mmarkers.MarkerStyle):
4421 marker_obj = marker
4422 else:
4423 marker_obj = mmarkers.MarkerStyle(marker)
4425 path = marker_obj.get_path().transformed(
4426 marker_obj.get_transform())
4427 if not marker_obj.is_filled():
4428 edgecolors = 'face'
4429 linewidths = rcParams['lines.linewidth']
4431 offsets = np.ma.column_stack([x, y])
4433 collection = mcoll.PathCollection(
4434 (path,), scales,
4435 facecolors=colors,
4436 edgecolors=edgecolors,
4437 linewidths=linewidths,
4438 offsets=offsets,
4439 transOffset=kwargs.pop('transform', self.transData),
4440 alpha=alpha
4441 )
4442 collection.set_transform(mtransforms.IdentityTransform())
4443 collection.update(kwargs)
4445 if colors is None:
4446 collection.set_array(c)
4447 collection.set_cmap(cmap)
4448 collection.set_norm(norm)
4450 if vmin is not None or vmax is not None:
4451 collection.set_clim(vmin, vmax)
4452 else:
4453 collection.autoscale_None()
4455 # Classic mode only:
4456 # ensure there are margins to allow for the
4457 # finite size of the symbols. In v2.x, margins
4458 # are present by default, so we disable this
4459 # scatter-specific override.
4460 if rcParams['_internal.classic_mode']:
4461 if self._xmargin < 0.05 and x.size > 0:
4462 self.set_xmargin(0.05)
4463 if self._ymargin < 0.05 and x.size > 0:
4464 self.set_ymargin(0.05)
4466 self.add_collection(collection)
4467 self._request_autoscale_view()
4469 return collection
4471 @_preprocess_data(replace_names=["x", "y"], label_namer="y")
4472 @docstring.dedent_interpd
4473 def hexbin(self, x, y, C=None, gridsize=100, bins=None,
4474 xscale='linear', yscale='linear', extent=None,
4475 cmap=None, norm=None, vmin=None, vmax=None,
4476 alpha=None, linewidths=None, edgecolors='face',
4477 reduce_C_function=np.mean, mincnt=None, marginals=False,
4478 **kwargs):
4479 """
4480 Make a 2D hexagonal binning plot of points *x*, *y*.
4482 If *C* is *None*, the value of the hexagon is determined by the number
4483 of points in the hexagon. Otherwise, *C* specifies values at the
4484 coordinate (x[i], y[i]). For each hexagon, these values are reduced
4485 using *reduce_C_function*.
4487 Parameters
4488 ----------
4489 x, y : array-like
4490 The data positions. *x* and *y* must be of the same length.
4492 C : array-like, optional
4493 If given, these values are accumulated in the bins. Otherwise,
4494 every point has a value of 1. Must be of the same length as *x*
4495 and *y*.
4497 gridsize : int or (int, int), default: 100
4498 If a single int, the number of hexagons in the *x*-direction.
4499 The number of hexagons in the *y*-direction is chosen such that
4500 the hexagons are approximately regular.
4502 Alternatively, if a tuple (*nx*, *ny*), the number of hexagons
4503 in the *x*-direction and the *y*-direction.
4505 bins : 'log' or int or sequence, default: *None*
4506 Discretization of the hexagon values.
4508 - If *None*, no binning is applied; the color of each hexagon
4509 directly corresponds to its count value.
4510 - If 'log', use a logarithmic scale for the color map.
4511 Internally, :math:`log_{10}(i+1)` is used to determine the
4512 hexagon color. This is equivalent to ``norm=LogNorm()``.
4513 - If an integer, divide the counts in the specified number
4514 of bins, and color the hexagons accordingly.
4515 - If a sequence of values, the values of the lower bound of
4516 the bins to be used.
4518 xscale : {'linear', 'log'}, default: 'linear'
4519 Use a linear or log10 scale on the horizontal axis.
4521 yscale : {'linear', 'log'}, default: 'linear'
4522 Use a linear or log10 scale on the vertical axis.
4524 mincnt : int > 0, default: *None*
4525 If not *None*, only display cells with more than *mincnt*
4526 number of points in the cell.
4528 marginals : bool, default: *False*
4529 If marginals is *True*, plot the marginal density as
4530 colormapped rectangles along the bottom of the x-axis and
4531 left of the y-axis.
4533 extent : float, default: *None*
4534 The limits of the bins. The default assigns the limits
4535 based on *gridsize*, *x*, *y*, *xscale* and *yscale*.
4537 If *xscale* or *yscale* is set to 'log', the limits are
4538 expected to be the exponent for a power of 10. E.g. for
4539 x-limits of 1 and 50 in 'linear' scale and y-limits
4540 of 10 and 1000 in 'log' scale, enter (1, 50, 1, 3).
4542 Order of scalars is (left, right, bottom, top).
4544 Other Parameters
4545 ----------------
4546 cmap : str or `~matplotlib.colors.Colormap`, optional
4547 The Colormap instance or registered colormap name used to map
4548 the bin values to colors. Defaults to :rc:`image.cmap`.
4550 norm : `~matplotlib.colors.Normalize`, optional
4551 The Normalize instance scales the bin values to the canonical
4552 colormap range [0, 1] for mapping to colors. By default, the data
4553 range is mapped to the colorbar range using linear scaling.
4555 vmin, vmax : float, optional, default: None
4556 The colorbar range. If *None*, suitable min/max values are
4557 automatically chosen by the `~.Normalize` instance (defaults to
4558 the respective min/max values of the bins in case of the default
4559 linear scaling). This is ignored if *norm* is given.
4561 alpha : float between 0 and 1, optional
4562 The alpha blending value, between 0 (transparent) and 1 (opaque).
4564 linewidths : float, default: *None*
4565 If *None*, defaults to 1.0.
4567 edgecolors : {'face', 'none', *None*} or color, default: 'face'
4568 The color of the hexagon edges. Possible values are:
4570 - 'face': Draw the edges in the same color as the fill color.
4571 - 'none': No edges are drawn. This can sometimes lead to unsightly
4572 unpainted pixels between the hexagons.
4573 - *None*: Draw outlines in the default color.
4574 - An explicit matplotlib color.
4576 reduce_C_function : callable, default is `numpy.mean`
4577 The function to aggregate *C* within the bins. It is ignored if
4578 *C* is not given. This must have the signature::
4580 def reduce_C_function(C: array) -> float
4582 Commonly used functions are:
4584 - `numpy.mean`: average of the points
4585 - `numpy.sum`: integral of the point values
4586 - `numpy.max`: value taken from the largest point
4588 **kwargs : `~matplotlib.collections.PolyCollection` properties
4589 All other keyword arguments are passed on to `.PolyCollection`:
4591 %(PolyCollection)s
4593 Returns
4594 -------
4595 polycollection : `~matplotlib.collections.PolyCollection`
4596 A `.PolyCollection` defining the hexagonal bins.
4598 - `.PolyCollection.get_offset` contains a Mx2 array containing
4599 the x, y positions of the M hexagon centers.
4600 - `.PolyCollection.get_array` contains the values of the M
4601 hexagons.
4603 If *marginals* is *True*, horizontal
4604 bar and vertical bar (both PolyCollections) will be attached
4605 to the return collection as attributes *hbar* and *vbar*.
4607 """
4608 self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
4610 x, y, C = cbook.delete_masked_points(x, y, C)
4612 # Set the size of the hexagon grid
4613 if np.iterable(gridsize):
4614 nx, ny = gridsize
4615 else:
4616 nx = gridsize
4617 ny = int(nx / math.sqrt(3))
4618 # Count the number of data in each hexagon
4619 x = np.array(x, float)
4620 y = np.array(y, float)
4621 if xscale == 'log':
4622 if np.any(x <= 0.0):
4623 raise ValueError("x contains non-positive values, so can not"
4624 " be log-scaled")
4625 x = np.log10(x)
4626 if yscale == 'log':
4627 if np.any(y <= 0.0):
4628 raise ValueError("y contains non-positive values, so can not"
4629 " be log-scaled")
4630 y = np.log10(y)
4631 if extent is not None:
4632 xmin, xmax, ymin, ymax = extent
4633 else:
4634 xmin, xmax = (np.min(x), np.max(x)) if len(x) else (0, 1)
4635 ymin, ymax = (np.min(y), np.max(y)) if len(y) else (0, 1)
4637 # to avoid issues with singular data, expand the min/max pairs
4638 xmin, xmax = mtransforms.nonsingular(xmin, xmax, expander=0.1)
4639 ymin, ymax = mtransforms.nonsingular(ymin, ymax, expander=0.1)
4641 # In the x-direction, the hexagons exactly cover the region from
4642 # xmin to xmax. Need some padding to avoid roundoff errors.
4643 padding = 1.e-9 * (xmax - xmin)
4644 xmin -= padding
4645 xmax += padding
4646 sx = (xmax - xmin) / nx
4647 sy = (ymax - ymin) / ny
4649 if marginals:
4650 xorig = x.copy()
4651 yorig = y.copy()
4653 x = (x - xmin) / sx
4654 y = (y - ymin) / sy
4655 ix1 = np.round(x).astype(int)
4656 iy1 = np.round(y).astype(int)
4657 ix2 = np.floor(x).astype(int)
4658 iy2 = np.floor(y).astype(int)
4660 nx1 = nx + 1
4661 ny1 = ny + 1
4662 nx2 = nx
4663 ny2 = ny
4664 n = nx1 * ny1 + nx2 * ny2
4666 d1 = (x - ix1) ** 2 + 3.0 * (y - iy1) ** 2
4667 d2 = (x - ix2 - 0.5) ** 2 + 3.0 * (y - iy2 - 0.5) ** 2
4668 bdist = (d1 < d2)
4669 if C is None:
4670 lattice1 = np.zeros((nx1, ny1))
4671 lattice2 = np.zeros((nx2, ny2))
4672 c1 = (0 <= ix1) & (ix1 < nx1) & (0 <= iy1) & (iy1 < ny1) & bdist
4673 c2 = (0 <= ix2) & (ix2 < nx2) & (0 <= iy2) & (iy2 < ny2) & ~bdist
4674 np.add.at(lattice1, (ix1[c1], iy1[c1]), 1)
4675 np.add.at(lattice2, (ix2[c2], iy2[c2]), 1)
4676 if mincnt is not None:
4677 lattice1[lattice1 < mincnt] = np.nan
4678 lattice2[lattice2 < mincnt] = np.nan
4679 accum = np.concatenate([lattice1.ravel(), lattice2.ravel()])
4680 good_idxs = ~np.isnan(accum)
4682 else:
4683 if mincnt is None:
4684 mincnt = 0
4686 # create accumulation arrays
4687 lattice1 = np.empty((nx1, ny1), dtype=object)
4688 for i in range(nx1):
4689 for j in range(ny1):
4690 lattice1[i, j] = []
4691 lattice2 = np.empty((nx2, ny2), dtype=object)
4692 for i in range(nx2):
4693 for j in range(ny2):
4694 lattice2[i, j] = []
4696 for i in range(len(x)):
4697 if bdist[i]:
4698 if 0 <= ix1[i] < nx1 and 0 <= iy1[i] < ny1:
4699 lattice1[ix1[i], iy1[i]].append(C[i])
4700 else:
4701 if 0 <= ix2[i] < nx2 and 0 <= iy2[i] < ny2:
4702 lattice2[ix2[i], iy2[i]].append(C[i])
4704 for i in range(nx1):
4705 for j in range(ny1):
4706 vals = lattice1[i, j]
4707 if len(vals) > mincnt:
4708 lattice1[i, j] = reduce_C_function(vals)
4709 else:
4710 lattice1[i, j] = np.nan
4711 for i in range(nx2):
4712 for j in range(ny2):
4713 vals = lattice2[i, j]
4714 if len(vals) > mincnt:
4715 lattice2[i, j] = reduce_C_function(vals)
4716 else:
4717 lattice2[i, j] = np.nan
4719 accum = np.hstack((lattice1.astype(float).ravel(),
4720 lattice2.astype(float).ravel()))
4721 good_idxs = ~np.isnan(accum)
4723 offsets = np.zeros((n, 2), float)
4724 offsets[:nx1 * ny1, 0] = np.repeat(np.arange(nx1), ny1)
4725 offsets[:nx1 * ny1, 1] = np.tile(np.arange(ny1), nx1)
4726 offsets[nx1 * ny1:, 0] = np.repeat(np.arange(nx2) + 0.5, ny2)
4727 offsets[nx1 * ny1:, 1] = np.tile(np.arange(ny2), nx2) + 0.5
4728 offsets[:, 0] *= sx
4729 offsets[:, 1] *= sy
4730 offsets[:, 0] += xmin
4731 offsets[:, 1] += ymin
4732 # remove accumulation bins with no data
4733 offsets = offsets[good_idxs, :]
4734 accum = accum[good_idxs]
4736 polygon = [sx, sy / 3] * np.array(
4737 [[.5, -.5], [.5, .5], [0., 1.], [-.5, .5], [-.5, -.5], [0., -1.]])
4739 if linewidths is None:
4740 linewidths = [1.0]
4742 if xscale == 'log' or yscale == 'log':
4743 polygons = np.expand_dims(polygon, 0) + np.expand_dims(offsets, 1)
4744 if xscale == 'log':
4745 polygons[:, :, 0] = 10.0 ** polygons[:, :, 0]
4746 xmin = 10.0 ** xmin
4747 xmax = 10.0 ** xmax
4748 self.set_xscale(xscale)
4749 if yscale == 'log':
4750 polygons[:, :, 1] = 10.0 ** polygons[:, :, 1]
4751 ymin = 10.0 ** ymin
4752 ymax = 10.0 ** ymax
4753 self.set_yscale(yscale)
4754 collection = mcoll.PolyCollection(
4755 polygons,
4756 edgecolors=edgecolors,
4757 linewidths=linewidths,
4758 )
4759 else:
4760 collection = mcoll.PolyCollection(
4761 [polygon],
4762 edgecolors=edgecolors,
4763 linewidths=linewidths,
4764 offsets=offsets,
4765 transOffset=mtransforms.IdentityTransform(),
4766 offset_position="data"
4767 )
4769 # Set normalizer if bins is 'log'
4770 if bins == 'log':
4771 if norm is not None:
4772 cbook._warn_external("Only one of 'bins' and 'norm' "
4773 "arguments can be supplied, ignoring "
4774 "bins={}".format(bins))
4775 else:
4776 norm = mcolors.LogNorm()
4777 bins = None
4779 if isinstance(norm, mcolors.LogNorm):
4780 if (accum == 0).any():
4781 # make sure we have no zeros
4782 accum += 1
4784 # autoscale the norm with curren accum values if it hasn't
4785 # been set
4786 if norm is not None:
4787 if norm.vmin is None and norm.vmax is None:
4788 norm.autoscale(accum)
4790 if bins is not None:
4791 if not np.iterable(bins):
4792 minimum, maximum = min(accum), max(accum)
4793 bins -= 1 # one less edge than bins
4794 bins = minimum + (maximum - minimum) * np.arange(bins) / bins
4795 bins = np.sort(bins)
4796 accum = bins.searchsorted(accum)
4798 collection.set_array(accum)
4799 collection.set_cmap(cmap)
4800 collection.set_norm(norm)
4801 collection.set_alpha(alpha)
4802 collection.update(kwargs)
4804 if vmin is not None or vmax is not None:
4805 collection.set_clim(vmin, vmax)
4806 else:
4807 collection.autoscale_None()
4809 corners = ((xmin, ymin), (xmax, ymax))
4810 self.update_datalim(corners)
4811 self._request_autoscale_view(tight=True)
4813 # add the collection last
4814 self.add_collection(collection, autolim=False)
4815 if not marginals:
4816 return collection
4818 if C is None:
4819 C = np.ones(len(x))
4821 def coarse_bin(x, y, coarse):
4822 ind = coarse.searchsorted(x).clip(0, len(coarse) - 1)
4823 mus = np.zeros(len(coarse))
4824 for i in range(len(coarse)):
4825 yi = y[ind == i]
4826 if len(yi) > 0:
4827 mu = reduce_C_function(yi)
4828 else:
4829 mu = np.nan
4830 mus[i] = mu
4831 return mus
4833 coarse = np.linspace(xmin, xmax, gridsize)
4835 xcoarse = coarse_bin(xorig, C, coarse)
4836 valid = ~np.isnan(xcoarse)
4837 verts, values = [], []
4838 for i, val in enumerate(xcoarse):
4839 thismin = coarse[i]
4840 if i < len(coarse) - 1:
4841 thismax = coarse[i + 1]
4842 else:
4843 thismax = thismin + np.diff(coarse)[-1]
4845 if not valid[i]:
4846 continue
4848 verts.append([(thismin, 0),
4849 (thismin, 0.05),
4850 (thismax, 0.05),
4851 (thismax, 0)])
4852 values.append(val)
4854 values = np.array(values)
4855 trans = self.get_xaxis_transform(which='grid')
4857 hbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face')
4859 hbar.set_array(values)
4860 hbar.set_cmap(cmap)
4861 hbar.set_norm(norm)
4862 hbar.set_alpha(alpha)
4863 hbar.update(kwargs)
4864 self.add_collection(hbar, autolim=False)
4866 coarse = np.linspace(ymin, ymax, gridsize)
4867 ycoarse = coarse_bin(yorig, C, coarse)
4868 valid = ~np.isnan(ycoarse)
4869 verts, values = [], []
4870 for i, val in enumerate(ycoarse):
4871 thismin = coarse[i]
4872 if i < len(coarse) - 1:
4873 thismax = coarse[i + 1]
4874 else:
4875 thismax = thismin + np.diff(coarse)[-1]
4876 if not valid[i]:
4877 continue
4878 verts.append([(0, thismin), (0.0, thismax),
4879 (0.05, thismax), (0.05, thismin)])
4880 values.append(val)
4882 values = np.array(values)
4884 trans = self.get_yaxis_transform(which='grid')
4886 vbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face')
4887 vbar.set_array(values)
4888 vbar.set_cmap(cmap)
4889 vbar.set_norm(norm)
4890 vbar.set_alpha(alpha)
4891 vbar.update(kwargs)
4892 self.add_collection(vbar, autolim=False)
4894 collection.hbar = hbar
4895 collection.vbar = vbar
4897 def on_changed(collection):
4898 hbar.set_cmap(collection.get_cmap())
4899 hbar.set_clim(collection.get_clim())
4900 vbar.set_cmap(collection.get_cmap())
4901 vbar.set_clim(collection.get_clim())
4903 collection.callbacksSM.connect('changed', on_changed)
4905 return collection
4907 @docstring.dedent_interpd
4908 def arrow(self, x, y, dx, dy, **kwargs):
4909 """
4910 Add an arrow to the axes.
4912 This draws an arrow from ``(x, y)`` to ``(x+dx, y+dy)``.
4914 Parameters
4915 ----------
4916 x, y : float
4917 The x and y coordinates of the arrow base.
4918 dx, dy : float
4919 The length of the arrow along x and y direction.
4921 Returns
4922 -------
4923 arrow : `.FancyArrow`
4924 The created `.FancyArrow` object.
4926 Other Parameters
4927 ----------------
4928 **kwargs
4929 Optional kwargs (inherited from `.FancyArrow` patch) control the
4930 arrow construction and properties:
4932 %(FancyArrow)s
4934 Notes
4935 -----
4936 The resulting arrow is affected by the axes aspect ratio and limits.
4937 This may produce an arrow whose head is not square with its stem. To
4938 create an arrow whose head is square with its stem,
4939 use :meth:`annotate` for example:
4941 >>> ax.annotate("", xy=(0.5, 0.5), xytext=(0, 0),
4942 ... arrowprops=dict(arrowstyle="->"))
4944 """
4945 # Strip away units for the underlying patch since units
4946 # do not make sense to most patch-like code
4947 x = self.convert_xunits(x)
4948 y = self.convert_yunits(y)
4949 dx = self.convert_xunits(dx)
4950 dy = self.convert_yunits(dy)
4952 a = mpatches.FancyArrow(x, y, dx, dy, **kwargs)
4953 self.add_artist(a)
4954 return a
4956 @docstring.copy(mquiver.QuiverKey.__init__)
4957 def quiverkey(self, Q, X, Y, U, label, **kw):
4958 qk = mquiver.QuiverKey(Q, X, Y, U, label, **kw)
4959 self.add_artist(qk)
4960 return qk
4962 # Handle units for x and y, if they've been passed
4963 def _quiver_units(self, args, kw):
4964 if len(args) > 3:
4965 x, y = args[0:2]
4966 self._process_unit_info(xdata=x, ydata=y, kwargs=kw)
4967 x = self.convert_xunits(x)
4968 y = self.convert_yunits(y)
4969 return (x, y) + args[2:]
4970 return args
4972 # args can by a combination if X, Y, U, V, C and all should be replaced
4973 @_preprocess_data()
4974 def quiver(self, *args, **kw):
4975 # Make sure units are handled for x and y values
4976 args = self._quiver_units(args, kw)
4978 q = mquiver.Quiver(self, *args, **kw)
4980 self.add_collection(q, autolim=True)
4981 self._request_autoscale_view()
4982 return q
4983 quiver.__doc__ = mquiver.Quiver.quiver_doc
4985 # args can be some combination of X, Y, U, V, C and all should be replaced
4986 @_preprocess_data()
4987 @docstring.dedent_interpd
4988 def barbs(self, *args, **kw):
4989 """
4990 %(barbs_doc)s
4991 """
4992 # Make sure units are handled for x and y values
4993 args = self._quiver_units(args, kw)
4995 b = mquiver.Barbs(self, *args, **kw)
4996 self.add_collection(b, autolim=True)
4997 self._request_autoscale_view()
4998 return b
5000 # Uses a custom implementation of data-kwarg handling in
5001 # _process_plot_var_args.
5002 def fill(self, *args, data=None, **kwargs):
5003 """
5004 Plot filled polygons.
5006 Parameters
5007 ----------
5008 *args : sequence of x, y, [color]
5009 Each polygon is defined by the lists of *x* and *y* positions of
5010 its nodes, optionally followed by a *color* specifier. See
5011 :mod:`matplotlib.colors` for supported color specifiers. The
5012 standard color cycle is used for polygons without a color
5013 specifier.
5015 You can plot multiple polygons by providing multiple *x*, *y*,
5016 *[color]* groups.
5018 For example, each of the following is legal::
5020 ax.fill(x, y) # a polygon with default color
5021 ax.fill(x, y, "b") # a blue polygon
5022 ax.fill(x, y, x2, y2) # two polygons
5023 ax.fill(x, y, "b", x2, y2, "r") # a blue and a red polygon
5025 data : indexable object, optional
5026 An object with labelled data. If given, provide the label names to
5027 plot in *x* and *y*, e.g.::
5029 ax.fill("time", "signal",
5030 data={"time": [0, 1, 2], "signal": [0, 1, 0]})
5032 Returns
5033 -------
5034 a list of :class:`~matplotlib.patches.Polygon`
5036 Other Parameters
5037 ----------------
5038 **kwargs : :class:`~matplotlib.patches.Polygon` properties
5040 Notes
5041 -----
5042 Use :meth:`fill_between` if you would like to fill the region between
5043 two curves.
5044 """
5045 # For compatibility(!), get aliases from Line2D rather than Patch.
5046 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
5047 # _get_patches_for_fill returns a generator, convert it to a list.
5048 patches = [*self._get_patches_for_fill(*args, data=data, **kwargs)]
5049 for poly in patches:
5050 self.add_patch(poly)
5051 self._request_autoscale_view()
5052 return patches
5054 @_preprocess_data(replace_names=["x", "y1", "y2", "where"])
5055 @docstring.dedent_interpd
5056 def fill_between(self, x, y1, y2=0, where=None, interpolate=False,
5057 step=None, **kwargs):
5058 """
5059 Fill the area between two horizontal curves.
5061 The curves are defined by the points (*x*, *y1*) and (*x*, *y2*). This
5062 creates one or multiple polygons describing the filled area.
5064 You may exclude some horizontal sections from filling using *where*.
5066 By default, the edges connect the given points directly. Use *step* if
5067 the filling should be a step function, i.e. constant in between *x*.
5070 Parameters
5071 ----------
5072 x : array (length N)
5073 The x coordinates of the nodes defining the curves.
5075 y1 : array (length N) or scalar
5076 The y coordinates of the nodes defining the first curve.
5078 y2 : array (length N) or scalar, optional, default: 0
5079 The y coordinates of the nodes defining the second curve.
5081 where : array of bool (length N), optional, default: None
5082 Define *where* to exclude some horizontal regions from being
5083 filled. The filled regions are defined by the coordinates
5084 ``x[where]``. More precisely, fill between ``x[i]`` and ``x[i+1]``
5085 if ``where[i] and where[i+1]``. Note that this definition implies
5086 that an isolated *True* value between two *False* values in
5087 *where* will not result in filling. Both sides of the *True*
5088 position remain unfilled due to the adjacent *False* values.
5090 interpolate : bool, optional
5091 This option is only relevant if *where* is used and the two curves
5092 are crossing each other.
5094 Semantically, *where* is often used for *y1* > *y2* or similar.
5095 By default, the nodes of the polygon defining the filled region
5096 will only be placed at the positions in the *x* array. Such a
5097 polygon cannot describe the above semantics close to the
5098 intersection. The x-sections containing the intersection are
5099 simply clipped.
5101 Setting *interpolate* to *True* will calculate the actual
5102 intersection point and extend the filled region up to this point.
5104 step : {'pre', 'post', 'mid'}, optional
5105 Define *step* if the filling should be a step function,
5106 i.e. constant in between *x*. The value determines where the
5107 step will occur:
5109 - 'pre': The y value is continued constantly to the left from
5110 every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
5111 value ``y[i]``.
5112 - 'post': The y value is continued constantly to the right from
5113 every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
5114 value ``y[i]``.
5115 - 'mid': Steps occur half-way between the *x* positions.
5117 Other Parameters
5118 ----------------
5119 **kwargs
5120 All other keyword arguments are passed on to `.PolyCollection`.
5121 They control the `.Polygon` properties:
5123 %(PolyCollection)s
5125 Returns
5126 -------
5127 `.PolyCollection`
5128 A `.PolyCollection` containing the plotted polygons.
5130 See Also
5131 --------
5132 fill_betweenx : Fill between two sets of x-values.
5134 Notes
5135 -----
5136 .. [notes section required to get data note injection right]
5138 """
5139 if not rcParams['_internal.classic_mode']:
5140 kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection)
5141 if not any(c in kwargs for c in ('color', 'facecolor')):
5142 kwargs['facecolor'] = \
5143 self._get_patches_for_fill.get_next_color()
5145 # Handle united data, such as dates
5146 self._process_unit_info(xdata=x, ydata=y1, kwargs=kwargs)
5147 self._process_unit_info(ydata=y2)
5149 # Convert the arrays so we can work with them
5150 x = ma.masked_invalid(self.convert_xunits(x))
5151 y1 = ma.masked_invalid(self.convert_yunits(y1))
5152 y2 = ma.masked_invalid(self.convert_yunits(y2))
5154 for name, array in [('x', x), ('y1', y1), ('y2', y2)]:
5155 if array.ndim > 1:
5156 raise ValueError('Input passed into argument "%r"' % name +
5157 'is not 1-dimensional.')
5159 if where is None:
5160 where = True
5161 else:
5162 where = np.asarray(where, dtype=bool)
5163 if where.size != x.size:
5164 cbook.warn_deprecated(
5165 "3.2",
5166 message="The parameter where must have the same size as x "
5167 "in fill_between(). This will become an error in "
5168 "future versions of Matplotlib.")
5169 where = where & ~functools.reduce(np.logical_or,
5170 map(np.ma.getmask, [x, y1, y2]))
5172 x, y1, y2 = np.broadcast_arrays(np.atleast_1d(x), y1, y2)
5174 polys = []
5175 for ind0, ind1 in cbook.contiguous_regions(where):
5176 xslice = x[ind0:ind1]
5177 y1slice = y1[ind0:ind1]
5178 y2slice = y2[ind0:ind1]
5179 if step is not None:
5180 step_func = cbook.STEP_LOOKUP_MAP["steps-" + step]
5181 xslice, y1slice, y2slice = step_func(xslice, y1slice, y2slice)
5183 if not len(xslice):
5184 continue
5186 N = len(xslice)
5187 X = np.zeros((2 * N + 2, 2), float)
5189 if interpolate:
5190 def get_interp_point(ind):
5191 im1 = max(ind - 1, 0)
5192 x_values = x[im1:ind + 1]
5193 diff_values = y1[im1:ind + 1] - y2[im1:ind + 1]
5194 y1_values = y1[im1:ind + 1]
5196 if len(diff_values) == 2:
5197 if np.ma.is_masked(diff_values[1]):
5198 return x[im1], y1[im1]
5199 elif np.ma.is_masked(diff_values[0]):
5200 return x[ind], y1[ind]
5202 diff_order = diff_values.argsort()
5203 diff_root_x = np.interp(
5204 0, diff_values[diff_order], x_values[diff_order])
5205 x_order = x_values.argsort()
5206 diff_root_y = np.interp(diff_root_x, x_values[x_order],
5207 y1_values[x_order])
5208 return diff_root_x, diff_root_y
5210 start = get_interp_point(ind0)
5211 end = get_interp_point(ind1)
5212 else:
5213 # the purpose of the next two lines is for when y2 is a
5214 # scalar like 0 and we want the fill to go all the way
5215 # down to 0 even if none of the y1 sample points do
5216 start = xslice[0], y2slice[0]
5217 end = xslice[-1], y2slice[-1]
5219 X[0] = start
5220 X[N + 1] = end
5222 X[1:N + 1, 0] = xslice
5223 X[1:N + 1, 1] = y1slice
5224 X[N + 2:, 0] = xslice[::-1]
5225 X[N + 2:, 1] = y2slice[::-1]
5227 polys.append(X)
5229 collection = mcoll.PolyCollection(polys, **kwargs)
5231 # now update the datalim and autoscale
5232 XY1 = np.array([x[where], y1[where]]).T
5233 XY2 = np.array([x[where], y2[where]]).T
5234 self.dataLim.update_from_data_xy(XY1, self.ignore_existing_data_limits,
5235 updatex=True, updatey=True)
5236 self.ignore_existing_data_limits = False
5237 self.dataLim.update_from_data_xy(XY2, self.ignore_existing_data_limits,
5238 updatex=False, updatey=True)
5239 self.add_collection(collection, autolim=False)
5240 self._request_autoscale_view()
5241 return collection
5243 @_preprocess_data(replace_names=["y", "x1", "x2", "where"])
5244 @docstring.dedent_interpd
5245 def fill_betweenx(self, y, x1, x2=0, where=None,
5246 step=None, interpolate=False, **kwargs):
5247 """
5248 Fill the area between two vertical curves.
5250 The curves are defined by the points (*x1*, *y*) and (*x2*, *y*). This
5251 creates one or multiple polygons describing the filled area.
5253 You may exclude some vertical sections from filling using *where*.
5255 By default, the edges connect the given points directly. Use *step* if
5256 the filling should be a step function, i.e. constant in between *y*.
5259 Parameters
5260 ----------
5261 y : array (length N)
5262 The y coordinates of the nodes defining the curves.
5264 x1 : array (length N) or scalar
5265 The x coordinates of the nodes defining the first curve.
5267 x2 : array (length N) or scalar, optional, default: 0
5268 The x coordinates of the nodes defining the second curve.
5270 where : array of bool (length N), optional, default: None
5271 Define *where* to exclude some vertical regions from being
5272 filled. The filled regions are defined by the coordinates
5273 ``y[where]``. More precisely, fill between ``y[i]`` and ``y[i+1]``
5274 if ``where[i] and where[i+1]``. Note that this definition implies
5275 that an isolated *True* value between two *False* values in
5276 *where* will not result in filling. Both sides of the *True*
5277 position remain unfilled due to the adjacent *False* values.
5279 interpolate : bool, optional
5280 This option is only relevant if *where* is used and the two curves
5281 are crossing each other.
5283 Semantically, *where* is often used for *x1* > *x2* or similar.
5284 By default, the nodes of the polygon defining the filled region
5285 will only be placed at the positions in the *y* array. Such a
5286 polygon cannot describe the above semantics close to the
5287 intersection. The y-sections containing the intersection are
5288 simply clipped.
5290 Setting *interpolate* to *True* will calculate the actual
5291 intersection point and extend the filled region up to this point.
5293 step : {'pre', 'post', 'mid'}, optional
5294 Define *step* if the filling should be a step function,
5295 i.e. constant in between *y*. The value determines where the
5296 step will occur:
5298 - 'pre': The y value is continued constantly to the left from
5299 every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
5300 value ``y[i]``.
5301 - 'post': The y value is continued constantly to the right from
5302 every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
5303 value ``y[i]``.
5304 - 'mid': Steps occur half-way between the *x* positions.
5306 Other Parameters
5307 ----------------
5308 **kwargs
5309 All other keyword arguments are passed on to `.PolyCollection`.
5310 They control the `.Polygon` properties:
5312 %(PolyCollection)s
5314 Returns
5315 -------
5316 `.PolyCollection`
5317 A `.PolyCollection` containing the plotted polygons.
5319 See Also
5320 --------
5321 fill_between : Fill between two sets of y-values.
5323 Notes
5324 -----
5325 .. [notes section required to get data note injection right]
5327 """
5328 if not rcParams['_internal.classic_mode']:
5329 kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection)
5330 if not any(c in kwargs for c in ('color', 'facecolor')):
5331 kwargs['facecolor'] = \
5332 self._get_patches_for_fill.get_next_color()
5334 # Handle united data, such as dates
5335 self._process_unit_info(ydata=y, xdata=x1, kwargs=kwargs)
5336 self._process_unit_info(xdata=x2)
5338 # Convert the arrays so we can work with them
5339 y = ma.masked_invalid(self.convert_yunits(y))
5340 x1 = ma.masked_invalid(self.convert_xunits(x1))
5341 x2 = ma.masked_invalid(self.convert_xunits(x2))
5343 for name, array in [('y', y), ('x1', x1), ('x2', x2)]:
5344 if array.ndim > 1:
5345 raise ValueError('Input passed into argument "%r"' % name +
5346 'is not 1-dimensional.')
5348 if where is None:
5349 where = True
5350 else:
5351 where = np.asarray(where, dtype=bool)
5352 if where.size != y.size:
5353 cbook.warn_deprecated(
5354 "3.2",
5355 message="The parameter where must have the same size as y "
5356 "in fill_between(). This will become an error in "
5357 "future versions of Matplotlib.")
5358 where = where & ~functools.reduce(np.logical_or,
5359 map(np.ma.getmask, [y, x1, x2]))
5361 y, x1, x2 = np.broadcast_arrays(np.atleast_1d(y), x1, x2)
5363 polys = []
5364 for ind0, ind1 in cbook.contiguous_regions(where):
5365 yslice = y[ind0:ind1]
5366 x1slice = x1[ind0:ind1]
5367 x2slice = x2[ind0:ind1]
5368 if step is not None:
5369 step_func = cbook.STEP_LOOKUP_MAP["steps-" + step]
5370 yslice, x1slice, x2slice = step_func(yslice, x1slice, x2slice)
5372 if not len(yslice):
5373 continue
5375 N = len(yslice)
5376 Y = np.zeros((2 * N + 2, 2), float)
5377 if interpolate:
5378 def get_interp_point(ind):
5379 im1 = max(ind - 1, 0)
5380 y_values = y[im1:ind + 1]
5381 diff_values = x1[im1:ind + 1] - x2[im1:ind + 1]
5382 x1_values = x1[im1:ind + 1]
5384 if len(diff_values) == 2:
5385 if np.ma.is_masked(diff_values[1]):
5386 return x1[im1], y[im1]
5387 elif np.ma.is_masked(diff_values[0]):
5388 return x1[ind], y[ind]
5390 diff_order = diff_values.argsort()
5391 diff_root_y = np.interp(
5392 0, diff_values[diff_order], y_values[diff_order])
5393 y_order = y_values.argsort()
5394 diff_root_x = np.interp(diff_root_y, y_values[y_order],
5395 x1_values[y_order])
5396 return diff_root_x, diff_root_y
5398 start = get_interp_point(ind0)
5399 end = get_interp_point(ind1)
5400 else:
5401 # the purpose of the next two lines is for when x2 is a
5402 # scalar like 0 and we want the fill to go all the way
5403 # down to 0 even if none of the x1 sample points do
5404 start = x2slice[0], yslice[0]
5405 end = x2slice[-1], yslice[-1]
5407 Y[0] = start
5408 Y[N + 1] = end
5410 Y[1:N + 1, 0] = x1slice
5411 Y[1:N + 1, 1] = yslice
5412 Y[N + 2:, 0] = x2slice[::-1]
5413 Y[N + 2:, 1] = yslice[::-1]
5415 polys.append(Y)
5417 collection = mcoll.PolyCollection(polys, **kwargs)
5419 # now update the datalim and autoscale
5420 X1Y = np.array([x1[where], y[where]]).T
5421 X2Y = np.array([x2[where], y[where]]).T
5422 self.dataLim.update_from_data_xy(X1Y, self.ignore_existing_data_limits,
5423 updatex=True, updatey=True)
5424 self.ignore_existing_data_limits = False
5425 self.dataLim.update_from_data_xy(X2Y, self.ignore_existing_data_limits,
5426 updatex=True, updatey=False)
5427 self.add_collection(collection, autolim=False)
5428 self._request_autoscale_view()
5429 return collection
5431 #### plotting z(x, y): imshow, pcolor and relatives, contour
5432 @_preprocess_data()
5433 @cbook._delete_parameter("3.1", "shape")
5434 @cbook._delete_parameter("3.1", "imlim")
5435 def imshow(self, X, cmap=None, norm=None, aspect=None,
5436 interpolation=None, alpha=None, vmin=None, vmax=None,
5437 origin=None, extent=None, shape=None, filternorm=1,
5438 filterrad=4.0, imlim=None, resample=None, url=None, **kwargs):
5439 """
5440 Display data as an image; i.e. on a 2D regular raster.
5442 The input may either be actual RGB(A) data, or 2D scalar data, which
5443 will be rendered as a pseudocolor image. Note: For actually displaying
5444 a grayscale image set up the color mapping using the parameters
5445 ``cmap='gray', vmin=0, vmax=255``.
5447 Parameters
5448 ----------
5449 X : array-like or PIL image
5450 The image data. Supported array shapes are:
5452 - (M, N): an image with scalar data. The values are mapped to
5453 colors using normalization and a colormap. See parameters *norm*,
5454 *cmap*, *vmin*, *vmax*.
5455 - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
5456 - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
5457 i.e. including transparency.
5459 The first two dimensions (M, N) define the rows and columns of
5460 the image.
5462 Out-of-range RGB(A) values are clipped.
5464 cmap : str or `~matplotlib.colors.Colormap`, optional
5465 The Colormap instance or registered colormap name used to map
5466 scalar data to colors. This parameter is ignored for RGB(A) data.
5467 Defaults to :rc:`image.cmap`.
5469 norm : `~matplotlib.colors.Normalize`, optional
5470 The `Normalize` instance used to scale scalar data to the [0, 1]
5471 range before mapping to colors using *cmap*. By default, a linear
5472 scaling mapping the lowest value to 0 and the highest to 1 is used.
5473 This parameter is ignored for RGB(A) data.
5475 aspect : {'equal', 'auto'} or float, optional
5476 Controls the aspect ratio of the axes. The aspect is of particular
5477 relevance for images since it may distort the image, i.e. pixel
5478 will not be square.
5480 This parameter is a shortcut for explicitly calling
5481 `.Axes.set_aspect`. See there for further details.
5483 - 'equal': Ensures an aspect ratio of 1. Pixels will be square
5484 (unless pixel sizes are explicitly made non-square in data
5485 coordinates using *extent*).
5486 - 'auto': The axes is kept fixed and the aspect is adjusted so
5487 that the data fit in the axes. In general, this will result in
5488 non-square pixels.
5490 If not given, use :rc:`image.aspect`.
5492 interpolation : str, optional
5493 The interpolation method used. If *None*, :rc:`image.interpolation`
5494 is used.
5496 Supported values are 'none', 'antialiased', 'nearest', 'bilinear',
5497 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite',
5498 'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell',
5499 'sinc', 'lanczos'.
5501 If *interpolation* is 'none', then no interpolation is performed
5502 on the Agg, ps, pdf and svg backends. Other backends will fall back
5503 to 'nearest'. Note that most SVG renders perform interpolation at
5504 rendering and that the default interpolation method they implement
5505 may differ.
5507 If *interpolation* is the default 'antialiased', then 'nearest'
5508 interpolation is used if the image is upsampled by more than a
5509 factor of three (i.e. the number of display pixels is at least
5510 three times the size of the data array). If the upsampling rate is
5511 smaller than 3, or the image is downsampled, then 'hanning'
5512 interpolation is used to act as an anti-aliasing filter, unless the
5513 image happens to be upsampled by exactly a factor of two or one.
5515 See
5516 :doc:`/gallery/images_contours_and_fields/interpolation_methods`
5517 for an overview of the supported interpolation methods, and
5518 :doc:`/gallery/images_contours_and_fields/image_antialiasing` for
5519 a discussion of image antialiasing.
5521 Some interpolation methods require an additional radius parameter,
5522 which can be set by *filterrad*. Additionally, the antigrain image
5523 resize filter is controlled by the parameter *filternorm*.
5525 alpha : scalar or array-like, optional
5526 The alpha blending value, between 0 (transparent) and 1 (opaque).
5527 If *alpha* is an array, the alpha blending values are applied pixel
5528 by pixel, and *alpha* must have the same shape as *X*.
5530 vmin, vmax : scalar, optional
5531 When using scalar data and no explicit *norm*, *vmin* and *vmax*
5532 define the data range that the colormap covers. By default,
5533 the colormap covers the complete value range of the supplied
5534 data. *vmin*, *vmax* are ignored if the *norm* parameter is used.
5536 origin : {'upper', 'lower'}, optional
5537 Place the [0, 0] index of the array in the upper left or lower left
5538 corner of the axes. The convention 'upper' is typically used for
5539 matrices and images.
5540 If not given, :rc:`image.origin` is used, defaulting to 'upper'.
5542 Note that the vertical axes points upward for 'lower'
5543 but downward for 'upper'.
5545 See the :doc:`/tutorials/intermediate/imshow_extent` tutorial for
5546 examples and a more detailed description.
5548 extent : scalars (left, right, bottom, top), optional
5549 The bounding box in data coordinates that the image will fill.
5550 The image is stretched individually along x and y to fill the box.
5552 The default extent is determined by the following conditions.
5553 Pixels have unit size in data coordinates. Their centers are on
5554 integer coordinates, and their center coordinates range from 0 to
5555 columns-1 horizontally and from 0 to rows-1 vertically.
5557 Note that the direction of the vertical axis and thus the default
5558 values for top and bottom depend on *origin*:
5560 - For ``origin == 'upper'`` the default is
5561 ``(-0.5, numcols-0.5, numrows-0.5, -0.5)``.
5562 - For ``origin == 'lower'`` the default is
5563 ``(-0.5, numcols-0.5, -0.5, numrows-0.5)``.
5565 See the :doc:`/tutorials/intermediate/imshow_extent` tutorial for
5566 examples and a more detailed description.
5568 filternorm : bool, optional, default: True
5569 A parameter for the antigrain image resize filter (see the
5570 antigrain documentation). If *filternorm* is set, the filter
5571 normalizes integer values and corrects the rounding errors. It
5572 doesn't do anything with the source floating point values, it
5573 corrects only integers according to the rule of 1.0 which means
5574 that any sum of pixel weights must be equal to 1.0. So, the
5575 filter function must produce a graph of the proper shape.
5577 filterrad : float > 0, optional, default: 4.0
5578 The filter radius for filters that have a radius parameter, i.e.
5579 when interpolation is one of: 'sinc', 'lanczos' or 'blackman'.
5581 resample : bool, optional
5582 When *True*, use a full resampling method. When *False*, only
5583 resample when the output image is larger than the input image.
5585 url : str, optional
5586 Set the url of the created `.AxesImage`. See `.Artist.set_url`.
5588 Returns
5589 -------
5590 image : `~matplotlib.image.AxesImage`
5592 Other Parameters
5593 ----------------
5594 **kwargs : `~matplotlib.artist.Artist` properties
5595 These parameters are passed on to the constructor of the
5596 `.AxesImage` artist.
5598 See also
5599 --------
5600 matshow : Plot a matrix or an array as an image.
5602 Notes
5603 -----
5604 Unless *extent* is used, pixel centers will be located at integer
5605 coordinates. In other words: the origin will coincide with the center
5606 of pixel (0, 0).
5608 There are two common representations for RGB images with an alpha
5609 channel:
5611 - Straight (unassociated) alpha: R, G, and B channels represent the
5612 color of the pixel, disregarding its opacity.
5613 - Premultiplied (associated) alpha: R, G, and B channels represent
5614 the color of the pixel, adjusted for its opacity by multiplication.
5616 `~matplotlib.pyplot.imshow` expects RGB images adopting the straight
5617 (unassociated) alpha representation.
5618 """
5619 if aspect is None:
5620 aspect = rcParams['image.aspect']
5621 self.set_aspect(aspect)
5622 im = mimage.AxesImage(self, cmap, norm, interpolation, origin, extent,
5623 filternorm=filternorm, filterrad=filterrad,
5624 resample=resample, **kwargs)
5626 im.set_data(X)
5627 im.set_alpha(alpha)
5628 if im.get_clip_path() is None:
5629 # image does not already have clipping set, clip to axes patch
5630 im.set_clip_path(self.patch)
5631 if vmin is not None or vmax is not None:
5632 im.set_clim(vmin, vmax)
5633 else:
5634 im.autoscale_None()
5635 im.set_url(url)
5637 # update ax.dataLim, and, if autoscaling, set viewLim
5638 # to tightly fit the image, regardless of dataLim.
5639 im.set_extent(im.get_extent())
5641 self.add_image(im)
5642 return im
5644 @staticmethod
5645 def _pcolorargs(funcname, *args, allmatch=False):
5646 # If allmatch is True, then the incoming X, Y, C must have matching
5647 # dimensions, taking into account that X and Y can be 1-D rather than
5648 # 2-D. This perfect match is required for Gouraud shading. For flat
5649 # shading, X and Y specify boundaries, so we need one more boundary
5650 # than color in each direction. For convenience, and consistent with
5651 # Matlab, we discard the last row and/or column of C if necessary to
5652 # meet this condition. This is done if allmatch is False.
5654 if len(args) == 1:
5655 C = np.asanyarray(args[0])
5656 nrows, ncols = C.shape
5657 if allmatch:
5658 X, Y = np.meshgrid(np.arange(ncols), np.arange(nrows))
5659 else:
5660 X, Y = np.meshgrid(np.arange(ncols + 1), np.arange(nrows + 1))
5661 C = cbook.safe_masked_invalid(C)
5662 return X, Y, C
5664 if len(args) == 3:
5665 # Check x and y for bad data...
5666 C = np.asanyarray(args[2])
5667 X, Y = [cbook.safe_masked_invalid(a) for a in args[:2]]
5668 if funcname == 'pcolormesh':
5669 if np.ma.is_masked(X) or np.ma.is_masked(Y):
5670 raise ValueError(
5671 'x and y arguments to pcolormesh cannot have '
5672 'non-finite values or be of type '
5673 'numpy.ma.core.MaskedArray with masked values')
5674 # safe_masked_invalid() returns an ndarray for dtypes other
5675 # than floating point.
5676 if isinstance(X, np.ma.core.MaskedArray):
5677 X = X.data # strip mask as downstream doesn't like it...
5678 if isinstance(Y, np.ma.core.MaskedArray):
5679 Y = Y.data
5680 nrows, ncols = C.shape
5681 else:
5682 raise TypeError(
5683 'Illegal arguments to %s; see help(%s)' % (funcname, funcname))
5685 Nx = X.shape[-1]
5686 Ny = Y.shape[0]
5687 if X.ndim != 2 or X.shape[0] == 1:
5688 x = X.reshape(1, Nx)
5689 X = x.repeat(Ny, axis=0)
5690 if Y.ndim != 2 or Y.shape[1] == 1:
5691 y = Y.reshape(Ny, 1)
5692 Y = y.repeat(Nx, axis=1)
5693 if X.shape != Y.shape:
5694 raise TypeError(
5695 'Incompatible X, Y inputs to %s; see help(%s)' % (
5696 funcname, funcname))
5697 if allmatch:
5698 if (Nx, Ny) != (ncols, nrows):
5699 raise TypeError('Dimensions of C %s are incompatible with'
5700 ' X (%d) and/or Y (%d); see help(%s)' % (
5701 C.shape, Nx, Ny, funcname))
5702 else:
5703 if not (ncols in (Nx, Nx - 1) and nrows in (Ny, Ny - 1)):
5704 raise TypeError('Dimensions of C %s are incompatible with'
5705 ' X (%d) and/or Y (%d); see help(%s)' % (
5706 C.shape, Nx, Ny, funcname))
5707 C = C[:Ny - 1, :Nx - 1]
5708 C = cbook.safe_masked_invalid(C)
5709 return X, Y, C
5711 @_preprocess_data()
5712 @docstring.dedent_interpd
5713 def pcolor(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
5714 vmax=None, **kwargs):
5715 r"""
5716 Create a pseudocolor plot with a non-regular rectangular grid.
5718 Call signature::
5720 pcolor([X, Y,] C, **kwargs)
5722 *X* and *Y* can be used to specify the corners of the quadrilaterals.
5724 .. hint::
5726 ``pcolor()`` can be very slow for large arrays. In most
5727 cases you should use the similar but much faster
5728 `~.Axes.pcolormesh` instead. See there for a discussion of the
5729 differences.
5731 Parameters
5732 ----------
5733 C : array-like
5734 A scalar 2-D array. The values will be color-mapped.
5736 X, Y : array-like, optional
5737 The coordinates of the quadrilateral corners. The quadrilateral
5738 for ``C[i, j]`` has corners at::
5740 (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1])
5741 +---------+
5742 | C[i, j] |
5743 +---------+
5744 (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1])
5746 Note that the column index corresponds to the
5747 x-coordinate, and the row index corresponds to y. For
5748 details, see the :ref:`Notes <axes-pcolor-grid-orientation>`
5749 section below.
5751 The dimensions of *X* and *Y* should be one greater than those of
5752 *C*. Alternatively, *X*, *Y* and *C* may have equal dimensions, in
5753 which case the last row and column of *C* will be ignored.
5755 If *X* and/or *Y* are 1-D arrays or column vectors they will be
5756 expanded as needed into the appropriate 2-D arrays, making a
5757 rectangular grid.
5759 cmap : str or `~matplotlib.colors.Colormap`, optional
5760 A Colormap instance or registered colormap name. The colormap
5761 maps the *C* values to colors. Defaults to :rc:`image.cmap`.
5763 norm : `~matplotlib.colors.Normalize`, optional
5764 The Normalize instance scales the data values to the canonical
5765 colormap range [0, 1] for mapping to colors. By default, the data
5766 range is mapped to the colorbar range using linear scaling.
5768 vmin, vmax : scalar, optional, default: None
5769 The colorbar range. If *None*, suitable min/max values are
5770 automatically chosen by the `~.Normalize` instance (defaults to
5771 the respective min/max values of *C* in case of the default linear
5772 scaling).
5774 edgecolors : {'none', None, 'face', color, color sequence}, optional
5775 The color of the edges. Defaults to 'none'. Possible values:
5777 - 'none' or '': No edge.
5778 - *None*: :rc:`patch.edgecolor` will be used. Note that currently
5779 :rc:`patch.force_edgecolor` has to be True for this to work.
5780 - 'face': Use the adjacent face color.
5781 - A color or sequence of colors will set the edge color.
5783 The singular form *edgecolor* works as an alias.
5785 alpha : scalar, optional, default: None
5786 The alpha blending value of the face color, between 0 (transparent)
5787 and 1 (opaque). Note: The edgecolor is currently not affected by
5788 this.
5790 snap : bool, optional, default: False
5791 Whether to snap the mesh to pixel boundaries.
5793 Returns
5794 -------
5795 collection : `matplotlib.collections.Collection`
5797 Other Parameters
5798 ----------------
5799 antialiaseds : bool, optional, default: False
5800 The default *antialiaseds* is False if the default
5801 *edgecolors*\ ="none" is used. This eliminates artificial lines
5802 at patch boundaries, and works regardless of the value of alpha.
5803 If *edgecolors* is not "none", then the default *antialiaseds*
5804 is taken from :rc:`patch.antialiased`.
5805 Stroking the edges may be preferred if *alpha* is 1, but will
5806 cause artifacts otherwise.
5808 **kwargs
5809 Additionally, the following arguments are allowed. They are passed
5810 along to the `~matplotlib.collections.PolyCollection` constructor:
5812 %(PolyCollection)s
5814 See Also
5815 --------
5816 pcolormesh : for an explanation of the differences between
5817 pcolor and pcolormesh.
5818 imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a
5819 faster alternative.
5821 Notes
5822 -----
5823 **Masked arrays**
5825 *X*, *Y* and *C* may be masked arrays. If either ``C[i, j]``, or one
5826 of the vertices surrounding ``C[i, j]`` (*X* or *Y* at
5827 ``[i, j], [i+1, j], [i, j+1], [i+1, j+1]``) is masked, nothing is
5828 plotted.
5830 .. _axes-pcolor-grid-orientation:
5832 **Grid orientation**
5834 The grid orientation follows the standard matrix convention: An array
5835 *C* with shape (nrows, ncolumns) is plotted with the column number as
5836 *X* and the row number as *Y*.
5838 **Handling of pcolor() end-cases**
5840 ``pcolor()`` displays all columns of *C* if *X* and *Y* are not
5841 specified, or if *X* and *Y* have one more column than *C*.
5842 If *X* and *Y* have the same number of columns as *C* then the last
5843 column of *C* is dropped. Similarly for the rows.
5845 Note: This behavior is different from MATLAB's ``pcolor()``, which
5846 always discards the last row and column of *C*.
5847 """
5848 X, Y, C = self._pcolorargs('pcolor', *args, allmatch=False)
5849 Ny, Nx = X.shape
5851 # unit conversion allows e.g. datetime objects as axis values
5852 self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
5853 X = self.convert_xunits(X)
5854 Y = self.convert_yunits(Y)
5856 # convert to MA, if necessary.
5857 C = ma.asarray(C)
5858 X = ma.asarray(X)
5859 Y = ma.asarray(Y)
5861 mask = ma.getmaskarray(X) + ma.getmaskarray(Y)
5862 xymask = (mask[0:-1, 0:-1] + mask[1:, 1:] +
5863 mask[0:-1, 1:] + mask[1:, 0:-1])
5864 # don't plot if C or any of the surrounding vertices are masked.
5865 mask = ma.getmaskarray(C) + xymask
5867 unmask = ~mask
5868 X1 = ma.filled(X[:-1, :-1])[unmask]
5869 Y1 = ma.filled(Y[:-1, :-1])[unmask]
5870 X2 = ma.filled(X[1:, :-1])[unmask]
5871 Y2 = ma.filled(Y[1:, :-1])[unmask]
5872 X3 = ma.filled(X[1:, 1:])[unmask]
5873 Y3 = ma.filled(Y[1:, 1:])[unmask]
5874 X4 = ma.filled(X[:-1, 1:])[unmask]
5875 Y4 = ma.filled(Y[:-1, 1:])[unmask]
5876 npoly = len(X1)
5878 xy = np.stack([X1, Y1, X2, Y2, X3, Y3, X4, Y4, X1, Y1], axis=-1)
5879 verts = xy.reshape((npoly, 5, 2))
5881 C = ma.filled(C[:Ny - 1, :Nx - 1])[unmask]
5883 linewidths = (0.25,)
5884 if 'linewidth' in kwargs:
5885 kwargs['linewidths'] = kwargs.pop('linewidth')
5886 kwargs.setdefault('linewidths', linewidths)
5888 if 'edgecolor' in kwargs:
5889 kwargs['edgecolors'] = kwargs.pop('edgecolor')
5890 ec = kwargs.setdefault('edgecolors', 'none')
5892 # aa setting will default via collections to patch.antialiased
5893 # unless the boundary is not stroked, in which case the
5894 # default will be False; with unstroked boundaries, aa
5895 # makes artifacts that are often disturbing.
5896 if 'antialiased' in kwargs:
5897 kwargs['antialiaseds'] = kwargs.pop('antialiased')
5898 if 'antialiaseds' not in kwargs and cbook._str_lower_equal(ec, "none"):
5899 kwargs['antialiaseds'] = False
5901 kwargs.setdefault('snap', False)
5903 collection = mcoll.PolyCollection(verts, **kwargs)
5905 collection.set_alpha(alpha)
5906 collection.set_array(C)
5907 collection.set_cmap(cmap)
5908 collection.set_norm(norm)
5909 collection.set_clim(vmin, vmax)
5910 collection.autoscale_None()
5911 self.grid(False)
5913 x = X.compressed()
5914 y = Y.compressed()
5916 # Transform from native to data coordinates?
5917 t = collection._transform
5918 if (not isinstance(t, mtransforms.Transform) and
5919 hasattr(t, '_as_mpl_transform')):
5920 t = t._as_mpl_transform(self.axes)
5922 if t and any(t.contains_branch_seperately(self.transData)):
5923 trans_to_data = t - self.transData
5924 pts = np.vstack([x, y]).T.astype(float)
5925 transformed_pts = trans_to_data.transform(pts)
5926 x = transformed_pts[..., 0]
5927 y = transformed_pts[..., 1]
5929 self.add_collection(collection, autolim=False)
5931 minx = np.min(x)
5932 maxx = np.max(x)
5933 miny = np.min(y)
5934 maxy = np.max(y)
5935 collection.sticky_edges.x[:] = [minx, maxx]
5936 collection.sticky_edges.y[:] = [miny, maxy]
5937 corners = (minx, miny), (maxx, maxy)
5938 self.update_datalim(corners)
5939 self._request_autoscale_view()
5940 return collection
5942 @_preprocess_data()
5943 @docstring.dedent_interpd
5944 def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
5945 vmax=None, shading='flat', antialiased=False, **kwargs):
5946 """
5947 Create a pseudocolor plot with a non-regular rectangular grid.
5949 Call signature::
5951 pcolor([X, Y,] C, **kwargs)
5953 *X* and *Y* can be used to specify the corners of the quadrilaterals.
5955 .. note::
5957 `~Axes.pcolormesh` is similar to `~Axes.pcolor`. It's much faster
5958 and preferred in most cases. For a detailed discussion on the
5959 differences see :ref:`Differences between pcolor() and pcolormesh()
5960 <differences-pcolor-pcolormesh>`.
5962 Parameters
5963 ----------
5964 C : array-like
5965 A scalar 2-D array. The values will be color-mapped.
5967 X, Y : array-like, optional
5968 The coordinates of the quadrilateral corners. The quadrilateral
5969 for ``C[i, j]`` has corners at::
5971 (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1])
5972 +---------+
5973 | C[i, j] |
5974 +---------+
5975 (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1])
5977 Note that the column index corresponds to the
5978 x-coordinate, and the row index corresponds to y. For
5979 details, see the :ref:`Notes <axes-pcolormesh-grid-orientation>`
5980 section below.
5982 The dimensions of *X* and *Y* should be one greater than those of
5983 *C*. Alternatively, *X*, *Y* and *C* may have equal dimensions, in
5984 which case the last row and column of *C* will be ignored.
5986 If *X* and/or *Y* are 1-D arrays or column vectors they will be
5987 expanded as needed into the appropriate 2-D arrays, making a
5988 rectangular grid.
5990 cmap : str or `~matplotlib.colors.Colormap`, optional
5991 A Colormap instance or registered colormap name. The colormap
5992 maps the *C* values to colors. Defaults to :rc:`image.cmap`.
5994 norm : `~matplotlib.colors.Normalize`, optional
5995 The Normalize instance scales the data values to the canonical
5996 colormap range [0, 1] for mapping to colors. By default, the data
5997 range is mapped to the colorbar range using linear scaling.
5999 vmin, vmax : scalar, optional, default: None
6000 The colorbar range. If *None*, suitable min/max values are
6001 automatically chosen by the `~.Normalize` instance (defaults to
6002 the respective min/max values of *C* in case of the default linear
6003 scaling).
6005 edgecolors : {'none', None, 'face', color, color sequence}, optional
6006 The color of the edges. Defaults to 'none'. Possible values:
6008 - 'none' or '': No edge.
6009 - *None*: :rc:`patch.edgecolor` will be used. Note that currently
6010 :rc:`patch.force_edgecolor` has to be True for this to work.
6011 - 'face': Use the adjacent face color.
6012 - A color or sequence of colors will set the edge color.
6014 The singular form *edgecolor* works as an alias.
6016 alpha : scalar, optional, default: None
6017 The alpha blending value, between 0 (transparent) and 1 (opaque).
6019 shading : {'flat', 'gouraud'}, optional
6020 The fill style, Possible values:
6022 - 'flat': A solid color is used for each quad. The color of the
6023 quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by
6024 ``C[i, j]``.
6025 - 'gouraud': Each quad will be Gouraud shaded: The color of the
6026 corners (i', j') are given by ``C[i',j']``. The color values of
6027 the area in between is interpolated from the corner values.
6028 When Gouraud shading is used, *edgecolors* is ignored.
6030 snap : bool, optional, default: False
6031 Whether to snap the mesh to pixel boundaries.
6033 Returns
6034 -------
6035 mesh : `matplotlib.collections.QuadMesh`
6037 Other Parameters
6038 ----------------
6039 **kwargs
6040 Additionally, the following arguments are allowed. They are passed
6041 along to the `~matplotlib.collections.QuadMesh` constructor:
6043 %(QuadMesh)s
6045 See Also
6046 --------
6047 pcolor : An alternative implementation with slightly different
6048 features. For a detailed discussion on the differences see
6049 :ref:`Differences between pcolor() and pcolormesh()
6050 <differences-pcolor-pcolormesh>`.
6051 imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a
6052 faster alternative.
6054 Notes
6055 -----
6056 **Masked arrays**
6058 *C* may be a masked array. If ``C[i, j]`` is masked, the corresponding
6059 quadrilateral will be transparent. Masking of *X* and *Y* is not
6060 supported. Use `~.Axes.pcolor` if you need this functionality.
6062 .. _axes-pcolormesh-grid-orientation:
6064 **Grid orientation**
6066 The grid orientation follows the standard matrix convention: An array
6067 *C* with shape (nrows, ncolumns) is plotted with the column number as
6068 *X* and the row number as *Y*.
6070 .. _differences-pcolor-pcolormesh:
6072 **Differences between pcolor() and pcolormesh()**
6074 Both methods are used to create a pseudocolor plot of a 2-D array
6075 using quadrilaterals.
6077 The main difference lies in the created object and internal data
6078 handling:
6079 While `~.Axes.pcolor` returns a `.PolyCollection`, `~.Axes.pcolormesh`
6080 returns a `.QuadMesh`. The latter is more specialized for the given
6081 purpose and thus is faster. It should almost always be preferred.
6083 There is also a slight difference in the handling of masked arrays.
6084 Both `~.Axes.pcolor` and `~.Axes.pcolormesh` support masked arrays
6085 for *C*. However, only `~.Axes.pcolor` supports masked arrays for *X*
6086 and *Y*. The reason lies in the internal handling of the masked values.
6087 `~.Axes.pcolor` leaves out the respective polygons from the
6088 PolyCollection. `~.Axes.pcolormesh` sets the facecolor of the masked
6089 elements to transparent. You can see the difference when using
6090 edgecolors. While all edges are drawn irrespective of masking in a
6091 QuadMesh, the edge between two adjacent masked quadrilaterals in
6092 `~.Axes.pcolor` is not drawn as the corresponding polygons do not
6093 exist in the PolyCollection.
6095 Another difference is the support of Gouraud shading in
6096 `~.Axes.pcolormesh`, which is not available with `~.Axes.pcolor`.
6098 """
6099 shading = shading.lower()
6100 kwargs.setdefault('edgecolors', 'None')
6102 allmatch = (shading == 'gouraud')
6104 X, Y, C = self._pcolorargs('pcolormesh', *args, allmatch=allmatch)
6105 Ny, Nx = X.shape
6106 X = X.ravel()
6107 Y = Y.ravel()
6108 # unit conversion allows e.g. datetime objects as axis values
6109 self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
6110 X = self.convert_xunits(X)
6111 Y = self.convert_yunits(Y)
6113 # convert to one dimensional arrays
6114 C = C.ravel()
6115 coords = np.column_stack((X, Y)).astype(float, copy=False)
6116 collection = mcoll.QuadMesh(Nx - 1, Ny - 1, coords,
6117 antialiased=antialiased, shading=shading,
6118 **kwargs)
6119 collection.set_alpha(alpha)
6120 collection.set_array(C)
6121 collection.set_cmap(cmap)
6122 collection.set_norm(norm)
6123 collection.set_clim(vmin, vmax)
6124 collection.autoscale_None()
6126 self.grid(False)
6128 # Transform from native to data coordinates?
6129 t = collection._transform
6130 if (not isinstance(t, mtransforms.Transform) and
6131 hasattr(t, '_as_mpl_transform')):
6132 t = t._as_mpl_transform(self.axes)
6134 if t and any(t.contains_branch_seperately(self.transData)):
6135 trans_to_data = t - self.transData
6136 coords = trans_to_data.transform(coords)
6138 self.add_collection(collection, autolim=False)
6140 minx, miny = np.min(coords, axis=0)
6141 maxx, maxy = np.max(coords, axis=0)
6142 collection.sticky_edges.x[:] = [minx, maxx]
6143 collection.sticky_edges.y[:] = [miny, maxy]
6144 corners = (minx, miny), (maxx, maxy)
6145 self.update_datalim(corners)
6146 self._request_autoscale_view()
6147 return collection
6149 @_preprocess_data()
6150 @docstring.dedent_interpd
6151 def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
6152 vmax=None, **kwargs):
6153 """
6154 Create a pseudocolor plot with a non-regular rectangular grid.
6156 Call signature::
6158 ax.pcolorfast([X, Y], C, /, **kwargs)
6160 This method is similar to ~.Axes.pcolor` and `~.Axes.pcolormesh`.
6161 It's designed to provide the fastest pcolor-type plotting with the
6162 Agg backend. To achieve this, it uses different algorithms internally
6163 depending on the complexity of the input grid (regular rectangular,
6164 non-regular rectangular or arbitrary quadrilateral).
6166 .. warning::
6168 This method is experimental. Compared to `~.Axes.pcolor` or
6169 `~.Axes.pcolormesh` it has some limitations:
6171 - It supports only flat shading (no outlines)
6172 - It lacks support for log scaling of the axes.
6173 - It does not have a have a pyplot wrapper.
6175 Parameters
6176 ----------
6177 C : array-like(M, N)
6178 The image data. Supported array shapes are:
6180 - (M, N): an image with scalar data. The data is visualized
6181 using a colormap.
6182 - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
6183 - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
6184 i.e. including transparency.
6186 The first two dimensions (M, N) define the rows and columns of
6187 the image.
6189 This parameter can only be passed positionally.
6191 X, Y : tuple or array-like, default: ``(0, N)``, ``(0, M)``
6192 *X* and *Y* are used to specify the coordinates of the
6193 quadrilaterals. There are different ways to do this:
6195 - Use tuples ``X=(xmin, xmax)`` and ``Y=(ymin, ymax)`` to define
6196 a *uniform rectangular grid*.
6198 The tuples define the outer edges of the grid. All individual
6199 quadrilaterals will be of the same size. This is the fastest
6200 version.
6202 - Use 1D arrays *X*, *Y* to specify a *non-uniform rectangular
6203 grid*.
6205 In this case *X* and *Y* have to be monotonic 1D arrays of length
6206 *N+1* and *M+1*, specifying the x and y boundaries of the cells.
6208 The speed is intermediate. Note: The grid is checked, and if
6209 found to be uniform the fast version is used.
6211 - Use 2D arrays *X*, *Y* if you need an *arbitrary quadrilateral
6212 grid* (i.e. if the quadrilaterals are not rectangular).
6214 In this case *X* and *Y* are 2D arrays with shape (M + 1, N + 1),
6215 specifying the x and y coordinates of the corners of the colored
6216 quadrilaterals.
6218 This is the most general, but the slowest to render. It may
6219 produce faster and more compact output using ps, pdf, and
6220 svg backends, however.
6222 These arguments can only be passed positionally.
6224 cmap : str or `~matplotlib.colors.Colormap`, optional
6225 A Colormap instance or registered colormap name. The colormap
6226 maps the *C* values to colors. Defaults to :rc:`image.cmap`.
6228 norm : `~matplotlib.colors.Normalize`, optional
6229 The Normalize instance scales the data values to the canonical
6230 colormap range [0, 1] for mapping to colors. By default, the data
6231 range is mapped to the colorbar range using linear scaling.
6233 vmin, vmax : scalar, optional, default: None
6234 The colorbar range. If *None*, suitable min/max values are
6235 automatically chosen by the `~.Normalize` instance (defaults to
6236 the respective min/max values of *C* in case of the default linear
6237 scaling).
6239 alpha : scalar, optional, default: None
6240 The alpha blending value, between 0 (transparent) and 1 (opaque).
6242 snap : bool, optional, default: False
6243 Whether to snap the mesh to pixel boundaries.
6245 Returns
6246 -------
6247 image : `.AxesImage` or `.PcolorImage` or `.QuadMesh`
6248 The return type depends on the type of grid:
6250 - `.AxesImage` for a regular rectangular grid.
6251 - `.PcolorImage` for a non-regular rectangular grid.
6252 - `.QuadMesh` for a non-rectangular grid.
6254 Notes
6255 -----
6256 .. [notes section required to get data note injection right]
6257 """
6259 C = args[-1]
6260 nr, nc = np.shape(C)[:2]
6261 if len(args) == 1:
6262 style = "image"
6263 x = [0, nc]
6264 y = [0, nr]
6265 elif len(args) == 3:
6266 x, y = args[:2]
6267 x = np.asarray(x)
6268 y = np.asarray(y)
6269 if x.ndim == 1 and y.ndim == 1:
6270 if x.size == 2 and y.size == 2:
6271 style = "image"
6272 else:
6273 dx = np.diff(x)
6274 dy = np.diff(y)
6275 if (np.ptp(dx) < 0.01 * np.abs(dx.mean()) and
6276 np.ptp(dy) < 0.01 * np.abs(dy.mean())):
6277 style = "image"
6278 else:
6279 style = "pcolorimage"
6280 elif x.ndim == 2 and y.ndim == 2:
6281 style = "quadmesh"
6282 else:
6283 raise TypeError("arguments do not match valid signatures")
6284 else:
6285 raise TypeError("need 1 argument or 3 arguments")
6287 if style == "quadmesh":
6288 # data point in each cell is value at lower left corner
6289 coords = np.stack([x, y], axis=-1)
6290 if np.ndim(C) == 2:
6291 qm_kwargs = {"array": np.ma.ravel(C)}
6292 elif np.ndim(C) == 3:
6293 qm_kwargs = {"color": np.ma.reshape(C, (-1, C.shape[-1]))}
6294 else:
6295 raise ValueError("C must be 2D or 3D")
6296 collection = mcoll.QuadMesh(
6297 nc, nr, coords, **qm_kwargs,
6298 alpha=alpha, cmap=cmap, norm=norm,
6299 antialiased=False, edgecolors="none")
6300 self.add_collection(collection, autolim=False)
6301 xl, xr, yb, yt = x.min(), x.max(), y.min(), y.max()
6302 ret = collection
6304 else: # It's one of the two image styles.
6305 extent = xl, xr, yb, yt = x[0], x[-1], y[0], y[-1]
6306 if style == "image":
6307 im = mimage.AxesImage(
6308 self, cmap, norm,
6309 data=C, alpha=alpha, extent=extent,
6310 interpolation='nearest', origin='lower',
6311 **kwargs)
6312 elif style == "pcolorimage":
6313 im = mimage.PcolorImage(
6314 self, x, y, C,
6315 cmap=cmap, norm=norm, alpha=alpha, extent=extent,
6316 **kwargs)
6317 self.add_image(im)
6318 ret = im
6320 if vmin is not None or vmax is not None:
6321 ret.set_clim(vmin, vmax)
6322 elif np.ndim(C) == 2: # C.ndim == 3 is RGB(A) so doesn't need scaling.
6323 ret.autoscale_None()
6324 if ret.get_clip_path() is None:
6325 # image does not already have clipping set, clip to axes patch
6326 ret.set_clip_path(self.patch)
6328 ret.sticky_edges.x[:] = [xl, xr]
6329 ret.sticky_edges.y[:] = [yb, yt]
6330 self.update_datalim(np.array([[xl, yb], [xr, yt]]))
6331 self._request_autoscale_view(tight=True)
6332 return ret
6334 @_preprocess_data()
6335 def contour(self, *args, **kwargs):
6336 kwargs['filled'] = False
6337 contours = mcontour.QuadContourSet(self, *args, **kwargs)
6338 self._request_autoscale_view()
6339 return contours
6340 contour.__doc__ = mcontour.QuadContourSet._contour_doc
6342 @_preprocess_data()
6343 def contourf(self, *args, **kwargs):
6344 kwargs['filled'] = True
6345 contours = mcontour.QuadContourSet(self, *args, **kwargs)
6346 self._request_autoscale_view()
6347 return contours
6348 contourf.__doc__ = mcontour.QuadContourSet._contour_doc
6350 def clabel(self, CS, *args, **kwargs):
6351 return CS.clabel(*args, **kwargs)
6352 clabel.__doc__ = mcontour.ContourSet.clabel.__doc__
6354 #### Data analysis
6356 @_preprocess_data(replace_names=["x", 'weights'], label_namer="x")
6357 def hist(self, x, bins=None, range=None, density=False, weights=None,
6358 cumulative=False, bottom=None, histtype='bar', align='mid',
6359 orientation='vertical', rwidth=None, log=False,
6360 color=None, label=None, stacked=False, **kwargs):
6361 """
6362 Plot a histogram.
6364 Compute and draw the histogram of *x*. The return value is a tuple
6365 (*n*, *bins*, *patches*) or ([*n0*, *n1*, ...], *bins*, [*patches0*,
6366 *patches1*,...]) if the input contains multiple data. See the
6367 documentation of the *weights* parameter to draw a histogram of
6368 already-binned data.
6370 Multiple data can be provided via *x* as a list of datasets
6371 of potentially different length ([*x0*, *x1*, ...]), or as
6372 a 2-D ndarray in which each column is a dataset. Note that
6373 the ndarray form is transposed relative to the list form.
6375 Masked arrays are not supported.
6377 The *bins*, *range*, *weights*, and *density* parameters behave as in
6378 `numpy.histogram`.
6380 Parameters
6381 ----------
6382 x : (n,) array or sequence of (n,) arrays
6383 Input values, this takes either a single array or a sequence of
6384 arrays which are not required to be of the same length.
6386 bins : int or sequence or str, optional
6387 If *bins* is an integer, it defines the number of equal-width bins
6388 in the range.
6390 If *bins* is a sequence, it defines the bin edges, including the
6391 left edge of the first bin and the right edge of the last bin;
6392 in this case, bins may be unequally spaced. All but the last
6393 (righthand-most) bin is half-open. In other words, if *bins* is::
6395 [1, 2, 3, 4]
6397 then the first bin is ``[1, 2)`` (including 1, but excluding 2) and
6398 the second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which
6399 *includes* 4.
6401 If *bins* is a string, it is one of the binning strategies
6402 supported by `numpy.histogram_bin_edges`: 'auto', 'fd', 'doane',
6403 'scott', 'stone', 'rice', 'sturges', or 'sqrt'.
6405 The default is :rc:`hist.bins`.
6407 range : tuple or None, optional
6408 The lower and upper range of the bins. Lower and upper outliers
6409 are ignored. If not provided, *range* is ``(x.min(), x.max())``.
6410 Range has no effect if *bins* is a sequence.
6412 If *bins* is a sequence or *range* is specified, autoscaling
6413 is based on the specified bin range instead of the
6414 range of x.
6416 Default is ``None``
6418 density : bool, optional
6419 If ``True``, the first element of the return tuple will
6420 be the counts normalized to form a probability density, i.e.,
6421 the area (or integral) under the histogram will sum to 1.
6422 This is achieved by dividing the count by the number of
6423 observations times the bin width and not dividing by the total
6424 number of observations. If *stacked* is also ``True``, the sum of
6425 the histograms is normalized to 1.
6427 Default is ``False``.
6429 weights : (n, ) array-like or None, optional
6430 An array of weights, of the same shape as *x*. Each value in *x*
6431 only contributes its associated weight towards the bin count
6432 (instead of 1). If *normed* or *density* is ``True``,
6433 the weights are normalized, so that the integral of the density
6434 over the range remains 1.
6436 Default is ``None``.
6438 This parameter can be used to draw a histogram of data that has
6439 already been binned, e.g. using `np.histogram` (by treating each
6440 bin as a single point with a weight equal to its count) ::
6442 counts, bins = np.histogram(data)
6443 plt.hist(bins[:-1], bins, weights=counts)
6445 (or you may alternatively use `~.bar()`).
6447 cumulative : bool or -1, optional
6448 If ``True``, then a histogram is computed where each bin gives the
6449 counts in that bin plus all bins for smaller values. The last bin
6450 gives the total number of datapoints.
6452 If *density* is also ``True`` then the histogram is normalized such
6453 that the last bin equals 1.
6455 If *cumulative* is a number less than 0 (e.g., -1), the direction
6456 of accumulation is reversed. In this case, if *density* is also
6457 ``True``, then the histogram is normalized such that the first bin
6458 equals 1.
6460 bottom : array-like, scalar, or None, default: None
6461 Location of the bottom of each bin, ie. bins are drawn from
6462 ``bottom`` to ``bottom + hist(x, bins)`` If a scalar, the bottom
6463 of each bin is shifted by the same amount. If an array, each bin
6464 is shifted independently and the length of bottom must match the
6465 number of bins. If None, defaults to 0.
6467 histtype : {'bar', 'barstacked', 'step', 'stepfilled'}, optional
6468 The type of histogram to draw.
6470 - 'bar' is a traditional bar-type histogram. If multiple data
6471 are given the bars are arranged side by side.
6472 - 'barstacked' is a bar-type histogram where multiple
6473 data are stacked on top of each other.
6474 - 'step' generates a lineplot that is by default unfilled.
6475 - 'stepfilled' generates a lineplot that is by default filled.
6477 Default is 'bar'
6479 align : {'left', 'mid', 'right'}, optional
6480 Controls how the histogram is plotted.
6482 - 'left': bars are centered on the left bin edges.
6483 - 'mid': bars are centered between the bin edges.
6484 - 'right': bars are centered on the right bin edges.
6486 Default is 'mid'
6488 orientation : {'horizontal', 'vertical'}, optional
6489 If 'horizontal', `~matplotlib.pyplot.barh` will be used for
6490 bar-type histograms and the *bottom* kwarg will be the left edges.
6492 rwidth : scalar or None, optional
6493 The relative width of the bars as a fraction of the bin width. If
6494 ``None``, automatically compute the width.
6496 Ignored if *histtype* is 'step' or 'stepfilled'.
6498 Default is ``None``
6500 log : bool, optional
6501 If ``True``, the histogram axis will be set to a log scale. If
6502 *log* is ``True`` and *x* is a 1D array, empty bins will be
6503 filtered out and only the non-empty ``(n, bins, patches)``
6504 will be returned.
6506 Default is ``False``
6508 color : color or array-like of colors or None, optional
6509 Color or sequence of colors, one per dataset. Default (``None``)
6510 uses the standard line color sequence.
6512 Default is ``None``
6514 label : str or None, optional
6515 String, or sequence of strings to match multiple datasets. Bar
6516 charts yield multiple patches per dataset, but only the first gets
6517 the label, so that the legend command will work as expected.
6519 default is ``None``
6521 stacked : bool, optional
6522 If ``True``, multiple data are stacked on top of each other If
6523 ``False`` multiple data are arranged side by side if histtype is
6524 'bar' or on top of each other if histtype is 'step'
6526 Default is ``False``
6528 Returns
6529 -------
6530 n : array or list of arrays
6531 The values of the histogram bins. See *density* and *weights* for a
6532 description of the possible semantics. If input *x* is an array,
6533 then this is an array of length *nbins*. If input is a sequence of
6534 arrays ``[data1, data2, ...]``, then this is a list of arrays with
6535 the values of the histograms for each of the arrays in the same
6536 order. The dtype of the array *n* (or of its element arrays) will
6537 always be float even if no weighting or normalization is used.
6539 bins : array
6540 The edges of the bins. Length nbins + 1 (nbins left edges and right
6541 edge of last bin). Always a single array even when multiple data
6542 sets are passed in.
6544 patches : list or list of lists
6545 Silent list of individual patches used to create the histogram
6546 or list of such list if multiple input datasets.
6548 Other Parameters
6549 ----------------
6550 **kwargs : `~matplotlib.patches.Patch` properties
6552 See also
6553 --------
6554 hist2d : 2D histograms
6556 """
6557 # Avoid shadowing the builtin.
6558 bin_range = range
6559 from builtins import range
6561 if np.isscalar(x):
6562 x = [x]
6564 if bins is None:
6565 bins = rcParams['hist.bins']
6567 # Validate string inputs here to avoid cluttering subsequent code.
6568 cbook._check_in_list(['bar', 'barstacked', 'step', 'stepfilled'],
6569 histtype=histtype)
6570 cbook._check_in_list(['left', 'mid', 'right'], align=align)
6571 cbook._check_in_list(['horizontal', 'vertical'],
6572 orientation=orientation)
6574 if histtype == 'barstacked' and not stacked:
6575 stacked = True
6577 # basic input validation
6578 input_empty = np.size(x) == 0
6579 # Massage 'x' for processing.
6580 x = cbook._reshape_2D(x, 'x')
6581 nx = len(x) # number of datasets
6583 # Process unit information
6584 # Unit conversion is done individually on each dataset
6585 self._process_unit_info(xdata=x[0], kwargs=kwargs)
6586 x = [self.convert_xunits(xi) for xi in x]
6588 if bin_range is not None:
6589 bin_range = self.convert_xunits(bin_range)
6591 if not cbook.is_scalar_or_string(bins):
6592 bins = self.convert_xunits(bins)
6594 # We need to do to 'weights' what was done to 'x'
6595 if weights is not None:
6596 w = cbook._reshape_2D(weights, 'weights')
6597 else:
6598 w = [None] * nx
6600 if len(w) != nx:
6601 raise ValueError('weights should have the same shape as x')
6603 for xi, wi in zip(x, w):
6604 if wi is not None and len(wi) != len(xi):
6605 raise ValueError(
6606 'weights should have the same shape as x')
6608 if color is None:
6609 color = [self._get_lines.get_next_color() for i in range(nx)]
6610 else:
6611 color = mcolors.to_rgba_array(color)
6612 if len(color) != nx:
6613 error_message = (
6614 "color kwarg must have one color per data set. %d data "
6615 "sets and %d colors were provided" % (nx, len(color)))
6616 raise ValueError(error_message)
6618 hist_kwargs = dict()
6620 # if the bin_range is not given, compute without nan numpy
6621 # does not do this for us when guessing the range (but will
6622 # happily ignore nans when computing the histogram).
6623 if bin_range is None:
6624 xmin = np.inf
6625 xmax = -np.inf
6626 for xi in x:
6627 if len(xi):
6628 # python's min/max ignore nan,
6629 # np.minnan returns nan for all nan input
6630 xmin = min(xmin, np.nanmin(xi))
6631 xmax = max(xmax, np.nanmax(xi))
6632 # make sure we have seen at least one non-nan and finite
6633 # value before we reset the bin range
6634 if not np.isnan([xmin, xmax]).any() and not (xmin > xmax):
6635 bin_range = (xmin, xmax)
6637 # If bins are not specified either explicitly or via range,
6638 # we need to figure out the range required for all datasets,
6639 # and supply that to np.histogram.
6640 if not input_empty and len(x) > 1:
6641 if weights is not None:
6642 _w = np.concatenate(w)
6643 else:
6644 _w = None
6646 bins = _histogram_bin_edges(np.concatenate(x), bins, bin_range, _w)
6647 else:
6648 hist_kwargs['range'] = bin_range
6650 density = bool(density)
6651 if density and not stacked:
6652 hist_kwargs['density'] = density
6654 # List to store all the top coordinates of the histograms
6655 tops = [] # Will have shape (n_datasets, n_bins).
6656 # Loop through datasets
6657 for i in range(nx):
6658 # this will automatically overwrite bins,
6659 # so that each histogram uses the same bins
6660 m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)
6661 tops.append(m)
6662 tops = np.array(tops, float) # causes problems later if it's an int
6663 if stacked:
6664 tops = tops.cumsum(axis=0)
6665 # If a stacked density plot, normalize so the area of all the
6666 # stacked histograms together is 1
6667 if density:
6668 tops = (tops / np.diff(bins)) / tops[-1].sum()
6669 if cumulative:
6670 slc = slice(None)
6671 if isinstance(cumulative, Number) and cumulative < 0:
6672 slc = slice(None, None, -1)
6673 if density:
6674 tops = (tops * np.diff(bins))[:, slc].cumsum(axis=1)[:, slc]
6675 else:
6676 tops = tops[:, slc].cumsum(axis=1)[:, slc]
6678 patches = []
6680 # Save autoscale state for later restoration; turn autoscaling
6681 # off so we can do it all a single time at the end, instead
6682 # of having it done by bar or fill and then having to be redone.
6683 _saved_autoscalex = self.get_autoscalex_on()
6684 _saved_autoscaley = self.get_autoscaley_on()
6685 self.set_autoscalex_on(False)
6686 self.set_autoscaley_on(False)
6688 if histtype.startswith('bar'):
6690 totwidth = np.diff(bins)
6692 if rwidth is not None:
6693 dr = np.clip(rwidth, 0, 1)
6694 elif (len(tops) > 1 and
6695 ((not stacked) or rcParams['_internal.classic_mode'])):
6696 dr = 0.8
6697 else:
6698 dr = 1.0
6700 if histtype == 'bar' and not stacked:
6701 width = dr * totwidth / nx
6702 dw = width
6703 boffset = -0.5 * dr * totwidth * (1 - 1 / nx)
6704 elif histtype == 'barstacked' or stacked:
6705 width = dr * totwidth
6706 boffset, dw = 0.0, 0.0
6708 if align == 'mid':
6709 boffset += 0.5 * totwidth
6710 elif align == 'right':
6711 boffset += totwidth
6713 if orientation == 'horizontal':
6714 _barfunc = self.barh
6715 bottom_kwarg = 'left'
6716 else: # orientation == 'vertical'
6717 _barfunc = self.bar
6718 bottom_kwarg = 'bottom'
6720 for m, c in zip(tops, color):
6721 if bottom is None:
6722 bottom = np.zeros(len(m))
6723 if stacked:
6724 height = m - bottom
6725 else:
6726 height = m
6727 patch = _barfunc(bins[:-1]+boffset, height, width,
6728 align='center', log=log,
6729 color=c, **{bottom_kwarg: bottom})
6730 patches.append(patch)
6731 if stacked:
6732 bottom[:] = m
6733 boffset += dw
6735 elif histtype.startswith('step'):
6736 # these define the perimeter of the polygon
6737 x = np.zeros(4 * len(bins) - 3)
6738 y = np.zeros(4 * len(bins) - 3)
6740 x[0:2*len(bins)-1:2], x[1:2*len(bins)-1:2] = bins, bins[:-1]
6741 x[2*len(bins)-1:] = x[1:2*len(bins)-1][::-1]
6743 if bottom is None:
6744 bottom = np.zeros(len(bins) - 1)
6746 y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = bottom, bottom
6747 y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1]
6749 if log:
6750 if orientation == 'horizontal':
6751 self.set_xscale('log', nonposx='clip')
6752 else: # orientation == 'vertical'
6753 self.set_yscale('log', nonposy='clip')
6755 if align == 'left':
6756 x -= 0.5*(bins[1]-bins[0])
6757 elif align == 'right':
6758 x += 0.5*(bins[1]-bins[0])
6760 # If fill kwarg is set, it will be passed to the patch collection,
6761 # overriding this
6762 fill = (histtype == 'stepfilled')
6764 xvals, yvals = [], []
6765 for m in tops:
6766 if stacked:
6767 # starting point for drawing polygon
6768 y[0] = y[1]
6769 # top of the previous polygon becomes the bottom
6770 y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1]
6771 # set the top of this polygon
6772 y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = (m + bottom,
6773 m + bottom)
6774 if orientation == 'horizontal':
6775 xvals.append(y.copy())
6776 yvals.append(x.copy())
6777 else:
6778 xvals.append(x.copy())
6779 yvals.append(y.copy())
6781 # stepfill is closed, step is not
6782 split = -1 if fill else 2 * len(bins)
6783 # add patches in reverse order so that when stacking,
6784 # items lower in the stack are plotted on top of
6785 # items higher in the stack
6786 for x, y, c in reversed(list(zip(xvals, yvals, color))):
6787 patches.append(self.fill(
6788 x[:split], y[:split],
6789 closed=True if fill else None,
6790 facecolor=c,
6791 edgecolor=None if fill else c,
6792 fill=fill if fill else None))
6793 for patch_list in patches:
6794 for patch in patch_list:
6795 if orientation == 'vertical':
6796 patch.sticky_edges.y.append(0)
6797 elif orientation == 'horizontal':
6798 patch.sticky_edges.x.append(0)
6800 # we return patches, so put it back in the expected order
6801 patches.reverse()
6803 self.set_autoscalex_on(_saved_autoscalex)
6804 self.set_autoscaley_on(_saved_autoscaley)
6805 self._request_autoscale_view()
6807 if label is None:
6808 labels = [None]
6809 elif isinstance(label, str):
6810 labels = [label]
6811 elif not np.iterable(label):
6812 labels = [str(label)]
6813 else:
6814 labels = [str(lab) for lab in label]
6816 for patch, lbl in itertools.zip_longest(patches, labels):
6817 if patch:
6818 p = patch[0]
6819 p.update(kwargs)
6820 if lbl is not None:
6821 p.set_label(lbl)
6823 for p in patch[1:]:
6824 p.update(kwargs)
6825 p.set_label('_nolegend_')
6827 if nx == 1:
6828 return tops[0], bins, cbook.silent_list('Patch', patches[0])
6829 else:
6830 return tops, bins, cbook.silent_list('Lists of Patches', patches)
6832 @_preprocess_data(replace_names=["x", "y", "weights"])
6833 @cbook._rename_parameter("3.1", "normed", "density")
6834 def hist2d(self, x, y, bins=10, range=None, density=False, weights=None,
6835 cmin=None, cmax=None, **kwargs):
6836 """
6837 Make a 2D histogram plot.
6839 Parameters
6840 ----------
6841 x, y : array-like, shape (n, )
6842 Input values
6844 bins : None or int or [int, int] or array-like or [array, array]
6846 The bin specification:
6848 - If int, the number of bins for the two dimensions
6849 (nx=ny=bins).
6850 - If ``[int, int]``, the number of bins in each dimension
6851 (nx, ny = bins).
6852 - If array-like, the bin edges for the two dimensions
6853 (x_edges=y_edges=bins).
6854 - If ``[array, array]``, the bin edges in each dimension
6855 (x_edges, y_edges = bins).
6857 The default value is 10.
6859 range : array-like shape(2, 2), optional, default: None
6860 The leftmost and rightmost edges of the bins along each dimension
6861 (if not specified explicitly in the bins parameters): ``[[xmin,
6862 xmax], [ymin, ymax]]``. All values outside of this range will be
6863 considered outliers and not tallied in the histogram.
6865 density : bool, optional, default: False
6866 Normalize histogram. *normed* is a deprecated synonym for this
6867 parameter.
6869 weights : array-like, shape (n, ), optional, default: None
6870 An array of values w_i weighing each sample (x_i, y_i).
6872 cmin : scalar, optional, default: None
6873 All bins that has count less than cmin will not be displayed (set
6874 to NaN before passing to imshow) and these count values in the
6875 return value count histogram will also be set to nan upon return.
6877 cmax : scalar, optional, default: None
6878 All bins that has count more than cmax will not be displayed (set
6879 to NaN before passing to imshow) and these count values in the
6880 return value count histogram will also be set to nan upon return.
6882 Returns
6883 -------
6884 h : 2D array
6885 The bi-dimensional histogram of samples x and y. Values in x are
6886 histogrammed along the first dimension and values in y are
6887 histogrammed along the second dimension.
6888 xedges : 1D array
6889 The bin edges along the x axis.
6890 yedges : 1D array
6891 The bin edges along the y axis.
6892 image : `~.matplotlib.collections.QuadMesh`
6894 Other Parameters
6895 ----------------
6896 cmap : Colormap or str, optional
6897 A `.colors.Colormap` instance. If not set, use rc settings.
6899 norm : Normalize, optional
6900 A `.colors.Normalize` instance is used to
6901 scale luminance data to ``[0, 1]``. If not set, defaults to
6902 `.colors.Normalize()`.
6904 vmin/vmax : None or scalar, optional
6905 Arguments passed to the `~.colors.Normalize` instance.
6907 alpha : ``0 <= scalar <= 1`` or ``None``, optional
6908 The alpha blending value.
6910 See also
6911 --------
6912 hist : 1D histogram plotting
6914 Notes
6915 -----
6916 - Currently ``hist2d`` calculates its own axis limits, and any limits
6917 previously set are ignored.
6918 - Rendering the histogram with a logarithmic color scale is
6919 accomplished by passing a `.colors.LogNorm` instance to the *norm*
6920 keyword argument. Likewise, power-law normalization (similar
6921 in effect to gamma correction) can be accomplished with
6922 `.colors.PowerNorm`.
6923 """
6925 h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range,
6926 normed=density, weights=weights)
6928 if cmin is not None:
6929 h[h < cmin] = None
6930 if cmax is not None:
6931 h[h > cmax] = None
6933 pc = self.pcolormesh(xedges, yedges, h.T, **kwargs)
6934 self.set_xlim(xedges[0], xedges[-1])
6935 self.set_ylim(yedges[0], yedges[-1])
6937 return h, xedges, yedges, pc
6939 @_preprocess_data(replace_names=["x"])
6940 @docstring.dedent_interpd
6941 def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
6942 window=None, noverlap=None, pad_to=None,
6943 sides=None, scale_by_freq=None, return_line=None, **kwargs):
6944 r"""
6945 Plot the power spectral density.
6947 The power spectral density :math:`P_{xx}` by Welch's average
6948 periodogram method. The vector *x* is divided into *NFFT* length
6949 segments. Each segment is detrended by function *detrend* and
6950 windowed by function *window*. *noverlap* gives the length of
6951 the overlap between segments. The :math:`|\mathrm{fft}(i)|^2`
6952 of each segment :math:`i` are averaged to compute :math:`P_{xx}`,
6953 with a scaling to correct for power loss due to windowing.
6955 If len(*x*) < *NFFT*, it will be zero padded to *NFFT*.
6957 Parameters
6958 ----------
6959 x : 1-D array or sequence
6960 Array or sequence containing the data
6962 %(Spectral)s
6964 %(PSD)s
6966 noverlap : int
6967 The number of points of overlap between segments.
6968 The default value is 0 (no overlap).
6970 Fc : int
6971 The center frequency of *x* (defaults to 0), which offsets
6972 the x extents of the plot to reflect the frequency range used
6973 when a signal is acquired and then filtered and downsampled to
6974 baseband.
6976 return_line : bool
6977 Whether to include the line object plotted in the returned values.
6978 Default is False.
6980 Returns
6981 -------
6982 Pxx : 1-D array
6983 The values for the power spectrum `P_{xx}` before scaling
6984 (real valued).
6986 freqs : 1-D array
6987 The frequencies corresponding to the elements in *Pxx*.
6989 line : `~matplotlib.lines.Line2D`
6990 The line created by this function.
6991 Only returned if *return_line* is True.
6993 Other Parameters
6994 ----------------
6995 **kwargs
6996 Keyword arguments control the `.Line2D` properties:
6998 %(_Line2D_docstr)s
7000 See Also
7001 --------
7002 :func:`specgram`
7003 :func:`specgram` differs in the default overlap; in not returning
7004 the mean of the segment periodograms; in returning the times of the
7005 segments; and in plotting a colormap instead of a line.
7007 :func:`magnitude_spectrum`
7008 :func:`magnitude_spectrum` plots the magnitude spectrum.
7010 :func:`csd`
7011 :func:`csd` plots the spectral density between two signals.
7013 Notes
7014 -----
7015 For plotting, the power is plotted as
7016 :math:`10\log_{10}(P_{xx})` for decibels, though *Pxx* itself
7017 is returned.
7019 References
7020 ----------
7021 Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
7022 John Wiley & Sons (1986)
7023 """
7024 if Fc is None:
7025 Fc = 0
7027 pxx, freqs = mlab.psd(x=x, NFFT=NFFT, Fs=Fs, detrend=detrend,
7028 window=window, noverlap=noverlap, pad_to=pad_to,
7029 sides=sides, scale_by_freq=scale_by_freq)
7030 freqs += Fc
7032 if scale_by_freq in (None, True):
7033 psd_units = 'dB/Hz'
7034 else:
7035 psd_units = 'dB'
7037 line = self.plot(freqs, 10 * np.log10(pxx), **kwargs)
7038 self.set_xlabel('Frequency')
7039 self.set_ylabel('Power Spectral Density (%s)' % psd_units)
7040 self.grid(True)
7041 vmin, vmax = self.viewLim.intervaly
7042 intv = vmax - vmin
7043 logi = int(np.log10(intv))
7044 if logi == 0:
7045 logi = .1
7046 step = 10 * logi
7047 ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step)
7048 self.set_yticks(ticks)
7050 if return_line is None or not return_line:
7051 return pxx, freqs
7052 else:
7053 return pxx, freqs, line
7055 @_preprocess_data(replace_names=["x", "y"], label_namer="y")
7056 @docstring.dedent_interpd
7057 def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None,
7058 window=None, noverlap=None, pad_to=None,
7059 sides=None, scale_by_freq=None, return_line=None, **kwargs):
7060 r"""
7061 Plot the cross-spectral density.
7063 The cross spectral density :math:`P_{xy}` by Welch's average
7064 periodogram method. The vectors *x* and *y* are divided into
7065 *NFFT* length segments. Each segment is detrended by function
7066 *detrend* and windowed by function *window*. *noverlap* gives
7067 the length of the overlap between segments. The product of
7068 the direct FFTs of *x* and *y* are averaged over each segment
7069 to compute :math:`P_{xy}`, with a scaling to correct for power
7070 loss due to windowing.
7072 If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero
7073 padded to *NFFT*.
7075 Parameters
7076 ----------
7077 x, y : 1-D arrays or sequences
7078 Arrays or sequences containing the data.
7080 %(Spectral)s
7082 %(PSD)s
7084 noverlap : int
7085 The number of points of overlap between segments.
7086 The default value is 0 (no overlap).
7088 Fc : int
7089 The center frequency of *x* (defaults to 0), which offsets
7090 the x extents of the plot to reflect the frequency range used
7091 when a signal is acquired and then filtered and downsampled to
7092 baseband.
7094 return_line : bool
7095 Whether to include the line object plotted in the returned values.
7096 Default is False.
7098 Returns
7099 -------
7100 Pxy : 1-D array
7101 The values for the cross spectrum `P_{xy}` before scaling
7102 (complex valued).
7104 freqs : 1-D array
7105 The frequencies corresponding to the elements in *Pxy*.
7107 line : `~matplotlib.lines.Line2D`
7108 The line created by this function.
7109 Only returned if *return_line* is True.
7111 Other Parameters
7112 ----------------
7113 **kwargs
7114 Keyword arguments control the `.Line2D` properties:
7116 %(_Line2D_docstr)s
7118 See Also
7119 --------
7120 :func:`psd`
7121 :func:`psd` is the equivalent to setting y=x.
7123 Notes
7124 -----
7125 For plotting, the power is plotted as
7126 :math:`10 \log_{10}(P_{xy})` for decibels, though `P_{xy}` itself
7127 is returned.
7129 References
7130 ----------
7131 Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
7132 John Wiley & Sons (1986)
7133 """
7134 if Fc is None:
7135 Fc = 0
7137 pxy, freqs = mlab.csd(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend,
7138 window=window, noverlap=noverlap, pad_to=pad_to,
7139 sides=sides, scale_by_freq=scale_by_freq)
7140 # pxy is complex
7141 freqs += Fc
7143 line = self.plot(freqs, 10 * np.log10(np.abs(pxy)), **kwargs)
7144 self.set_xlabel('Frequency')
7145 self.set_ylabel('Cross Spectrum Magnitude (dB)')
7146 self.grid(True)
7147 vmin, vmax = self.viewLim.intervaly
7149 intv = vmax - vmin
7150 step = 10 * int(np.log10(intv))
7152 ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step)
7153 self.set_yticks(ticks)
7155 if return_line is None or not return_line:
7156 return pxy, freqs
7157 else:
7158 return pxy, freqs, line
7160 @_preprocess_data(replace_names=["x"])
7161 @docstring.dedent_interpd
7162 def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None,
7163 pad_to=None, sides=None, scale=None,
7164 **kwargs):
7165 """
7166 Plot the magnitude spectrum.
7168 Compute the magnitude spectrum of *x*. Data is padded to a
7169 length of *pad_to* and the windowing function *window* is applied to
7170 the signal.
7172 Parameters
7173 ----------
7174 x : 1-D array or sequence
7175 Array or sequence containing the data.
7177 %(Spectral)s
7179 %(Single_Spectrum)s
7181 scale : {'default', 'linear', 'dB'}
7182 The scaling of the values in the *spec*. 'linear' is no scaling.
7183 'dB' returns the values in dB scale, i.e., the dB amplitude
7184 (20 * log10). 'default' is 'linear'.
7186 Fc : int
7187 The center frequency of *x* (defaults to 0), which offsets
7188 the x extents of the plot to reflect the frequency range used
7189 when a signal is acquired and then filtered and downsampled to
7190 baseband.
7192 Returns
7193 -------
7194 spectrum : 1-D array
7195 The values for the magnitude spectrum before scaling (real valued).
7197 freqs : 1-D array
7198 The frequencies corresponding to the elements in *spectrum*.
7200 line : `~matplotlib.lines.Line2D`
7201 The line created by this function.
7203 Other Parameters
7204 ----------------
7205 **kwargs
7206 Keyword arguments control the `.Line2D` properties:
7208 %(_Line2D_docstr)s
7210 See Also
7211 --------
7212 :func:`psd`
7213 :func:`psd` plots the power spectral density.`.
7215 :func:`angle_spectrum`
7216 :func:`angle_spectrum` plots the angles of the corresponding
7217 frequencies.
7219 :func:`phase_spectrum`
7220 :func:`phase_spectrum` plots the phase (unwrapped angle) of the
7221 corresponding frequencies.
7223 :func:`specgram`
7224 :func:`specgram` can plot the magnitude spectrum of segments within
7225 the signal in a colormap.
7227 """
7228 if Fc is None:
7229 Fc = 0
7231 if scale is None or scale == 'default':
7232 scale = 'linear'
7234 spec, freqs = mlab.magnitude_spectrum(x=x, Fs=Fs, window=window,
7235 pad_to=pad_to, sides=sides)
7236 freqs += Fc
7238 if scale == 'linear':
7239 Z = spec
7240 yunits = 'energy'
7241 elif scale == 'dB':
7242 Z = 20. * np.log10(spec)
7243 yunits = 'dB'
7244 else:
7245 raise ValueError('Unknown scale %s', scale)
7247 lines = self.plot(freqs, Z, **kwargs)
7248 self.set_xlabel('Frequency')
7249 self.set_ylabel('Magnitude (%s)' % yunits)
7251 return spec, freqs, lines[0]
7253 @_preprocess_data(replace_names=["x"])
7254 @docstring.dedent_interpd
7255 def angle_spectrum(self, x, Fs=None, Fc=None, window=None,
7256 pad_to=None, sides=None, **kwargs):
7257 """
7258 Plot the angle spectrum.
7260 Compute the angle spectrum (wrapped phase spectrum) of *x*.
7261 Data is padded to a length of *pad_to* and the windowing function
7262 *window* is applied to the signal.
7264 Parameters
7265 ----------
7266 x : 1-D array or sequence
7267 Array or sequence containing the data.
7269 %(Spectral)s
7271 %(Single_Spectrum)s
7273 Fc : int
7274 The center frequency of *x* (defaults to 0), which offsets
7275 the x extents of the plot to reflect the frequency range used
7276 when a signal is acquired and then filtered and downsampled to
7277 baseband.
7279 Returns
7280 -------
7281 spectrum : 1-D array
7282 The values for the angle spectrum in radians (real valued).
7284 freqs : 1-D array
7285 The frequencies corresponding to the elements in *spectrum*.
7287 line : `~matplotlib.lines.Line2D`
7288 The line created by this function.
7290 Other Parameters
7291 ----------------
7292 **kwargs
7293 Keyword arguments control the `.Line2D` properties:
7295 %(_Line2D_docstr)s
7297 See Also
7298 --------
7299 :func:`magnitude_spectrum`
7300 :func:`angle_spectrum` plots the magnitudes of the corresponding
7301 frequencies.
7303 :func:`phase_spectrum`
7304 :func:`phase_spectrum` plots the unwrapped version of this
7305 function.
7307 :func:`specgram`
7308 :func:`specgram` can plot the angle spectrum of segments within the
7309 signal in a colormap.
7311 """
7312 if Fc is None:
7313 Fc = 0
7315 spec, freqs = mlab.angle_spectrum(x=x, Fs=Fs, window=window,
7316 pad_to=pad_to, sides=sides)
7317 freqs += Fc
7319 lines = self.plot(freqs, spec, **kwargs)
7320 self.set_xlabel('Frequency')
7321 self.set_ylabel('Angle (radians)')
7323 return spec, freqs, lines[0]
7325 @_preprocess_data(replace_names=["x"])
7326 @docstring.dedent_interpd
7327 def phase_spectrum(self, x, Fs=None, Fc=None, window=None,
7328 pad_to=None, sides=None, **kwargs):
7329 """
7330 Plot the phase spectrum.
7332 Compute the phase spectrum (unwrapped angle spectrum) of *x*.
7333 Data is padded to a length of *pad_to* and the windowing function
7334 *window* is applied to the signal.
7336 Parameters
7337 ----------
7338 x : 1-D array or sequence
7339 Array or sequence containing the data
7341 %(Spectral)s
7343 %(Single_Spectrum)s
7345 Fc : int
7346 The center frequency of *x* (defaults to 0), which offsets
7347 the x extents of the plot to reflect the frequency range used
7348 when a signal is acquired and then filtered and downsampled to
7349 baseband.
7351 Returns
7352 -------
7353 spectrum : 1-D array
7354 The values for the phase spectrum in radians (real valued).
7356 freqs : 1-D array
7357 The frequencies corresponding to the elements in *spectrum*.
7359 line : `~matplotlib.lines.Line2D`
7360 The line created by this function.
7362 Other Parameters
7363 ----------------
7364 **kwargs
7365 Keyword arguments control the `.Line2D` properties:
7367 %(_Line2D_docstr)s
7369 See Also
7370 --------
7371 :func:`magnitude_spectrum`
7372 :func:`magnitude_spectrum` plots the magnitudes of the
7373 corresponding frequencies.
7375 :func:`angle_spectrum`
7376 :func:`angle_spectrum` plots the wrapped version of this function.
7378 :func:`specgram`
7379 :func:`specgram` can plot the phase spectrum of segments within the
7380 signal in a colormap.
7382 """
7383 if Fc is None:
7384 Fc = 0
7386 spec, freqs = mlab.phase_spectrum(x=x, Fs=Fs, window=window,
7387 pad_to=pad_to, sides=sides)
7388 freqs += Fc
7390 lines = self.plot(freqs, spec, **kwargs)
7391 self.set_xlabel('Frequency')
7392 self.set_ylabel('Phase (radians)')
7394 return spec, freqs, lines[0]
7396 @_preprocess_data(replace_names=["x", "y"])
7397 @docstring.dedent_interpd
7398 def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,
7399 window=mlab.window_hanning, noverlap=0, pad_to=None,
7400 sides='default', scale_by_freq=None, **kwargs):
7401 r"""
7402 Plot the coherence between *x* and *y*.
7404 Plot the coherence between *x* and *y*. Coherence is the
7405 normalized cross spectral density:
7407 .. math::
7409 C_{xy} = \frac{|P_{xy}|^2}{P_{xx}P_{yy}}
7411 Parameters
7412 ----------
7413 %(Spectral)s
7415 %(PSD)s
7417 noverlap : int
7418 The number of points of overlap between blocks. The
7419 default value is 0 (no overlap).
7421 Fc : int
7422 The center frequency of *x* (defaults to 0), which offsets
7423 the x extents of the plot to reflect the frequency range used
7424 when a signal is acquired and then filtered and downsampled to
7425 baseband.
7428 Returns
7429 -------
7430 Cxy : 1-D array
7431 The coherence vector.
7433 freqs : 1-D array
7434 The frequencies for the elements in *Cxy*.
7436 Other Parameters
7437 ----------------
7438 **kwargs
7439 Keyword arguments control the `.Line2D` properties:
7441 %(_Line2D_docstr)s
7443 References
7444 ----------
7445 Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
7446 John Wiley & Sons (1986)
7447 """
7448 cxy, freqs = mlab.cohere(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend,
7449 window=window, noverlap=noverlap,
7450 scale_by_freq=scale_by_freq)
7451 freqs += Fc
7453 self.plot(freqs, cxy, **kwargs)
7454 self.set_xlabel('Frequency')
7455 self.set_ylabel('Coherence')
7456 self.grid(True)
7458 return cxy, freqs
7460 @_preprocess_data(replace_names=["x"])
7461 @docstring.dedent_interpd
7462 def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
7463 window=None, noverlap=None,
7464 cmap=None, xextent=None, pad_to=None, sides=None,
7465 scale_by_freq=None, mode=None, scale=None,
7466 vmin=None, vmax=None, **kwargs):
7467 """
7468 Plot a spectrogram.
7470 Compute and plot a spectrogram of data in *x*. Data are split into
7471 *NFFT* length segments and the spectrum of each section is
7472 computed. The windowing function *window* is applied to each
7473 segment, and the amount of overlap of each segment is
7474 specified with *noverlap*. The spectrogram is plotted as a colormap
7475 (using imshow).
7477 Parameters
7478 ----------
7479 x : 1-D array or sequence
7480 Array or sequence containing the data.
7482 %(Spectral)s
7484 %(PSD)s
7486 mode : {'default', 'psd', 'magnitude', 'angle', 'phase'}
7487 What sort of spectrum to use. Default is 'psd', which takes the
7488 power spectral density. 'magnitude' returns the magnitude
7489 spectrum. 'angle' returns the phase spectrum without unwrapping.
7490 'phase' returns the phase spectrum with unwrapping.
7492 noverlap : int
7493 The number of points of overlap between blocks. The
7494 default value is 128.
7496 scale : {'default', 'linear', 'dB'}
7497 The scaling of the values in the *spec*. 'linear' is no scaling.
7498 'dB' returns the values in dB scale. When *mode* is 'psd',
7499 this is dB power (10 * log10). Otherwise this is dB amplitude
7500 (20 * log10). 'default' is 'dB' if *mode* is 'psd' or
7501 'magnitude' and 'linear' otherwise. This must be 'linear'
7502 if *mode* is 'angle' or 'phase'.
7504 Fc : int
7505 The center frequency of *x* (defaults to 0), which offsets
7506 the x extents of the plot to reflect the frequency range used
7507 when a signal is acquired and then filtered and downsampled to
7508 baseband.
7510 cmap
7511 A :class:`matplotlib.colors.Colormap` instance; if *None*, use
7512 default determined by rc
7514 xextent : *None* or (xmin, xmax)
7515 The image extent along the x-axis. The default sets *xmin* to the
7516 left border of the first bin (*spectrum* column) and *xmax* to the
7517 right border of the last bin. Note that for *noverlap>0* the width
7518 of the bins is smaller than those of the segments.
7520 **kwargs
7521 Additional keyword arguments are passed on to imshow which makes
7522 the specgram image.
7524 Returns
7525 -------
7526 spectrum : 2-D array
7527 Columns are the periodograms of successive segments.
7529 freqs : 1-D array
7530 The frequencies corresponding to the rows in *spectrum*.
7532 t : 1-D array
7533 The times corresponding to midpoints of segments (i.e., the columns
7534 in *spectrum*).
7536 im : instance of class :class:`~matplotlib.image.AxesImage`
7537 The image created by imshow containing the spectrogram
7539 See Also
7540 --------
7541 :func:`psd`
7542 :func:`psd` differs in the default overlap; in returning the mean
7543 of the segment periodograms; in not returning times; and in
7544 generating a line plot instead of colormap.
7546 :func:`magnitude_spectrum`
7547 A single spectrum, similar to having a single segment when *mode*
7548 is 'magnitude'. Plots a line instead of a colormap.
7550 :func:`angle_spectrum`
7551 A single spectrum, similar to having a single segment when *mode*
7552 is 'angle'. Plots a line instead of a colormap.
7554 :func:`phase_spectrum`
7555 A single spectrum, similar to having a single segment when *mode*
7556 is 'phase'. Plots a line instead of a colormap.
7558 Notes
7559 -----
7560 The parameters *detrend* and *scale_by_freq* do only apply when *mode*
7561 is set to 'psd'.
7562 """
7563 if NFFT is None:
7564 NFFT = 256 # same default as in mlab.specgram()
7565 if Fc is None:
7566 Fc = 0 # same default as in mlab._spectral_helper()
7567 if noverlap is None:
7568 noverlap = 128 # same default as in mlab.specgram()
7570 if mode == 'complex':
7571 raise ValueError('Cannot plot a complex specgram')
7573 if scale is None or scale == 'default':
7574 if mode in ['angle', 'phase']:
7575 scale = 'linear'
7576 else:
7577 scale = 'dB'
7578 elif mode in ['angle', 'phase'] and scale == 'dB':
7579 raise ValueError('Cannot use dB scale with angle or phase mode')
7581 spec, freqs, t = mlab.specgram(x=x, NFFT=NFFT, Fs=Fs,
7582 detrend=detrend, window=window,
7583 noverlap=noverlap, pad_to=pad_to,
7584 sides=sides,
7585 scale_by_freq=scale_by_freq,
7586 mode=mode)
7588 if scale == 'linear':
7589 Z = spec
7590 elif scale == 'dB':
7591 if mode is None or mode == 'default' or mode == 'psd':
7592 Z = 10. * np.log10(spec)
7593 else:
7594 Z = 20. * np.log10(spec)
7595 else:
7596 raise ValueError('Unknown scale %s', scale)
7598 Z = np.flipud(Z)
7600 if xextent is None:
7601 # padding is needed for first and last segment:
7602 pad_xextent = (NFFT-noverlap) / Fs / 2
7603 xextent = np.min(t) - pad_xextent, np.max(t) + pad_xextent
7604 xmin, xmax = xextent
7605 freqs += Fc
7606 extent = xmin, xmax, freqs[0], freqs[-1]
7607 im = self.imshow(Z, cmap, extent=extent, vmin=vmin, vmax=vmax,
7608 **kwargs)
7609 self.axis('auto')
7611 return spec, freqs, t, im
7613 @docstring.dedent_interpd
7614 def spy(self, Z, precision=0, marker=None, markersize=None,
7615 aspect='equal', origin="upper", **kwargs):
7616 """
7617 Plot the sparsity pattern of a 2D array.
7619 This visualizes the non-zero values of the array.
7621 Two plotting styles are available: image and marker. Both
7622 are available for full arrays, but only the marker style
7623 works for `scipy.sparse.spmatrix` instances.
7625 **Image style**
7627 If *marker* and *markersize* are *None*, `~.Axes.imshow` is used. Any
7628 extra remaining keyword arguments are passed to this method.
7630 **Marker style**
7632 If *Z* is a `scipy.sparse.spmatrix` or *marker* or *markersize* are
7633 *None*, a `.Line2D` object will be returned with the value of marker
7634 determining the marker type, and any remaining keyword arguments
7635 passed to `~.Axes.plot`.
7637 Parameters
7638 ----------
7639 Z : array-like (M, N)
7640 The array to be plotted.
7642 precision : float or 'present', optional, default: 0
7643 If *precision* is 0, any non-zero value will be plotted. Otherwise,
7644 values of :math:`|Z| > precision` will be plotted.
7646 For :class:`scipy.sparse.spmatrix` instances, you can also
7647 pass 'present'. In this case any value present in the array
7648 will be plotted, even if it is identically zero.
7650 origin : {'upper', 'lower'}, optional
7651 Place the [0, 0] index of the array in the upper left or lower left
7652 corner of the axes. The convention 'upper' is typically used for
7653 matrices and images.
7654 If not given, :rc:`image.origin` is used, defaulting to 'upper'.
7657 aspect : {'equal', 'auto', None} or float, optional
7658 Controls the aspect ratio of the axes. The aspect is of particular
7659 relevance for images since it may distort the image, i.e. pixel
7660 will not be square.
7662 This parameter is a shortcut for explicitly calling
7663 `.Axes.set_aspect`. See there for further details.
7665 - 'equal': Ensures an aspect ratio of 1. Pixels will be square.
7666 - 'auto': The axes is kept fixed and the aspect is adjusted so
7667 that the data fit in the axes. In general, this will result in
7668 non-square pixels.
7669 - *None*: Use :rc:`image.aspect`.
7671 Default: 'equal'
7673 Returns
7674 -------
7675 ret : `~matplotlib.image.AxesImage` or `.Line2D`
7676 The return type depends on the plotting style (see above).
7678 Other Parameters
7679 ----------------
7680 **kwargs
7681 The supported additional parameters depend on the plotting style.
7683 For the image style, you can pass the following additional
7684 parameters of `~.Axes.imshow`:
7686 - *cmap*
7687 - *alpha*
7688 - *url*
7689 - any `.Artist` properties (passed on to the `.AxesImage`)
7691 For the marker style, you can pass any `.Line2D` property except
7692 for *linestyle*:
7694 %(_Line2D_docstr)s
7695 """
7696 if marker is None and markersize is None and hasattr(Z, 'tocoo'):
7697 marker = 's'
7698 if marker is None and markersize is None:
7699 Z = np.asarray(Z)
7700 mask = np.abs(Z) > precision
7702 if 'cmap' not in kwargs:
7703 kwargs['cmap'] = mcolors.ListedColormap(['w', 'k'],
7704 name='binary')
7705 if 'interpolation' in kwargs:
7706 raise TypeError(
7707 "spy() got an unexpected keyword argument 'interpolation'")
7708 ret = self.imshow(mask, interpolation='nearest', aspect=aspect,
7709 origin=origin, **kwargs)
7710 else:
7711 if hasattr(Z, 'tocoo'):
7712 c = Z.tocoo()
7713 if precision == 'present':
7714 y = c.row
7715 x = c.col
7716 else:
7717 nonzero = np.abs(c.data) > precision
7718 y = c.row[nonzero]
7719 x = c.col[nonzero]
7720 else:
7721 Z = np.asarray(Z)
7722 nonzero = np.abs(Z) > precision
7723 y, x = np.nonzero(nonzero)
7724 if marker is None:
7725 marker = 's'
7726 if markersize is None:
7727 markersize = 10
7728 if 'linestyle' in kwargs:
7729 raise TypeError(
7730 "spy() got an unexpected keyword argument 'linestyle'")
7731 marks = mlines.Line2D(x, y, linestyle='None',
7732 marker=marker, markersize=markersize, **kwargs)
7733 self.add_line(marks)
7734 nr, nc = Z.shape
7735 self.set_xlim(-0.5, nc - 0.5)
7736 self.set_ylim(nr - 0.5, -0.5)
7737 self.set_aspect(aspect)
7738 ret = marks
7739 self.title.set_y(1.05)
7740 self.xaxis.tick_top()
7741 self.xaxis.set_ticks_position('both')
7742 self.xaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
7743 steps=[1, 2, 5, 10],
7744 integer=True))
7745 self.yaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
7746 steps=[1, 2, 5, 10],
7747 integer=True))
7748 return ret
7750 def matshow(self, Z, **kwargs):
7751 """
7752 Plot the values of a 2D matrix or array as color-coded image.
7754 The matrix will be shown the way it would be printed, with the first
7755 row at the top. Row and column numbering is zero-based.
7757 Parameters
7758 ----------
7759 Z : array-like(M, N)
7760 The matrix to be displayed.
7762 Returns
7763 -------
7764 image : `~matplotlib.image.AxesImage`
7766 Other Parameters
7767 ----------------
7768 **kwargs : `~matplotlib.axes.Axes.imshow` arguments
7770 See Also
7771 --------
7772 imshow : More general function to plot data on a 2D regular raster.
7774 Notes
7775 -----
7776 This is just a convenience function wrapping `.imshow` to set useful
7777 defaults for displaying a matrix. In particular:
7779 - Set ``origin='upper'``.
7780 - Set ``interpolation='nearest'``.
7781 - Set ``aspect='equal'``.
7782 - Ticks are placed to the left and above.
7783 - Ticks are formatted to show integer indices.
7785 """
7786 Z = np.asanyarray(Z)
7787 kw = {'origin': 'upper',
7788 'interpolation': 'nearest',
7789 'aspect': 'equal', # (already the imshow default)
7790 **kwargs}
7791 im = self.imshow(Z, **kw)
7792 self.title.set_y(1.05)
7793 self.xaxis.tick_top()
7794 self.xaxis.set_ticks_position('both')
7795 self.xaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
7796 steps=[1, 2, 5, 10],
7797 integer=True))
7798 self.yaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
7799 steps=[1, 2, 5, 10],
7800 integer=True))
7801 return im
7803 @_preprocess_data(replace_names=["dataset"])
7804 def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
7805 showmeans=False, showextrema=True, showmedians=False,
7806 quantiles=None, points=100, bw_method=None):
7807 """
7808 Make a violin plot.
7810 Make a violin plot for each column of *dataset* or each vector in
7811 sequence *dataset*. Each filled area extends to represent the
7812 entire data range, with optional lines at the mean, the median,
7813 the minimum, the maximum, and user-specified quantiles.
7815 Parameters
7816 ----------
7817 dataset : Array or a sequence of vectors.
7818 The input data.
7820 positions : array-like, default = [1, 2, ..., n]
7821 Sets the positions of the violins. The ticks and limits are
7822 automatically set to match the positions.
7824 vert : bool, default = True.
7825 If true, creates a vertical violin plot.
7826 Otherwise, creates a horizontal violin plot.
7828 widths : array-like, default = 0.5
7829 Either a scalar or a vector that sets the maximal width of
7830 each violin. The default is 0.5, which uses about half of the
7831 available horizontal space.
7833 showmeans : bool, default = False
7834 If `True`, will toggle rendering of the means.
7836 showextrema : bool, default = True
7837 If `True`, will toggle rendering of the extrema.
7839 showmedians : bool, default = False
7840 If `True`, will toggle rendering of the medians.
7842 quantiles : array-like, default = None
7843 If not None, set a list of floats in interval [0, 1] for each violin,
7844 which stands for the quantiles that will be rendered for that
7845 violin.
7847 points : scalar, default = 100
7848 Defines the number of points to evaluate each of the
7849 gaussian kernel density estimations at.
7851 bw_method : str, scalar or callable, optional
7852 The method used to calculate the estimator bandwidth. This can be
7853 'scott', 'silverman', a scalar constant or a callable. If a
7854 scalar, this will be used directly as `kde.factor`. If a
7855 callable, it should take a `GaussianKDE` instance as its only
7856 parameter and return a scalar. If None (default), 'scott' is used.
7858 Returns
7859 -------
7860 result : dict
7861 A dictionary mapping each component of the violinplot to a
7862 list of the corresponding collection instances created. The
7863 dictionary has the following keys:
7865 - ``bodies``: A list of the `~.collections.PolyCollection`
7866 instances containing the filled area of each violin.
7868 - ``cmeans``: A `~.collections.LineCollection` instance that marks
7869 the mean values of each of the violin's distribution.
7871 - ``cmins``: A `~.collections.LineCollection` instance that marks
7872 the bottom of each violin's distribution.
7874 - ``cmaxes``: A `~.collections.LineCollection` instance that marks
7875 the top of each violin's distribution.
7877 - ``cbars``: A `~.collections.LineCollection` instance that marks
7878 the centers of each violin's distribution.
7880 - ``cmedians``: A `~.collections.LineCollection` instance that
7881 marks the median values of each of the violin's distribution.
7883 - ``cquantiles``: A `~.collections.LineCollection` instance created
7884 to identify the quantile values of each of the violin's
7885 distribution.
7887 """
7889 def _kde_method(X, coords):
7890 # fallback gracefully if the vector contains only one value
7891 if np.all(X[0] == X):
7892 return (X[0] == coords).astype(float)
7893 kde = mlab.GaussianKDE(X, bw_method)
7894 return kde.evaluate(coords)
7896 vpstats = cbook.violin_stats(dataset, _kde_method, points=points,
7897 quantiles=quantiles)
7898 return self.violin(vpstats, positions=positions, vert=vert,
7899 widths=widths, showmeans=showmeans,
7900 showextrema=showextrema, showmedians=showmedians)
7902 def violin(self, vpstats, positions=None, vert=True, widths=0.5,
7903 showmeans=False, showextrema=True, showmedians=False):
7904 """Drawing function for violin plots.
7906 Draw a violin plot for each column of *vpstats*. Each filled area
7907 extends to represent the entire data range, with optional lines at the
7908 mean, the median, the minimum, the maximum, and the quantiles values.
7910 Parameters
7911 ----------
7912 vpstats : list of dicts
7913 A list of dictionaries containing stats for each violin plot.
7914 Required keys are:
7916 - ``coords``: A list of scalars containing the coordinates that
7917 the violin's kernel density estimate were evaluated at.
7919 - ``vals``: A list of scalars containing the values of the
7920 kernel density estimate at each of the coordinates given
7921 in *coords*.
7923 - ``mean``: The mean value for this violin's dataset.
7925 - ``median``: The median value for this violin's dataset.
7927 - ``min``: The minimum value for this violin's dataset.
7929 - ``max``: The maximum value for this violin's dataset.
7931 Optional keys are:
7933 - ``quantiles``: A list of scalars containing the quantile values
7934 for this violin's dataset.
7936 positions : array-like, default = [1, 2, ..., n]
7937 Sets the positions of the violins. The ticks and limits are
7938 automatically set to match the positions.
7940 vert : bool, default = True.
7941 If true, plots the violins vertically.
7942 Otherwise, plots the violins horizontally.
7944 widths : array-like, default = 0.5
7945 Either a scalar or a vector that sets the maximal width of
7946 each violin. The default is 0.5, which uses about half of the
7947 available horizontal space.
7949 showmeans : bool, default = False
7950 If true, will toggle rendering of the means.
7952 showextrema : bool, default = True
7953 If true, will toggle rendering of the extrema.
7955 showmedians : bool, default = False
7956 If true, will toggle rendering of the medians.
7958 Returns
7959 -------
7960 result : dict
7961 A dictionary mapping each component of the violinplot to a
7962 list of the corresponding collection instances created. The
7963 dictionary has the following keys:
7965 - ``bodies``: A list of the `~.collections.PolyCollection`
7966 instances containing the filled area of each violin.
7968 - ``cmeans``: A `~.collections.LineCollection` instance that marks
7969 the mean values of each of the violin's distribution.
7971 - ``cmins``: A `~.collections.LineCollection` instance that marks
7972 the bottom of each violin's distribution.
7974 - ``cmaxes``: A `~.collections.LineCollection` instance that marks
7975 the top of each violin's distribution.
7977 - ``cbars``: A `~.collections.LineCollection` instance that marks
7978 the centers of each violin's distribution.
7980 - ``cmedians``: A `~.collections.LineCollection` instance that
7981 marks the median values of each of the violin's distribution.
7983 - ``cquantiles``: A `~.collections.LineCollection` instance created
7984 to identify the quantiles values of each of the violin's
7985 distribution.
7987 """
7989 # Statistical quantities to be plotted on the violins
7990 means = []
7991 mins = []
7992 maxes = []
7993 medians = []
7994 quantiles = np.asarray([])
7996 # Collections to be returned
7997 artists = {}
7999 N = len(vpstats)
8000 datashape_message = ("List of violinplot statistics and `{0}` "
8001 "values must have the same length")
8003 # Validate positions
8004 if positions is None:
8005 positions = range(1, N + 1)
8006 elif len(positions) != N:
8007 raise ValueError(datashape_message.format("positions"))
8009 # Validate widths
8010 if np.isscalar(widths):
8011 widths = [widths] * N
8012 elif len(widths) != N:
8013 raise ValueError(datashape_message.format("widths"))
8015 # Calculate ranges for statistics lines
8016 pmins = -0.25 * np.array(widths) + positions
8017 pmaxes = 0.25 * np.array(widths) + positions
8019 # Check whether we are rendering vertically or horizontally
8020 if vert:
8021 fill = self.fill_betweenx
8022 perp_lines = self.hlines
8023 par_lines = self.vlines
8024 else:
8025 fill = self.fill_between
8026 perp_lines = self.vlines
8027 par_lines = self.hlines
8029 if rcParams['_internal.classic_mode']:
8030 fillcolor = 'y'
8031 edgecolor = 'r'
8032 else:
8033 fillcolor = edgecolor = self._get_lines.get_next_color()
8035 # Render violins
8036 bodies = []
8037 for stats, pos, width in zip(vpstats, positions, widths):
8038 # The 0.5 factor reflects the fact that we plot from v-p to
8039 # v+p
8040 vals = np.array(stats['vals'])
8041 vals = 0.5 * width * vals / vals.max()
8042 bodies += [fill(stats['coords'],
8043 -vals + pos,
8044 vals + pos,
8045 facecolor=fillcolor,
8046 alpha=0.3)]
8047 means.append(stats['mean'])
8048 mins.append(stats['min'])
8049 maxes.append(stats['max'])
8050 medians.append(stats['median'])
8051 q = stats.get('quantiles')
8052 if q is not None:
8053 # If exist key quantiles, assume it's a list of floats
8054 quantiles = np.concatenate((quantiles, q))
8055 artists['bodies'] = bodies
8057 # Render means
8058 if showmeans:
8059 artists['cmeans'] = perp_lines(means, pmins, pmaxes,
8060 colors=edgecolor)
8062 # Render extrema
8063 if showextrema:
8064 artists['cmaxes'] = perp_lines(maxes, pmins, pmaxes,
8065 colors=edgecolor)
8066 artists['cmins'] = perp_lines(mins, pmins, pmaxes,
8067 colors=edgecolor)
8068 artists['cbars'] = par_lines(positions, mins, maxes,
8069 colors=edgecolor)
8071 # Render medians
8072 if showmedians:
8073 artists['cmedians'] = perp_lines(medians,
8074 pmins,
8075 pmaxes,
8076 colors=edgecolor)
8078 # Render quantile values
8079 if quantiles.size > 0:
8080 # Recalculate ranges for statistics lines for quantiles.
8081 # ppmins are the left end of quantiles lines
8082 ppmins = np.asarray([])
8083 # pmaxes are the right end of quantiles lines
8084 ppmaxs = np.asarray([])
8085 for stats, cmin, cmax in zip(vpstats, pmins, pmaxes):
8086 q = stats.get('quantiles')
8087 if q is not None:
8088 ppmins = np.concatenate((ppmins, [cmin] * np.size(q)))
8089 ppmaxs = np.concatenate((ppmaxs, [cmax] * np.size(q)))
8090 # Start rendering
8091 artists['cquantiles'] = perp_lines(quantiles, ppmins, ppmaxs,
8092 colors=edgecolor)
8094 return artists
8096 # Methods that are entirely implemented in other modules.
8098 table = mtable.table
8100 # args can by either Y or y1, y2, ... and all should be replaced
8101 stackplot = _preprocess_data()(mstack.stackplot)
8103 streamplot = _preprocess_data(
8104 replace_names=["x", "y", "u", "v", "start_points"])(mstream.streamplot)
8106 tricontour = mtri.tricontour
8107 tricontourf = mtri.tricontourf
8108 tripcolor = mtri.tripcolor
8109 triplot = mtri.triplot