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