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