Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/matplotlib/axes/_axes.py: 9%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

2334 statements  

1import functools 

2import itertools 

3import logging 

4import math 

5from numbers import Integral, Number, Real 

6 

7import re 

8import numpy as np 

9from numpy import ma 

10 

11import matplotlib as mpl 

12import matplotlib.category # Register category unit converter as side effect. 

13import matplotlib.cbook as cbook 

14import matplotlib.collections as mcoll 

15import matplotlib.colors as mcolors 

16import matplotlib.contour as mcontour 

17import matplotlib.dates # noqa # Register date unit converter as side effect. 

18import matplotlib.image as mimage 

19import matplotlib.legend as mlegend 

20import matplotlib.lines as mlines 

21import matplotlib.markers as mmarkers 

22import matplotlib.mlab as mlab 

23import matplotlib.patches as mpatches 

24import matplotlib.path as mpath 

25import matplotlib.quiver as mquiver 

26import matplotlib.stackplot as mstack 

27import matplotlib.streamplot as mstream 

28import matplotlib.table as mtable 

29import matplotlib.text as mtext 

30import matplotlib.ticker as mticker 

31import matplotlib.transforms as mtransforms 

32import matplotlib.tri as mtri 

33import matplotlib.units as munits 

34from matplotlib import _api, _docstring, _preprocess_data 

35from matplotlib.axes._base import ( 

36 _AxesBase, _TransformedBoundsLocator, _process_plot_format) 

37from matplotlib.axes._secondary_axes import SecondaryAxis 

38from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer 

39 

40_log = logging.getLogger(__name__) 

41 

42 

43# The axes module contains all the wrappers to plotting functions. 

44# All the other methods should go in the _AxesBase class. 

45 

46 

47def _make_axes_method(func): 

48 """ 

49 Patch the qualname for functions that are directly added to Axes. 

50 

51 Some Axes functionality is defined in functions in other submodules. 

52 These are simply added as attributes to Axes. As a result, their 

53 ``__qualname__`` is e.g. only "table" and not "Axes.table". This 

54 function fixes that. 

55 

56 Note that the function itself is patched, so that 

57 ``matplotlib.table.table.__qualname__` will also show "Axes.table". 

58 However, since these functions are not intended to be standalone, 

59 this is bearable. 

60 """ 

61 func.__qualname__ = f"Axes.{func.__name__}" 

62 return func 

63 

64 

65@_docstring.interpd 

66class Axes(_AxesBase): 

67 """ 

68 An Axes object encapsulates all the elements of an individual (sub-)plot in 

69 a figure. 

70 

71 It contains most of the (sub-)plot elements: `~.axis.Axis`, 

72 `~.axis.Tick`, `~.lines.Line2D`, `~.text.Text`, `~.patches.Polygon`, etc., 

73 and sets the coordinate system. 

74 

75 Like all visible elements in a figure, Axes is an `.Artist` subclass. 

76 

77 The `Axes` instance supports callbacks through a callbacks attribute which 

78 is a `~.cbook.CallbackRegistry` instance. The events you can connect to 

79 are 'xlim_changed' and 'ylim_changed' and the callback will be called with 

80 func(*ax*) where *ax* is the `Axes` instance. 

81 

82 .. note:: 

83 

84 As a user, you do not instantiate Axes directly, but use Axes creation 

85 methods instead; e.g. from `.pyplot` or `.Figure`: 

86 `~.pyplot.subplots`, `~.pyplot.subplot_mosaic` or `.Figure.add_axes`. 

87 

88 Attributes 

89 ---------- 

90 dataLim : `.Bbox` 

91 The bounding box enclosing all data displayed in the Axes. 

92 viewLim : `.Bbox` 

93 The view limits in data coordinates. 

94 

95 """ 

96 ### Labelling, legend and texts 

97 

98 def get_title(self, loc="center"): 

99 """ 

100 Get an Axes title. 

101 

102 Get one of the three available Axes titles. The available titles 

103 are positioned above the Axes in the center, flush with the left 

104 edge, and flush with the right edge. 

105 

106 Parameters 

107 ---------- 

108 loc : {'center', 'left', 'right'}, str, default: 'center' 

109 Which title to return. 

110 

111 Returns 

112 ------- 

113 str 

114 The title text string. 

115 

116 """ 

117 titles = {'left': self._left_title, 

118 'center': self.title, 

119 'right': self._right_title} 

120 title = _api.check_getitem(titles, loc=loc.lower()) 

121 return title.get_text() 

122 

123 def set_title(self, label, fontdict=None, loc=None, pad=None, *, y=None, 

124 **kwargs): 

125 """ 

126 Set a title for the Axes. 

127 

128 Set one of the three available Axes titles. The available titles 

129 are positioned above the Axes in the center, flush with the left 

130 edge, and flush with the right edge. 

131 

132 Parameters 

133 ---------- 

134 label : str 

135 Text to use for the title 

136 

137 fontdict : dict 

138 

139 .. admonition:: Discouraged 

140 

141 The use of *fontdict* is discouraged. Parameters should be passed as 

142 individual keyword arguments or using dictionary-unpacking 

143 ``set_title(..., **fontdict)``. 

144 

145 A dictionary controlling the appearance of the title text, 

146 the default *fontdict* is:: 

147 

148 {'fontsize': rcParams['axes.titlesize'], 

149 'fontweight': rcParams['axes.titleweight'], 

150 'color': rcParams['axes.titlecolor'], 

151 'verticalalignment': 'baseline', 

152 'horizontalalignment': loc} 

153 

154 loc : {'center', 'left', 'right'}, default: :rc:`axes.titlelocation` 

155 Which title to set. 

156 

157 y : float, default: :rc:`axes.titley` 

158 Vertical Axes location for the title (1.0 is the top). If 

159 None (the default) and :rc:`axes.titley` is also None, y is 

160 determined automatically to avoid decorators on the Axes. 

161 

162 pad : float, default: :rc:`axes.titlepad` 

163 The offset of the title from the top of the Axes, in points. 

164 

165 Returns 

166 ------- 

167 `.Text` 

168 The matplotlib text instance representing the title 

169 

170 Other Parameters 

171 ---------------- 

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

173 Other keyword arguments are text properties, see `.Text` for a list 

174 of valid text properties. 

175 """ 

176 if loc is None: 

177 loc = mpl.rcParams['axes.titlelocation'] 

178 

179 if y is None: 

180 y = mpl.rcParams['axes.titley'] 

181 if y is None: 

182 y = 1.0 

183 else: 

184 self._autotitlepos = False 

185 kwargs['y'] = y 

186 

187 titles = {'left': self._left_title, 

188 'center': self.title, 

189 'right': self._right_title} 

190 title = _api.check_getitem(titles, loc=loc.lower()) 

191 default = { 

192 'fontsize': mpl.rcParams['axes.titlesize'], 

193 'fontweight': mpl.rcParams['axes.titleweight'], 

194 'verticalalignment': 'baseline', 

195 'horizontalalignment': loc.lower()} 

196 titlecolor = mpl.rcParams['axes.titlecolor'] 

197 if not cbook._str_lower_equal(titlecolor, 'auto'): 

198 default["color"] = titlecolor 

199 if pad is None: 

200 pad = mpl.rcParams['axes.titlepad'] 

201 self._set_title_offset_trans(float(pad)) 

202 title.set_text(label) 

203 title.update(default) 

204 if fontdict is not None: 

205 title.update(fontdict) 

206 title._internal_update(kwargs) 

207 return title 

208 

209 def get_legend_handles_labels(self, legend_handler_map=None): 

210 """ 

211 Return handles and labels for legend 

212 

213 ``ax.legend()`` is equivalent to :: 

214 

215 h, l = ax.get_legend_handles_labels() 

216 ax.legend(h, l) 

217 """ 

218 # pass through to legend. 

219 handles, labels = mlegend._get_legend_handles_labels( 

220 [self], legend_handler_map) 

221 return handles, labels 

222 

223 @_docstring.dedent_interpd 

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

225 """ 

226 Place a legend on the Axes. 

227 

228 Call signatures:: 

229 

230 legend() 

231 legend(handles, labels) 

232 legend(handles=handles) 

233 legend(labels) 

234 

235 The call signatures correspond to the following different ways to use 

236 this method: 

237 

238 **1. Automatic detection of elements to be shown in the legend** 

239 

240 The elements to be added to the legend are automatically determined, 

241 when you do not pass in any extra arguments. 

242 

243 In this case, the labels are taken from the artist. You can specify 

244 them either at artist creation or by calling the 

245 :meth:`~.Artist.set_label` method on the artist:: 

246 

247 ax.plot([1, 2, 3], label='Inline label') 

248 ax.legend() 

249 

250 or:: 

251 

252 line, = ax.plot([1, 2, 3]) 

253 line.set_label('Label via method') 

254 ax.legend() 

255 

256 .. note:: 

257 Specific artists can be excluded from the automatic legend element 

258 selection by using a label starting with an underscore, "_". 

259 A string starting with an underscore is the default label for all 

260 artists, so calling `.Axes.legend` without any arguments and 

261 without setting the labels manually will result in a ``UserWarning`` 

262 and an empty legend being drawn. 

263 

264 

265 **2. Explicitly listing the artists and labels in the legend** 

266 

267 For full control of which artists have a legend entry, it is possible 

268 to pass an iterable of legend artists followed by an iterable of 

269 legend labels respectively:: 

270 

271 ax.legend([line1, line2, line3], ['label1', 'label2', 'label3']) 

272 

273 

274 **3. Explicitly listing the artists in the legend** 

275 

276 This is similar to 2, but the labels are taken from the artists' 

277 label properties. Example:: 

278 

279 line1, = ax.plot([1, 2, 3], label='label1') 

280 line2, = ax.plot([1, 2, 3], label='label2') 

281 ax.legend(handles=[line1, line2]) 

282 

283 

284 **4. Labeling existing plot elements** 

285 

286 .. admonition:: Discouraged 

287 

288 This call signature is discouraged, because the relation between 

289 plot elements and labels is only implicit by their order and can 

290 easily be mixed up. 

291 

292 To make a legend for all artists on an Axes, call this function with 

293 an iterable of strings, one for each legend item. For example:: 

294 

295 ax.plot([1, 2, 3]) 

296 ax.plot([5, 6, 7]) 

297 ax.legend(['First line', 'Second line']) 

298 

299 

300 Parameters 

301 ---------- 

302 handles : list of (`.Artist` or tuple of `.Artist`), optional 

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

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

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

306 is not sufficient. 

307 

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

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

310 

311 If an entry contains a tuple, then the legend handler for all Artists in the 

312 tuple will be placed alongside a single label. 

313 

314 labels : list of str, optional 

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

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

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

318 is not sufficient. 

319 

320 Returns 

321 ------- 

322 `~matplotlib.legend.Legend` 

323 

324 Other Parameters 

325 ---------------- 

326 %(_legend_kw_axes)s 

327 

328 See Also 

329 -------- 

330 .Figure.legend 

331 

332 Notes 

333 ----- 

334 Some artists are not supported by this function. See 

335 :ref:`legend_guide` for details. 

336 

337 Examples 

338 -------- 

339 .. plot:: gallery/text_labels_and_annotations/legend.py 

340 """ 

341 handles, labels, kwargs = mlegend._parse_legend_args([self], *args, **kwargs) 

342 self.legend_ = mlegend.Legend(self, handles, labels, **kwargs) 

343 self.legend_._remove_method = self._remove_legend 

344 return self.legend_ 

345 

346 def _remove_legend(self, legend): 

347 self.legend_ = None 

348 

349 def inset_axes(self, bounds, *, transform=None, zorder=5, **kwargs): 

350 """ 

351 Add a child inset Axes to this existing Axes. 

352 

353 

354 Parameters 

355 ---------- 

356 bounds : [x0, y0, width, height] 

357 Lower-left corner of inset Axes, and its width and height. 

358 

359 transform : `.Transform` 

360 Defaults to `ax.transAxes`, i.e. the units of *rect* are in 

361 Axes-relative coordinates. 

362 

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

364'polar', 'rectilinear', str}, optional 

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

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

367 None results in a 'rectilinear' projection. 

368 

369 polar : bool, default: False 

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

371 

372 axes_class : subclass type of `~.axes.Axes`, optional 

373 The `.axes.Axes` subclass that is instantiated. This parameter 

374 is incompatible with *projection* and *polar*. See 

375 :ref:`axisartist_users-guide-index` for examples. 

376 

377 zorder : number 

378 Defaults to 5 (same as `.Axes.legend`). Adjust higher or lower 

379 to change whether it is above or below data plotted on the 

380 parent Axes. 

381 

382 **kwargs 

383 Other keyword arguments are passed on to the inset Axes class. 

384 

385 Returns 

386 ------- 

387 ax 

388 The created `~.axes.Axes` instance. 

389 

390 Examples 

391 -------- 

392 This example makes two inset Axes, the first is in Axes-relative 

393 coordinates, and the second in data-coordinates:: 

394 

395 fig, ax = plt.subplots() 

396 ax.plot(range(10)) 

397 axin1 = ax.inset_axes([0.8, 0.1, 0.15, 0.15]) 

398 axin2 = ax.inset_axes( 

399 [5, 7, 2.3, 2.3], transform=ax.transData) 

400 

401 """ 

402 if transform is None: 

403 transform = self.transAxes 

404 kwargs.setdefault('label', 'inset_axes') 

405 

406 # This puts the rectangle into figure-relative coordinates. 

407 inset_locator = _TransformedBoundsLocator(bounds, transform) 

408 bounds = inset_locator(self, None).bounds 

409 projection_class, pkw = self.figure._process_projection_requirements(**kwargs) 

410 inset_ax = projection_class(self.figure, bounds, zorder=zorder, **pkw) 

411 

412 # this locator lets the axes move if in data coordinates. 

413 # it gets called in `ax.apply_aspect() (of all places) 

414 inset_ax.set_axes_locator(inset_locator) 

415 

416 self.add_child_axes(inset_ax) 

417 

418 return inset_ax 

419 

420 @_docstring.dedent_interpd 

421 def indicate_inset(self, bounds, inset_ax=None, *, transform=None, 

422 facecolor='none', edgecolor='0.5', alpha=0.5, 

423 zorder=4.99, **kwargs): 

424 """ 

425 Add an inset indicator to the Axes. This is a rectangle on the plot 

426 at the position indicated by *bounds* that optionally has lines that 

427 connect the rectangle to an inset Axes (`.Axes.inset_axes`). 

428 

429 Warnings 

430 -------- 

431 This method is experimental as of 3.0, and the API may change. 

432 

433 Parameters 

434 ---------- 

435 bounds : [x0, y0, width, height] 

436 Lower-left corner of rectangle to be marked, and its width 

437 and height. 

438 

439 inset_ax : `.Axes` 

440 An optional inset Axes to draw connecting lines to. Two lines are 

441 drawn connecting the indicator box to the inset Axes on corners 

442 chosen so as to not overlap with the indicator box. 

443 

444 transform : `.Transform` 

445 Transform for the rectangle coordinates. Defaults to 

446 `ax.transAxes`, i.e. the units of *rect* are in Axes-relative 

447 coordinates. 

448 

449 facecolor : :mpltype:`color`, default: 'none' 

450 Facecolor of the rectangle. 

451 

452 edgecolor : :mpltype:`color`, default: '0.5' 

453 Color of the rectangle and color of the connecting lines. 

454 

455 alpha : float, default: 0.5 

456 Transparency of the rectangle and connector lines. 

457 

458 zorder : float, default: 4.99 

459 Drawing order of the rectangle and connector lines. The default, 

460 4.99, is just below the default level of inset Axes. 

461 

462 **kwargs 

463 Other keyword arguments are passed on to the `.Rectangle` patch: 

464 

465 %(Rectangle:kwdoc)s 

466 

467 Returns 

468 ------- 

469 rectangle_patch : `.patches.Rectangle` 

470 The indicator frame. 

471 

472 connector_lines : 4-tuple of `.patches.ConnectionPatch` 

473 The four connector lines connecting to (lower_left, upper_left, 

474 lower_right upper_right) corners of *inset_ax*. Two lines are 

475 set with visibility to *False*, but the user can set the 

476 visibility to True if the automatic choice is not deemed correct. 

477 

478 """ 

479 # to make the Axes connectors work, we need to apply the aspect to 

480 # the parent Axes. 

481 self.apply_aspect() 

482 

483 if transform is None: 

484 transform = self.transData 

485 kwargs.setdefault('label', '_indicate_inset') 

486 

487 x, y, width, height = bounds 

488 rectangle_patch = mpatches.Rectangle( 

489 (x, y), width, height, 

490 facecolor=facecolor, edgecolor=edgecolor, alpha=alpha, 

491 zorder=zorder, transform=transform, **kwargs) 

492 self.add_patch(rectangle_patch) 

493 

494 connects = [] 

495 

496 if inset_ax is not None: 

497 # connect the inset_axes to the rectangle 

498 for xy_inset_ax in [(0, 0), (0, 1), (1, 0), (1, 1)]: 

499 # inset_ax positions are in axes coordinates 

500 # The 0, 1 values define the four edges if the inset_ax 

501 # lower_left, upper_left, lower_right upper_right. 

502 ex, ey = xy_inset_ax 

503 if self.xaxis.get_inverted(): 

504 ex = 1 - ex 

505 if self.yaxis.get_inverted(): 

506 ey = 1 - ey 

507 xy_data = x + ex * width, y + ey * height 

508 p = mpatches.ConnectionPatch( 

509 xyA=xy_inset_ax, coordsA=inset_ax.transAxes, 

510 xyB=xy_data, coordsB=self.transData, 

511 arrowstyle="-", zorder=zorder, 

512 edgecolor=edgecolor, alpha=alpha) 

513 connects.append(p) 

514 self.add_patch(p) 

515 

516 # decide which two of the lines to keep visible.... 

517 pos = inset_ax.get_position() 

518 bboxins = pos.transformed(self.figure.transSubfigure) 

519 rectbbox = mtransforms.Bbox.from_bounds( 

520 *bounds 

521 ).transformed(transform) 

522 x0 = rectbbox.x0 < bboxins.x0 

523 x1 = rectbbox.x1 < bboxins.x1 

524 y0 = rectbbox.y0 < bboxins.y0 

525 y1 = rectbbox.y1 < bboxins.y1 

526 connects[0].set_visible(x0 ^ y0) 

527 connects[1].set_visible(x0 == y1) 

528 connects[2].set_visible(x1 == y0) 

529 connects[3].set_visible(x1 ^ y1) 

530 

531 return rectangle_patch, tuple(connects) if connects else None 

532 

533 def indicate_inset_zoom(self, inset_ax, **kwargs): 

534 """ 

535 Add an inset indicator rectangle to the Axes based on the axis 

536 limits for an *inset_ax* and draw connectors between *inset_ax* 

537 and the rectangle. 

538 

539 Warnings 

540 -------- 

541 This method is experimental as of 3.0, and the API may change. 

542 

543 Parameters 

544 ---------- 

545 inset_ax : `.Axes` 

546 Inset Axes to draw connecting lines to. Two lines are 

547 drawn connecting the indicator box to the inset Axes on corners 

548 chosen so as to not overlap with the indicator box. 

549 

550 **kwargs 

551 Other keyword arguments are passed on to `.Axes.indicate_inset` 

552 

553 Returns 

554 ------- 

555 rectangle_patch : `.patches.Rectangle` 

556 Rectangle artist. 

557 

558 connector_lines : 4-tuple of `.patches.ConnectionPatch` 

559 Each of four connector lines coming from the rectangle drawn on 

560 this axis, in the order lower left, upper left, lower right, 

561 upper right. 

562 Two are set with visibility to *False*, but the user can 

563 set the visibility to *True* if the automatic choice is not deemed 

564 correct. 

565 """ 

566 

567 xlim = inset_ax.get_xlim() 

568 ylim = inset_ax.get_ylim() 

569 rect = (xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]) 

570 return self.indicate_inset(rect, inset_ax, **kwargs) 

571 

572 @_docstring.dedent_interpd 

573 def secondary_xaxis(self, location, *, functions=None, transform=None, **kwargs): 

574 """ 

575 Add a second x-axis to this `~.axes.Axes`. 

576 

577 For example if we want to have a second scale for the data plotted on 

578 the xaxis. 

579 

580 %(_secax_docstring)s 

581 

582 Examples 

583 -------- 

584 The main axis shows frequency, and the secondary axis shows period. 

585 

586 .. plot:: 

587 

588 fig, ax = plt.subplots() 

589 ax.loglog(range(1, 360, 5), range(1, 360, 5)) 

590 ax.set_xlabel('frequency [Hz]') 

591 

592 def invert(x): 

593 # 1/x with special treatment of x == 0 

594 x = np.array(x).astype(float) 

595 near_zero = np.isclose(x, 0) 

596 x[near_zero] = np.inf 

597 x[~near_zero] = 1 / x[~near_zero] 

598 return x 

599 

600 # the inverse of 1/x is itself 

601 secax = ax.secondary_xaxis('top', functions=(invert, invert)) 

602 secax.set_xlabel('Period [s]') 

603 plt.show() 

604 

605 To add a secondary axis relative to your data, you can pass a transform 

606 to the new axis. 

607 

608 .. plot:: 

609 

610 fig, ax = plt.subplots() 

611 ax.plot(range(0, 5), range(-1, 4)) 

612 

613 # Pass 'ax.transData' as a transform to place the axis 

614 # relative to your data at y=0 

615 secax = ax.secondary_xaxis(0, transform=ax.transData) 

616 """ 

617 if not (location in ['top', 'bottom'] or isinstance(location, Real)): 

618 raise ValueError('secondary_xaxis location must be either ' 

619 'a float or "top"/"bottom"') 

620 

621 secondary_ax = SecondaryAxis(self, 'x', location, functions, 

622 transform, **kwargs) 

623 self.add_child_axes(secondary_ax) 

624 return secondary_ax 

625 

626 @_docstring.dedent_interpd 

627 def secondary_yaxis(self, location, *, functions=None, transform=None, **kwargs): 

628 """ 

629 Add a second y-axis to this `~.axes.Axes`. 

630 

631 For example if we want to have a second scale for the data plotted on 

632 the yaxis. 

633 

634 %(_secax_docstring)s 

635 

636 Examples 

637 -------- 

638 Add a secondary Axes that converts from radians to degrees 

639 

640 .. plot:: 

641 

642 fig, ax = plt.subplots() 

643 ax.plot(range(1, 360, 5), range(1, 360, 5)) 

644 ax.set_ylabel('degrees') 

645 secax = ax.secondary_yaxis('right', functions=(np.deg2rad, 

646 np.rad2deg)) 

647 secax.set_ylabel('radians') 

648 

649 To add a secondary axis relative to your data, you can pass a transform 

650 to the new axis. 

651 

652 .. plot:: 

653 

654 fig, ax = plt.subplots() 

655 ax.plot(range(0, 5), range(-1, 4)) 

656 

657 # Pass 'ax.transData' as a transform to place the axis 

658 # relative to your data at x=3 

659 secax = ax.secondary_yaxis(3, transform=ax.transData) 

660 """ 

661 if not (location in ['left', 'right'] or isinstance(location, Real)): 

662 raise ValueError('secondary_yaxis location must be either ' 

663 'a float or "left"/"right"') 

664 

665 secondary_ax = SecondaryAxis(self, 'y', location, functions, 

666 transform, **kwargs) 

667 self.add_child_axes(secondary_ax) 

668 return secondary_ax 

669 

670 @_docstring.dedent_interpd 

671 def text(self, x, y, s, fontdict=None, **kwargs): 

672 """ 

673 Add text to the Axes. 

674 

675 Add the text *s* to the Axes at location *x*, *y* in data coordinates, 

676 with a default ``horizontalalignment`` on the ``left`` and 

677 ``verticalalignment`` at the ``baseline``. See 

678 :doc:`/gallery/text_labels_and_annotations/text_alignment`. 

679 

680 Parameters 

681 ---------- 

682 x, y : float 

683 The position to place the text. By default, this is in data 

684 coordinates. The coordinate system can be changed using the 

685 *transform* parameter. 

686 

687 s : str 

688 The text. 

689 

690 fontdict : dict, default: None 

691 

692 .. admonition:: Discouraged 

693 

694 The use of *fontdict* is discouraged. Parameters should be passed as 

695 individual keyword arguments or using dictionary-unpacking 

696 ``text(..., **fontdict)``. 

697 

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

699 is None, the defaults are determined by `.rcParams`. 

700 

701 Returns 

702 ------- 

703 `.Text` 

704 The created `.Text` instance. 

705 

706 Other Parameters 

707 ---------------- 

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

709 Other miscellaneous text parameters. 

710 

711 %(Text:kwdoc)s 

712 

713 Examples 

714 -------- 

715 Individual keyword arguments can be used to override any given 

716 parameter:: 

717 

718 >>> text(x, y, s, fontsize=12) 

719 

720 The default transform specifies that text is in data coords, 

721 alternatively, you can specify text in axis coords ((0, 0) is 

722 lower-left and (1, 1) is upper-right). The example below places 

723 text in the center of the Axes:: 

724 

725 >>> text(0.5, 0.5, 'matplotlib', horizontalalignment='center', 

726 ... verticalalignment='center', transform=ax.transAxes) 

727 

728 You can put a rectangular box around the text instance (e.g., to 

729 set a background color) by using the keyword *bbox*. *bbox* is 

730 a dictionary of `~matplotlib.patches.Rectangle` 

731 properties. For example:: 

732 

733 >>> text(x, y, s, bbox=dict(facecolor='red', alpha=0.5)) 

734 """ 

735 effective_kwargs = { 

736 'verticalalignment': 'baseline', 

737 'horizontalalignment': 'left', 

738 'transform': self.transData, 

739 'clip_on': False, 

740 **(fontdict if fontdict is not None else {}), 

741 **kwargs, 

742 } 

743 t = mtext.Text(x, y, text=s, **effective_kwargs) 

744 if t.get_clip_path() is None: 

745 t.set_clip_path(self.patch) 

746 self._add_text(t) 

747 return t 

748 

749 @_docstring.dedent_interpd 

750 def annotate(self, text, xy, xytext=None, xycoords='data', textcoords=None, 

751 arrowprops=None, annotation_clip=None, **kwargs): 

752 # Signature must match Annotation. This is verified in 

753 # test_annotate_signature(). 

754 a = mtext.Annotation(text, xy, xytext=xytext, xycoords=xycoords, 

755 textcoords=textcoords, arrowprops=arrowprops, 

756 annotation_clip=annotation_clip, **kwargs) 

757 a.set_transform(mtransforms.IdentityTransform()) 

758 if kwargs.get('clip_on', False) and a.get_clip_path() is None: 

759 a.set_clip_path(self.patch) 

760 self._add_text(a) 

761 return a 

762 annotate.__doc__ = mtext.Annotation.__init__.__doc__ 

763 #### Lines and spans 

764 

765 @_docstring.dedent_interpd 

766 def axhline(self, y=0, xmin=0, xmax=1, **kwargs): 

767 """ 

768 Add a horizontal line across the Axes. 

769 

770 Parameters 

771 ---------- 

772 y : float, default: 0 

773 y position in data coordinates of the horizontal line. 

774 

775 xmin : float, default: 0 

776 Should be between 0 and 1, 0 being the far left of the plot, 1 the 

777 far right of the plot. 

778 

779 xmax : float, default: 1 

780 Should be between 0 and 1, 0 being the far left of the plot, 1 the 

781 far right of the plot. 

782 

783 Returns 

784 ------- 

785 `~matplotlib.lines.Line2D` 

786 

787 Other Parameters 

788 ---------------- 

789 **kwargs 

790 Valid keyword arguments are `.Line2D` properties, except for 

791 'transform': 

792 

793 %(Line2D:kwdoc)s 

794 

795 See Also 

796 -------- 

797 hlines : Add horizontal lines in data coordinates. 

798 axhspan : Add a horizontal span (rectangle) across the axis. 

799 axline : Add a line with an arbitrary slope. 

800 

801 Examples 

802 -------- 

803 * draw a thick red hline at 'y' = 0 that spans the xrange:: 

804 

805 >>> axhline(linewidth=4, color='r') 

806 

807 * draw a default hline at 'y' = 1 that spans the xrange:: 

808 

809 >>> axhline(y=1) 

810 

811 * draw a default hline at 'y' = .5 that spans the middle half of 

812 the xrange:: 

813 

814 >>> axhline(y=.5, xmin=0.25, xmax=0.75) 

815 """ 

816 self._check_no_units([xmin, xmax], ['xmin', 'xmax']) 

817 if "transform" in kwargs: 

818 raise ValueError("'transform' is not allowed as a keyword " 

819 "argument; axhline generates its own transform.") 

820 ymin, ymax = self.get_ybound() 

821 

822 # Strip away the units for comparison with non-unitized bounds. 

823 yy, = self._process_unit_info([("y", y)], kwargs) 

824 scaley = (yy < ymin) or (yy > ymax) 

825 

826 trans = self.get_yaxis_transform(which='grid') 

827 l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs) 

828 self.add_line(l) 

829 l.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS 

830 if scaley: 

831 self._request_autoscale_view("y") 

832 return l 

833 

834 @_docstring.dedent_interpd 

835 def axvline(self, x=0, ymin=0, ymax=1, **kwargs): 

836 """ 

837 Add a vertical line across the Axes. 

838 

839 Parameters 

840 ---------- 

841 x : float, default: 0 

842 x position in data coordinates of the vertical line. 

843 

844 ymin : float, default: 0 

845 Should be between 0 and 1, 0 being the bottom of the plot, 1 the 

846 top of the plot. 

847 

848 ymax : float, default: 1 

849 Should be between 0 and 1, 0 being the bottom of the plot, 1 the 

850 top of the plot. 

851 

852 Returns 

853 ------- 

854 `~matplotlib.lines.Line2D` 

855 

856 Other Parameters 

857 ---------------- 

858 **kwargs 

859 Valid keyword arguments are `.Line2D` properties, except for 

860 'transform': 

861 

862 %(Line2D:kwdoc)s 

863 

864 See Also 

865 -------- 

866 vlines : Add vertical lines in data coordinates. 

867 axvspan : Add a vertical span (rectangle) across the axis. 

868 axline : Add a line with an arbitrary slope. 

869 

870 Examples 

871 -------- 

872 * draw a thick red vline at *x* = 0 that spans the yrange:: 

873 

874 >>> axvline(linewidth=4, color='r') 

875 

876 * draw a default vline at *x* = 1 that spans the yrange:: 

877 

878 >>> axvline(x=1) 

879 

880 * draw a default vline at *x* = .5 that spans the middle half of 

881 the yrange:: 

882 

883 >>> axvline(x=.5, ymin=0.25, ymax=0.75) 

884 """ 

885 self._check_no_units([ymin, ymax], ['ymin', 'ymax']) 

886 if "transform" in kwargs: 

887 raise ValueError("'transform' is not allowed as a keyword " 

888 "argument; axvline generates its own transform.") 

889 xmin, xmax = self.get_xbound() 

890 

891 # Strip away the units for comparison with non-unitized bounds. 

892 xx, = self._process_unit_info([("x", x)], kwargs) 

893 scalex = (xx < xmin) or (xx > xmax) 

894 

895 trans = self.get_xaxis_transform(which='grid') 

896 l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs) 

897 self.add_line(l) 

898 l.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS 

899 if scalex: 

900 self._request_autoscale_view("x") 

901 return l 

902 

903 @staticmethod 

904 def _check_no_units(vals, names): 

905 # Helper method to check that vals are not unitized 

906 for val, name in zip(vals, names): 

907 if not munits._is_natively_supported(val): 

908 raise ValueError(f"{name} must be a single scalar value, " 

909 f"but got {val}") 

910 

911 @_docstring.dedent_interpd 

912 def axline(self, xy1, xy2=None, *, slope=None, **kwargs): 

913 """ 

914 Add an infinitely long straight line. 

915 

916 The line can be defined either by two points *xy1* and *xy2*, or 

917 by one point *xy1* and a *slope*. 

918 

919 This draws a straight line "on the screen", regardless of the x and y 

920 scales, and is thus also suitable for drawing exponential decays in 

921 semilog plots, power laws in loglog plots, etc. However, *slope* 

922 should only be used with linear scales; It has no clear meaning for 

923 all other scales, and thus the behavior is undefined. Please specify 

924 the line using the points *xy1*, *xy2* for non-linear scales. 

925 

926 The *transform* keyword argument only applies to the points *xy1*, 

927 *xy2*. The *slope* (if given) is always in data coordinates. This can 

928 be used e.g. with ``ax.transAxes`` for drawing grid lines with a fixed 

929 slope. 

930 

931 Parameters 

932 ---------- 

933 xy1, xy2 : (float, float) 

934 Points for the line to pass through. 

935 Either *xy2* or *slope* has to be given. 

936 slope : float, optional 

937 The slope of the line. Either *xy2* or *slope* has to be given. 

938 

939 Returns 

940 ------- 

941 `.AxLine` 

942 

943 Other Parameters 

944 ---------------- 

945 **kwargs 

946 Valid kwargs are `.Line2D` properties 

947 

948 %(Line2D:kwdoc)s 

949 

950 See Also 

951 -------- 

952 axhline : for horizontal lines 

953 axvline : for vertical lines 

954 

955 Examples 

956 -------- 

957 Draw a thick red line passing through (0, 0) and (1, 1):: 

958 

959 >>> axline((0, 0), (1, 1), linewidth=4, color='r') 

960 """ 

961 if slope is not None and (self.get_xscale() != 'linear' or 

962 self.get_yscale() != 'linear'): 

963 raise TypeError("'slope' cannot be used with non-linear scales") 

964 

965 datalim = [xy1] if xy2 is None else [xy1, xy2] 

966 if "transform" in kwargs: 

967 # if a transform is passed (i.e. line points not in data space), 

968 # data limits should not be adjusted. 

969 datalim = [] 

970 

971 line = mlines.AxLine(xy1, xy2, slope, **kwargs) 

972 # Like add_line, but correctly handling data limits. 

973 self._set_artist_props(line) 

974 if line.get_clip_path() is None: 

975 line.set_clip_path(self.patch) 

976 if not line.get_label(): 

977 line.set_label(f"_child{len(self._children)}") 

978 self._children.append(line) 

979 line._remove_method = self._children.remove 

980 self.update_datalim(datalim) 

981 

982 self._request_autoscale_view() 

983 return line 

984 

985 @_docstring.dedent_interpd 

986 def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs): 

987 """ 

988 Add a horizontal span (rectangle) across the Axes. 

989 

990 The rectangle spans from *ymin* to *ymax* vertically, and, by default, 

991 the whole x-axis horizontally. The x-span can be set using *xmin* 

992 (default: 0) and *xmax* (default: 1) which are in axis units; e.g. 

993 ``xmin = 0.5`` always refers to the middle of the x-axis regardless of 

994 the limits set by `~.Axes.set_xlim`. 

995 

996 Parameters 

997 ---------- 

998 ymin : float 

999 Lower y-coordinate of the span, in data units. 

1000 ymax : float 

1001 Upper y-coordinate of the span, in data units. 

1002 xmin : float, default: 0 

1003 Lower x-coordinate of the span, in x-axis (0-1) units. 

1004 xmax : float, default: 1 

1005 Upper x-coordinate of the span, in x-axis (0-1) units. 

1006 

1007 Returns 

1008 ------- 

1009 `~matplotlib.patches.Rectangle` 

1010 Horizontal span (rectangle) from (xmin, ymin) to (xmax, ymax). 

1011 

1012 Other Parameters 

1013 ---------------- 

1014 **kwargs : `~matplotlib.patches.Rectangle` properties 

1015 

1016 %(Rectangle:kwdoc)s 

1017 

1018 See Also 

1019 -------- 

1020 axvspan : Add a vertical span across the Axes. 

1021 """ 

1022 # Strip units away. 

1023 self._check_no_units([xmin, xmax], ['xmin', 'xmax']) 

1024 (ymin, ymax), = self._process_unit_info([("y", [ymin, ymax])], kwargs) 

1025 

1026 p = mpatches.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, **kwargs) 

1027 p.set_transform(self.get_yaxis_transform(which="grid")) 

1028 # For Rectangles and non-separable transforms, add_patch can be buggy 

1029 # and update the x limits even though it shouldn't do so for an 

1030 # yaxis_transformed patch, so undo that update. 

1031 ix = self.dataLim.intervalx.copy() 

1032 mx = self.dataLim.minposx 

1033 self.add_patch(p) 

1034 self.dataLim.intervalx = ix 

1035 self.dataLim.minposx = mx 

1036 p.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS 

1037 self._request_autoscale_view("y") 

1038 return p 

1039 

1040 @_docstring.dedent_interpd 

1041 def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs): 

1042 """ 

1043 Add a vertical span (rectangle) across the Axes. 

1044 

1045 The rectangle spans from *xmin* to *xmax* horizontally, and, by 

1046 default, the whole y-axis vertically. The y-span can be set using 

1047 *ymin* (default: 0) and *ymax* (default: 1) which are in axis units; 

1048 e.g. ``ymin = 0.5`` always refers to the middle of the y-axis 

1049 regardless of the limits set by `~.Axes.set_ylim`. 

1050 

1051 Parameters 

1052 ---------- 

1053 xmin : float 

1054 Lower x-coordinate of the span, in data units. 

1055 xmax : float 

1056 Upper x-coordinate of the span, in data units. 

1057 ymin : float, default: 0 

1058 Lower y-coordinate of the span, in y-axis units (0-1). 

1059 ymax : float, default: 1 

1060 Upper y-coordinate of the span, in y-axis units (0-1). 

1061 

1062 Returns 

1063 ------- 

1064 `~matplotlib.patches.Rectangle` 

1065 Vertical span (rectangle) from (xmin, ymin) to (xmax, ymax). 

1066 

1067 Other Parameters 

1068 ---------------- 

1069 **kwargs : `~matplotlib.patches.Rectangle` properties 

1070 

1071 %(Rectangle:kwdoc)s 

1072 

1073 See Also 

1074 -------- 

1075 axhspan : Add a horizontal span across the Axes. 

1076 

1077 Examples 

1078 -------- 

1079 Draw a vertical, green, translucent rectangle from x = 1.25 to 

1080 x = 1.55 that spans the yrange of the Axes. 

1081 

1082 >>> axvspan(1.25, 1.55, facecolor='g', alpha=0.5) 

1083 

1084 """ 

1085 # Strip units away. 

1086 self._check_no_units([ymin, ymax], ['ymin', 'ymax']) 

1087 (xmin, xmax), = self._process_unit_info([("x", [xmin, xmax])], kwargs) 

1088 

1089 p = mpatches.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, **kwargs) 

1090 p.set_transform(self.get_xaxis_transform(which="grid")) 

1091 # For Rectangles and non-separable transforms, add_patch can be buggy 

1092 # and update the y limits even though it shouldn't do so for an 

1093 # xaxis_transformed patch, so undo that update. 

1094 iy = self.dataLim.intervaly.copy() 

1095 my = self.dataLim.minposy 

1096 self.add_patch(p) 

1097 self.dataLim.intervaly = iy 

1098 self.dataLim.minposy = my 

1099 p.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS 

1100 self._request_autoscale_view("x") 

1101 return p 

1102 

1103 @_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"], 

1104 label_namer="y") 

1105 def hlines(self, y, xmin, xmax, colors=None, linestyles='solid', 

1106 label='', **kwargs): 

1107 """ 

1108 Plot horizontal lines at each *y* from *xmin* to *xmax*. 

1109 

1110 Parameters 

1111 ---------- 

1112 y : float or array-like 

1113 y-indexes where to plot the lines. 

1114 

1115 xmin, xmax : float or array-like 

1116 Respective beginning and end of each line. If scalars are 

1117 provided, all lines will have the same length. 

1118 

1119 colors : :mpltype:`color` or list of color , default: :rc:`lines.color` 

1120 

1121 linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, default: 'solid' 

1122 

1123 label : str, default: '' 

1124 

1125 Returns 

1126 ------- 

1127 `~matplotlib.collections.LineCollection` 

1128 

1129 Other Parameters 

1130 ---------------- 

1131 data : indexable object, optional 

1132 DATA_PARAMETER_PLACEHOLDER 

1133 **kwargs : `~matplotlib.collections.LineCollection` properties. 

1134 

1135 See Also 

1136 -------- 

1137 vlines : vertical lines 

1138 axhline : horizontal line across the Axes 

1139 """ 

1140 

1141 # We do the conversion first since not all unitized data is uniform 

1142 xmin, xmax, y = self._process_unit_info( 

1143 [("x", xmin), ("x", xmax), ("y", y)], kwargs) 

1144 

1145 if not np.iterable(y): 

1146 y = [y] 

1147 if not np.iterable(xmin): 

1148 xmin = [xmin] 

1149 if not np.iterable(xmax): 

1150 xmax = [xmax] 

1151 

1152 # Create and combine masked_arrays from input 

1153 y, xmin, xmax = cbook._combine_masks(y, xmin, xmax) 

1154 y = np.ravel(y) 

1155 xmin = np.ravel(xmin) 

1156 xmax = np.ravel(xmax) 

1157 

1158 masked_verts = np.ma.empty((len(y), 2, 2)) 

1159 masked_verts[:, 0, 0] = xmin 

1160 masked_verts[:, 0, 1] = y 

1161 masked_verts[:, 1, 0] = xmax 

1162 masked_verts[:, 1, 1] = y 

1163 

1164 lines = mcoll.LineCollection(masked_verts, colors=colors, 

1165 linestyles=linestyles, label=label) 

1166 self.add_collection(lines, autolim=False) 

1167 lines._internal_update(kwargs) 

1168 

1169 if len(y) > 0: 

1170 # Extreme values of xmin/xmax/y. Using masked_verts here handles 

1171 # the case of y being a masked *object* array (as can be generated 

1172 # e.g. by errorbar()), which would make nanmin/nanmax stumble. 

1173 updatex = True 

1174 updatey = True 

1175 if self.name == "rectilinear": 

1176 datalim = lines.get_datalim(self.transData) 

1177 t = lines.get_transform() 

1178 updatex, updatey = t.contains_branch_seperately(self.transData) 

1179 minx = np.nanmin(datalim.xmin) 

1180 maxx = np.nanmax(datalim.xmax) 

1181 miny = np.nanmin(datalim.ymin) 

1182 maxy = np.nanmax(datalim.ymax) 

1183 else: 

1184 minx = np.nanmin(masked_verts[..., 0]) 

1185 maxx = np.nanmax(masked_verts[..., 0]) 

1186 miny = np.nanmin(masked_verts[..., 1]) 

1187 maxy = np.nanmax(masked_verts[..., 1]) 

1188 

1189 corners = (minx, miny), (maxx, maxy) 

1190 self.update_datalim(corners, updatex, updatey) 

1191 self._request_autoscale_view() 

1192 return lines 

1193 

1194 @_preprocess_data(replace_names=["x", "ymin", "ymax", "colors"], 

1195 label_namer="x") 

1196 def vlines(self, x, ymin, ymax, colors=None, linestyles='solid', 

1197 label='', **kwargs): 

1198 """ 

1199 Plot vertical lines at each *x* from *ymin* to *ymax*. 

1200 

1201 Parameters 

1202 ---------- 

1203 x : float or array-like 

1204 x-indexes where to plot the lines. 

1205 

1206 ymin, ymax : float or array-like 

1207 Respective beginning and end of each line. If scalars are 

1208 provided, all lines will have the same length. 

1209 

1210 colors : :mpltype:`color` or list of color, default: :rc:`lines.color` 

1211 

1212 linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, default: 'solid' 

1213 

1214 label : str, default: '' 

1215 

1216 Returns 

1217 ------- 

1218 `~matplotlib.collections.LineCollection` 

1219 

1220 Other Parameters 

1221 ---------------- 

1222 data : indexable object, optional 

1223 DATA_PARAMETER_PLACEHOLDER 

1224 **kwargs : `~matplotlib.collections.LineCollection` properties. 

1225 

1226 See Also 

1227 -------- 

1228 hlines : horizontal lines 

1229 axvline : vertical line across the Axes 

1230 """ 

1231 

1232 # We do the conversion first since not all unitized data is uniform 

1233 x, ymin, ymax = self._process_unit_info( 

1234 [("x", x), ("y", ymin), ("y", ymax)], kwargs) 

1235 

1236 if not np.iterable(x): 

1237 x = [x] 

1238 if not np.iterable(ymin): 

1239 ymin = [ymin] 

1240 if not np.iterable(ymax): 

1241 ymax = [ymax] 

1242 

1243 # Create and combine masked_arrays from input 

1244 x, ymin, ymax = cbook._combine_masks(x, ymin, ymax) 

1245 x = np.ravel(x) 

1246 ymin = np.ravel(ymin) 

1247 ymax = np.ravel(ymax) 

1248 

1249 masked_verts = np.ma.empty((len(x), 2, 2)) 

1250 masked_verts[:, 0, 0] = x 

1251 masked_verts[:, 0, 1] = ymin 

1252 masked_verts[:, 1, 0] = x 

1253 masked_verts[:, 1, 1] = ymax 

1254 

1255 lines = mcoll.LineCollection(masked_verts, colors=colors, 

1256 linestyles=linestyles, label=label) 

1257 self.add_collection(lines, autolim=False) 

1258 lines._internal_update(kwargs) 

1259 

1260 if len(x) > 0: 

1261 # Extreme values of x/ymin/ymax. Using masked_verts here handles 

1262 # the case of x being a masked *object* array (as can be generated 

1263 # e.g. by errorbar()), which would make nanmin/nanmax stumble. 

1264 updatex = True 

1265 updatey = True 

1266 if self.name == "rectilinear": 

1267 datalim = lines.get_datalim(self.transData) 

1268 t = lines.get_transform() 

1269 updatex, updatey = t.contains_branch_seperately(self.transData) 

1270 minx = np.nanmin(datalim.xmin) 

1271 maxx = np.nanmax(datalim.xmax) 

1272 miny = np.nanmin(datalim.ymin) 

1273 maxy = np.nanmax(datalim.ymax) 

1274 else: 

1275 minx = np.nanmin(masked_verts[..., 0]) 

1276 maxx = np.nanmax(masked_verts[..., 0]) 

1277 miny = np.nanmin(masked_verts[..., 1]) 

1278 maxy = np.nanmax(masked_verts[..., 1]) 

1279 

1280 corners = (minx, miny), (maxx, maxy) 

1281 self.update_datalim(corners, updatex, updatey) 

1282 self._request_autoscale_view() 

1283 return lines 

1284 

1285 @_preprocess_data(replace_names=["positions", "lineoffsets", 

1286 "linelengths", "linewidths", 

1287 "colors", "linestyles"]) 

1288 @_docstring.dedent_interpd 

1289 def eventplot(self, positions, orientation='horizontal', lineoffsets=1, 

1290 linelengths=1, linewidths=None, colors=None, alpha=None, 

1291 linestyles='solid', **kwargs): 

1292 """ 

1293 Plot identical parallel lines at the given positions. 

1294 

1295 This type of plot is commonly used in neuroscience for representing 

1296 neural events, where it is usually called a spike raster, dot raster, 

1297 or raster plot. 

1298 

1299 However, it is useful in any situation where you wish to show the 

1300 timing or position of multiple sets of discrete events, such as the 

1301 arrival times of people to a business on each day of the month or the 

1302 date of hurricanes each year of the last century. 

1303 

1304 Parameters 

1305 ---------- 

1306 positions : array-like or list of array-like 

1307 A 1D array-like defines the positions of one sequence of events. 

1308 

1309 Multiple groups of events may be passed as a list of array-likes. 

1310 Each group can be styled independently by passing lists of values 

1311 to *lineoffsets*, *linelengths*, *linewidths*, *colors* and 

1312 *linestyles*. 

1313 

1314 Note that *positions* can be a 2D array, but in practice different 

1315 event groups usually have different counts so that one will use a 

1316 list of different-length arrays rather than a 2D array. 

1317 

1318 orientation : {'horizontal', 'vertical'}, default: 'horizontal' 

1319 The direction of the event sequence: 

1320 

1321 - 'horizontal': the events are arranged horizontally. 

1322 The indicator lines are vertical. 

1323 - 'vertical': the events are arranged vertically. 

1324 The indicator lines are horizontal. 

1325 

1326 lineoffsets : float or array-like, default: 1 

1327 The offset of the center of the lines from the origin, in the 

1328 direction orthogonal to *orientation*. 

1329 

1330 If *positions* is 2D, this can be a sequence with length matching 

1331 the length of *positions*. 

1332 

1333 linelengths : float or array-like, default: 1 

1334 The total height of the lines (i.e. the lines stretches from 

1335 ``lineoffset - linelength/2`` to ``lineoffset + linelength/2``). 

1336 

1337 If *positions* is 2D, this can be a sequence with length matching 

1338 the length of *positions*. 

1339 

1340 linewidths : float or array-like, default: :rc:`lines.linewidth` 

1341 The line width(s) of the event lines, in points. 

1342 

1343 If *positions* is 2D, this can be a sequence with length matching 

1344 the length of *positions*. 

1345 

1346 colors : :mpltype:`color` or list of color, default: :rc:`lines.color` 

1347 The color(s) of the event lines. 

1348 

1349 If *positions* is 2D, this can be a sequence with length matching 

1350 the length of *positions*. 

1351 

1352 alpha : float or array-like, default: 1 

1353 The alpha blending value(s), between 0 (transparent) and 1 

1354 (opaque). 

1355 

1356 If *positions* is 2D, this can be a sequence with length matching 

1357 the length of *positions*. 

1358 

1359 linestyles : str or tuple or list of such values, default: 'solid' 

1360 Default is 'solid'. Valid strings are ['solid', 'dashed', 

1361 'dashdot', 'dotted', '-', '--', '-.', ':']. Dash tuples 

1362 should be of the form:: 

1363 

1364 (offset, onoffseq), 

1365 

1366 where *onoffseq* is an even length tuple of on and off ink 

1367 in points. 

1368 

1369 If *positions* is 2D, this can be a sequence with length matching 

1370 the length of *positions*. 

1371 

1372 data : indexable object, optional 

1373 DATA_PARAMETER_PLACEHOLDER 

1374 

1375 **kwargs 

1376 Other keyword arguments are line collection properties. See 

1377 `.LineCollection` for a list of the valid properties. 

1378 

1379 Returns 

1380 ------- 

1381 list of `.EventCollection` 

1382 The `.EventCollection` that were added. 

1383 

1384 Notes 

1385 ----- 

1386 For *linelengths*, *linewidths*, *colors*, *alpha* and *linestyles*, if 

1387 only a single value is given, that value is applied to all lines. If an 

1388 array-like is given, it must have the same length as *positions*, and 

1389 each value will be applied to the corresponding row of the array. 

1390 

1391 Examples 

1392 -------- 

1393 .. plot:: gallery/lines_bars_and_markers/eventplot_demo.py 

1394 """ 

1395 

1396 lineoffsets, linelengths = self._process_unit_info( 

1397 [("y", lineoffsets), ("y", linelengths)], kwargs) 

1398 

1399 # fix positions, noting that it can be a list of lists: 

1400 if not np.iterable(positions): 

1401 positions = [positions] 

1402 elif any(np.iterable(position) for position in positions): 

1403 positions = [np.asanyarray(position) for position in positions] 

1404 else: 

1405 positions = [np.asanyarray(positions)] 

1406 

1407 poss = [] 

1408 for position in positions: 

1409 poss += self._process_unit_info([("x", position)], kwargs) 

1410 positions = poss 

1411 

1412 # prevent 'singular' keys from **kwargs dict from overriding the effect 

1413 # of 'plural' keyword arguments (e.g. 'color' overriding 'colors') 

1414 colors = cbook._local_over_kwdict(colors, kwargs, 'color') 

1415 linewidths = cbook._local_over_kwdict(linewidths, kwargs, 'linewidth') 

1416 linestyles = cbook._local_over_kwdict(linestyles, kwargs, 'linestyle') 

1417 

1418 if not np.iterable(lineoffsets): 

1419 lineoffsets = [lineoffsets] 

1420 if not np.iterable(linelengths): 

1421 linelengths = [linelengths] 

1422 if not np.iterable(linewidths): 

1423 linewidths = [linewidths] 

1424 if not np.iterable(colors): 

1425 colors = [colors] 

1426 if not np.iterable(alpha): 

1427 alpha = [alpha] 

1428 if hasattr(linestyles, 'lower') or not np.iterable(linestyles): 

1429 linestyles = [linestyles] 

1430 

1431 lineoffsets = np.asarray(lineoffsets) 

1432 linelengths = np.asarray(linelengths) 

1433 linewidths = np.asarray(linewidths) 

1434 

1435 if len(lineoffsets) == 0: 

1436 raise ValueError('lineoffsets cannot be empty') 

1437 if len(linelengths) == 0: 

1438 raise ValueError('linelengths cannot be empty') 

1439 if len(linestyles) == 0: 

1440 raise ValueError('linestyles cannot be empty') 

1441 if len(linewidths) == 0: 

1442 raise ValueError('linewidths cannot be empty') 

1443 if len(alpha) == 0: 

1444 raise ValueError('alpha cannot be empty') 

1445 if len(colors) == 0: 

1446 colors = [None] 

1447 try: 

1448 # Early conversion of the colors into RGBA values to take care 

1449 # of cases like colors='0.5' or colors='C1'. (Issue #8193) 

1450 colors = mcolors.to_rgba_array(colors) 

1451 except ValueError: 

1452 # Will fail if any element of *colors* is None. But as long 

1453 # as len(colors) == 1 or len(positions), the rest of the 

1454 # code should process *colors* properly. 

1455 pass 

1456 

1457 if len(lineoffsets) == 1 and len(positions) != 1: 

1458 lineoffsets = np.tile(lineoffsets, len(positions)) 

1459 lineoffsets[0] = 0 

1460 lineoffsets = np.cumsum(lineoffsets) 

1461 if len(linelengths) == 1: 

1462 linelengths = np.tile(linelengths, len(positions)) 

1463 if len(linewidths) == 1: 

1464 linewidths = np.tile(linewidths, len(positions)) 

1465 if len(colors) == 1: 

1466 colors = list(colors) * len(positions) 

1467 if len(alpha) == 1: 

1468 alpha = list(alpha) * len(positions) 

1469 if len(linestyles) == 1: 

1470 linestyles = [linestyles] * len(positions) 

1471 

1472 if len(lineoffsets) != len(positions): 

1473 raise ValueError('lineoffsets and positions are unequal sized ' 

1474 'sequences') 

1475 if len(linelengths) != len(positions): 

1476 raise ValueError('linelengths and positions are unequal sized ' 

1477 'sequences') 

1478 if len(linewidths) != len(positions): 

1479 raise ValueError('linewidths and positions are unequal sized ' 

1480 'sequences') 

1481 if len(colors) != len(positions): 

1482 raise ValueError('colors and positions are unequal sized ' 

1483 'sequences') 

1484 if len(alpha) != len(positions): 

1485 raise ValueError('alpha and positions are unequal sized ' 

1486 'sequences') 

1487 if len(linestyles) != len(positions): 

1488 raise ValueError('linestyles and positions are unequal sized ' 

1489 'sequences') 

1490 

1491 colls = [] 

1492 for position, lineoffset, linelength, linewidth, color, alpha_, \ 

1493 linestyle in \ 

1494 zip(positions, lineoffsets, linelengths, linewidths, 

1495 colors, alpha, linestyles): 

1496 coll = mcoll.EventCollection(position, 

1497 orientation=orientation, 

1498 lineoffset=lineoffset, 

1499 linelength=linelength, 

1500 linewidth=linewidth, 

1501 color=color, 

1502 alpha=alpha_, 

1503 linestyle=linestyle) 

1504 self.add_collection(coll, autolim=False) 

1505 coll._internal_update(kwargs) 

1506 colls.append(coll) 

1507 

1508 if len(positions) > 0: 

1509 # try to get min/max 

1510 min_max = [(np.min(_p), np.max(_p)) for _p in positions 

1511 if len(_p) > 0] 

1512 # if we have any non-empty positions, try to autoscale 

1513 if len(min_max) > 0: 

1514 mins, maxes = zip(*min_max) 

1515 minpos = np.min(mins) 

1516 maxpos = np.max(maxes) 

1517 

1518 minline = (lineoffsets - linelengths).min() 

1519 maxline = (lineoffsets + linelengths).max() 

1520 

1521 if orientation == "vertical": 

1522 corners = (minline, minpos), (maxline, maxpos) 

1523 else: # "horizontal" 

1524 corners = (minpos, minline), (maxpos, maxline) 

1525 self.update_datalim(corners) 

1526 self._request_autoscale_view() 

1527 

1528 return colls 

1529 

1530 #### Basic plotting 

1531 

1532 # Uses a custom implementation of data-kwarg handling in 

1533 # _process_plot_var_args. 

1534 @_docstring.dedent_interpd 

1535 def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs): 

1536 """ 

1537 Plot y versus x as lines and/or markers. 

1538 

1539 Call signatures:: 

1540 

1541 plot([x], y, [fmt], *, data=None, **kwargs) 

1542 plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) 

1543 

1544 The coordinates of the points or line nodes are given by *x*, *y*. 

1545 

1546 The optional parameter *fmt* is a convenient way for defining basic 

1547 formatting like color, marker and linestyle. It's a shortcut string 

1548 notation described in the *Notes* section below. 

1549 

1550 >>> plot(x, y) # plot x and y using default line style and color 

1551 >>> plot(x, y, 'bo') # plot x and y using blue circle markers 

1552 >>> plot(y) # plot y using x as index array 0..N-1 

1553 >>> plot(y, 'r+') # ditto, but with red plusses 

1554 

1555 You can use `.Line2D` properties as keyword arguments for more 

1556 control on the appearance. Line properties and *fmt* can be mixed. 

1557 The following two calls yield identical results: 

1558 

1559 >>> plot(x, y, 'go--', linewidth=2, markersize=12) 

1560 >>> plot(x, y, color='green', marker='o', linestyle='dashed', 

1561 ... linewidth=2, markersize=12) 

1562 

1563 When conflicting with *fmt*, keyword arguments take precedence. 

1564 

1565 

1566 **Plotting labelled data** 

1567 

1568 There's a convenient way for plotting objects with labelled data (i.e. 

1569 data that can be accessed by index ``obj['y']``). Instead of giving 

1570 the data in *x* and *y*, you can provide the object in the *data* 

1571 parameter and just give the labels for *x* and *y*:: 

1572 

1573 >>> plot('xlabel', 'ylabel', data=obj) 

1574 

1575 All indexable objects are supported. This could e.g. be a `dict`, a 

1576 `pandas.DataFrame` or a structured numpy array. 

1577 

1578 

1579 **Plotting multiple sets of data** 

1580 

1581 There are various ways to plot multiple sets of data. 

1582 

1583 - The most straight forward way is just to call `plot` multiple times. 

1584 Example: 

1585 

1586 >>> plot(x1, y1, 'bo') 

1587 >>> plot(x2, y2, 'go') 

1588 

1589 - If *x* and/or *y* are 2D arrays, a separate data set will be drawn 

1590 for every column. If both *x* and *y* are 2D, they must have the 

1591 same shape. If only one of them is 2D with shape (N, m) the other 

1592 must have length N and will be used for every data set m. 

1593 

1594 Example: 

1595 

1596 >>> x = [1, 2, 3] 

1597 >>> y = np.array([[1, 2], [3, 4], [5, 6]]) 

1598 >>> plot(x, y) 

1599 

1600 is equivalent to: 

1601 

1602 >>> for col in range(y.shape[1]): 

1603 ... plot(x, y[:, col]) 

1604 

1605 - The third way is to specify multiple sets of *[x]*, *y*, *[fmt]* 

1606 groups:: 

1607 

1608 >>> plot(x1, y1, 'g^', x2, y2, 'g-') 

1609 

1610 In this case, any additional keyword argument applies to all 

1611 datasets. Also, this syntax cannot be combined with the *data* 

1612 parameter. 

1613 

1614 By default, each line is assigned a different style specified by a 

1615 'style cycle'. The *fmt* and line property parameters are only 

1616 necessary if you want explicit deviations from these defaults. 

1617 Alternatively, you can also change the style cycle using 

1618 :rc:`axes.prop_cycle`. 

1619 

1620 

1621 Parameters 

1622 ---------- 

1623 x, y : array-like or scalar 

1624 The horizontal / vertical coordinates of the data points. 

1625 *x* values are optional and default to ``range(len(y))``. 

1626 

1627 Commonly, these parameters are 1D arrays. 

1628 

1629 They can also be scalars, or two-dimensional (in that case, the 

1630 columns represent separate data sets). 

1631 

1632 These arguments cannot be passed as keywords. 

1633 

1634 fmt : str, optional 

1635 A format string, e.g. 'ro' for red circles. See the *Notes* 

1636 section for a full description of the format strings. 

1637 

1638 Format strings are just an abbreviation for quickly setting 

1639 basic line properties. All of these and more can also be 

1640 controlled by keyword arguments. 

1641 

1642 This argument cannot be passed as keyword. 

1643 

1644 data : indexable object, optional 

1645 An object with labelled data. If given, provide the label names to 

1646 plot in *x* and *y*. 

1647 

1648 .. note:: 

1649 Technically there's a slight ambiguity in calls where the 

1650 second label is a valid *fmt*. ``plot('n', 'o', data=obj)`` 

1651 could be ``plt(x, y)`` or ``plt(y, fmt)``. In such cases, 

1652 the former interpretation is chosen, but a warning is issued. 

1653 You may suppress the warning by adding an empty format string 

1654 ``plot('n', 'o', '', data=obj)``. 

1655 

1656 Returns 

1657 ------- 

1658 list of `.Line2D` 

1659 A list of lines representing the plotted data. 

1660 

1661 Other Parameters 

1662 ---------------- 

1663 scalex, scaley : bool, default: True 

1664 These parameters determine if the view limits are adapted to the 

1665 data limits. The values are passed on to 

1666 `~.axes.Axes.autoscale_view`. 

1667 

1668 **kwargs : `~matplotlib.lines.Line2D` properties, optional 

1669 *kwargs* are used to specify properties like a line label (for 

1670 auto legends), linewidth, antialiasing, marker face color. 

1671 Example:: 

1672 

1673 >>> plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2) 

1674 >>> plot([1, 2, 3], [1, 4, 9], 'rs', label='line 2') 

1675 

1676 If you specify multiple lines with one plot call, the kwargs apply 

1677 to all those lines. In case the label object is iterable, each 

1678 element is used as labels for each set of data. 

1679 

1680 Here is a list of available `.Line2D` properties: 

1681 

1682 %(Line2D:kwdoc)s 

1683 

1684 See Also 

1685 -------- 

1686 scatter : XY scatter plot with markers of varying size and/or color ( 

1687 sometimes also called bubble chart). 

1688 

1689 Notes 

1690 ----- 

1691 **Format Strings** 

1692 

1693 A format string consists of a part for color, marker and line:: 

1694 

1695 fmt = '[marker][line][color]' 

1696 

1697 Each of them is optional. If not provided, the value from the style 

1698 cycle is used. Exception: If ``line`` is given, but no ``marker``, 

1699 the data will be a line without markers. 

1700 

1701 Other combinations such as ``[color][marker][line]`` are also 

1702 supported, but note that their parsing may be ambiguous. 

1703 

1704 **Markers** 

1705 

1706 ============= =============================== 

1707 character description 

1708 ============= =============================== 

1709 ``'.'`` point marker 

1710 ``','`` pixel marker 

1711 ``'o'`` circle marker 

1712 ``'v'`` triangle_down marker 

1713 ``'^'`` triangle_up marker 

1714 ``'<'`` triangle_left marker 

1715 ``'>'`` triangle_right marker 

1716 ``'1'`` tri_down marker 

1717 ``'2'`` tri_up marker 

1718 ``'3'`` tri_left marker 

1719 ``'4'`` tri_right marker 

1720 ``'8'`` octagon marker 

1721 ``'s'`` square marker 

1722 ``'p'`` pentagon marker 

1723 ``'P'`` plus (filled) marker 

1724 ``'*'`` star marker 

1725 ``'h'`` hexagon1 marker 

1726 ``'H'`` hexagon2 marker 

1727 ``'+'`` plus marker 

1728 ``'x'`` x marker 

1729 ``'X'`` x (filled) marker 

1730 ``'D'`` diamond marker 

1731 ``'d'`` thin_diamond marker 

1732 ``'|'`` vline marker 

1733 ``'_'`` hline marker 

1734 ============= =============================== 

1735 

1736 **Line Styles** 

1737 

1738 ============= =============================== 

1739 character description 

1740 ============= =============================== 

1741 ``'-'`` solid line style 

1742 ``'--'`` dashed line style 

1743 ``'-.'`` dash-dot line style 

1744 ``':'`` dotted line style 

1745 ============= =============================== 

1746 

1747 Example format strings:: 

1748 

1749 'b' # blue markers with default shape 

1750 'or' # red circles 

1751 '-g' # green solid line 

1752 '--' # dashed line with default color 

1753 '^k:' # black triangle_up markers connected by a dotted line 

1754 

1755 **Colors** 

1756 

1757 The supported color abbreviations are the single letter codes 

1758 

1759 ============= =============================== 

1760 character color 

1761 ============= =============================== 

1762 ``'b'`` blue 

1763 ``'g'`` green 

1764 ``'r'`` red 

1765 ``'c'`` cyan 

1766 ``'m'`` magenta 

1767 ``'y'`` yellow 

1768 ``'k'`` black 

1769 ``'w'`` white 

1770 ============= =============================== 

1771 

1772 and the ``'CN'`` colors that index into the default property cycle. 

1773 

1774 If the color is the only part of the format string, you can 

1775 additionally use any `matplotlib.colors` spec, e.g. full names 

1776 (``'green'``) or hex strings (``'#008000'``). 

1777 """ 

1778 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D) 

1779 lines = [*self._get_lines(self, *args, data=data, **kwargs)] 

1780 for line in lines: 

1781 self.add_line(line) 

1782 if scalex: 

1783 self._request_autoscale_view("x") 

1784 if scaley: 

1785 self._request_autoscale_view("y") 

1786 return lines 

1787 

1788 @_api.deprecated("3.9", alternative="plot") 

1789 @_preprocess_data(replace_names=["x", "y"], label_namer="y") 

1790 @_docstring.dedent_interpd 

1791 def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False, 

1792 **kwargs): 

1793 """ 

1794 Plot coercing the axis to treat floats as dates. 

1795 

1796 .. deprecated:: 3.9 

1797 

1798 This method exists for historic reasons and will be removed in version 3.11. 

1799 

1800 - ``datetime``-like data should directly be plotted using 

1801 `~.Axes.plot`. 

1802 - If you need to plot plain numeric data as :ref:`date-format` or 

1803 need to set a timezone, call ``ax.xaxis.axis_date`` / 

1804 ``ax.yaxis.axis_date`` before `~.Axes.plot`. See 

1805 `.Axis.axis_date`. 

1806 

1807 Similar to `.plot`, this plots *y* vs. *x* as lines or markers. 

1808 However, the axis labels are formatted as dates depending on *xdate* 

1809 and *ydate*. Note that `.plot` will work with `datetime` and 

1810 `numpy.datetime64` objects without resorting to this method. 

1811 

1812 Parameters 

1813 ---------- 

1814 x, y : array-like 

1815 The coordinates of the data points. If *xdate* or *ydate* is 

1816 *True*, the respective values *x* or *y* are interpreted as 

1817 :ref:`Matplotlib dates <date-format>`. 

1818 

1819 fmt : str, optional 

1820 The plot format string. For details, see the corresponding 

1821 parameter in `.plot`. 

1822 

1823 tz : timezone string or `datetime.tzinfo`, default: :rc:`timezone` 

1824 The time zone to use in labeling dates. 

1825 

1826 xdate : bool, default: True 

1827 If *True*, the *x*-axis will be interpreted as Matplotlib dates. 

1828 

1829 ydate : bool, default: False 

1830 If *True*, the *y*-axis will be interpreted as Matplotlib dates. 

1831 

1832 Returns 

1833 ------- 

1834 list of `.Line2D` 

1835 Objects representing the plotted data. 

1836 

1837 Other Parameters 

1838 ---------------- 

1839 data : indexable object, optional 

1840 DATA_PARAMETER_PLACEHOLDER 

1841 **kwargs 

1842 Keyword arguments control the `.Line2D` properties: 

1843 

1844 %(Line2D:kwdoc)s 

1845 

1846 See Also 

1847 -------- 

1848 matplotlib.dates : Helper functions on dates. 

1849 matplotlib.dates.date2num : Convert dates to num. 

1850 matplotlib.dates.num2date : Convert num to dates. 

1851 matplotlib.dates.drange : Create an equally spaced sequence of dates. 

1852 

1853 Notes 

1854 ----- 

1855 If you are using custom date tickers and formatters, it may be 

1856 necessary to set the formatters/locators after the call to 

1857 `.plot_date`. `.plot_date` will set the default tick locator to 

1858 `.AutoDateLocator` (if the tick locator is not already set to a 

1859 `.DateLocator` instance) and the default tick formatter to 

1860 `.AutoDateFormatter` (if the tick formatter is not already set to a 

1861 `.DateFormatter` instance). 

1862 """ 

1863 if xdate: 

1864 self.xaxis_date(tz) 

1865 if ydate: 

1866 self.yaxis_date(tz) 

1867 return self.plot(x, y, fmt, **kwargs) 

1868 

1869 # @_preprocess_data() # let 'plot' do the unpacking.. 

1870 @_docstring.dedent_interpd 

1871 def loglog(self, *args, **kwargs): 

1872 """ 

1873 Make a plot with log scaling on both the x- and y-axis. 

1874 

1875 Call signatures:: 

1876 

1877 loglog([x], y, [fmt], data=None, **kwargs) 

1878 loglog([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) 

1879 

1880 This is just a thin wrapper around `.plot` which additionally changes 

1881 both the x-axis and the y-axis to log scaling. All the concepts and 

1882 parameters of plot can be used here as well. 

1883 

1884 The additional parameters *base*, *subs* and *nonpositive* control the 

1885 x/y-axis properties. They are just forwarded to `.Axes.set_xscale` and 

1886 `.Axes.set_yscale`. To use different properties on the x-axis and the 

1887 y-axis, use e.g. 

1888 ``ax.set_xscale("log", base=10); ax.set_yscale("log", base=2)``. 

1889 

1890 Parameters 

1891 ---------- 

1892 base : float, default: 10 

1893 Base of the logarithm. 

1894 

1895 subs : sequence, optional 

1896 The location of the minor ticks. If *None*, reasonable locations 

1897 are automatically chosen depending on the number of decades in the 

1898 plot. See `.Axes.set_xscale`/`.Axes.set_yscale` for details. 

1899 

1900 nonpositive : {'mask', 'clip'}, default: 'clip' 

1901 Non-positive values can be masked as invalid, or clipped to a very 

1902 small positive number. 

1903 

1904 **kwargs 

1905 All parameters supported by `.plot`. 

1906 

1907 Returns 

1908 ------- 

1909 list of `.Line2D` 

1910 Objects representing the plotted data. 

1911 """ 

1912 dx = {k: v for k, v in kwargs.items() 

1913 if k in ['base', 'subs', 'nonpositive', 

1914 'basex', 'subsx', 'nonposx']} 

1915 self.set_xscale('log', **dx) 

1916 dy = {k: v for k, v in kwargs.items() 

1917 if k in ['base', 'subs', 'nonpositive', 

1918 'basey', 'subsy', 'nonposy']} 

1919 self.set_yscale('log', **dy) 

1920 return self.plot( 

1921 *args, **{k: v for k, v in kwargs.items() if k not in {*dx, *dy}}) 

1922 

1923 # @_preprocess_data() # let 'plot' do the unpacking.. 

1924 @_docstring.dedent_interpd 

1925 def semilogx(self, *args, **kwargs): 

1926 """ 

1927 Make a plot with log scaling on the x-axis. 

1928 

1929 Call signatures:: 

1930 

1931 semilogx([x], y, [fmt], data=None, **kwargs) 

1932 semilogx([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) 

1933 

1934 This is just a thin wrapper around `.plot` which additionally changes 

1935 the x-axis to log scaling. All the concepts and parameters of plot can 

1936 be used here as well. 

1937 

1938 The additional parameters *base*, *subs*, and *nonpositive* control the 

1939 x-axis properties. They are just forwarded to `.Axes.set_xscale`. 

1940 

1941 Parameters 

1942 ---------- 

1943 base : float, default: 10 

1944 Base of the x logarithm. 

1945 

1946 subs : array-like, optional 

1947 The location of the minor xticks. If *None*, reasonable locations 

1948 are automatically chosen depending on the number of decades in the 

1949 plot. See `.Axes.set_xscale` for details. 

1950 

1951 nonpositive : {'mask', 'clip'}, default: 'clip' 

1952 Non-positive values in x can be masked as invalid, or clipped to a 

1953 very small positive number. 

1954 

1955 **kwargs 

1956 All parameters supported by `.plot`. 

1957 

1958 Returns 

1959 ------- 

1960 list of `.Line2D` 

1961 Objects representing the plotted data. 

1962 """ 

1963 d = {k: v for k, v in kwargs.items() 

1964 if k in ['base', 'subs', 'nonpositive', 

1965 'basex', 'subsx', 'nonposx']} 

1966 self.set_xscale('log', **d) 

1967 return self.plot( 

1968 *args, **{k: v for k, v in kwargs.items() if k not in d}) 

1969 

1970 # @_preprocess_data() # let 'plot' do the unpacking.. 

1971 @_docstring.dedent_interpd 

1972 def semilogy(self, *args, **kwargs): 

1973 """ 

1974 Make a plot with log scaling on the y-axis. 

1975 

1976 Call signatures:: 

1977 

1978 semilogy([x], y, [fmt], data=None, **kwargs) 

1979 semilogy([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) 

1980 

1981 This is just a thin wrapper around `.plot` which additionally changes 

1982 the y-axis to log scaling. All the concepts and parameters of plot can 

1983 be used here as well. 

1984 

1985 The additional parameters *base*, *subs*, and *nonpositive* control the 

1986 y-axis properties. They are just forwarded to `.Axes.set_yscale`. 

1987 

1988 Parameters 

1989 ---------- 

1990 base : float, default: 10 

1991 Base of the y logarithm. 

1992 

1993 subs : array-like, optional 

1994 The location of the minor yticks. If *None*, reasonable locations 

1995 are automatically chosen depending on the number of decades in the 

1996 plot. See `.Axes.set_yscale` for details. 

1997 

1998 nonpositive : {'mask', 'clip'}, default: 'clip' 

1999 Non-positive values in y can be masked as invalid, or clipped to a 

2000 very small positive number. 

2001 

2002 **kwargs 

2003 All parameters supported by `.plot`. 

2004 

2005 Returns 

2006 ------- 

2007 list of `.Line2D` 

2008 Objects representing the plotted data. 

2009 """ 

2010 d = {k: v for k, v in kwargs.items() 

2011 if k in ['base', 'subs', 'nonpositive', 

2012 'basey', 'subsy', 'nonposy']} 

2013 self.set_yscale('log', **d) 

2014 return self.plot( 

2015 *args, **{k: v for k, v in kwargs.items() if k not in d}) 

2016 

2017 @_preprocess_data(replace_names=["x"], label_namer="x") 

2018 def acorr(self, x, **kwargs): 

2019 """ 

2020 Plot the autocorrelation of *x*. 

2021 

2022 Parameters 

2023 ---------- 

2024 x : array-like 

2025 Not run through Matplotlib's unit conversion, so this should 

2026 be a unit-less array. 

2027 

2028 detrend : callable, default: `.mlab.detrend_none` (no detrending) 

2029 A detrending function applied to *x*. It must have the 

2030 signature :: 

2031 

2032 detrend(x: np.ndarray) -> np.ndarray 

2033 

2034 normed : bool, default: True 

2035 If ``True``, input vectors are normalised to unit length. 

2036 

2037 usevlines : bool, default: True 

2038 Determines the plot style. 

2039 

2040 If ``True``, vertical lines are plotted from 0 to the acorr value 

2041 using `.Axes.vlines`. Additionally, a horizontal line is plotted 

2042 at y=0 using `.Axes.axhline`. 

2043 

2044 If ``False``, markers are plotted at the acorr values using 

2045 `.Axes.plot`. 

2046 

2047 maxlags : int, default: 10 

2048 Number of lags to show. If ``None``, will return all 

2049 ``2 * len(x) - 1`` lags. 

2050 

2051 Returns 

2052 ------- 

2053 lags : array (length ``2*maxlags+1``) 

2054 The lag vector. 

2055 c : array (length ``2*maxlags+1``) 

2056 The auto correlation vector. 

2057 line : `.LineCollection` or `.Line2D` 

2058 `.Artist` added to the Axes of the correlation: 

2059 

2060 - `.LineCollection` if *usevlines* is True. 

2061 - `.Line2D` if *usevlines* is False. 

2062 b : `~matplotlib.lines.Line2D` or None 

2063 Horizontal line at 0 if *usevlines* is True 

2064 None *usevlines* is False. 

2065 

2066 Other Parameters 

2067 ---------------- 

2068 linestyle : `~matplotlib.lines.Line2D` property, optional 

2069 The linestyle for plotting the data points. 

2070 Only used if *usevlines* is ``False``. 

2071 

2072 marker : str, default: 'o' 

2073 The marker for plotting the data points. 

2074 Only used if *usevlines* is ``False``. 

2075 

2076 data : indexable object, optional 

2077 DATA_PARAMETER_PLACEHOLDER 

2078 

2079 **kwargs 

2080 Additional parameters are passed to `.Axes.vlines` and 

2081 `.Axes.axhline` if *usevlines* is ``True``; otherwise they are 

2082 passed to `.Axes.plot`. 

2083 

2084 Notes 

2085 ----- 

2086 The cross correlation is performed with `numpy.correlate` with 

2087 ``mode = "full"``. 

2088 """ 

2089 return self.xcorr(x, x, **kwargs) 

2090 

2091 @_preprocess_data(replace_names=["x", "y"], label_namer="y") 

2092 def xcorr(self, x, y, normed=True, detrend=mlab.detrend_none, 

2093 usevlines=True, maxlags=10, **kwargs): 

2094 r""" 

2095 Plot the cross correlation between *x* and *y*. 

2096 

2097 The correlation with lag k is defined as 

2098 :math:`\sum_n x[n+k] \cdot y^*[n]`, where :math:`y^*` is the complex 

2099 conjugate of :math:`y`. 

2100 

2101 Parameters 

2102 ---------- 

2103 x, y : array-like of length n 

2104 Neither *x* nor *y* are run through Matplotlib's unit conversion, so 

2105 these should be unit-less arrays. 

2106 

2107 detrend : callable, default: `.mlab.detrend_none` (no detrending) 

2108 A detrending function applied to *x* and *y*. It must have the 

2109 signature :: 

2110 

2111 detrend(x: np.ndarray) -> np.ndarray 

2112 

2113 normed : bool, default: True 

2114 If ``True``, input vectors are normalised to unit length. 

2115 

2116 usevlines : bool, default: True 

2117 Determines the plot style. 

2118 

2119 If ``True``, vertical lines are plotted from 0 to the xcorr value 

2120 using `.Axes.vlines`. Additionally, a horizontal line is plotted 

2121 at y=0 using `.Axes.axhline`. 

2122 

2123 If ``False``, markers are plotted at the xcorr values using 

2124 `.Axes.plot`. 

2125 

2126 maxlags : int, default: 10 

2127 Number of lags to show. If None, will return all ``2 * len(x) - 1`` 

2128 lags. 

2129 

2130 Returns 

2131 ------- 

2132 lags : array (length ``2*maxlags+1``) 

2133 The lag vector. 

2134 c : array (length ``2*maxlags+1``) 

2135 The auto correlation vector. 

2136 line : `.LineCollection` or `.Line2D` 

2137 `.Artist` added to the Axes of the correlation: 

2138 

2139 - `.LineCollection` if *usevlines* is True. 

2140 - `.Line2D` if *usevlines* is False. 

2141 b : `~matplotlib.lines.Line2D` or None 

2142 Horizontal line at 0 if *usevlines* is True 

2143 None *usevlines* is False. 

2144 

2145 Other Parameters 

2146 ---------------- 

2147 linestyle : `~matplotlib.lines.Line2D` property, optional 

2148 The linestyle for plotting the data points. 

2149 Only used if *usevlines* is ``False``. 

2150 

2151 marker : str, default: 'o' 

2152 The marker for plotting the data points. 

2153 Only used if *usevlines* is ``False``. 

2154 

2155 data : indexable object, optional 

2156 DATA_PARAMETER_PLACEHOLDER 

2157 

2158 **kwargs 

2159 Additional parameters are passed to `.Axes.vlines` and 

2160 `.Axes.axhline` if *usevlines* is ``True``; otherwise they are 

2161 passed to `.Axes.plot`. 

2162 

2163 Notes 

2164 ----- 

2165 The cross correlation is performed with `numpy.correlate` with 

2166 ``mode = "full"``. 

2167 """ 

2168 Nx = len(x) 

2169 if Nx != len(y): 

2170 raise ValueError('x and y must be equal length') 

2171 

2172 x = detrend(np.asarray(x)) 

2173 y = detrend(np.asarray(y)) 

2174 

2175 correls = np.correlate(x, y, mode="full") 

2176 

2177 if normed: 

2178 correls = correls / np.sqrt(np.dot(x, x) * np.dot(y, y)) 

2179 

2180 if maxlags is None: 

2181 maxlags = Nx - 1 

2182 

2183 if maxlags >= Nx or maxlags < 1: 

2184 raise ValueError('maxlags must be None or strictly ' 

2185 'positive < %d' % Nx) 

2186 

2187 lags = np.arange(-maxlags, maxlags + 1) 

2188 correls = correls[Nx - 1 - maxlags:Nx + maxlags] 

2189 

2190 if usevlines: 

2191 a = self.vlines(lags, [0], correls, **kwargs) 

2192 # Make label empty so only vertical lines get a legend entry 

2193 kwargs.pop('label', '') 

2194 b = self.axhline(**kwargs) 

2195 else: 

2196 kwargs.setdefault('marker', 'o') 

2197 kwargs.setdefault('linestyle', 'None') 

2198 a, = self.plot(lags, correls, **kwargs) 

2199 b = None 

2200 return lags, correls, a, b 

2201 

2202 #### Specialized plotting 

2203 

2204 # @_preprocess_data() # let 'plot' do the unpacking.. 

2205 def step(self, x, y, *args, where='pre', data=None, **kwargs): 

2206 """ 

2207 Make a step plot. 

2208 

2209 Call signatures:: 

2210 

2211 step(x, y, [fmt], *, data=None, where='pre', **kwargs) 

2212 step(x, y, [fmt], x2, y2, [fmt2], ..., *, where='pre', **kwargs) 

2213 

2214 This is just a thin wrapper around `.plot` which changes some 

2215 formatting options. Most of the concepts and parameters of plot can be 

2216 used here as well. 

2217 

2218 .. note:: 

2219 

2220 This method uses a standard plot with a step drawstyle: The *x* 

2221 values are the reference positions and steps extend left/right/both 

2222 directions depending on *where*. 

2223 

2224 For the common case where you know the values and edges of the 

2225 steps, use `~.Axes.stairs` instead. 

2226 

2227 Parameters 

2228 ---------- 

2229 x : array-like 

2230 1D sequence of x positions. It is assumed, but not checked, that 

2231 it is uniformly increasing. 

2232 

2233 y : array-like 

2234 1D sequence of y levels. 

2235 

2236 fmt : str, optional 

2237 A format string, e.g. 'g' for a green line. See `.plot` for a more 

2238 detailed description. 

2239 

2240 Note: While full format strings are accepted, it is recommended to 

2241 only specify the color. Line styles are currently ignored (use 

2242 the keyword argument *linestyle* instead). Markers are accepted 

2243 and plotted on the given positions, however, this is a rarely 

2244 needed feature for step plots. 

2245 

2246 where : {'pre', 'post', 'mid'}, default: 'pre' 

2247 Define where the steps should be placed: 

2248 

2249 - 'pre': The y value is continued constantly to the left from 

2250 every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the 

2251 value ``y[i]``. 

2252 - 'post': The y value is continued constantly to the right from 

2253 every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the 

2254 value ``y[i]``. 

2255 - 'mid': Steps occur half-way between the *x* positions. 

2256 

2257 data : indexable object, optional 

2258 An object with labelled data. If given, provide the label names to 

2259 plot in *x* and *y*. 

2260 

2261 **kwargs 

2262 Additional parameters are the same as those for `.plot`. 

2263 

2264 Returns 

2265 ------- 

2266 list of `.Line2D` 

2267 Objects representing the plotted data. 

2268 """ 

2269 _api.check_in_list(('pre', 'post', 'mid'), where=where) 

2270 kwargs['drawstyle'] = 'steps-' + where 

2271 return self.plot(x, y, *args, data=data, **kwargs) 

2272 

2273 @staticmethod 

2274 def _convert_dx(dx, x0, xconv, convert): 

2275 """ 

2276 Small helper to do logic of width conversion flexibly. 

2277 

2278 *dx* and *x0* have units, but *xconv* has already been converted 

2279 to unitless (and is an ndarray). This allows the *dx* to have units 

2280 that are different from *x0*, but are still accepted by the 

2281 ``__add__`` operator of *x0*. 

2282 """ 

2283 

2284 # x should be an array... 

2285 assert type(xconv) is np.ndarray 

2286 

2287 if xconv.size == 0: 

2288 # xconv has already been converted, but maybe empty... 

2289 return convert(dx) 

2290 

2291 try: 

2292 # attempt to add the width to x0; this works for 

2293 # datetime+timedelta, for instance 

2294 

2295 # only use the first element of x and x0. This saves 

2296 # having to be sure addition works across the whole 

2297 # vector. This is particularly an issue if 

2298 # x0 and dx are lists so x0 + dx just concatenates the lists. 

2299 # We can't just cast x0 and dx to numpy arrays because that 

2300 # removes the units from unit packages like `pint` that 

2301 # wrap numpy arrays. 

2302 try: 

2303 x0 = cbook._safe_first_finite(x0) 

2304 except (TypeError, IndexError, KeyError): 

2305 pass 

2306 

2307 try: 

2308 x = cbook._safe_first_finite(xconv) 

2309 except (TypeError, IndexError, KeyError): 

2310 x = xconv 

2311 

2312 delist = False 

2313 if not np.iterable(dx): 

2314 dx = [dx] 

2315 delist = True 

2316 dx = [convert(x0 + ddx) - x for ddx in dx] 

2317 if delist: 

2318 dx = dx[0] 

2319 except (ValueError, TypeError, AttributeError): 

2320 # if the above fails (for any reason) just fallback to what 

2321 # we do by default and convert dx by itself. 

2322 dx = convert(dx) 

2323 return dx 

2324 

2325 @_preprocess_data() 

2326 @_docstring.dedent_interpd 

2327 def bar(self, x, height, width=0.8, bottom=None, *, align="center", 

2328 **kwargs): 

2329 r""" 

2330 Make a bar plot. 

2331 

2332 The bars are positioned at *x* with the given *align*\ment. Their 

2333 dimensions are given by *height* and *width*. The vertical baseline 

2334 is *bottom* (default 0). 

2335 

2336 Many parameters can take either a single value applying to all bars 

2337 or a sequence of values, one for each bar. 

2338 

2339 Parameters 

2340 ---------- 

2341 x : float or array-like 

2342 The x coordinates of the bars. See also *align* for the 

2343 alignment of the bars to the coordinates. 

2344 

2345 height : float or array-like 

2346 The height(s) of the bars. 

2347 

2348 Note that if *bottom* has units (e.g. datetime), *height* should be in 

2349 units that are a difference from the value of *bottom* (e.g. timedelta). 

2350 

2351 width : float or array-like, default: 0.8 

2352 The width(s) of the bars. 

2353 

2354 Note that if *x* has units (e.g. datetime), then *width* should be in 

2355 units that are a difference (e.g. timedelta) around the *x* values. 

2356 

2357 bottom : float or array-like, default: 0 

2358 The y coordinate(s) of the bottom side(s) of the bars. 

2359 

2360 Note that if *bottom* has units, then the y-axis will get a Locator and 

2361 Formatter appropriate for the units (e.g. dates, or categorical). 

2362 

2363 align : {'center', 'edge'}, default: 'center' 

2364 Alignment of the bars to the *x* coordinates: 

2365 

2366 - 'center': Center the base on the *x* positions. 

2367 - 'edge': Align the left edges of the bars with the *x* positions. 

2368 

2369 To align the bars on the right edge pass a negative *width* and 

2370 ``align='edge'``. 

2371 

2372 Returns 

2373 ------- 

2374 `.BarContainer` 

2375 Container with all the bars and optionally errorbars. 

2376 

2377 Other Parameters 

2378 ---------------- 

2379 color : :mpltype:`color` or list of :mpltype:`color`, optional 

2380 The colors of the bar faces. 

2381 

2382 edgecolor : :mpltype:`color` or list of :mpltype:`color`, optional 

2383 The colors of the bar edges. 

2384 

2385 linewidth : float or array-like, optional 

2386 Width of the bar edge(s). If 0, don't draw edges. 

2387 

2388 tick_label : str or list of str, optional 

2389 The tick labels of the bars. 

2390 Default: None (Use default numeric labels.) 

2391 

2392 label : str or list of str, optional 

2393 A single label is attached to the resulting `.BarContainer` as a 

2394 label for the whole dataset. 

2395 If a list is provided, it must be the same length as *x* and 

2396 labels the individual bars. Repeated labels are not de-duplicated 

2397 and will cause repeated label entries, so this is best used when 

2398 bars also differ in style (e.g., by passing a list to *color*.) 

2399 

2400 xerr, yerr : float or array-like of shape(N,) or shape(2, N), optional 

2401 If not *None*, add horizontal / vertical errorbars to the bar tips. 

2402 The values are +/- sizes relative to the data: 

2403 

2404 - scalar: symmetric +/- values for all bars 

2405 - shape(N,): symmetric +/- values for each bar 

2406 - shape(2, N): Separate - and + values for each bar. First row 

2407 contains the lower errors, the second row contains the upper 

2408 errors. 

2409 - *None*: No errorbar. (Default) 

2410 

2411 See :doc:`/gallery/statistics/errorbar_features` for an example on 

2412 the usage of *xerr* and *yerr*. 

2413 

2414 ecolor : :mpltype:`color` or list of :mpltype:`color`, default: 'black' 

2415 The line color of the errorbars. 

2416 

2417 capsize : float, default: :rc:`errorbar.capsize` 

2418 The length of the error bar caps in points. 

2419 

2420 error_kw : dict, optional 

2421 Dictionary of keyword arguments to be passed to the 

2422 `~.Axes.errorbar` method. Values of *ecolor* or *capsize* defined 

2423 here take precedence over the independent keyword arguments. 

2424 

2425 log : bool, default: False 

2426 If *True*, set the y-axis to be log scale. 

2427 

2428 data : indexable object, optional 

2429 DATA_PARAMETER_PLACEHOLDER 

2430 

2431 **kwargs : `.Rectangle` properties 

2432 

2433 %(Rectangle:kwdoc)s 

2434 

2435 See Also 

2436 -------- 

2437 barh : Plot a horizontal bar plot. 

2438 

2439 Notes 

2440 ----- 

2441 Stacked bars can be achieved by passing individual *bottom* values per 

2442 bar. See :doc:`/gallery/lines_bars_and_markers/bar_stacked`. 

2443 """ 

2444 kwargs = cbook.normalize_kwargs(kwargs, mpatches.Patch) 

2445 color = kwargs.pop('color', None) 

2446 if color is None: 

2447 color = self._get_patches_for_fill.get_next_color() 

2448 edgecolor = kwargs.pop('edgecolor', None) 

2449 linewidth = kwargs.pop('linewidth', None) 

2450 hatch = kwargs.pop('hatch', None) 

2451 

2452 # Because xerr and yerr will be passed to errorbar, most dimension 

2453 # checking and processing will be left to the errorbar method. 

2454 xerr = kwargs.pop('xerr', None) 

2455 yerr = kwargs.pop('yerr', None) 

2456 error_kw = kwargs.pop('error_kw', None) 

2457 error_kw = {} if error_kw is None else error_kw.copy() 

2458 ezorder = error_kw.pop('zorder', None) 

2459 if ezorder is None: 

2460 ezorder = kwargs.get('zorder', None) 

2461 if ezorder is not None: 

2462 # If using the bar zorder, increment slightly to make sure 

2463 # errorbars are drawn on top of bars 

2464 ezorder += 0.01 

2465 error_kw.setdefault('zorder', ezorder) 

2466 ecolor = kwargs.pop('ecolor', 'k') 

2467 capsize = kwargs.pop('capsize', mpl.rcParams["errorbar.capsize"]) 

2468 error_kw.setdefault('ecolor', ecolor) 

2469 error_kw.setdefault('capsize', capsize) 

2470 

2471 # The keyword argument *orientation* is used by barh() to defer all 

2472 # logic and drawing to bar(). It is considered internal and is 

2473 # intentionally not mentioned in the docstring. 

2474 orientation = kwargs.pop('orientation', 'vertical') 

2475 _api.check_in_list(['vertical', 'horizontal'], orientation=orientation) 

2476 log = kwargs.pop('log', False) 

2477 label = kwargs.pop('label', '') 

2478 tick_labels = kwargs.pop('tick_label', None) 

2479 

2480 y = bottom # Matches barh call signature. 

2481 if orientation == 'vertical': 

2482 if y is None: 

2483 y = 0 

2484 else: # horizontal 

2485 if x is None: 

2486 x = 0 

2487 

2488 if orientation == 'vertical': 

2489 # It is possible for y (bottom) to contain unit information. 

2490 # However, it is also possible for y=0 for the default and height 

2491 # to contain unit information. This will prioritize the units of y. 

2492 self._process_unit_info( 

2493 [("x", x), ("y", y), ("y", height)], kwargs, convert=False) 

2494 if log: 

2495 self.set_yscale('log', nonpositive='clip') 

2496 else: # horizontal 

2497 # It is possible for x (left) to contain unit information. 

2498 # However, it is also possible for x=0 for the default and width 

2499 # to contain unit information. This will prioritize the units of x. 

2500 self._process_unit_info( 

2501 [("x", x), ("x", width), ("y", y)], kwargs, convert=False) 

2502 if log: 

2503 self.set_xscale('log', nonpositive='clip') 

2504 

2505 # lets do some conversions now since some types cannot be 

2506 # subtracted uniformly 

2507 if self.xaxis is not None: 

2508 x0 = x 

2509 x = np.asarray(self.convert_xunits(x)) 

2510 width = self._convert_dx(width, x0, x, self.convert_xunits) 

2511 if xerr is not None: 

2512 xerr = self._convert_dx(xerr, x0, x, self.convert_xunits) 

2513 if self.yaxis is not None: 

2514 y0 = y 

2515 y = np.asarray(self.convert_yunits(y)) 

2516 height = self._convert_dx(height, y0, y, self.convert_yunits) 

2517 if yerr is not None: 

2518 yerr = self._convert_dx(yerr, y0, y, self.convert_yunits) 

2519 

2520 x, height, width, y, linewidth, hatch = np.broadcast_arrays( 

2521 # Make args iterable too. 

2522 np.atleast_1d(x), height, width, y, linewidth, hatch) 

2523 

2524 # Now that units have been converted, set the tick locations. 

2525 if orientation == 'vertical': 

2526 tick_label_axis = self.xaxis 

2527 tick_label_position = x 

2528 else: # horizontal 

2529 tick_label_axis = self.yaxis 

2530 tick_label_position = y 

2531 

2532 if not isinstance(label, str) and np.iterable(label): 

2533 bar_container_label = '_nolegend_' 

2534 patch_labels = label 

2535 else: 

2536 bar_container_label = label 

2537 patch_labels = ['_nolegend_'] * len(x) 

2538 if len(patch_labels) != len(x): 

2539 raise ValueError(f'number of labels ({len(patch_labels)}) ' 

2540 f'does not match number of bars ({len(x)}).') 

2541 

2542 linewidth = itertools.cycle(np.atleast_1d(linewidth)) 

2543 hatch = itertools.cycle(np.atleast_1d(hatch)) 

2544 color = itertools.chain(itertools.cycle(mcolors.to_rgba_array(color)), 

2545 # Fallback if color == "none". 

2546 itertools.repeat('none')) 

2547 if edgecolor is None: 

2548 edgecolor = itertools.repeat(None) 

2549 else: 

2550 edgecolor = itertools.chain( 

2551 itertools.cycle(mcolors.to_rgba_array(edgecolor)), 

2552 # Fallback if edgecolor == "none". 

2553 itertools.repeat('none')) 

2554 

2555 # We will now resolve the alignment and really have 

2556 # left, bottom, width, height vectors 

2557 _api.check_in_list(['center', 'edge'], align=align) 

2558 if align == 'center': 

2559 if orientation == 'vertical': 

2560 try: 

2561 left = x - width / 2 

2562 except TypeError as e: 

2563 raise TypeError(f'the dtypes of parameters x ({x.dtype}) ' 

2564 f'and width ({width.dtype}) ' 

2565 f'are incompatible') from e 

2566 bottom = y 

2567 else: # horizontal 

2568 try: 

2569 bottom = y - height / 2 

2570 except TypeError as e: 

2571 raise TypeError(f'the dtypes of parameters y ({y.dtype}) ' 

2572 f'and height ({height.dtype}) ' 

2573 f'are incompatible') from e 

2574 left = x 

2575 else: # edge 

2576 left = x 

2577 bottom = y 

2578 

2579 patches = [] 

2580 args = zip(left, bottom, width, height, color, edgecolor, linewidth, 

2581 hatch, patch_labels) 

2582 for l, b, w, h, c, e, lw, htch, lbl in args: 

2583 r = mpatches.Rectangle( 

2584 xy=(l, b), width=w, height=h, 

2585 facecolor=c, 

2586 edgecolor=e, 

2587 linewidth=lw, 

2588 label=lbl, 

2589 hatch=htch, 

2590 ) 

2591 r._internal_update(kwargs) 

2592 r.get_path()._interpolation_steps = 100 

2593 if orientation == 'vertical': 

2594 r.sticky_edges.y.append(b) 

2595 else: # horizontal 

2596 r.sticky_edges.x.append(l) 

2597 self.add_patch(r) 

2598 patches.append(r) 

2599 

2600 if xerr is not None or yerr is not None: 

2601 if orientation == 'vertical': 

2602 # using list comps rather than arrays to preserve unit info 

2603 ex = [l + 0.5 * w for l, w in zip(left, width)] 

2604 ey = [b + h for b, h in zip(bottom, height)] 

2605 

2606 else: # horizontal 

2607 # using list comps rather than arrays to preserve unit info 

2608 ex = [l + w for l, w in zip(left, width)] 

2609 ey = [b + 0.5 * h for b, h in zip(bottom, height)] 

2610 

2611 error_kw.setdefault("label", '_nolegend_') 

2612 

2613 errorbar = self.errorbar(ex, ey, yerr=yerr, xerr=xerr, fmt='none', 

2614 **error_kw) 

2615 else: 

2616 errorbar = None 

2617 

2618 self._request_autoscale_view() 

2619 

2620 if orientation == 'vertical': 

2621 datavalues = height 

2622 else: # horizontal 

2623 datavalues = width 

2624 

2625 bar_container = BarContainer(patches, errorbar, datavalues=datavalues, 

2626 orientation=orientation, 

2627 label=bar_container_label) 

2628 self.add_container(bar_container) 

2629 

2630 if tick_labels is not None: 

2631 tick_labels = np.broadcast_to(tick_labels, len(patches)) 

2632 tick_label_axis.set_ticks(tick_label_position) 

2633 tick_label_axis.set_ticklabels(tick_labels) 

2634 

2635 return bar_container 

2636 

2637 # @_preprocess_data() # let 'bar' do the unpacking.. 

2638 @_docstring.dedent_interpd 

2639 def barh(self, y, width, height=0.8, left=None, *, align="center", 

2640 data=None, **kwargs): 

2641 r""" 

2642 Make a horizontal bar plot. 

2643 

2644 The bars are positioned at *y* with the given *align*\ment. Their 

2645 dimensions are given by *width* and *height*. The horizontal baseline 

2646 is *left* (default 0). 

2647 

2648 Many parameters can take either a single value applying to all bars 

2649 or a sequence of values, one for each bar. 

2650 

2651 Parameters 

2652 ---------- 

2653 y : float or array-like 

2654 The y coordinates of the bars. See also *align* for the 

2655 alignment of the bars to the coordinates. 

2656 

2657 width : float or array-like 

2658 The width(s) of the bars. 

2659 

2660 Note that if *left* has units (e.g. datetime), *width* should be in 

2661 units that are a difference from the value of *left* (e.g. timedelta). 

2662 

2663 height : float or array-like, default: 0.8 

2664 The heights of the bars. 

2665 

2666 Note that if *y* has units (e.g. datetime), then *height* should be in 

2667 units that are a difference (e.g. timedelta) around the *y* values. 

2668 

2669 left : float or array-like, default: 0 

2670 The x coordinates of the left side(s) of the bars. 

2671 

2672 Note that if *left* has units, then the x-axis will get a Locator and 

2673 Formatter appropriate for the units (e.g. dates, or categorical). 

2674 

2675 align : {'center', 'edge'}, default: 'center' 

2676 Alignment of the base to the *y* coordinates*: 

2677 

2678 - 'center': Center the bars on the *y* positions. 

2679 - 'edge': Align the bottom edges of the bars with the *y* 

2680 positions. 

2681 

2682 To align the bars on the top edge pass a negative *height* and 

2683 ``align='edge'``. 

2684 

2685 Returns 

2686 ------- 

2687 `.BarContainer` 

2688 Container with all the bars and optionally errorbars. 

2689 

2690 Other Parameters 

2691 ---------------- 

2692 color : :mpltype:`color` or list of :mpltype:`color`, optional 

2693 The colors of the bar faces. 

2694 

2695 edgecolor : :mpltype:`color` or list of :mpltype:`color`, optional 

2696 The colors of the bar edges. 

2697 

2698 linewidth : float or array-like, optional 

2699 Width of the bar edge(s). If 0, don't draw edges. 

2700 

2701 tick_label : str or list of str, optional 

2702 The tick labels of the bars. 

2703 Default: None (Use default numeric labels.) 

2704 

2705 label : str or list of str, optional 

2706 A single label is attached to the resulting `.BarContainer` as a 

2707 label for the whole dataset. 

2708 If a list is provided, it must be the same length as *y* and 

2709 labels the individual bars. Repeated labels are not de-duplicated 

2710 and will cause repeated label entries, so this is best used when 

2711 bars also differ in style (e.g., by passing a list to *color*.) 

2712 

2713 xerr, yerr : float or array-like of shape(N,) or shape(2, N), optional 

2714 If not *None*, add horizontal / vertical errorbars to the bar tips. 

2715 The values are +/- sizes relative to the data: 

2716 

2717 - scalar: symmetric +/- values for all bars 

2718 - shape(N,): symmetric +/- values for each bar 

2719 - shape(2, N): Separate - and + values for each bar. First row 

2720 contains the lower errors, the second row contains the upper 

2721 errors. 

2722 - *None*: No errorbar. (default) 

2723 

2724 See :doc:`/gallery/statistics/errorbar_features` for an example on 

2725 the usage of *xerr* and *yerr*. 

2726 

2727 ecolor : :mpltype:`color` or list of :mpltype:`color`, default: 'black' 

2728 The line color of the errorbars. 

2729 

2730 capsize : float, default: :rc:`errorbar.capsize` 

2731 The length of the error bar caps in points. 

2732 

2733 error_kw : dict, optional 

2734 Dictionary of keyword arguments to be passed to the 

2735 `~.Axes.errorbar` method. Values of *ecolor* or *capsize* defined 

2736 here take precedence over the independent keyword arguments. 

2737 

2738 log : bool, default: False 

2739 If ``True``, set the x-axis to be log scale. 

2740 

2741 data : indexable object, optional 

2742 If given, all parameters also accept a string ``s``, which is 

2743 interpreted as ``data[s]`` (unless this raises an exception). 

2744 

2745 **kwargs : `.Rectangle` properties 

2746 

2747 %(Rectangle:kwdoc)s 

2748 

2749 See Also 

2750 -------- 

2751 bar : Plot a vertical bar plot. 

2752 

2753 Notes 

2754 ----- 

2755 Stacked bars can be achieved by passing individual *left* values per 

2756 bar. See 

2757 :doc:`/gallery/lines_bars_and_markers/horizontal_barchart_distribution`. 

2758 """ 

2759 kwargs.setdefault('orientation', 'horizontal') 

2760 patches = self.bar(x=left, height=height, width=width, bottom=y, 

2761 align=align, data=data, **kwargs) 

2762 return patches 

2763 

2764 def bar_label(self, container, labels=None, *, fmt="%g", label_type="edge", 

2765 padding=0, **kwargs): 

2766 """ 

2767 Label a bar plot. 

2768 

2769 Adds labels to bars in the given `.BarContainer`. 

2770 You may need to adjust the axis limits to fit the labels. 

2771 

2772 Parameters 

2773 ---------- 

2774 container : `.BarContainer` 

2775 Container with all the bars and optionally errorbars, likely 

2776 returned from `.bar` or `.barh`. 

2777 

2778 labels : array-like, optional 

2779 A list of label texts, that should be displayed. If not given, the 

2780 label texts will be the data values formatted with *fmt*. 

2781 

2782 fmt : str or callable, default: '%g' 

2783 An unnamed %-style or {}-style format string for the label or a 

2784 function to call with the value as the first argument. 

2785 When *fmt* is a string and can be interpreted in both formats, 

2786 %-style takes precedence over {}-style. 

2787 

2788 .. versionadded:: 3.7 

2789 Support for {}-style format string and callables. 

2790 

2791 label_type : {'edge', 'center'}, default: 'edge' 

2792 The label type. Possible values: 

2793 

2794 - 'edge': label placed at the end-point of the bar segment, and the 

2795 value displayed will be the position of that end-point. 

2796 - 'center': label placed in the center of the bar segment, and the 

2797 value displayed will be the length of that segment. 

2798 (useful for stacked bars, i.e., 

2799 :doc:`/gallery/lines_bars_and_markers/bar_label_demo`) 

2800 

2801 padding : float, default: 0 

2802 Distance of label from the end of the bar, in points. 

2803 

2804 **kwargs 

2805 Any remaining keyword arguments are passed through to 

2806 `.Axes.annotate`. The alignment parameters ( 

2807 *horizontalalignment* / *ha*, *verticalalignment* / *va*) are 

2808 not supported because the labels are automatically aligned to 

2809 the bars. 

2810 

2811 Returns 

2812 ------- 

2813 list of `.Annotation` 

2814 A list of `.Annotation` instances for the labels. 

2815 """ 

2816 for key in ['horizontalalignment', 'ha', 'verticalalignment', 'va']: 

2817 if key in kwargs: 

2818 raise ValueError( 

2819 f"Passing {key!r} to bar_label() is not supported.") 

2820 

2821 a, b = self.yaxis.get_view_interval() 

2822 y_inverted = a > b 

2823 c, d = self.xaxis.get_view_interval() 

2824 x_inverted = c > d 

2825 

2826 # want to know whether to put label on positive or negative direction 

2827 # cannot use np.sign here because it will return 0 if x == 0 

2828 def sign(x): 

2829 return 1 if x >= 0 else -1 

2830 

2831 _api.check_in_list(['edge', 'center'], label_type=label_type) 

2832 

2833 bars = container.patches 

2834 errorbar = container.errorbar 

2835 datavalues = container.datavalues 

2836 orientation = container.orientation 

2837 

2838 if errorbar: 

2839 # check "ErrorbarContainer" for the definition of these elements 

2840 lines = errorbar.lines # attribute of "ErrorbarContainer" (tuple) 

2841 barlinecols = lines[2] # 0: data_line, 1: caplines, 2: barlinecols 

2842 barlinecol = barlinecols[0] # the "LineCollection" of error bars 

2843 errs = barlinecol.get_segments() 

2844 else: 

2845 errs = [] 

2846 

2847 if labels is None: 

2848 labels = [] 

2849 

2850 annotations = [] 

2851 

2852 for bar, err, dat, lbl in itertools.zip_longest( 

2853 bars, errs, datavalues, labels 

2854 ): 

2855 (x0, y0), (x1, y1) = bar.get_bbox().get_points() 

2856 xc, yc = (x0 + x1) / 2, (y0 + y1) / 2 

2857 

2858 if orientation == "vertical": 

2859 extrema = max(y0, y1) if dat >= 0 else min(y0, y1) 

2860 length = abs(y0 - y1) 

2861 else: # horizontal 

2862 extrema = max(x0, x1) if dat >= 0 else min(x0, x1) 

2863 length = abs(x0 - x1) 

2864 

2865 if err is None or np.size(err) == 0: 

2866 endpt = extrema 

2867 elif orientation == "vertical": 

2868 endpt = err[:, 1].max() if dat >= 0 else err[:, 1].min() 

2869 else: # horizontal 

2870 endpt = err[:, 0].max() if dat >= 0 else err[:, 0].min() 

2871 

2872 if label_type == "center": 

2873 value = sign(dat) * length 

2874 else: # edge 

2875 value = extrema 

2876 

2877 if label_type == "center": 

2878 xy = (0.5, 0.5) 

2879 kwargs["xycoords"] = ( 

2880 lambda r, b=bar: 

2881 mtransforms.Bbox.intersection( 

2882 b.get_window_extent(r), b.get_clip_box() 

2883 ) or mtransforms.Bbox.null() 

2884 ) 

2885 else: # edge 

2886 if orientation == "vertical": 

2887 xy = xc, endpt 

2888 else: # horizontal 

2889 xy = endpt, yc 

2890 

2891 if orientation == "vertical": 

2892 y_direction = -1 if y_inverted else 1 

2893 xytext = 0, y_direction * sign(dat) * padding 

2894 else: # horizontal 

2895 x_direction = -1 if x_inverted else 1 

2896 xytext = x_direction * sign(dat) * padding, 0 

2897 

2898 if label_type == "center": 

2899 ha, va = "center", "center" 

2900 else: # edge 

2901 if orientation == "vertical": 

2902 ha = 'center' 

2903 if y_inverted: 

2904 va = 'top' if dat > 0 else 'bottom' # also handles NaN 

2905 else: 

2906 va = 'top' if dat < 0 else 'bottom' # also handles NaN 

2907 else: # horizontal 

2908 if x_inverted: 

2909 ha = 'right' if dat > 0 else 'left' # also handles NaN 

2910 else: 

2911 ha = 'right' if dat < 0 else 'left' # also handles NaN 

2912 va = 'center' 

2913 

2914 if np.isnan(dat): 

2915 lbl = '' 

2916 

2917 if lbl is None: 

2918 if isinstance(fmt, str): 

2919 lbl = cbook._auto_format_str(fmt, value) 

2920 elif callable(fmt): 

2921 lbl = fmt(value) 

2922 else: 

2923 raise TypeError("fmt must be a str or callable") 

2924 annotation = self.annotate(lbl, 

2925 xy, xytext, textcoords="offset points", 

2926 ha=ha, va=va, **kwargs) 

2927 annotations.append(annotation) 

2928 

2929 return annotations 

2930 

2931 @_preprocess_data() 

2932 @_docstring.dedent_interpd 

2933 def broken_barh(self, xranges, yrange, **kwargs): 

2934 """ 

2935 Plot a horizontal sequence of rectangles. 

2936 

2937 A rectangle is drawn for each element of *xranges*. All rectangles 

2938 have the same vertical position and size defined by *yrange*. 

2939 

2940 Parameters 

2941 ---------- 

2942 xranges : sequence of tuples (*xmin*, *xwidth*) 

2943 The x-positions and extents of the rectangles. For each tuple 

2944 (*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* + 

2945 *xwidth*. 

2946 yrange : (*ymin*, *yheight*) 

2947 The y-position and extent for all the rectangles. 

2948 

2949 Returns 

2950 ------- 

2951 `~.collections.PolyCollection` 

2952 

2953 Other Parameters 

2954 ---------------- 

2955 data : indexable object, optional 

2956 DATA_PARAMETER_PLACEHOLDER 

2957 **kwargs : `.PolyCollection` properties 

2958 

2959 Each *kwarg* can be either a single argument applying to all 

2960 rectangles, e.g.:: 

2961 

2962 facecolors='black' 

2963 

2964 or a sequence of arguments over which is cycled, e.g.:: 

2965 

2966 facecolors=('black', 'blue') 

2967 

2968 would create interleaving black and blue rectangles. 

2969 

2970 Supported keywords: 

2971 

2972 %(PolyCollection:kwdoc)s 

2973 """ 

2974 # process the unit information 

2975 xdata = cbook._safe_first_finite(xranges) if len(xranges) else None 

2976 ydata = cbook._safe_first_finite(yrange) if len(yrange) else None 

2977 self._process_unit_info( 

2978 [("x", xdata), ("y", ydata)], kwargs, convert=False) 

2979 

2980 vertices = [] 

2981 y0, dy = yrange 

2982 y0, y1 = self.convert_yunits((y0, y0 + dy)) 

2983 for xr in xranges: # convert the absolute values, not the x and dx 

2984 try: 

2985 x0, dx = xr 

2986 except Exception: 

2987 raise ValueError( 

2988 "each range in xrange must be a sequence with two " 

2989 "elements (i.e. xrange must be an (N, 2) array)") from None 

2990 x0, x1 = self.convert_xunits((x0, x0 + dx)) 

2991 vertices.append([(x0, y0), (x0, y1), (x1, y1), (x1, y0)]) 

2992 

2993 col = mcoll.PolyCollection(np.array(vertices), **kwargs) 

2994 self.add_collection(col, autolim=True) 

2995 self._request_autoscale_view() 

2996 

2997 return col 

2998 

2999 @_preprocess_data() 

3000 def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0, 

3001 label=None, orientation='vertical'): 

3002 """ 

3003 Create a stem plot. 

3004 

3005 A stem plot draws lines perpendicular to a baseline at each location 

3006 *locs* from the baseline to *heads*, and places a marker there. For 

3007 vertical stem plots (the default), the *locs* are *x* positions, and 

3008 the *heads* are *y* values. For horizontal stem plots, the *locs* are 

3009 *y* positions, and the *heads* are *x* values. 

3010 

3011 Call signature:: 

3012 

3013 stem([locs,] heads, linefmt=None, markerfmt=None, basefmt=None) 

3014 

3015 The *locs*-positions are optional. *linefmt* may be provided as 

3016 positional, but all other formats must be provided as keyword 

3017 arguments. 

3018 

3019 Parameters 

3020 ---------- 

3021 locs : array-like, default: (0, 1, ..., len(heads) - 1) 

3022 For vertical stem plots, the x-positions of the stems. 

3023 For horizontal stem plots, the y-positions of the stems. 

3024 

3025 heads : array-like 

3026 For vertical stem plots, the y-values of the stem heads. 

3027 For horizontal stem plots, the x-values of the stem heads. 

3028 

3029 linefmt : str, optional 

3030 A string defining the color and/or linestyle of the vertical lines: 

3031 

3032 ========= ============= 

3033 Character Line Style 

3034 ========= ============= 

3035 ``'-'`` solid line 

3036 ``'--'`` dashed line 

3037 ``'-.'`` dash-dot line 

3038 ``':'`` dotted line 

3039 ========= ============= 

3040 

3041 Default: 'C0-', i.e. solid line with the first color of the color 

3042 cycle. 

3043 

3044 Note: Markers specified through this parameter (e.g. 'x') will be 

3045 silently ignored. Instead, markers should be specified using 

3046 *markerfmt*. 

3047 

3048 markerfmt : str, optional 

3049 A string defining the color and/or shape of the markers at the stem 

3050 heads. If the marker is not given, use the marker 'o', i.e. filled 

3051 circles. If the color is not given, use the color from *linefmt*. 

3052 

3053 basefmt : str, default: 'C3-' ('C2-' in classic mode) 

3054 A format string defining the properties of the baseline. 

3055 

3056 orientation : {'vertical', 'horizontal'}, default: 'vertical' 

3057 The orientation of the stems. 

3058 

3059 bottom : float, default: 0 

3060 The y/x-position of the baseline (depending on *orientation*). 

3061 

3062 label : str, optional 

3063 The label to use for the stems in legends. 

3064 

3065 data : indexable object, optional 

3066 DATA_PARAMETER_PLACEHOLDER 

3067 

3068 Returns 

3069 ------- 

3070 `.StemContainer` 

3071 The container may be treated like a tuple 

3072 (*markerline*, *stemlines*, *baseline*) 

3073 

3074 Notes 

3075 ----- 

3076 .. seealso:: 

3077 The MATLAB function 

3078 `stem <https://www.mathworks.com/help/matlab/ref/stem.html>`_ 

3079 which inspired this method. 

3080 """ 

3081 if not 1 <= len(args) <= 3: 

3082 raise _api.nargs_error('stem', '1-3', len(args)) 

3083 _api.check_in_list(['horizontal', 'vertical'], orientation=orientation) 

3084 

3085 if len(args) == 1: 

3086 heads, = args 

3087 locs = np.arange(len(heads)) 

3088 args = () 

3089 elif isinstance(args[1], str): 

3090 heads, *args = args 

3091 locs = np.arange(len(heads)) 

3092 else: 

3093 locs, heads, *args = args 

3094 

3095 if orientation == 'vertical': 

3096 locs, heads = self._process_unit_info([("x", locs), ("y", heads)]) 

3097 else: # horizontal 

3098 heads, locs = self._process_unit_info([("x", heads), ("y", locs)]) 

3099 

3100 # resolve line format 

3101 if linefmt is None: 

3102 linefmt = args[0] if len(args) > 0 else "C0-" 

3103 linestyle, linemarker, linecolor = _process_plot_format(linefmt) 

3104 

3105 # resolve marker format 

3106 if markerfmt is None: 

3107 # if not given as kwarg, fall back to 'o' 

3108 markerfmt = "o" 

3109 if markerfmt == '': 

3110 markerfmt = ' ' # = empty line style; '' would resolve rcParams 

3111 markerstyle, markermarker, markercolor = \ 

3112 _process_plot_format(markerfmt) 

3113 if markermarker is None: 

3114 markermarker = 'o' 

3115 if markerstyle is None: 

3116 markerstyle = 'None' 

3117 if markercolor is None: 

3118 markercolor = linecolor 

3119 

3120 # resolve baseline format 

3121 if basefmt is None: 

3122 basefmt = ("C2-" if mpl.rcParams["_internal.classic_mode"] else 

3123 "C3-") 

3124 basestyle, basemarker, basecolor = _process_plot_format(basefmt) 

3125 

3126 # New behaviour in 3.1 is to use a LineCollection for the stemlines 

3127 if linestyle is None: 

3128 linestyle = mpl.rcParams['lines.linestyle'] 

3129 xlines = self.vlines if orientation == "vertical" else self.hlines 

3130 stemlines = xlines( 

3131 locs, bottom, heads, 

3132 colors=linecolor, linestyles=linestyle, label="_nolegend_") 

3133 

3134 if orientation == 'horizontal': 

3135 marker_x = heads 

3136 marker_y = locs 

3137 baseline_x = [bottom, bottom] 

3138 baseline_y = [np.min(locs), np.max(locs)] 

3139 else: 

3140 marker_x = locs 

3141 marker_y = heads 

3142 baseline_x = [np.min(locs), np.max(locs)] 

3143 baseline_y = [bottom, bottom] 

3144 

3145 markerline, = self.plot(marker_x, marker_y, 

3146 color=markercolor, linestyle=markerstyle, 

3147 marker=markermarker, label="_nolegend_") 

3148 

3149 baseline, = self.plot(baseline_x, baseline_y, 

3150 color=basecolor, linestyle=basestyle, 

3151 marker=basemarker, label="_nolegend_") 

3152 

3153 stem_container = StemContainer((markerline, stemlines, baseline), 

3154 label=label) 

3155 self.add_container(stem_container) 

3156 return stem_container 

3157 

3158 @_preprocess_data(replace_names=["x", "explode", "labels", "colors"]) 

3159 def pie(self, x, explode=None, labels=None, colors=None, 

3160 autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1, 

3161 startangle=0, radius=1, counterclock=True, 

3162 wedgeprops=None, textprops=None, center=(0, 0), 

3163 frame=False, rotatelabels=False, *, normalize=True, hatch=None): 

3164 """ 

3165 Plot a pie chart. 

3166 

3167 Make a pie chart of array *x*. The fractional area of each wedge is 

3168 given by ``x/sum(x)``. 

3169 

3170 The wedges are plotted counterclockwise, by default starting from the 

3171 x-axis. 

3172 

3173 Parameters 

3174 ---------- 

3175 x : 1D array-like 

3176 The wedge sizes. 

3177 

3178 explode : array-like, default: None 

3179 If not *None*, is a ``len(x)`` array which specifies the fraction 

3180 of the radius with which to offset each wedge. 

3181 

3182 labels : list, default: None 

3183 A sequence of strings providing the labels for each wedge 

3184 

3185 colors : :mpltype:`color` or list of :mpltype:`color`, default: None 

3186 A sequence of colors through which the pie chart will cycle. If 

3187 *None*, will use the colors in the currently active cycle. 

3188 

3189 hatch : str or list, default: None 

3190 Hatching pattern applied to all pie wedges or sequence of patterns 

3191 through which the chart will cycle. For a list of valid patterns, 

3192 see :doc:`/gallery/shapes_and_collections/hatch_style_reference`. 

3193 

3194 .. versionadded:: 3.7 

3195 

3196 autopct : None or str or callable, default: None 

3197 If not *None*, *autopct* is a string or function used to label the 

3198 wedges with their numeric value. The label will be placed inside 

3199 the wedge. If *autopct* is a format string, the label will be 

3200 ``fmt % pct``. If *autopct* is a function, then it will be called. 

3201 

3202 pctdistance : float, default: 0.6 

3203 The relative distance along the radius at which the text 

3204 generated by *autopct* is drawn. To draw the text outside the pie, 

3205 set *pctdistance* > 1. This parameter is ignored if *autopct* is 

3206 ``None``. 

3207 

3208 labeldistance : float or None, default: 1.1 

3209 The relative distance along the radius at which the labels are 

3210 drawn. To draw the labels inside the pie, set *labeldistance* < 1. 

3211 If set to ``None``, labels are not drawn but are still stored for 

3212 use in `.legend`. 

3213 

3214 shadow : bool or dict, default: False 

3215 If bool, whether to draw a shadow beneath the pie. If dict, draw a shadow 

3216 passing the properties in the dict to `.Shadow`. 

3217 

3218 .. versionadded:: 3.8 

3219 *shadow* can be a dict. 

3220 

3221 startangle : float, default: 0 degrees 

3222 The angle by which the start of the pie is rotated, 

3223 counterclockwise from the x-axis. 

3224 

3225 radius : float, default: 1 

3226 The radius of the pie. 

3227 

3228 counterclock : bool, default: True 

3229 Specify fractions direction, clockwise or counterclockwise. 

3230 

3231 wedgeprops : dict, default: None 

3232 Dict of arguments passed to each `.patches.Wedge` of the pie. 

3233 For example, ``wedgeprops = {'linewidth': 3}`` sets the width of 

3234 the wedge border lines equal to 3. By default, ``clip_on=False``. 

3235 When there is a conflict between these properties and other 

3236 keywords, properties passed to *wedgeprops* take precedence. 

3237 

3238 textprops : dict, default: None 

3239 Dict of arguments to pass to the text objects. 

3240 

3241 center : (float, float), default: (0, 0) 

3242 The coordinates of the center of the chart. 

3243 

3244 frame : bool, default: False 

3245 Plot Axes frame with the chart if true. 

3246 

3247 rotatelabels : bool, default: False 

3248 Rotate each label to the angle of the corresponding slice if true. 

3249 

3250 normalize : bool, default: True 

3251 When *True*, always make a full pie by normalizing x so that 

3252 ``sum(x) == 1``. *False* makes a partial pie if ``sum(x) <= 1`` 

3253 and raises a `ValueError` for ``sum(x) > 1``. 

3254 

3255 data : indexable object, optional 

3256 DATA_PARAMETER_PLACEHOLDER 

3257 

3258 Returns 

3259 ------- 

3260 patches : list 

3261 A sequence of `matplotlib.patches.Wedge` instances 

3262 

3263 texts : list 

3264 A list of the label `.Text` instances. 

3265 

3266 autotexts : list 

3267 A list of `.Text` instances for the numeric labels. This will only 

3268 be returned if the parameter *autopct* is not *None*. 

3269 

3270 Notes 

3271 ----- 

3272 The pie chart will probably look best if the figure and Axes are 

3273 square, or the Axes aspect is equal. 

3274 This method sets the aspect ratio of the axis to "equal". 

3275 The Axes aspect ratio can be controlled with `.Axes.set_aspect`. 

3276 """ 

3277 self.set_aspect('equal') 

3278 # The use of float32 is "historical", but can't be changed without 

3279 # regenerating the test baselines. 

3280 x = np.asarray(x, np.float32) 

3281 if x.ndim > 1: 

3282 raise ValueError("x must be 1D") 

3283 

3284 if np.any(x < 0): 

3285 raise ValueError("Wedge sizes 'x' must be non negative values") 

3286 

3287 sx = x.sum() 

3288 

3289 if normalize: 

3290 x = x / sx 

3291 elif sx > 1: 

3292 raise ValueError('Cannot plot an unnormalized pie with sum(x) > 1') 

3293 if labels is None: 

3294 labels = [''] * len(x) 

3295 if explode is None: 

3296 explode = [0] * len(x) 

3297 if len(x) != len(labels): 

3298 raise ValueError("'label' must be of length 'x'") 

3299 if len(x) != len(explode): 

3300 raise ValueError("'explode' must be of length 'x'") 

3301 if colors is None: 

3302 get_next_color = self._get_patches_for_fill.get_next_color 

3303 else: 

3304 color_cycle = itertools.cycle(colors) 

3305 

3306 def get_next_color(): 

3307 return next(color_cycle) 

3308 

3309 hatch_cycle = itertools.cycle(np.atleast_1d(hatch)) 

3310 

3311 _api.check_isinstance(Real, radius=radius, startangle=startangle) 

3312 if radius <= 0: 

3313 raise ValueError(f'radius must be a positive number, not {radius}') 

3314 

3315 # Starting theta1 is the start fraction of the circle 

3316 theta1 = startangle / 360 

3317 

3318 if wedgeprops is None: 

3319 wedgeprops = {} 

3320 if textprops is None: 

3321 textprops = {} 

3322 

3323 texts = [] 

3324 slices = [] 

3325 autotexts = [] 

3326 

3327 for frac, label, expl in zip(x, labels, explode): 

3328 x, y = center 

3329 theta2 = (theta1 + frac) if counterclock else (theta1 - frac) 

3330 thetam = 2 * np.pi * 0.5 * (theta1 + theta2) 

3331 x += expl * math.cos(thetam) 

3332 y += expl * math.sin(thetam) 

3333 

3334 w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2), 

3335 360. * max(theta1, theta2), 

3336 facecolor=get_next_color(), 

3337 hatch=next(hatch_cycle), 

3338 clip_on=False, 

3339 label=label) 

3340 w.set(**wedgeprops) 

3341 slices.append(w) 

3342 self.add_patch(w) 

3343 

3344 if shadow: 

3345 # Make sure to add a shadow after the call to add_patch so the 

3346 # figure and transform props will be set. 

3347 shadow_dict = {'ox': -0.02, 'oy': -0.02, 'label': '_nolegend_'} 

3348 if isinstance(shadow, dict): 

3349 shadow_dict.update(shadow) 

3350 self.add_patch(mpatches.Shadow(w, **shadow_dict)) 

3351 

3352 if labeldistance is not None: 

3353 xt = x + labeldistance * radius * math.cos(thetam) 

3354 yt = y + labeldistance * radius * math.sin(thetam) 

3355 label_alignment_h = 'left' if xt > 0 else 'right' 

3356 label_alignment_v = 'center' 

3357 label_rotation = 'horizontal' 

3358 if rotatelabels: 

3359 label_alignment_v = 'bottom' if yt > 0 else 'top' 

3360 label_rotation = (np.rad2deg(thetam) 

3361 + (0 if xt > 0 else 180)) 

3362 t = self.text(xt, yt, label, 

3363 clip_on=False, 

3364 horizontalalignment=label_alignment_h, 

3365 verticalalignment=label_alignment_v, 

3366 rotation=label_rotation, 

3367 size=mpl.rcParams['xtick.labelsize']) 

3368 t.set(**textprops) 

3369 texts.append(t) 

3370 

3371 if autopct is not None: 

3372 xt = x + pctdistance * radius * math.cos(thetam) 

3373 yt = y + pctdistance * radius * math.sin(thetam) 

3374 if isinstance(autopct, str): 

3375 s = autopct % (100. * frac) 

3376 elif callable(autopct): 

3377 s = autopct(100. * frac) 

3378 else: 

3379 raise TypeError( 

3380 'autopct must be callable or a format string') 

3381 if mpl._val_or_rc(textprops.get("usetex"), "text.usetex"): 

3382 # escape % (i.e. \%) if it is not already escaped 

3383 s = re.sub(r"([^\\])%", r"\1\\%", s) 

3384 t = self.text(xt, yt, s, 

3385 clip_on=False, 

3386 horizontalalignment='center', 

3387 verticalalignment='center') 

3388 t.set(**textprops) 

3389 autotexts.append(t) 

3390 

3391 theta1 = theta2 

3392 

3393 if frame: 

3394 self._request_autoscale_view() 

3395 else: 

3396 self.set(frame_on=False, xticks=[], yticks=[], 

3397 xlim=(-1.25 + center[0], 1.25 + center[0]), 

3398 ylim=(-1.25 + center[1], 1.25 + center[1])) 

3399 

3400 if autopct is None: 

3401 return slices, texts 

3402 else: 

3403 return slices, texts, autotexts 

3404 

3405 @staticmethod 

3406 def _errorevery_to_mask(x, errorevery): 

3407 """ 

3408 Normalize `errorbar`'s *errorevery* to be a boolean mask for data *x*. 

3409 

3410 This function is split out to be usable both by 2D and 3D errorbars. 

3411 """ 

3412 if isinstance(errorevery, Integral): 

3413 errorevery = (0, errorevery) 

3414 if isinstance(errorevery, tuple): 

3415 if (len(errorevery) == 2 and 

3416 isinstance(errorevery[0], Integral) and 

3417 isinstance(errorevery[1], Integral)): 

3418 errorevery = slice(errorevery[0], None, errorevery[1]) 

3419 else: 

3420 raise ValueError( 

3421 f'{errorevery=!r} is a not a tuple of two integers') 

3422 elif isinstance(errorevery, slice): 

3423 pass 

3424 elif not isinstance(errorevery, str) and np.iterable(errorevery): 

3425 try: 

3426 x[errorevery] # fancy indexing 

3427 except (ValueError, IndexError) as err: 

3428 raise ValueError( 

3429 f"{errorevery=!r} is iterable but not a valid NumPy fancy " 

3430 "index to match 'xerr'/'yerr'") from err 

3431 else: 

3432 raise ValueError(f"{errorevery=!r} is not a recognized value") 

3433 everymask = np.zeros(len(x), bool) 

3434 everymask[errorevery] = True 

3435 return everymask 

3436 

3437 @_preprocess_data(replace_names=["x", "y", "xerr", "yerr"], 

3438 label_namer="y") 

3439 @_docstring.dedent_interpd 

3440 def errorbar(self, x, y, yerr=None, xerr=None, 

3441 fmt='', ecolor=None, elinewidth=None, capsize=None, 

3442 barsabove=False, lolims=False, uplims=False, 

3443 xlolims=False, xuplims=False, errorevery=1, capthick=None, 

3444 **kwargs): 

3445 """ 

3446 Plot y versus x as lines and/or markers with attached errorbars. 

3447 

3448 *x*, *y* define the data locations, *xerr*, *yerr* define the errorbar 

3449 sizes. By default, this draws the data markers/lines as well as the 

3450 errorbars. Use fmt='none' to draw errorbars without any data markers. 

3451 

3452 .. versionadded:: 3.7 

3453 Caps and error lines are drawn in polar coordinates on polar plots. 

3454 

3455 

3456 Parameters 

3457 ---------- 

3458 x, y : float or array-like 

3459 The data positions. 

3460 

3461 xerr, yerr : float or array-like, shape(N,) or shape(2, N), optional 

3462 The errorbar sizes: 

3463 

3464 - scalar: Symmetric +/- values for all data points. 

3465 - shape(N,): Symmetric +/-values for each data point. 

3466 - shape(2, N): Separate - and + values for each bar. First row 

3467 contains the lower errors, the second row contains the upper 

3468 errors. 

3469 - *None*: No errorbar. 

3470 

3471 All values must be >= 0. 

3472 

3473 See :doc:`/gallery/statistics/errorbar_features` 

3474 for an example on the usage of ``xerr`` and ``yerr``. 

3475 

3476 fmt : str, default: '' 

3477 The format for the data points / data lines. See `.plot` for 

3478 details. 

3479 

3480 Use 'none' (case-insensitive) to plot errorbars without any data 

3481 markers. 

3482 

3483 ecolor : :mpltype:`color`, default: None 

3484 The color of the errorbar lines. If None, use the color of the 

3485 line connecting the markers. 

3486 

3487 elinewidth : float, default: None 

3488 The linewidth of the errorbar lines. If None, the linewidth of 

3489 the current style is used. 

3490 

3491 capsize : float, default: :rc:`errorbar.capsize` 

3492 The length of the error bar caps in points. 

3493 

3494 capthick : float, default: None 

3495 An alias to the keyword argument *markeredgewidth* (a.k.a. *mew*). 

3496 This setting is a more sensible name for the property that 

3497 controls the thickness of the error bar cap in points. For 

3498 backwards compatibility, if *mew* or *markeredgewidth* are given, 

3499 then they will over-ride *capthick*. This may change in future 

3500 releases. 

3501 

3502 barsabove : bool, default: False 

3503 If True, will plot the errorbars above the plot 

3504 symbols. Default is below. 

3505 

3506 lolims, uplims, xlolims, xuplims : bool or array-like, default: False 

3507 These arguments can be used to indicate that a value gives only 

3508 upper/lower limits. In that case a caret symbol is used to 

3509 indicate this. *lims*-arguments may be scalars, or array-likes of 

3510 the same length as *xerr* and *yerr*. To use limits with inverted 

3511 axes, `~.Axes.set_xlim` or `~.Axes.set_ylim` must be called before 

3512 :meth:`errorbar`. Note the tricky parameter names: setting e.g. 

3513 *lolims* to True means that the y-value is a *lower* limit of the 

3514 True value, so, only an *upward*-pointing arrow will be drawn! 

3515 

3516 errorevery : int or (int, int), default: 1 

3517 draws error bars on a subset of the data. *errorevery* =N draws 

3518 error bars on the points (x[::N], y[::N]). 

3519 *errorevery* =(start, N) draws error bars on the points 

3520 (x[start::N], y[start::N]). e.g. errorevery=(6, 3) 

3521 adds error bars to the data at (x[6], x[9], x[12], x[15], ...). 

3522 Used to avoid overlapping error bars when two series share x-axis 

3523 values. 

3524 

3525 Returns 

3526 ------- 

3527 `.ErrorbarContainer` 

3528 The container contains: 

3529 

3530 - data_line : A `~matplotlib.lines.Line2D` instance of x, y plot markers 

3531 and/or line. 

3532 - caplines : A tuple of `~matplotlib.lines.Line2D` instances of the error 

3533 bar caps. 

3534 - barlinecols : A tuple of `.LineCollection` with the horizontal and 

3535 vertical error ranges. 

3536 

3537 Other Parameters 

3538 ---------------- 

3539 data : indexable object, optional 

3540 DATA_PARAMETER_PLACEHOLDER 

3541 

3542 **kwargs 

3543 All other keyword arguments are passed on to the `~.Axes.plot` call 

3544 drawing the markers. For example, this code makes big red squares 

3545 with thick green edges:: 

3546 

3547 x, y, yerr = rand(3, 10) 

3548 errorbar(x, y, yerr, marker='s', mfc='red', 

3549 mec='green', ms=20, mew=4) 

3550 

3551 where *mfc*, *mec*, *ms* and *mew* are aliases for the longer 

3552 property names, *markerfacecolor*, *markeredgecolor*, *markersize* 

3553 and *markeredgewidth*. 

3554 

3555 Valid kwargs for the marker properties are: 

3556 

3557 - *dashes* 

3558 - *dash_capstyle* 

3559 - *dash_joinstyle* 

3560 - *drawstyle* 

3561 - *fillstyle* 

3562 - *linestyle* 

3563 - *marker* 

3564 - *markeredgecolor* 

3565 - *markeredgewidth* 

3566 - *markerfacecolor* 

3567 - *markerfacecoloralt* 

3568 - *markersize* 

3569 - *markevery* 

3570 - *solid_capstyle* 

3571 - *solid_joinstyle* 

3572 

3573 Refer to the corresponding `.Line2D` property for more details: 

3574 

3575 %(Line2D:kwdoc)s 

3576 """ 

3577 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D) 

3578 # Drop anything that comes in as None to use the default instead. 

3579 kwargs = {k: v for k, v in kwargs.items() if v is not None} 

3580 kwargs.setdefault('zorder', 2) 

3581 

3582 # Casting to object arrays preserves units. 

3583 if not isinstance(x, np.ndarray): 

3584 x = np.asarray(x, dtype=object) 

3585 if not isinstance(y, np.ndarray): 

3586 y = np.asarray(y, dtype=object) 

3587 

3588 def _upcast_err(err): 

3589 """ 

3590 Safely handle tuple of containers that carry units. 

3591 

3592 This function covers the case where the input to the xerr/yerr is a 

3593 length 2 tuple of equal length ndarray-subclasses that carry the 

3594 unit information in the container. 

3595 

3596 If we have a tuple of nested numpy array (subclasses), we defer 

3597 coercing the units to be consistent to the underlying unit 

3598 library (and implicitly the broadcasting). 

3599 

3600 Otherwise, fallback to casting to an object array. 

3601 """ 

3602 

3603 if ( 

3604 # make sure it is not a scalar 

3605 np.iterable(err) and 

3606 # and it is not empty 

3607 len(err) > 0 and 

3608 # and the first element is an array sub-class use 

3609 # safe_first_element because getitem is index-first not 

3610 # location first on pandas objects so err[0] almost always 

3611 # fails. 

3612 isinstance(cbook._safe_first_finite(err), np.ndarray) 

3613 ): 

3614 # Get the type of the first element 

3615 atype = type(cbook._safe_first_finite(err)) 

3616 # Promote the outer container to match the inner container 

3617 if atype is np.ndarray: 

3618 # Converts using np.asarray, because data cannot 

3619 # be directly passed to init of np.ndarray 

3620 return np.asarray(err, dtype=object) 

3621 # If atype is not np.ndarray, directly pass data to init. 

3622 # This works for types such as unyts and astropy units 

3623 return atype(err) 

3624 # Otherwise wrap it in an object array 

3625 return np.asarray(err, dtype=object) 

3626 

3627 if xerr is not None and not isinstance(xerr, np.ndarray): 

3628 xerr = _upcast_err(xerr) 

3629 if yerr is not None and not isinstance(yerr, np.ndarray): 

3630 yerr = _upcast_err(yerr) 

3631 x, y = np.atleast_1d(x, y) # Make sure all the args are iterable. 

3632 if len(x) != len(y): 

3633 raise ValueError("'x' and 'y' must have the same size") 

3634 

3635 everymask = self._errorevery_to_mask(x, errorevery) 

3636 

3637 label = kwargs.pop("label", None) 

3638 kwargs['label'] = '_nolegend_' 

3639 

3640 # Create the main line and determine overall kwargs for child artists. 

3641 # We avoid calling self.plot() directly, or self._get_lines(), because 

3642 # that would call self._process_unit_info again, and do other indirect 

3643 # data processing. 

3644 (data_line, base_style), = self._get_lines._plot_args( 

3645 self, (x, y) if fmt == '' else (x, y, fmt), kwargs, return_kwargs=True) 

3646 

3647 # Do this after creating `data_line` to avoid modifying `base_style`. 

3648 if barsabove: 

3649 data_line.set_zorder(kwargs['zorder'] - .1) 

3650 else: 

3651 data_line.set_zorder(kwargs['zorder'] + .1) 

3652 

3653 # Add line to plot, or throw it away and use it to determine kwargs. 

3654 if fmt.lower() != 'none': 

3655 self.add_line(data_line) 

3656 else: 

3657 data_line = None 

3658 # Remove alpha=0 color that _get_lines._plot_args returns for 

3659 # 'none' format, and replace it with user-specified color, if 

3660 # supplied. 

3661 base_style.pop('color') 

3662 if 'color' in kwargs: 

3663 base_style['color'] = kwargs.pop('color') 

3664 

3665 if 'color' not in base_style: 

3666 base_style['color'] = 'C0' 

3667 if ecolor is None: 

3668 ecolor = base_style['color'] 

3669 

3670 # Eject any line-specific information from format string, as it's not 

3671 # needed for bars or caps. 

3672 for key in ['marker', 'markersize', 'markerfacecolor', 

3673 'markerfacecoloralt', 

3674 'markeredgewidth', 'markeredgecolor', 'markevery', 

3675 'linestyle', 'fillstyle', 'drawstyle', 'dash_capstyle', 

3676 'dash_joinstyle', 'solid_capstyle', 'solid_joinstyle', 

3677 'dashes']: 

3678 base_style.pop(key, None) 

3679 

3680 # Make the style dict for the line collections (the bars). 

3681 eb_lines_style = {**base_style, 'color': ecolor} 

3682 

3683 if elinewidth is not None: 

3684 eb_lines_style['linewidth'] = elinewidth 

3685 elif 'linewidth' in kwargs: 

3686 eb_lines_style['linewidth'] = kwargs['linewidth'] 

3687 

3688 for key in ('transform', 'alpha', 'zorder', 'rasterized'): 

3689 if key in kwargs: 

3690 eb_lines_style[key] = kwargs[key] 

3691 

3692 # Make the style dict for caps (the "hats"). 

3693 eb_cap_style = {**base_style, 'linestyle': 'none'} 

3694 if capsize is None: 

3695 capsize = mpl.rcParams["errorbar.capsize"] 

3696 if capsize > 0: 

3697 eb_cap_style['markersize'] = 2. * capsize 

3698 if capthick is not None: 

3699 eb_cap_style['markeredgewidth'] = capthick 

3700 

3701 # For backwards-compat, allow explicit setting of 

3702 # 'markeredgewidth' to over-ride capthick. 

3703 for key in ('markeredgewidth', 'transform', 'alpha', 

3704 'zorder', 'rasterized'): 

3705 if key in kwargs: 

3706 eb_cap_style[key] = kwargs[key] 

3707 eb_cap_style['color'] = ecolor 

3708 

3709 barcols = [] 

3710 caplines = {'x': [], 'y': []} 

3711 

3712 # Vectorized fancy-indexer. 

3713 def apply_mask(arrays, mask): 

3714 return [array[mask] for array in arrays] 

3715 

3716 # dep: dependent dataset, indep: independent dataset 

3717 for (dep_axis, dep, err, lolims, uplims, indep, lines_func, 

3718 marker, lomarker, himarker) in [ 

3719 ("x", x, xerr, xlolims, xuplims, y, self.hlines, 

3720 "|", mlines.CARETRIGHTBASE, mlines.CARETLEFTBASE), 

3721 ("y", y, yerr, lolims, uplims, x, self.vlines, 

3722 "_", mlines.CARETUPBASE, mlines.CARETDOWNBASE), 

3723 ]: 

3724 if err is None: 

3725 continue 

3726 lolims = np.broadcast_to(lolims, len(dep)).astype(bool) 

3727 uplims = np.broadcast_to(uplims, len(dep)).astype(bool) 

3728 try: 

3729 np.broadcast_to(err, (2, len(dep))) 

3730 except ValueError: 

3731 raise ValueError( 

3732 f"'{dep_axis}err' (shape: {np.shape(err)}) must be a " 

3733 f"scalar or a 1D or (2, n) array-like whose shape matches " 

3734 f"'{dep_axis}' (shape: {np.shape(dep)})") from None 

3735 if err.dtype is np.dtype(object) and np.any(err == None): # noqa: E711 

3736 raise ValueError( 

3737 f"'{dep_axis}err' must not contain None. " 

3738 "Use NaN if you want to skip a value.") 

3739 

3740 res = np.zeros(err.shape, dtype=bool) # Default in case of nan 

3741 if np.any(np.less(err, -err, out=res, where=(err == err))): 

3742 # like err<0, but also works for timedelta and nan. 

3743 raise ValueError( 

3744 f"'{dep_axis}err' must not contain negative values") 

3745 # This is like 

3746 # elow, ehigh = np.broadcast_to(...) 

3747 # return dep - elow * ~lolims, dep + ehigh * ~uplims 

3748 # except that broadcast_to would strip units. 

3749 low, high = dep + np.vstack([-(1 - lolims), 1 - uplims]) * err 

3750 barcols.append(lines_func( 

3751 *apply_mask([indep, low, high], everymask), **eb_lines_style)) 

3752 if self.name == "polar" and dep_axis == "x": 

3753 for b in barcols: 

3754 for p in b.get_paths(): 

3755 p._interpolation_steps = 2 

3756 # Normal errorbars for points without upper/lower limits. 

3757 nolims = ~(lolims | uplims) 

3758 if nolims.any() and capsize > 0: 

3759 indep_masked, lo_masked, hi_masked = apply_mask( 

3760 [indep, low, high], nolims & everymask) 

3761 for lh_masked in [lo_masked, hi_masked]: 

3762 # Since this has to work for x and y as dependent data, we 

3763 # first set both x and y to the independent variable and 

3764 # overwrite the respective dependent data in a second step. 

3765 line = mlines.Line2D(indep_masked, indep_masked, 

3766 marker=marker, **eb_cap_style) 

3767 line.set(**{f"{dep_axis}data": lh_masked}) 

3768 caplines[dep_axis].append(line) 

3769 for idx, (lims, hl) in enumerate([(lolims, high), (uplims, low)]): 

3770 if not lims.any(): 

3771 continue 

3772 hlmarker = ( 

3773 himarker 

3774 if self._axis_map[dep_axis].get_inverted() ^ idx 

3775 else lomarker) 

3776 x_masked, y_masked, hl_masked = apply_mask( 

3777 [x, y, hl], lims & everymask) 

3778 # As above, we set the dependent data in a second step. 

3779 line = mlines.Line2D(x_masked, y_masked, 

3780 marker=hlmarker, **eb_cap_style) 

3781 line.set(**{f"{dep_axis}data": hl_masked}) 

3782 caplines[dep_axis].append(line) 

3783 if capsize > 0: 

3784 caplines[dep_axis].append(mlines.Line2D( 

3785 x_masked, y_masked, marker=marker, **eb_cap_style)) 

3786 if self.name == 'polar': 

3787 for axis in caplines: 

3788 for l in caplines[axis]: 

3789 # Rotate caps to be perpendicular to the error bars 

3790 for theta, r in zip(l.get_xdata(), l.get_ydata()): 

3791 rotation = mtransforms.Affine2D().rotate(theta) 

3792 if axis == 'y': 

3793 rotation.rotate(-np.pi / 2) 

3794 ms = mmarkers.MarkerStyle(marker=marker, 

3795 transform=rotation) 

3796 self.add_line(mlines.Line2D([theta], [r], marker=ms, 

3797 **eb_cap_style)) 

3798 else: 

3799 for axis in caplines: 

3800 for l in caplines[axis]: 

3801 self.add_line(l) 

3802 

3803 self._request_autoscale_view() 

3804 caplines = caplines['x'] + caplines['y'] 

3805 errorbar_container = ErrorbarContainer( 

3806 (data_line, tuple(caplines), tuple(barcols)), 

3807 has_xerr=(xerr is not None), has_yerr=(yerr is not None), 

3808 label=label) 

3809 self.containers.append(errorbar_container) 

3810 

3811 return errorbar_container # (l0, caplines, barcols) 

3812 

3813 @_preprocess_data() 

3814 @_api.rename_parameter("3.9", "labels", "tick_labels") 

3815 def boxplot(self, x, notch=None, sym=None, vert=None, whis=None, 

3816 positions=None, widths=None, patch_artist=None, 

3817 bootstrap=None, usermedians=None, conf_intervals=None, 

3818 meanline=None, showmeans=None, showcaps=None, 

3819 showbox=None, showfliers=None, boxprops=None, 

3820 tick_labels=None, flierprops=None, medianprops=None, 

3821 meanprops=None, capprops=None, whiskerprops=None, 

3822 manage_ticks=True, autorange=False, zorder=None, 

3823 capwidths=None, label=None): 

3824 """ 

3825 Draw a box and whisker plot. 

3826 

3827 The box extends from the first quartile (Q1) to the third 

3828 quartile (Q3) of the data, with a line at the median. 

3829 The whiskers extend from the box to the farthest data point 

3830 lying within 1.5x the inter-quartile range (IQR) from the box. 

3831 Flier points are those past the end of the whiskers. 

3832 See https://en.wikipedia.org/wiki/Box_plot for reference. 

3833 

3834 .. code-block:: none 

3835 

3836 Q1-1.5IQR Q1 median Q3 Q3+1.5IQR 

3837 |-----:-----| 

3838 o |--------| : |--------| o o 

3839 |-----:-----| 

3840 flier <-----------> fliers 

3841 IQR 

3842 

3843 

3844 Parameters 

3845 ---------- 

3846 x : Array or a sequence of vectors. 

3847 The input data. If a 2D array, a boxplot is drawn for each column 

3848 in *x*. If a sequence of 1D arrays, a boxplot is drawn for each 

3849 array in *x*. 

3850 

3851 notch : bool, default: :rc:`boxplot.notch` 

3852 Whether to draw a notched boxplot (`True`), or a rectangular 

3853 boxplot (`False`). The notches represent the confidence interval 

3854 (CI) around the median. The documentation for *bootstrap* 

3855 describes how the locations of the notches are computed by 

3856 default, but their locations may also be overridden by setting the 

3857 *conf_intervals* parameter. 

3858 

3859 .. note:: 

3860 

3861 In cases where the values of the CI are less than the 

3862 lower quartile or greater than the upper quartile, the 

3863 notches will extend beyond the box, giving it a 

3864 distinctive "flipped" appearance. This is expected 

3865 behavior and consistent with other statistical 

3866 visualization packages. 

3867 

3868 sym : str, optional 

3869 The default symbol for flier points. An empty string ('') hides 

3870 the fliers. If `None`, then the fliers default to 'b+'. More 

3871 control is provided by the *flierprops* parameter. 

3872 

3873 vert : bool, default: :rc:`boxplot.vertical` 

3874 If `True`, draws vertical boxes. 

3875 If `False`, draw horizontal boxes. 

3876 

3877 whis : float or (float, float), default: 1.5 

3878 The position of the whiskers. 

3879 

3880 If a float, the lower whisker is at the lowest datum above 

3881 ``Q1 - whis*(Q3-Q1)``, and the upper whisker at the highest datum 

3882 below ``Q3 + whis*(Q3-Q1)``, where Q1 and Q3 are the first and 

3883 third quartiles. The default value of ``whis = 1.5`` corresponds 

3884 to Tukey's original definition of boxplots. 

3885 

3886 If a pair of floats, they indicate the percentiles at which to 

3887 draw the whiskers (e.g., (5, 95)). In particular, setting this to 

3888 (0, 100) results in whiskers covering the whole range of the data. 

3889 

3890 In the edge case where ``Q1 == Q3``, *whis* is automatically set 

3891 to (0, 100) (cover the whole range of the data) if *autorange* is 

3892 True. 

3893 

3894 Beyond the whiskers, data are considered outliers and are plotted 

3895 as individual points. 

3896 

3897 bootstrap : int, optional 

3898 Specifies whether to bootstrap the confidence intervals 

3899 around the median for notched boxplots. If *bootstrap* is 

3900 None, no bootstrapping is performed, and notches are 

3901 calculated using a Gaussian-based asymptotic approximation 

3902 (see McGill, R., Tukey, J.W., and Larsen, W.A., 1978, and 

3903 Kendall and Stuart, 1967). Otherwise, bootstrap specifies 

3904 the number of times to bootstrap the median to determine its 

3905 95% confidence intervals. Values between 1000 and 10000 are 

3906 recommended. 

3907 

3908 usermedians : 1D array-like, optional 

3909 A 1D array-like of length ``len(x)``. Each entry that is not 

3910 `None` forces the value of the median for the corresponding 

3911 dataset. For entries that are `None`, the medians are computed 

3912 by Matplotlib as normal. 

3913 

3914 conf_intervals : array-like, optional 

3915 A 2D array-like of shape ``(len(x), 2)``. Each entry that is not 

3916 None forces the location of the corresponding notch (which is 

3917 only drawn if *notch* is `True`). For entries that are `None`, 

3918 the notches are computed by the method specified by the other 

3919 parameters (e.g., *bootstrap*). 

3920 

3921 positions : array-like, optional 

3922 The positions of the boxes. The ticks and limits are 

3923 automatically set to match the positions. Defaults to 

3924 ``range(1, N+1)`` where N is the number of boxes to be drawn. 

3925 

3926 widths : float or array-like 

3927 The widths of the boxes. The default is 0.5, or ``0.15*(distance 

3928 between extreme positions)``, if that is smaller. 

3929 

3930 patch_artist : bool, default: :rc:`boxplot.patchartist` 

3931 If `False` produces boxes with the Line2D artist. Otherwise, 

3932 boxes are drawn with Patch artists. 

3933 

3934 tick_labels : list of str, optional 

3935 The tick labels of each boxplot. 

3936 Ticks are always placed at the box *positions*. If *tick_labels* is given, 

3937 the ticks are labelled accordingly. Otherwise, they keep their numeric 

3938 values. 

3939 

3940 .. versionchanged:: 3.9 

3941 Renamed from *labels*, which is deprecated since 3.9 

3942 and will be removed in 3.11. 

3943 

3944 manage_ticks : bool, default: True 

3945 If True, the tick locations and labels will be adjusted to match 

3946 the boxplot positions. 

3947 

3948 autorange : bool, default: False 

3949 When `True` and the data are distributed such that the 25th and 

3950 75th percentiles are equal, *whis* is set to (0, 100) such 

3951 that the whisker ends are at the minimum and maximum of the data. 

3952 

3953 meanline : bool, default: :rc:`boxplot.meanline` 

3954 If `True` (and *showmeans* is `True`), will try to render the 

3955 mean as a line spanning the full width of the box according to 

3956 *meanprops* (see below). Not recommended if *shownotches* is also 

3957 True. Otherwise, means will be shown as points. 

3958 

3959 zorder : float, default: ``Line2D.zorder = 2`` 

3960 The zorder of the boxplot. 

3961 

3962 Returns 

3963 ------- 

3964 dict 

3965 A dictionary mapping each component of the boxplot to a list 

3966 of the `.Line2D` instances created. That dictionary has the 

3967 following keys (assuming vertical boxplots): 

3968 

3969 - ``boxes``: the main body of the boxplot showing the 

3970 quartiles and the median's confidence intervals if 

3971 enabled. 

3972 

3973 - ``medians``: horizontal lines at the median of each box. 

3974 

3975 - ``whiskers``: the vertical lines extending to the most 

3976 extreme, non-outlier data points. 

3977 

3978 - ``caps``: the horizontal lines at the ends of the 

3979 whiskers. 

3980 

3981 - ``fliers``: points representing data that extend beyond 

3982 the whiskers (fliers). 

3983 

3984 - ``means``: points or lines representing the means. 

3985 

3986 Other Parameters 

3987 ---------------- 

3988 showcaps : bool, default: :rc:`boxplot.showcaps` 

3989 Show the caps on the ends of whiskers. 

3990 showbox : bool, default: :rc:`boxplot.showbox` 

3991 Show the central box. 

3992 showfliers : bool, default: :rc:`boxplot.showfliers` 

3993 Show the outliers beyond the caps. 

3994 showmeans : bool, default: :rc:`boxplot.showmeans` 

3995 Show the arithmetic means. 

3996 capprops : dict, default: None 

3997 The style of the caps. 

3998 capwidths : float or array, default: None 

3999 The widths of the caps. 

4000 boxprops : dict, default: None 

4001 The style of the box. 

4002 whiskerprops : dict, default: None 

4003 The style of the whiskers. 

4004 flierprops : dict, default: None 

4005 The style of the fliers. 

4006 medianprops : dict, default: None 

4007 The style of the median. 

4008 meanprops : dict, default: None 

4009 The style of the mean. 

4010 label : str or list of str, optional 

4011 Legend labels. Use a single string when all boxes have the same style and 

4012 you only want a single legend entry for them. Use a list of strings to 

4013 label all boxes individually. To be distinguishable, the boxes should be 

4014 styled individually, which is currently only possible by modifying the 

4015 returned artists, see e.g. :doc:`/gallery/statistics/boxplot_demo`. 

4016 

4017 In the case of a single string, the legend entry will technically be 

4018 associated with the first box only. By default, the legend will show the 

4019 median line (``result["medians"]``); if *patch_artist* is True, the legend 

4020 will show the box `.Patch` artists (``result["boxes"]``) instead. 

4021 

4022 .. versionadded:: 3.9 

4023 

4024 data : indexable object, optional 

4025 DATA_PARAMETER_PLACEHOLDER 

4026 

4027 See Also 

4028 -------- 

4029 .Axes.bxp : Draw a boxplot from pre-computed statistics. 

4030 violinplot : Draw an estimate of the probability density function. 

4031 """ 

4032 

4033 # Missing arguments default to rcParams. 

4034 if whis is None: 

4035 whis = mpl.rcParams['boxplot.whiskers'] 

4036 if bootstrap is None: 

4037 bootstrap = mpl.rcParams['boxplot.bootstrap'] 

4038 

4039 bxpstats = cbook.boxplot_stats(x, whis=whis, bootstrap=bootstrap, 

4040 labels=tick_labels, autorange=autorange) 

4041 if notch is None: 

4042 notch = mpl.rcParams['boxplot.notch'] 

4043 if vert is None: 

4044 vert = mpl.rcParams['boxplot.vertical'] 

4045 if patch_artist is None: 

4046 patch_artist = mpl.rcParams['boxplot.patchartist'] 

4047 if meanline is None: 

4048 meanline = mpl.rcParams['boxplot.meanline'] 

4049 if showmeans is None: 

4050 showmeans = mpl.rcParams['boxplot.showmeans'] 

4051 if showcaps is None: 

4052 showcaps = mpl.rcParams['boxplot.showcaps'] 

4053 if showbox is None: 

4054 showbox = mpl.rcParams['boxplot.showbox'] 

4055 if showfliers is None: 

4056 showfliers = mpl.rcParams['boxplot.showfliers'] 

4057 

4058 if boxprops is None: 

4059 boxprops = {} 

4060 if whiskerprops is None: 

4061 whiskerprops = {} 

4062 if capprops is None: 

4063 capprops = {} 

4064 if medianprops is None: 

4065 medianprops = {} 

4066 if meanprops is None: 

4067 meanprops = {} 

4068 if flierprops is None: 

4069 flierprops = {} 

4070 

4071 if patch_artist: 

4072 boxprops['linestyle'] = 'solid' # Not consistent with bxp. 

4073 if 'color' in boxprops: 

4074 boxprops['edgecolor'] = boxprops.pop('color') 

4075 

4076 # if non-default sym value, put it into the flier dictionary 

4077 # the logic for providing the default symbol ('b+') now lives 

4078 # in bxp in the initial value of flierkw 

4079 # handle all of the *sym* related logic here so we only have to pass 

4080 # on the flierprops dict. 

4081 if sym is not None: 

4082 # no-flier case, which should really be done with 

4083 # 'showfliers=False' but none-the-less deal with it to keep back 

4084 # compatibility 

4085 if sym == '': 

4086 # blow away existing dict and make one for invisible markers 

4087 flierprops = dict(linestyle='none', marker='', color='none') 

4088 # turn the fliers off just to be safe 

4089 showfliers = False 

4090 # now process the symbol string 

4091 else: 

4092 # process the symbol string 

4093 # discarded linestyle 

4094 _, marker, color = _process_plot_format(sym) 

4095 # if we have a marker, use it 

4096 if marker is not None: 

4097 flierprops['marker'] = marker 

4098 # if we have a color, use it 

4099 if color is not None: 

4100 # assume that if color is passed in the user want 

4101 # filled symbol, if the users want more control use 

4102 # flierprops 

4103 flierprops['color'] = color 

4104 flierprops['markerfacecolor'] = color 

4105 flierprops['markeredgecolor'] = color 

4106 

4107 # replace medians if necessary: 

4108 if usermedians is not None: 

4109 if (len(np.ravel(usermedians)) != len(bxpstats) or 

4110 np.shape(usermedians)[0] != len(bxpstats)): 

4111 raise ValueError( 

4112 "'usermedians' and 'x' have different lengths") 

4113 else: 

4114 # reassign medians as necessary 

4115 for stats, med in zip(bxpstats, usermedians): 

4116 if med is not None: 

4117 stats['med'] = med 

4118 

4119 if conf_intervals is not None: 

4120 if len(conf_intervals) != len(bxpstats): 

4121 raise ValueError( 

4122 "'conf_intervals' and 'x' have different lengths") 

4123 else: 

4124 for stats, ci in zip(bxpstats, conf_intervals): 

4125 if ci is not None: 

4126 if len(ci) != 2: 

4127 raise ValueError('each confidence interval must ' 

4128 'have two values') 

4129 else: 

4130 if ci[0] is not None: 

4131 stats['cilo'] = ci[0] 

4132 if ci[1] is not None: 

4133 stats['cihi'] = ci[1] 

4134 

4135 artists = self.bxp(bxpstats, positions=positions, widths=widths, 

4136 vert=vert, patch_artist=patch_artist, 

4137 shownotches=notch, showmeans=showmeans, 

4138 showcaps=showcaps, showbox=showbox, 

4139 boxprops=boxprops, flierprops=flierprops, 

4140 medianprops=medianprops, meanprops=meanprops, 

4141 meanline=meanline, showfliers=showfliers, 

4142 capprops=capprops, whiskerprops=whiskerprops, 

4143 manage_ticks=manage_ticks, zorder=zorder, 

4144 capwidths=capwidths, label=label) 

4145 return artists 

4146 

4147 def bxp(self, bxpstats, positions=None, widths=None, vert=True, 

4148 patch_artist=False, shownotches=False, showmeans=False, 

4149 showcaps=True, showbox=True, showfliers=True, 

4150 boxprops=None, whiskerprops=None, flierprops=None, 

4151 medianprops=None, capprops=None, meanprops=None, 

4152 meanline=False, manage_ticks=True, zorder=None, 

4153 capwidths=None, label=None): 

4154 """ 

4155 Draw a box and whisker plot from pre-computed statistics. 

4156 

4157 The box extends from the first quartile *q1* to the third 

4158 quartile *q3* of the data, with a line at the median (*med*). 

4159 The whiskers extend from *whislow* to *whishi*. 

4160 Flier points are markers past the end of the whiskers. 

4161 See https://en.wikipedia.org/wiki/Box_plot for reference. 

4162 

4163 .. code-block:: none 

4164 

4165 whislow q1 med q3 whishi 

4166 |-----:-----| 

4167 o |--------| : |--------| o o 

4168 |-----:-----| 

4169 flier fliers 

4170 

4171 .. note:: 

4172 This is a low-level drawing function for when you already 

4173 have the statistical parameters. If you want a boxplot based 

4174 on a dataset, use `~.Axes.boxplot` instead. 

4175 

4176 Parameters 

4177 ---------- 

4178 bxpstats : list of dicts 

4179 A list of dictionaries containing stats for each boxplot. 

4180 Required keys are: 

4181 

4182 - ``med``: Median (scalar). 

4183 - ``q1``, ``q3``: First & third quartiles (scalars). 

4184 - ``whislo``, ``whishi``: Lower & upper whisker positions (scalars). 

4185 

4186 Optional keys are: 

4187 

4188 - ``mean``: Mean (scalar). Needed if ``showmeans=True``. 

4189 - ``fliers``: Data beyond the whiskers (array-like). 

4190 Needed if ``showfliers=True``. 

4191 - ``cilo``, ``cihi``: Lower & upper confidence intervals 

4192 about the median. Needed if ``shownotches=True``. 

4193 - ``label``: Name of the dataset (str). If available, 

4194 this will be used a tick label for the boxplot 

4195 

4196 positions : array-like, default: [1, 2, ..., n] 

4197 The positions of the boxes. The ticks and limits 

4198 are automatically set to match the positions. 

4199 

4200 widths : float or array-like, default: None 

4201 The widths of the boxes. The default is 

4202 ``clip(0.15*(distance between extreme positions), 0.15, 0.5)``. 

4203 

4204 capwidths : float or array-like, default: None 

4205 Either a scalar or a vector and sets the width of each cap. 

4206 The default is ``0.5*(width of the box)``, see *widths*. 

4207 

4208 vert : bool, default: True 

4209 If `True` (default), makes the boxes vertical. 

4210 If `False`, makes horizontal boxes. 

4211 

4212 patch_artist : bool, default: False 

4213 If `False` produces boxes with the `.Line2D` artist. 

4214 If `True` produces boxes with the `~matplotlib.patches.Patch` artist. 

4215 

4216 shownotches, showmeans, showcaps, showbox, showfliers : bool 

4217 Whether to draw the CI notches, the mean value (both default to 

4218 False), the caps, the box, and the fliers (all three default to 

4219 True). 

4220 

4221 boxprops, whiskerprops, capprops, flierprops, medianprops, meanprops :\ 

4222 dict, optional 

4223 Artist properties for the boxes, whiskers, caps, fliers, medians, and 

4224 means. 

4225 

4226 meanline : bool, default: False 

4227 If `True` (and *showmeans* is `True`), will try to render the mean 

4228 as a line spanning the full width of the box according to 

4229 *meanprops*. Not recommended if *shownotches* is also True. 

4230 Otherwise, means will be shown as points. 

4231 

4232 manage_ticks : bool, default: True 

4233 If True, the tick locations and labels will be adjusted to match the 

4234 boxplot positions. 

4235 

4236 label : str or list of str, optional 

4237 Legend labels. Use a single string when all boxes have the same style and 

4238 you only want a single legend entry for them. Use a list of strings to 

4239 label all boxes individually. To be distinguishable, the boxes should be 

4240 styled individually, which is currently only possible by modifying the 

4241 returned artists, see e.g. :doc:`/gallery/statistics/boxplot_demo`. 

4242 

4243 In the case of a single string, the legend entry will technically be 

4244 associated with the first box only. By default, the legend will show the 

4245 median line (``result["medians"]``); if *patch_artist* is True, the legend 

4246 will show the box `.Patch` artists (``result["boxes"]``) instead. 

4247 

4248 .. versionadded:: 3.9 

4249 

4250 zorder : float, default: ``Line2D.zorder = 2`` 

4251 The zorder of the resulting boxplot. 

4252 

4253 Returns 

4254 ------- 

4255 dict 

4256 A dictionary mapping each component of the boxplot to a list 

4257 of the `.Line2D` instances created. That dictionary has the 

4258 following keys (assuming vertical boxplots): 

4259 

4260 - ``boxes``: main bodies of the boxplot showing the quartiles, and 

4261 the median's confidence intervals if enabled. 

4262 - ``medians``: horizontal lines at the median of each box. 

4263 - ``whiskers``: vertical lines up to the last non-outlier data. 

4264 - ``caps``: horizontal lines at the ends of the whiskers. 

4265 - ``fliers``: points representing data beyond the whiskers (fliers). 

4266 - ``means``: points or lines representing the means. 

4267 

4268 See Also 

4269 -------- 

4270 boxplot : Draw a boxplot from data instead of pre-computed statistics. 

4271 """ 

4272 # Clamp median line to edge of box by default. 

4273 medianprops = { 

4274 "solid_capstyle": "butt", 

4275 "dash_capstyle": "butt", 

4276 **(medianprops or {}), 

4277 } 

4278 meanprops = { 

4279 "solid_capstyle": "butt", 

4280 "dash_capstyle": "butt", 

4281 **(meanprops or {}), 

4282 } 

4283 

4284 # lists of artists to be output 

4285 whiskers = [] 

4286 caps = [] 

4287 boxes = [] 

4288 medians = [] 

4289 means = [] 

4290 fliers = [] 

4291 

4292 # empty list of xticklabels 

4293 datalabels = [] 

4294 

4295 # Use default zorder if none specified 

4296 if zorder is None: 

4297 zorder = mlines.Line2D.zorder 

4298 

4299 zdelta = 0.1 

4300 

4301 def merge_kw_rc(subkey, explicit, zdelta=0, usemarker=True): 

4302 d = {k.split('.')[-1]: v for k, v in mpl.rcParams.items() 

4303 if k.startswith(f'boxplot.{subkey}props')} 

4304 d['zorder'] = zorder + zdelta 

4305 if not usemarker: 

4306 d['marker'] = '' 

4307 d.update(cbook.normalize_kwargs(explicit, mlines.Line2D)) 

4308 return d 

4309 

4310 box_kw = { 

4311 'linestyle': mpl.rcParams['boxplot.boxprops.linestyle'], 

4312 'linewidth': mpl.rcParams['boxplot.boxprops.linewidth'], 

4313 'edgecolor': mpl.rcParams['boxplot.boxprops.color'], 

4314 'facecolor': ('white' if mpl.rcParams['_internal.classic_mode'] 

4315 else mpl.rcParams['patch.facecolor']), 

4316 'zorder': zorder, 

4317 **cbook.normalize_kwargs(boxprops, mpatches.PathPatch) 

4318 } if patch_artist else merge_kw_rc('box', boxprops, usemarker=False) 

4319 whisker_kw = merge_kw_rc('whisker', whiskerprops, usemarker=False) 

4320 cap_kw = merge_kw_rc('cap', capprops, usemarker=False) 

4321 flier_kw = merge_kw_rc('flier', flierprops) 

4322 median_kw = merge_kw_rc('median', medianprops, zdelta, usemarker=False) 

4323 mean_kw = merge_kw_rc('mean', meanprops, zdelta) 

4324 removed_prop = 'marker' if meanline else 'linestyle' 

4325 # Only remove the property if it's not set explicitly as a parameter. 

4326 if meanprops is None or removed_prop not in meanprops: 

4327 mean_kw[removed_prop] = '' 

4328 

4329 # vertical or horizontal plot? 

4330 maybe_swap = slice(None) if vert else slice(None, None, -1) 

4331 

4332 def do_plot(xs, ys, **kwargs): 

4333 return self.plot(*[xs, ys][maybe_swap], **kwargs)[0] 

4334 

4335 def do_patch(xs, ys, **kwargs): 

4336 path = mpath.Path._create_closed( 

4337 np.column_stack([xs, ys][maybe_swap])) 

4338 patch = mpatches.PathPatch(path, **kwargs) 

4339 self.add_artist(patch) 

4340 return patch 

4341 

4342 # input validation 

4343 N = len(bxpstats) 

4344 datashape_message = ("List of boxplot statistics and `{0}` " 

4345 "values must have same the length") 

4346 # check position 

4347 if positions is None: 

4348 positions = list(range(1, N + 1)) 

4349 elif len(positions) != N: 

4350 raise ValueError(datashape_message.format("positions")) 

4351 

4352 positions = np.array(positions) 

4353 if len(positions) > 0 and not all(isinstance(p, Real) for p in positions): 

4354 raise TypeError("positions should be an iterable of numbers") 

4355 

4356 # width 

4357 if widths is None: 

4358 widths = [np.clip(0.15 * np.ptp(positions), 0.15, 0.5)] * N 

4359 elif np.isscalar(widths): 

4360 widths = [widths] * N 

4361 elif len(widths) != N: 

4362 raise ValueError(datashape_message.format("widths")) 

4363 

4364 # capwidth 

4365 if capwidths is None: 

4366 capwidths = 0.5 * np.array(widths) 

4367 elif np.isscalar(capwidths): 

4368 capwidths = [capwidths] * N 

4369 elif len(capwidths) != N: 

4370 raise ValueError(datashape_message.format("capwidths")) 

4371 

4372 for pos, width, stats, capwidth in zip(positions, widths, bxpstats, 

4373 capwidths): 

4374 # try to find a new label 

4375 datalabels.append(stats.get('label', pos)) 

4376 

4377 # whisker coords 

4378 whis_x = [pos, pos] 

4379 whislo_y = [stats['q1'], stats['whislo']] 

4380 whishi_y = [stats['q3'], stats['whishi']] 

4381 # cap coords 

4382 cap_left = pos - capwidth * 0.5 

4383 cap_right = pos + capwidth * 0.5 

4384 cap_x = [cap_left, cap_right] 

4385 cap_lo = np.full(2, stats['whislo']) 

4386 cap_hi = np.full(2, stats['whishi']) 

4387 # box and median coords 

4388 box_left = pos - width * 0.5 

4389 box_right = pos + width * 0.5 

4390 med_y = [stats['med'], stats['med']] 

4391 # notched boxes 

4392 if shownotches: 

4393 notch_left = pos - width * 0.25 

4394 notch_right = pos + width * 0.25 

4395 box_x = [box_left, box_right, box_right, notch_right, 

4396 box_right, box_right, box_left, box_left, notch_left, 

4397 box_left, box_left] 

4398 box_y = [stats['q1'], stats['q1'], stats['cilo'], 

4399 stats['med'], stats['cihi'], stats['q3'], 

4400 stats['q3'], stats['cihi'], stats['med'], 

4401 stats['cilo'], stats['q1']] 

4402 med_x = [notch_left, notch_right] 

4403 # plain boxes 

4404 else: 

4405 box_x = [box_left, box_right, box_right, box_left, box_left] 

4406 box_y = [stats['q1'], stats['q1'], stats['q3'], stats['q3'], 

4407 stats['q1']] 

4408 med_x = [box_left, box_right] 

4409 

4410 # maybe draw the box 

4411 if showbox: 

4412 do_box = do_patch if patch_artist else do_plot 

4413 boxes.append(do_box(box_x, box_y, **box_kw)) 

4414 median_kw.setdefault('label', '_nolegend_') 

4415 # draw the whiskers 

4416 whisker_kw.setdefault('label', '_nolegend_') 

4417 whiskers.append(do_plot(whis_x, whislo_y, **whisker_kw)) 

4418 whiskers.append(do_plot(whis_x, whishi_y, **whisker_kw)) 

4419 # maybe draw the caps 

4420 if showcaps: 

4421 cap_kw.setdefault('label', '_nolegend_') 

4422 caps.append(do_plot(cap_x, cap_lo, **cap_kw)) 

4423 caps.append(do_plot(cap_x, cap_hi, **cap_kw)) 

4424 # draw the medians 

4425 medians.append(do_plot(med_x, med_y, **median_kw)) 

4426 # maybe draw the means 

4427 if showmeans: 

4428 if meanline: 

4429 means.append(do_plot( 

4430 [box_left, box_right], [stats['mean'], stats['mean']], 

4431 **mean_kw 

4432 )) 

4433 else: 

4434 means.append(do_plot([pos], [stats['mean']], **mean_kw)) 

4435 # maybe draw the fliers 

4436 if showfliers: 

4437 flier_kw.setdefault('label', '_nolegend_') 

4438 flier_x = np.full(len(stats['fliers']), pos, dtype=np.float64) 

4439 flier_y = stats['fliers'] 

4440 fliers.append(do_plot(flier_x, flier_y, **flier_kw)) 

4441 

4442 # Set legend labels 

4443 if label: 

4444 box_or_med = boxes if showbox and patch_artist else medians 

4445 if cbook.is_scalar_or_string(label): 

4446 # assign the label only to the first box 

4447 box_or_med[0].set_label(label) 

4448 else: # label is a sequence 

4449 if len(box_or_med) != len(label): 

4450 raise ValueError(datashape_message.format("label")) 

4451 for artist, lbl in zip(box_or_med, label): 

4452 artist.set_label(lbl) 

4453 

4454 if manage_ticks: 

4455 axis_name = "x" if vert else "y" 

4456 interval = getattr(self.dataLim, f"interval{axis_name}") 

4457 axis = self._axis_map[axis_name] 

4458 positions = axis.convert_units(positions) 

4459 # The 0.5 additional padding ensures reasonable-looking boxes 

4460 # even when drawing a single box. We set the sticky edge to 

4461 # prevent margins expansion, in order to match old behavior (back 

4462 # when separate calls to boxplot() would completely reset the axis 

4463 # limits regardless of what was drawn before). The sticky edges 

4464 # are attached to the median lines, as they are always present. 

4465 interval[:] = (min(interval[0], min(positions) - .5), 

4466 max(interval[1], max(positions) + .5)) 

4467 for median, position in zip(medians, positions): 

4468 getattr(median.sticky_edges, axis_name).extend( 

4469 [position - .5, position + .5]) 

4470 # Modified from Axis.set_ticks and Axis.set_ticklabels. 

4471 locator = axis.get_major_locator() 

4472 if not isinstance(axis.get_major_locator(), 

4473 mticker.FixedLocator): 

4474 locator = mticker.FixedLocator([]) 

4475 axis.set_major_locator(locator) 

4476 locator.locs = np.array([*locator.locs, *positions]) 

4477 formatter = axis.get_major_formatter() 

4478 if not isinstance(axis.get_major_formatter(), 

4479 mticker.FixedFormatter): 

4480 formatter = mticker.FixedFormatter([]) 

4481 axis.set_major_formatter(formatter) 

4482 formatter.seq = [*formatter.seq, *datalabels] 

4483 

4484 self._request_autoscale_view() 

4485 

4486 return dict(whiskers=whiskers, caps=caps, boxes=boxes, 

4487 medians=medians, fliers=fliers, means=means) 

4488 

4489 @staticmethod 

4490 def _parse_scatter_color_args(c, edgecolors, kwargs, xsize, 

4491 get_next_color_func): 

4492 """ 

4493 Helper function to process color related arguments of `.Axes.scatter`. 

4494 

4495 Argument precedence for facecolors: 

4496 

4497 - c (if not None) 

4498 - kwargs['facecolor'] 

4499 - kwargs['facecolors'] 

4500 - kwargs['color'] (==kwcolor) 

4501 - 'b' if in classic mode else the result of ``get_next_color_func()`` 

4502 

4503 Argument precedence for edgecolors: 

4504 

4505 - kwargs['edgecolor'] 

4506 - edgecolors (is an explicit kw argument in scatter()) 

4507 - kwargs['color'] (==kwcolor) 

4508 - 'face' if not in classic mode else None 

4509 

4510 Parameters 

4511 ---------- 

4512 c : :mpltype:`color` or array-like or list of :mpltype:`color` or None 

4513 See argument description of `.Axes.scatter`. 

4514 edgecolors : :mpltype:`color` or sequence of color or {'face', 'none'} or None 

4515 See argument description of `.Axes.scatter`. 

4516 kwargs : dict 

4517 Additional kwargs. If these keys exist, we pop and process them: 

4518 'facecolors', 'facecolor', 'edgecolor', 'color' 

4519 Note: The dict is modified by this function. 

4520 xsize : int 

4521 The size of the x and y arrays passed to `.Axes.scatter`. 

4522 get_next_color_func : callable 

4523 A callable that returns a color. This color is used as facecolor 

4524 if no other color is provided. 

4525 

4526 Note, that this is a function rather than a fixed color value to 

4527 support conditional evaluation of the next color. As of the 

4528 current implementation obtaining the next color from the 

4529 property cycle advances the cycle. This must only happen if we 

4530 actually use the color, which will only be decided within this 

4531 method. 

4532 

4533 Returns 

4534 ------- 

4535 c 

4536 The input *c* if it was not *None*, else a color derived from the 

4537 other inputs or defaults. 

4538 colors : array(N, 4) or None 

4539 The facecolors as RGBA values, or *None* if a colormap is used. 

4540 edgecolors 

4541 The edgecolor. 

4542 

4543 """ 

4544 facecolors = kwargs.pop('facecolors', None) 

4545 facecolors = kwargs.pop('facecolor', facecolors) 

4546 edgecolors = kwargs.pop('edgecolor', edgecolors) 

4547 

4548 kwcolor = kwargs.pop('color', None) 

4549 

4550 if kwcolor is not None and c is not None: 

4551 raise ValueError("Supply a 'c' argument or a 'color'" 

4552 " kwarg but not both; they differ but" 

4553 " their functionalities overlap.") 

4554 

4555 if kwcolor is not None: 

4556 try: 

4557 mcolors.to_rgba_array(kwcolor) 

4558 except ValueError as err: 

4559 raise ValueError( 

4560 "'color' kwarg must be a color or sequence of color " 

4561 "specs. For a sequence of values to be color-mapped, use " 

4562 "the 'c' argument instead.") from err 

4563 if edgecolors is None: 

4564 edgecolors = kwcolor 

4565 if facecolors is None: 

4566 facecolors = kwcolor 

4567 

4568 if edgecolors is None and not mpl.rcParams['_internal.classic_mode']: 

4569 edgecolors = mpl.rcParams['scatter.edgecolors'] 

4570 

4571 c_was_none = c is None 

4572 if c is None: 

4573 c = (facecolors if facecolors is not None 

4574 else "b" if mpl.rcParams['_internal.classic_mode'] 

4575 else get_next_color_func()) 

4576 c_is_string_or_strings = ( 

4577 isinstance(c, str) 

4578 or (np.iterable(c) and len(c) > 0 

4579 and isinstance(cbook._safe_first_finite(c), str))) 

4580 

4581 def invalid_shape_exception(csize, xsize): 

4582 return ValueError( 

4583 f"'c' argument has {csize} elements, which is inconsistent " 

4584 f"with 'x' and 'y' with size {xsize}.") 

4585 

4586 c_is_mapped = False # Unless proven otherwise below. 

4587 valid_shape = True # Unless proven otherwise below. 

4588 if not c_was_none and kwcolor is None and not c_is_string_or_strings: 

4589 try: # First, does 'c' look suitable for value-mapping? 

4590 c = np.asanyarray(c, dtype=float) 

4591 except ValueError: 

4592 pass # Failed to convert to float array; must be color specs. 

4593 else: 

4594 # handle the documented special case of a 2D array with 1 

4595 # row which as RGB(A) to broadcast. 

4596 if c.shape == (1, 4) or c.shape == (1, 3): 

4597 c_is_mapped = False 

4598 if c.size != xsize: 

4599 valid_shape = False 

4600 # If c can be either mapped values or an RGB(A) color, prefer 

4601 # the former if shapes match, the latter otherwise. 

4602 elif c.size == xsize: 

4603 c = c.ravel() 

4604 c_is_mapped = True 

4605 else: # Wrong size; it must not be intended for mapping. 

4606 if c.shape in ((3,), (4,)): 

4607 _api.warn_external( 

4608 "*c* argument looks like a single numeric RGB or " 

4609 "RGBA sequence, which should be avoided as value-" 

4610 "mapping will have precedence in case its length " 

4611 "matches with *x* & *y*. Please use the *color* " 

4612 "keyword-argument or provide a 2D array " 

4613 "with a single row if you intend to specify " 

4614 "the same RGB or RGBA value for all points.") 

4615 valid_shape = False 

4616 if not c_is_mapped: 

4617 try: # Is 'c' acceptable as PathCollection facecolors? 

4618 colors = mcolors.to_rgba_array(c) 

4619 except (TypeError, ValueError) as err: 

4620 if "RGBA values should be within 0-1 range" in str(err): 

4621 raise 

4622 else: 

4623 if not valid_shape: 

4624 raise invalid_shape_exception(c.size, xsize) from err 

4625 # Both the mapping *and* the RGBA conversion failed: pretty 

4626 # severe failure => one may appreciate a verbose feedback. 

4627 raise ValueError( 

4628 f"'c' argument must be a color, a sequence of colors, " 

4629 f"or a sequence of numbers, not {c!r}") from err 

4630 else: 

4631 if len(colors) not in (0, 1, xsize): 

4632 # NB: remember that a single color is also acceptable. 

4633 # Besides *colors* will be an empty array if c == 'none'. 

4634 raise invalid_shape_exception(len(colors), xsize) 

4635 else: 

4636 colors = None # use cmap, norm after collection is created 

4637 return c, colors, edgecolors 

4638 

4639 @_preprocess_data(replace_names=["x", "y", "s", "linewidths", 

4640 "edgecolors", "c", "facecolor", 

4641 "facecolors", "color"], 

4642 label_namer="y") 

4643 @_docstring.interpd 

4644 def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, 

4645 vmin=None, vmax=None, alpha=None, linewidths=None, *, 

4646 edgecolors=None, plotnonfinite=False, **kwargs): 

4647 """ 

4648 A scatter plot of *y* vs. *x* with varying marker size and/or color. 

4649 

4650 Parameters 

4651 ---------- 

4652 x, y : float or array-like, shape (n, ) 

4653 The data positions. 

4654 

4655 s : float or array-like, shape (n, ), optional 

4656 The marker size in points**2 (typographic points are 1/72 in.). 

4657 Default is ``rcParams['lines.markersize'] ** 2``. 

4658 

4659 The linewidth and edgecolor can visually interact with the marker 

4660 size, and can lead to artifacts if the marker size is smaller than 

4661 the linewidth. 

4662 

4663 If the linewidth is greater than 0 and the edgecolor is anything 

4664 but *'none'*, then the effective size of the marker will be 

4665 increased by half the linewidth because the stroke will be centered 

4666 on the edge of the shape. 

4667 

4668 To eliminate the marker edge either set *linewidth=0* or 

4669 *edgecolor='none'*. 

4670 

4671 c : array-like or list of :mpltype:`color` or :mpltype:`color`, optional 

4672 The marker colors. Possible values: 

4673 

4674 - A scalar or sequence of n numbers to be mapped to colors using 

4675 *cmap* and *norm*. 

4676 - A 2D array in which the rows are RGB or RGBA. 

4677 - A sequence of colors of length n. 

4678 - A single color format string. 

4679 

4680 Note that *c* should not be a single numeric RGB or RGBA sequence 

4681 because that is indistinguishable from an array of values to be 

4682 colormapped. If you want to specify the same RGB or RGBA value for 

4683 all points, use a 2D array with a single row. Otherwise, 

4684 value-matching will have precedence in case of a size matching with 

4685 *x* and *y*. 

4686 

4687 If you wish to specify a single color for all points 

4688 prefer the *color* keyword argument. 

4689 

4690 Defaults to `None`. In that case the marker color is determined 

4691 by the value of *color*, *facecolor* or *facecolors*. In case 

4692 those are not specified or `None`, the marker color is determined 

4693 by the next color of the ``Axes``' current "shape and fill" color 

4694 cycle. This cycle defaults to :rc:`axes.prop_cycle`. 

4695 

4696 marker : `~.markers.MarkerStyle`, default: :rc:`scatter.marker` 

4697 The marker style. *marker* can be either an instance of the class 

4698 or the text shorthand for a particular marker. 

4699 See :mod:`matplotlib.markers` for more information about marker 

4700 styles. 

4701 

4702 %(cmap_doc)s 

4703 

4704 This parameter is ignored if *c* is RGB(A). 

4705 

4706 %(norm_doc)s 

4707 

4708 This parameter is ignored if *c* is RGB(A). 

4709 

4710 %(vmin_vmax_doc)s 

4711 

4712 This parameter is ignored if *c* is RGB(A). 

4713 

4714 alpha : float, default: None 

4715 The alpha blending value, between 0 (transparent) and 1 (opaque). 

4716 

4717 linewidths : float or array-like, default: :rc:`lines.linewidth` 

4718 The linewidth of the marker edges. Note: The default *edgecolors* 

4719 is 'face'. You may want to change this as well. 

4720 

4721 edgecolors : {'face', 'none', *None*} or :mpltype:`color` or list of \ 

4722:mpltype:`color`, default: :rc:`scatter.edgecolors` 

4723 The edge color of the marker. Possible values: 

4724 

4725 - 'face': The edge color will always be the same as the face color. 

4726 - 'none': No patch boundary will be drawn. 

4727 - A color or sequence of colors. 

4728 

4729 For non-filled markers, *edgecolors* is ignored. Instead, the color 

4730 is determined like with 'face', i.e. from *c*, *colors*, or 

4731 *facecolors*. 

4732 

4733 plotnonfinite : bool, default: False 

4734 Whether to plot points with nonfinite *c* (i.e. ``inf``, ``-inf`` 

4735 or ``nan``). If ``True`` the points are drawn with the *bad* 

4736 colormap color (see `.Colormap.set_bad`). 

4737 

4738 Returns 

4739 ------- 

4740 `~matplotlib.collections.PathCollection` 

4741 

4742 Other Parameters 

4743 ---------------- 

4744 data : indexable object, optional 

4745 DATA_PARAMETER_PLACEHOLDER 

4746 **kwargs : `~matplotlib.collections.Collection` properties 

4747 

4748 See Also 

4749 -------- 

4750 plot : To plot scatter plots when markers are identical in size and 

4751 color. 

4752 

4753 Notes 

4754 ----- 

4755 * The `.plot` function will be faster for scatterplots where markers 

4756 don't vary in size or color. 

4757 

4758 * Any or all of *x*, *y*, *s*, and *c* may be masked arrays, in which 

4759 case all masks will be combined and only unmasked points will be 

4760 plotted. 

4761 

4762 * Fundamentally, scatter works with 1D arrays; *x*, *y*, *s*, and *c* 

4763 may be input as N-D arrays, but within scatter they will be 

4764 flattened. The exception is *c*, which will be flattened only if its 

4765 size matches the size of *x* and *y*. 

4766 

4767 """ 

4768 # add edgecolors and linewidths to kwargs so they 

4769 # can be processed by normailze_kwargs 

4770 if edgecolors is not None: 

4771 kwargs.update({'edgecolors': edgecolors}) 

4772 if linewidths is not None: 

4773 kwargs.update({'linewidths': linewidths}) 

4774 

4775 kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection) 

4776 # re direct linewidth and edgecolor so it can be 

4777 # further processed by the rest of the function 

4778 linewidths = kwargs.pop('linewidth', None) 

4779 edgecolors = kwargs.pop('edgecolor', None) 

4780 # Process **kwargs to handle aliases, conflicts with explicit kwargs: 

4781 x, y = self._process_unit_info([("x", x), ("y", y)], kwargs) 

4782 # np.ma.ravel yields an ndarray, not a masked array, 

4783 # unless its argument is a masked array. 

4784 x = np.ma.ravel(x) 

4785 y = np.ma.ravel(y) 

4786 if x.size != y.size: 

4787 raise ValueError("x and y must be the same size") 

4788 

4789 if s is None: 

4790 s = (20 if mpl.rcParams['_internal.classic_mode'] else 

4791 mpl.rcParams['lines.markersize'] ** 2.0) 

4792 s = np.ma.ravel(s) 

4793 if (len(s) not in (1, x.size) or 

4794 (not np.issubdtype(s.dtype, np.floating) and 

4795 not np.issubdtype(s.dtype, np.integer))): 

4796 raise ValueError( 

4797 "s must be a scalar, " 

4798 "or float array-like with the same size as x and y") 

4799 

4800 # get the original edgecolor the user passed before we normalize 

4801 orig_edgecolor = edgecolors 

4802 if edgecolors is None: 

4803 orig_edgecolor = kwargs.get('edgecolor', None) 

4804 c, colors, edgecolors = \ 

4805 self._parse_scatter_color_args( 

4806 c, edgecolors, kwargs, x.size, 

4807 get_next_color_func=self._get_patches_for_fill.get_next_color) 

4808 

4809 if plotnonfinite and colors is None: 

4810 c = np.ma.masked_invalid(c) 

4811 x, y, s, edgecolors, linewidths = \ 

4812 cbook._combine_masks(x, y, s, edgecolors, linewidths) 

4813 else: 

4814 x, y, s, c, colors, edgecolors, linewidths = \ 

4815 cbook._combine_masks( 

4816 x, y, s, c, colors, edgecolors, linewidths) 

4817 # Unmask edgecolors if it was actually a single RGB or RGBA. 

4818 if (x.size in (3, 4) 

4819 and np.ma.is_masked(edgecolors) 

4820 and not np.ma.is_masked(orig_edgecolor)): 

4821 edgecolors = edgecolors.data 

4822 

4823 scales = s # Renamed for readability below. 

4824 

4825 # load default marker from rcParams 

4826 if marker is None: 

4827 marker = mpl.rcParams['scatter.marker'] 

4828 

4829 if isinstance(marker, mmarkers.MarkerStyle): 

4830 marker_obj = marker 

4831 else: 

4832 marker_obj = mmarkers.MarkerStyle(marker) 

4833 

4834 path = marker_obj.get_path().transformed( 

4835 marker_obj.get_transform()) 

4836 if not marker_obj.is_filled(): 

4837 if orig_edgecolor is not None: 

4838 _api.warn_external( 

4839 f"You passed a edgecolor/edgecolors ({orig_edgecolor!r}) " 

4840 f"for an unfilled marker ({marker!r}). Matplotlib is " 

4841 "ignoring the edgecolor in favor of the facecolor. This " 

4842 "behavior may change in the future." 

4843 ) 

4844 # We need to handle markers that cannot be filled (like 

4845 # '+' and 'x') differently than markers that can be 

4846 # filled, but have their fillstyle set to 'none'. This is 

4847 # to get: 

4848 # 

4849 # - respecting the fillestyle if set 

4850 # - maintaining back-compatibility for querying the facecolor of 

4851 # the un-fillable markers. 

4852 # 

4853 # While not an ideal situation, but is better than the 

4854 # alternatives. 

4855 if marker_obj.get_fillstyle() == 'none': 

4856 # promote the facecolor to be the edgecolor 

4857 edgecolors = colors 

4858 # set the facecolor to 'none' (at the last chance) because 

4859 # we cannot fill a path if the facecolor is non-null 

4860 # (which is defendable at the renderer level). 

4861 colors = 'none' 

4862 else: 

4863 # if we are not nulling the face color we can do this 

4864 # simpler 

4865 edgecolors = 'face' 

4866 

4867 if linewidths is None: 

4868 linewidths = mpl.rcParams['lines.linewidth'] 

4869 elif np.iterable(linewidths): 

4870 linewidths = [ 

4871 lw if lw is not None else mpl.rcParams['lines.linewidth'] 

4872 for lw in linewidths] 

4873 

4874 offsets = np.ma.column_stack([x, y]) 

4875 

4876 collection = mcoll.PathCollection( 

4877 (path,), scales, 

4878 facecolors=colors, 

4879 edgecolors=edgecolors, 

4880 linewidths=linewidths, 

4881 offsets=offsets, 

4882 offset_transform=kwargs.pop('transform', self.transData), 

4883 alpha=alpha, 

4884 ) 

4885 collection.set_transform(mtransforms.IdentityTransform()) 

4886 if colors is None: 

4887 collection.set_array(c) 

4888 collection.set_cmap(cmap) 

4889 collection.set_norm(norm) 

4890 collection._scale_norm(norm, vmin, vmax) 

4891 else: 

4892 extra_kwargs = { 

4893 'cmap': cmap, 'norm': norm, 'vmin': vmin, 'vmax': vmax 

4894 } 

4895 extra_keys = [k for k, v in extra_kwargs.items() if v is not None] 

4896 if any(extra_keys): 

4897 keys_str = ", ".join(f"'{k}'" for k in extra_keys) 

4898 _api.warn_external( 

4899 "No data for colormapping provided via 'c'. " 

4900 f"Parameters {keys_str} will be ignored") 

4901 collection._internal_update(kwargs) 

4902 

4903 # Classic mode only: 

4904 # ensure there are margins to allow for the 

4905 # finite size of the symbols. In v2.x, margins 

4906 # are present by default, so we disable this 

4907 # scatter-specific override. 

4908 if mpl.rcParams['_internal.classic_mode']: 

4909 if self._xmargin < 0.05 and x.size > 0: 

4910 self.set_xmargin(0.05) 

4911 if self._ymargin < 0.05 and x.size > 0: 

4912 self.set_ymargin(0.05) 

4913 

4914 self.add_collection(collection) 

4915 self._request_autoscale_view() 

4916 

4917 return collection 

4918 

4919 @_preprocess_data(replace_names=["x", "y", "C"], label_namer="y") 

4920 @_docstring.dedent_interpd 

4921 def hexbin(self, x, y, C=None, gridsize=100, bins=None, 

4922 xscale='linear', yscale='linear', extent=None, 

4923 cmap=None, norm=None, vmin=None, vmax=None, 

4924 alpha=None, linewidths=None, edgecolors='face', 

4925 reduce_C_function=np.mean, mincnt=None, marginals=False, 

4926 **kwargs): 

4927 """ 

4928 Make a 2D hexagonal binning plot of points *x*, *y*. 

4929 

4930 If *C* is *None*, the value of the hexagon is determined by the number 

4931 of points in the hexagon. Otherwise, *C* specifies values at the 

4932 coordinate (x[i], y[i]). For each hexagon, these values are reduced 

4933 using *reduce_C_function*. 

4934 

4935 Parameters 

4936 ---------- 

4937 x, y : array-like 

4938 The data positions. *x* and *y* must be of the same length. 

4939 

4940 C : array-like, optional 

4941 If given, these values are accumulated in the bins. Otherwise, 

4942 every point has a value of 1. Must be of the same length as *x* 

4943 and *y*. 

4944 

4945 gridsize : int or (int, int), default: 100 

4946 If a single int, the number of hexagons in the *x*-direction. 

4947 The number of hexagons in the *y*-direction is chosen such that 

4948 the hexagons are approximately regular. 

4949 

4950 Alternatively, if a tuple (*nx*, *ny*), the number of hexagons 

4951 in the *x*-direction and the *y*-direction. In the 

4952 *y*-direction, counting is done along vertically aligned 

4953 hexagons, not along the zig-zag chains of hexagons; see the 

4954 following illustration. 

4955 

4956 .. plot:: 

4957 

4958 import numpy 

4959 import matplotlib.pyplot as plt 

4960 

4961 np.random.seed(19680801) 

4962 n= 300 

4963 x = np.random.standard_normal(n) 

4964 y = np.random.standard_normal(n) 

4965 

4966 fig, ax = plt.subplots(figsize=(4, 4)) 

4967 h = ax.hexbin(x, y, gridsize=(5, 3)) 

4968 hx, hy = h.get_offsets().T 

4969 ax.plot(hx[24::3], hy[24::3], 'ro-') 

4970 ax.plot(hx[-3:], hy[-3:], 'ro-') 

4971 ax.set_title('gridsize=(5, 3)') 

4972 ax.axis('off') 

4973 

4974 To get approximately regular hexagons, choose 

4975 :math:`n_x = \\sqrt{3}\\,n_y`. 

4976 

4977 bins : 'log' or int or sequence, default: None 

4978 Discretization of the hexagon values. 

4979 

4980 - If *None*, no binning is applied; the color of each hexagon 

4981 directly corresponds to its count value. 

4982 - If 'log', use a logarithmic scale for the colormap. 

4983 Internally, :math:`log_{10}(i+1)` is used to determine the 

4984 hexagon color. This is equivalent to ``norm=LogNorm()``. 

4985 - If an integer, divide the counts in the specified number 

4986 of bins, and color the hexagons accordingly. 

4987 - If a sequence of values, the values of the lower bound of 

4988 the bins to be used. 

4989 

4990 xscale : {'linear', 'log'}, default: 'linear' 

4991 Use a linear or log10 scale on the horizontal axis. 

4992 

4993 yscale : {'linear', 'log'}, default: 'linear' 

4994 Use a linear or log10 scale on the vertical axis. 

4995 

4996 mincnt : int >= 0, default: *None* 

4997 If not *None*, only display cells with at least *mincnt* 

4998 number of points in the cell. 

4999 

5000 marginals : bool, default: *False* 

5001 If marginals is *True*, plot the marginal density as 

5002 colormapped rectangles along the bottom of the x-axis and 

5003 left of the y-axis. 

5004 

5005 extent : 4-tuple of float, default: *None* 

5006 The limits of the bins (xmin, xmax, ymin, ymax). 

5007 The default assigns the limits based on 

5008 *gridsize*, *x*, *y*, *xscale* and *yscale*. 

5009 

5010 If *xscale* or *yscale* is set to 'log', the limits are 

5011 expected to be the exponent for a power of 10. E.g. for 

5012 x-limits of 1 and 50 in 'linear' scale and y-limits 

5013 of 10 and 1000 in 'log' scale, enter (1, 50, 1, 3). 

5014 

5015 Returns 

5016 ------- 

5017 `~matplotlib.collections.PolyCollection` 

5018 A `.PolyCollection` defining the hexagonal bins. 

5019 

5020 - `.PolyCollection.get_offsets` contains a Mx2 array containing 

5021 the x, y positions of the M hexagon centers. 

5022 - `.PolyCollection.get_array` contains the values of the M 

5023 hexagons. 

5024 

5025 If *marginals* is *True*, horizontal 

5026 bar and vertical bar (both PolyCollections) will be attached 

5027 to the return collection as attributes *hbar* and *vbar*. 

5028 

5029 Other Parameters 

5030 ---------------- 

5031 %(cmap_doc)s 

5032 

5033 %(norm_doc)s 

5034 

5035 %(vmin_vmax_doc)s 

5036 

5037 alpha : float between 0 and 1, optional 

5038 The alpha blending value, between 0 (transparent) and 1 (opaque). 

5039 

5040 linewidths : float, default: *None* 

5041 If *None*, defaults to :rc:`patch.linewidth`. 

5042 

5043 edgecolors : {'face', 'none', *None*} or color, default: 'face' 

5044 The color of the hexagon edges. Possible values are: 

5045 

5046 - 'face': Draw the edges in the same color as the fill color. 

5047 - 'none': No edges are drawn. This can sometimes lead to unsightly 

5048 unpainted pixels between the hexagons. 

5049 - *None*: Draw outlines in the default color. 

5050 - An explicit color. 

5051 

5052 reduce_C_function : callable, default: `numpy.mean` 

5053 The function to aggregate *C* within the bins. It is ignored if 

5054 *C* is not given. This must have the signature:: 

5055 

5056 def reduce_C_function(C: array) -> float 

5057 

5058 Commonly used functions are: 

5059 

5060 - `numpy.mean`: average of the points 

5061 - `numpy.sum`: integral of the point values 

5062 - `numpy.amax`: value taken from the largest point 

5063 

5064 By default will only reduce cells with at least 1 point because some 

5065 reduction functions (such as `numpy.amax`) will error/warn with empty 

5066 input. Changing *mincnt* will adjust the cutoff, and if set to 0 will 

5067 pass empty input to the reduction function. 

5068 

5069 data : indexable object, optional 

5070 DATA_PARAMETER_PLACEHOLDER 

5071 

5072 **kwargs : `~matplotlib.collections.PolyCollection` properties 

5073 All other keyword arguments are passed on to `.PolyCollection`: 

5074 

5075 %(PolyCollection:kwdoc)s 

5076 

5077 See Also 

5078 -------- 

5079 hist2d : 2D histogram rectangular bins 

5080 """ 

5081 self._process_unit_info([("x", x), ("y", y)], kwargs, convert=False) 

5082 

5083 x, y, C = cbook.delete_masked_points(x, y, C) 

5084 

5085 # Set the size of the hexagon grid 

5086 if np.iterable(gridsize): 

5087 nx, ny = gridsize 

5088 else: 

5089 nx = gridsize 

5090 ny = int(nx / math.sqrt(3)) 

5091 # Count the number of data in each hexagon 

5092 x = np.asarray(x, float) 

5093 y = np.asarray(y, float) 

5094 

5095 # Will be log()'d if necessary, and then rescaled. 

5096 tx = x 

5097 ty = y 

5098 

5099 if xscale == 'log': 

5100 if np.any(x <= 0.0): 

5101 raise ValueError( 

5102 "x contains non-positive values, so cannot be log-scaled") 

5103 tx = np.log10(tx) 

5104 if yscale == 'log': 

5105 if np.any(y <= 0.0): 

5106 raise ValueError( 

5107 "y contains non-positive values, so cannot be log-scaled") 

5108 ty = np.log10(ty) 

5109 if extent is not None: 

5110 xmin, xmax, ymin, ymax = extent 

5111 if xmin > xmax: 

5112 raise ValueError("In extent, xmax must be greater than xmin") 

5113 if ymin > ymax: 

5114 raise ValueError("In extent, ymax must be greater than ymin") 

5115 else: 

5116 xmin, xmax = (tx.min(), tx.max()) if len(x) else (0, 1) 

5117 ymin, ymax = (ty.min(), ty.max()) if len(y) else (0, 1) 

5118 

5119 # to avoid issues with singular data, expand the min/max pairs 

5120 xmin, xmax = mtransforms.nonsingular(xmin, xmax, expander=0.1) 

5121 ymin, ymax = mtransforms.nonsingular(ymin, ymax, expander=0.1) 

5122 

5123 nx1 = nx + 1 

5124 ny1 = ny + 1 

5125 nx2 = nx 

5126 ny2 = ny 

5127 n = nx1 * ny1 + nx2 * ny2 

5128 

5129 # In the x-direction, the hexagons exactly cover the region from 

5130 # xmin to xmax. Need some padding to avoid roundoff errors. 

5131 padding = 1.e-9 * (xmax - xmin) 

5132 xmin -= padding 

5133 xmax += padding 

5134 sx = (xmax - xmin) / nx 

5135 sy = (ymax - ymin) / ny 

5136 # Positions in hexagon index coordinates. 

5137 ix = (tx - xmin) / sx 

5138 iy = (ty - ymin) / sy 

5139 ix1 = np.round(ix).astype(int) 

5140 iy1 = np.round(iy).astype(int) 

5141 ix2 = np.floor(ix).astype(int) 

5142 iy2 = np.floor(iy).astype(int) 

5143 # flat indices, plus one so that out-of-range points go to position 0. 

5144 i1 = np.where((0 <= ix1) & (ix1 < nx1) & (0 <= iy1) & (iy1 < ny1), 

5145 ix1 * ny1 + iy1 + 1, 0) 

5146 i2 = np.where((0 <= ix2) & (ix2 < nx2) & (0 <= iy2) & (iy2 < ny2), 

5147 ix2 * ny2 + iy2 + 1, 0) 

5148 

5149 d1 = (ix - ix1) ** 2 + 3.0 * (iy - iy1) ** 2 

5150 d2 = (ix - ix2 - 0.5) ** 2 + 3.0 * (iy - iy2 - 0.5) ** 2 

5151 bdist = (d1 < d2) 

5152 

5153 if C is None: # [1:] drops out-of-range points. 

5154 counts1 = np.bincount(i1[bdist], minlength=1 + nx1 * ny1)[1:] 

5155 counts2 = np.bincount(i2[~bdist], minlength=1 + nx2 * ny2)[1:] 

5156 accum = np.concatenate([counts1, counts2]).astype(float) 

5157 if mincnt is not None: 

5158 accum[accum < mincnt] = np.nan 

5159 C = np.ones(len(x)) 

5160 else: 

5161 # store the C values in a list per hexagon index 

5162 Cs_at_i1 = [[] for _ in range(1 + nx1 * ny1)] 

5163 Cs_at_i2 = [[] for _ in range(1 + nx2 * ny2)] 

5164 for i in range(len(x)): 

5165 if bdist[i]: 

5166 Cs_at_i1[i1[i]].append(C[i]) 

5167 else: 

5168 Cs_at_i2[i2[i]].append(C[i]) 

5169 if mincnt is None: 

5170 mincnt = 1 

5171 accum = np.array( 

5172 [reduce_C_function(acc) if len(acc) >= mincnt else np.nan 

5173 for Cs_at_i in [Cs_at_i1, Cs_at_i2] 

5174 for acc in Cs_at_i[1:]], # [1:] drops out-of-range points. 

5175 float) 

5176 

5177 good_idxs = ~np.isnan(accum) 

5178 

5179 offsets = np.zeros((n, 2), float) 

5180 offsets[:nx1 * ny1, 0] = np.repeat(np.arange(nx1), ny1) 

5181 offsets[:nx1 * ny1, 1] = np.tile(np.arange(ny1), nx1) 

5182 offsets[nx1 * ny1:, 0] = np.repeat(np.arange(nx2) + 0.5, ny2) 

5183 offsets[nx1 * ny1:, 1] = np.tile(np.arange(ny2), nx2) + 0.5 

5184 offsets[:, 0] *= sx 

5185 offsets[:, 1] *= sy 

5186 offsets[:, 0] += xmin 

5187 offsets[:, 1] += ymin 

5188 # remove accumulation bins with no data 

5189 offsets = offsets[good_idxs, :] 

5190 accum = accum[good_idxs] 

5191 

5192 polygon = [sx, sy / 3] * np.array( 

5193 [[.5, -.5], [.5, .5], [0., 1.], [-.5, .5], [-.5, -.5], [0., -1.]]) 

5194 

5195 if linewidths is None: 

5196 linewidths = [mpl.rcParams['patch.linewidth']] 

5197 

5198 if xscale == 'log' or yscale == 'log': 

5199 polygons = np.expand_dims(polygon, 0) + np.expand_dims(offsets, 1) 

5200 if xscale == 'log': 

5201 polygons[:, :, 0] = 10.0 ** polygons[:, :, 0] 

5202 xmin = 10.0 ** xmin 

5203 xmax = 10.0 ** xmax 

5204 self.set_xscale(xscale) 

5205 if yscale == 'log': 

5206 polygons[:, :, 1] = 10.0 ** polygons[:, :, 1] 

5207 ymin = 10.0 ** ymin 

5208 ymax = 10.0 ** ymax 

5209 self.set_yscale(yscale) 

5210 collection = mcoll.PolyCollection( 

5211 polygons, 

5212 edgecolors=edgecolors, 

5213 linewidths=linewidths, 

5214 ) 

5215 else: 

5216 collection = mcoll.PolyCollection( 

5217 [polygon], 

5218 edgecolors=edgecolors, 

5219 linewidths=linewidths, 

5220 offsets=offsets, 

5221 offset_transform=mtransforms.AffineDeltaTransform( 

5222 self.transData), 

5223 ) 

5224 

5225 # Set normalizer if bins is 'log' 

5226 if cbook._str_equal(bins, 'log'): 

5227 if norm is not None: 

5228 _api.warn_external("Only one of 'bins' and 'norm' arguments " 

5229 f"can be supplied, ignoring {bins=}") 

5230 else: 

5231 norm = mcolors.LogNorm(vmin=vmin, vmax=vmax) 

5232 vmin = vmax = None 

5233 bins = None 

5234 

5235 # autoscale the norm with current accum values if it hasn't been set 

5236 if norm is not None: 

5237 if norm.vmin is None and norm.vmax is None: 

5238 norm.autoscale(accum) 

5239 

5240 if bins is not None: 

5241 if not np.iterable(bins): 

5242 minimum, maximum = min(accum), max(accum) 

5243 bins -= 1 # one less edge than bins 

5244 bins = minimum + (maximum - minimum) * np.arange(bins) / bins 

5245 bins = np.sort(bins) 

5246 accum = bins.searchsorted(accum) 

5247 

5248 collection.set_array(accum) 

5249 collection.set_cmap(cmap) 

5250 collection.set_norm(norm) 

5251 collection.set_alpha(alpha) 

5252 collection._internal_update(kwargs) 

5253 collection._scale_norm(norm, vmin, vmax) 

5254 

5255 corners = ((xmin, ymin), (xmax, ymax)) 

5256 self.update_datalim(corners) 

5257 self._request_autoscale_view(tight=True) 

5258 

5259 # add the collection last 

5260 self.add_collection(collection, autolim=False) 

5261 if not marginals: 

5262 return collection 

5263 

5264 # Process marginals 

5265 bars = [] 

5266 for zname, z, zmin, zmax, zscale, nbins in [ 

5267 ("x", x, xmin, xmax, xscale, nx), 

5268 ("y", y, ymin, ymax, yscale, 2 * ny), 

5269 ]: 

5270 

5271 if zscale == "log": 

5272 bin_edges = np.geomspace(zmin, zmax, nbins + 1) 

5273 else: 

5274 bin_edges = np.linspace(zmin, zmax, nbins + 1) 

5275 

5276 verts = np.empty((nbins, 4, 2)) 

5277 verts[:, 0, 0] = verts[:, 1, 0] = bin_edges[:-1] 

5278 verts[:, 2, 0] = verts[:, 3, 0] = bin_edges[1:] 

5279 verts[:, 0, 1] = verts[:, 3, 1] = .00 

5280 verts[:, 1, 1] = verts[:, 2, 1] = .05 

5281 if zname == "y": 

5282 verts = verts[:, :, ::-1] # Swap x and y. 

5283 

5284 # Sort z-values into bins defined by bin_edges. 

5285 bin_idxs = np.searchsorted(bin_edges, z) - 1 

5286 values = np.empty(nbins) 

5287 for i in range(nbins): 

5288 # Get C-values for each bin, and compute bin value with 

5289 # reduce_C_function. 

5290 ci = C[bin_idxs == i] 

5291 values[i] = reduce_C_function(ci) if len(ci) > 0 else np.nan 

5292 

5293 mask = ~np.isnan(values) 

5294 verts = verts[mask] 

5295 values = values[mask] 

5296 

5297 trans = getattr(self, f"get_{zname}axis_transform")(which="grid") 

5298 bar = mcoll.PolyCollection( 

5299 verts, transform=trans, edgecolors="face") 

5300 bar.set_array(values) 

5301 bar.set_cmap(cmap) 

5302 bar.set_norm(norm) 

5303 bar.set_alpha(alpha) 

5304 bar._internal_update(kwargs) 

5305 bars.append(self.add_collection(bar, autolim=False)) 

5306 

5307 collection.hbar, collection.vbar = bars 

5308 

5309 def on_changed(collection): 

5310 collection.hbar.set_cmap(collection.get_cmap()) 

5311 collection.hbar.set_cmap(collection.get_cmap()) 

5312 collection.vbar.set_clim(collection.get_clim()) 

5313 collection.vbar.set_clim(collection.get_clim()) 

5314 

5315 collection.callbacks.connect('changed', on_changed) 

5316 

5317 return collection 

5318 

5319 @_docstring.dedent_interpd 

5320 def arrow(self, x, y, dx, dy, **kwargs): 

5321 """ 

5322 Add an arrow to the Axes. 

5323 

5324 This draws an arrow from ``(x, y)`` to ``(x+dx, y+dy)``. 

5325 

5326 Parameters 

5327 ---------- 

5328 %(FancyArrow)s 

5329 

5330 Returns 

5331 ------- 

5332 `.FancyArrow` 

5333 The created `.FancyArrow` object. 

5334 

5335 Notes 

5336 ----- 

5337 The resulting arrow is affected by the Axes aspect ratio and limits. 

5338 This may produce an arrow whose head is not square with its stem. To 

5339 create an arrow whose head is square with its stem, 

5340 use :meth:`annotate` for example: 

5341 

5342 >>> ax.annotate("", xy=(0.5, 0.5), xytext=(0, 0), 

5343 ... arrowprops=dict(arrowstyle="->")) 

5344 

5345 """ 

5346 # Strip away units for the underlying patch since units 

5347 # do not make sense to most patch-like code 

5348 x = self.convert_xunits(x) 

5349 y = self.convert_yunits(y) 

5350 dx = self.convert_xunits(dx) 

5351 dy = self.convert_yunits(dy) 

5352 

5353 a = mpatches.FancyArrow(x, y, dx, dy, **kwargs) 

5354 self.add_patch(a) 

5355 self._request_autoscale_view() 

5356 return a 

5357 

5358 @_docstring.copy(mquiver.QuiverKey.__init__) 

5359 def quiverkey(self, Q, X, Y, U, label, **kwargs): 

5360 qk = mquiver.QuiverKey(Q, X, Y, U, label, **kwargs) 

5361 self.add_artist(qk) 

5362 return qk 

5363 

5364 # Handle units for x and y, if they've been passed 

5365 def _quiver_units(self, args, kwargs): 

5366 if len(args) > 3: 

5367 x, y = args[0:2] 

5368 x, y = self._process_unit_info([("x", x), ("y", y)], kwargs) 

5369 return (x, y) + args[2:] 

5370 return args 

5371 

5372 # args can be a combination of X, Y, U, V, C and all should be replaced 

5373 @_preprocess_data() 

5374 @_docstring.dedent_interpd 

5375 def quiver(self, *args, **kwargs): 

5376 """%(quiver_doc)s""" 

5377 # Make sure units are handled for x and y values 

5378 args = self._quiver_units(args, kwargs) 

5379 q = mquiver.Quiver(self, *args, **kwargs) 

5380 self.add_collection(q, autolim=True) 

5381 self._request_autoscale_view() 

5382 return q 

5383 

5384 # args can be some combination of X, Y, U, V, C and all should be replaced 

5385 @_preprocess_data() 

5386 @_docstring.dedent_interpd 

5387 def barbs(self, *args, **kwargs): 

5388 """%(barbs_doc)s""" 

5389 # Make sure units are handled for x and y values 

5390 args = self._quiver_units(args, kwargs) 

5391 b = mquiver.Barbs(self, *args, **kwargs) 

5392 self.add_collection(b, autolim=True) 

5393 self._request_autoscale_view() 

5394 return b 

5395 

5396 # Uses a custom implementation of data-kwarg handling in 

5397 # _process_plot_var_args. 

5398 def fill(self, *args, data=None, **kwargs): 

5399 """ 

5400 Plot filled polygons. 

5401 

5402 Parameters 

5403 ---------- 

5404 *args : sequence of x, y, [color] 

5405 Each polygon is defined by the lists of *x* and *y* positions of 

5406 its nodes, optionally followed by a *color* specifier. See 

5407 :mod:`matplotlib.colors` for supported color specifiers. The 

5408 standard color cycle is used for polygons without a color 

5409 specifier. 

5410 

5411 You can plot multiple polygons by providing multiple *x*, *y*, 

5412 *[color]* groups. 

5413 

5414 For example, each of the following is legal:: 

5415 

5416 ax.fill(x, y) # a polygon with default color 

5417 ax.fill(x, y, "b") # a blue polygon 

5418 ax.fill(x, y, x2, y2) # two polygons 

5419 ax.fill(x, y, "b", x2, y2, "r") # a blue and a red polygon 

5420 

5421 data : indexable object, optional 

5422 An object with labelled data. If given, provide the label names to 

5423 plot in *x* and *y*, e.g.:: 

5424 

5425 ax.fill("time", "signal", 

5426 data={"time": [0, 1, 2], "signal": [0, 1, 0]}) 

5427 

5428 Returns 

5429 ------- 

5430 list of `~matplotlib.patches.Polygon` 

5431 

5432 Other Parameters 

5433 ---------------- 

5434 **kwargs : `~matplotlib.patches.Polygon` properties 

5435 

5436 Notes 

5437 ----- 

5438 Use :meth:`fill_between` if you would like to fill the region between 

5439 two curves. 

5440 """ 

5441 # For compatibility(!), get aliases from Line2D rather than Patch. 

5442 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D) 

5443 # _get_patches_for_fill returns a generator, convert it to a list. 

5444 patches = [*self._get_patches_for_fill(self, *args, data=data, **kwargs)] 

5445 for poly in patches: 

5446 self.add_patch(poly) 

5447 self._request_autoscale_view() 

5448 return patches 

5449 

5450 def _fill_between_x_or_y( 

5451 self, ind_dir, ind, dep1, dep2=0, *, 

5452 where=None, interpolate=False, step=None, **kwargs): 

5453 # Common implementation between fill_between (*ind_dir*="x") and 

5454 # fill_betweenx (*ind_dir*="y"). *ind* is the independent variable, 

5455 # *dep* the dependent variable. The docstring below is interpolated 

5456 # to generate both methods' docstrings. 

5457 """ 

5458 Fill the area between two {dir} curves. 

5459 

5460 The curves are defined by the points (*{ind}*, *{dep}1*) and (*{ind}*, 

5461 *{dep}2*). This creates one or multiple polygons describing the filled 

5462 area. 

5463 

5464 You may exclude some {dir} sections from filling using *where*. 

5465 

5466 By default, the edges connect the given points directly. Use *step* 

5467 if the filling should be a step function, i.e. constant in between 

5468 *{ind}*. 

5469 

5470 Parameters 

5471 ---------- 

5472 {ind} : array (length N) 

5473 The {ind} coordinates of the nodes defining the curves. 

5474 

5475 {dep}1 : array (length N) or scalar 

5476 The {dep} coordinates of the nodes defining the first curve. 

5477 

5478 {dep}2 : array (length N) or scalar, default: 0 

5479 The {dep} coordinates of the nodes defining the second curve. 

5480 

5481 where : array of bool (length N), optional 

5482 Define *where* to exclude some {dir} regions from being filled. 

5483 The filled regions are defined by the coordinates ``{ind}[where]``. 

5484 More precisely, fill between ``{ind}[i]`` and ``{ind}[i+1]`` if 

5485 ``where[i] and where[i+1]``. Note that this definition implies 

5486 that an isolated *True* value between two *False* values in *where* 

5487 will not result in filling. Both sides of the *True* position 

5488 remain unfilled due to the adjacent *False* values. 

5489 

5490 interpolate : bool, default: False 

5491 This option is only relevant if *where* is used and the two curves 

5492 are crossing each other. 

5493 

5494 Semantically, *where* is often used for *{dep}1* > *{dep}2* or 

5495 similar. By default, the nodes of the polygon defining the filled 

5496 region will only be placed at the positions in the *{ind}* array. 

5497 Such a polygon cannot describe the above semantics close to the 

5498 intersection. The {ind}-sections containing the intersection are 

5499 simply clipped. 

5500 

5501 Setting *interpolate* to *True* will calculate the actual 

5502 intersection point and extend the filled region up to this point. 

5503 

5504 step : {{'pre', 'post', 'mid'}}, optional 

5505 Define *step* if the filling should be a step function, 

5506 i.e. constant in between *{ind}*. The value determines where the 

5507 step will occur: 

5508 

5509 - 'pre': The y value is continued constantly to the left from 

5510 every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the 

5511 value ``y[i]``. 

5512 - 'post': The y value is continued constantly to the right from 

5513 every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the 

5514 value ``y[i]``. 

5515 - 'mid': Steps occur half-way between the *x* positions. 

5516 

5517 Returns 

5518 ------- 

5519 `.PolyCollection` 

5520 A `.PolyCollection` containing the plotted polygons. 

5521 

5522 Other Parameters 

5523 ---------------- 

5524 data : indexable object, optional 

5525 DATA_PARAMETER_PLACEHOLDER 

5526 

5527 **kwargs 

5528 All other keyword arguments are passed on to `.PolyCollection`. 

5529 They control the `.Polygon` properties: 

5530 

5531 %(PolyCollection:kwdoc)s 

5532 

5533 See Also 

5534 -------- 

5535 fill_between : Fill between two sets of y-values. 

5536 fill_betweenx : Fill between two sets of x-values. 

5537 """ 

5538 

5539 dep_dir = {"x": "y", "y": "x"}[ind_dir] 

5540 

5541 if not mpl.rcParams["_internal.classic_mode"]: 

5542 kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection) 

5543 if not any(c in kwargs for c in ("color", "facecolor")): 

5544 kwargs["facecolor"] = \ 

5545 self._get_patches_for_fill.get_next_color() 

5546 

5547 # Handle united data, such as dates 

5548 ind, dep1, dep2 = map( 

5549 ma.masked_invalid, self._process_unit_info( 

5550 [(ind_dir, ind), (dep_dir, dep1), (dep_dir, dep2)], kwargs)) 

5551 

5552 for name, array in [ 

5553 (ind_dir, ind), (f"{dep_dir}1", dep1), (f"{dep_dir}2", dep2)]: 

5554 if array.ndim > 1: 

5555 raise ValueError(f"{name!r} is not 1-dimensional") 

5556 

5557 if where is None: 

5558 where = True 

5559 else: 

5560 where = np.asarray(where, dtype=bool) 

5561 if where.size != ind.size: 

5562 raise ValueError(f"where size ({where.size}) does not match " 

5563 f"{ind_dir} size ({ind.size})") 

5564 where = where & ~functools.reduce( 

5565 np.logical_or, map(np.ma.getmaskarray, [ind, dep1, dep2])) 

5566 

5567 ind, dep1, dep2 = np.broadcast_arrays( 

5568 np.atleast_1d(ind), dep1, dep2, subok=True) 

5569 

5570 polys = [] 

5571 for idx0, idx1 in cbook.contiguous_regions(where): 

5572 indslice = ind[idx0:idx1] 

5573 dep1slice = dep1[idx0:idx1] 

5574 dep2slice = dep2[idx0:idx1] 

5575 if step is not None: 

5576 step_func = cbook.STEP_LOOKUP_MAP["steps-" + step] 

5577 indslice, dep1slice, dep2slice = \ 

5578 step_func(indslice, dep1slice, dep2slice) 

5579 

5580 if not len(indslice): 

5581 continue 

5582 

5583 N = len(indslice) 

5584 pts = np.zeros((2 * N + 2, 2)) 

5585 

5586 if interpolate: 

5587 def get_interp_point(idx): 

5588 im1 = max(idx - 1, 0) 

5589 ind_values = ind[im1:idx+1] 

5590 diff_values = dep1[im1:idx+1] - dep2[im1:idx+1] 

5591 dep1_values = dep1[im1:idx+1] 

5592 

5593 if len(diff_values) == 2: 

5594 if np.ma.is_masked(diff_values[1]): 

5595 return ind[im1], dep1[im1] 

5596 elif np.ma.is_masked(diff_values[0]): 

5597 return ind[idx], dep1[idx] 

5598 

5599 diff_order = diff_values.argsort() 

5600 diff_root_ind = np.interp( 

5601 0, diff_values[diff_order], ind_values[diff_order]) 

5602 ind_order = ind_values.argsort() 

5603 diff_root_dep = np.interp( 

5604 diff_root_ind, 

5605 ind_values[ind_order], dep1_values[ind_order]) 

5606 return diff_root_ind, diff_root_dep 

5607 

5608 start = get_interp_point(idx0) 

5609 end = get_interp_point(idx1) 

5610 else: 

5611 # Handle scalar dep2 (e.g. 0): the fill should go all 

5612 # the way down to 0 even if none of the dep1 sample points do. 

5613 start = indslice[0], dep2slice[0] 

5614 end = indslice[-1], dep2slice[-1] 

5615 

5616 pts[0] = start 

5617 pts[N + 1] = end 

5618 

5619 pts[1:N+1, 0] = indslice 

5620 pts[1:N+1, 1] = dep1slice 

5621 pts[N+2:, 0] = indslice[::-1] 

5622 pts[N+2:, 1] = dep2slice[::-1] 

5623 

5624 if ind_dir == "y": 

5625 pts = pts[:, ::-1] 

5626 

5627 polys.append(pts) 

5628 

5629 collection = mcoll.PolyCollection(polys, **kwargs) 

5630 

5631 # now update the datalim and autoscale 

5632 pts = np.vstack([np.hstack([ind[where, None], dep1[where, None]]), 

5633 np.hstack([ind[where, None], dep2[where, None]])]) 

5634 if ind_dir == "y": 

5635 pts = pts[:, ::-1] 

5636 

5637 up_x = up_y = True 

5638 if "transform" in kwargs: 

5639 up_x, up_y = kwargs["transform"].contains_branch_seperately(self.transData) 

5640 self.update_datalim(pts, updatex=up_x, updatey=up_y) 

5641 

5642 self.add_collection(collection, autolim=False) 

5643 self._request_autoscale_view() 

5644 return collection 

5645 

5646 def fill_between(self, x, y1, y2=0, where=None, interpolate=False, 

5647 step=None, **kwargs): 

5648 return self._fill_between_x_or_y( 

5649 "x", x, y1, y2, 

5650 where=where, interpolate=interpolate, step=step, **kwargs) 

5651 

5652 if _fill_between_x_or_y.__doc__: 

5653 fill_between.__doc__ = _fill_between_x_or_y.__doc__.format( 

5654 dir="horizontal", ind="x", dep="y" 

5655 ) 

5656 fill_between = _preprocess_data( 

5657 _docstring.dedent_interpd(fill_between), 

5658 replace_names=["x", "y1", "y2", "where"]) 

5659 

5660 def fill_betweenx(self, y, x1, x2=0, where=None, 

5661 step=None, interpolate=False, **kwargs): 

5662 return self._fill_between_x_or_y( 

5663 "y", y, x1, x2, 

5664 where=where, interpolate=interpolate, step=step, **kwargs) 

5665 

5666 if _fill_between_x_or_y.__doc__: 

5667 fill_betweenx.__doc__ = _fill_between_x_or_y.__doc__.format( 

5668 dir="vertical", ind="y", dep="x" 

5669 ) 

5670 fill_betweenx = _preprocess_data( 

5671 _docstring.dedent_interpd(fill_betweenx), 

5672 replace_names=["y", "x1", "x2", "where"]) 

5673 

5674 #### plotting z(x, y): imshow, pcolor and relatives, contour 

5675 

5676 @_preprocess_data() 

5677 @_docstring.interpd 

5678 def imshow(self, X, cmap=None, norm=None, *, aspect=None, 

5679 interpolation=None, alpha=None, 

5680 vmin=None, vmax=None, origin=None, extent=None, 

5681 interpolation_stage=None, filternorm=True, filterrad=4.0, 

5682 resample=None, url=None, **kwargs): 

5683 """ 

5684 Display data as an image, i.e., on a 2D regular raster. 

5685 

5686 The input may either be actual RGB(A) data, or 2D scalar data, which 

5687 will be rendered as a pseudocolor image. For displaying a grayscale 

5688 image, set up the colormapping using the parameters 

5689 ``cmap='gray', vmin=0, vmax=255``. 

5690 

5691 The number of pixels used to render an image is set by the Axes size 

5692 and the figure *dpi*. This can lead to aliasing artifacts when 

5693 the image is resampled, because the displayed image size will usually 

5694 not match the size of *X* (see 

5695 :doc:`/gallery/images_contours_and_fields/image_antialiasing`). 

5696 The resampling can be controlled via the *interpolation* parameter 

5697 and/or :rc:`image.interpolation`. 

5698 

5699 Parameters 

5700 ---------- 

5701 X : array-like or PIL image 

5702 The image data. Supported array shapes are: 

5703 

5704 - (M, N): an image with scalar data. The values are mapped to 

5705 colors using normalization and a colormap. See parameters *norm*, 

5706 *cmap*, *vmin*, *vmax*. 

5707 - (M, N, 3): an image with RGB values (0-1 float or 0-255 int). 

5708 - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int), 

5709 i.e. including transparency. 

5710 

5711 The first two dimensions (M, N) define the rows and columns of 

5712 the image. 

5713 

5714 Out-of-range RGB(A) values are clipped. 

5715 

5716 %(cmap_doc)s 

5717 

5718 This parameter is ignored if *X* is RGB(A). 

5719 

5720 %(norm_doc)s 

5721 

5722 This parameter is ignored if *X* is RGB(A). 

5723 

5724 %(vmin_vmax_doc)s 

5725 

5726 This parameter is ignored if *X* is RGB(A). 

5727 

5728 aspect : {'equal', 'auto'} or float or None, default: None 

5729 The aspect ratio of the Axes. This parameter is particularly 

5730 relevant for images since it determines whether data pixels are 

5731 square. 

5732 

5733 This parameter is a shortcut for explicitly calling 

5734 `.Axes.set_aspect`. See there for further details. 

5735 

5736 - 'equal': Ensures an aspect ratio of 1. Pixels will be square 

5737 (unless pixel sizes are explicitly made non-square in data 

5738 coordinates using *extent*). 

5739 - 'auto': The Axes is kept fixed and the aspect is adjusted so 

5740 that the data fit in the Axes. In general, this will result in 

5741 non-square pixels. 

5742 

5743 Normally, None (the default) means to use :rc:`image.aspect`. However, if 

5744 the image uses a transform that does not contain the axes data transform, 

5745 then None means to not modify the axes aspect at all (in that case, directly 

5746 call `.Axes.set_aspect` if desired). 

5747 

5748 interpolation : str, default: :rc:`image.interpolation` 

5749 The interpolation method used. 

5750 

5751 Supported values are 'none', 'antialiased', 'nearest', 'bilinear', 

5752 'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 

5753 'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 

5754 'sinc', 'lanczos', 'blackman'. 

5755 

5756 The data *X* is resampled to the pixel size of the image on the 

5757 figure canvas, using the interpolation method to either up- or 

5758 downsample the data. 

5759 

5760 If *interpolation* is 'none', then for the ps, pdf, and svg 

5761 backends no down- or upsampling occurs, and the image data is 

5762 passed to the backend as a native image. Note that different ps, 

5763 pdf, and svg viewers may display these raw pixels differently. On 

5764 other backends, 'none' is the same as 'nearest'. 

5765 

5766 If *interpolation* is the default 'antialiased', then 'nearest' 

5767 interpolation is used if the image is upsampled by more than a 

5768 factor of three (i.e. the number of display pixels is at least 

5769 three times the size of the data array). If the upsampling rate is 

5770 smaller than 3, or the image is downsampled, then 'hanning' 

5771 interpolation is used to act as an anti-aliasing filter, unless the 

5772 image happens to be upsampled by exactly a factor of two or one. 

5773 

5774 See 

5775 :doc:`/gallery/images_contours_and_fields/interpolation_methods` 

5776 for an overview of the supported interpolation methods, and 

5777 :doc:`/gallery/images_contours_and_fields/image_antialiasing` for 

5778 a discussion of image antialiasing. 

5779 

5780 Some interpolation methods require an additional radius parameter, 

5781 which can be set by *filterrad*. Additionally, the antigrain image 

5782 resize filter is controlled by the parameter *filternorm*. 

5783 

5784 interpolation_stage : {'data', 'rgba'}, default: 'data' 

5785 If 'data', interpolation 

5786 is carried out on the data provided by the user. If 'rgba', the 

5787 interpolation is carried out after the colormapping has been 

5788 applied (visual interpolation). 

5789 

5790 alpha : float or array-like, optional 

5791 The alpha blending value, between 0 (transparent) and 1 (opaque). 

5792 If *alpha* is an array, the alpha blending values are applied pixel 

5793 by pixel, and *alpha* must have the same shape as *X*. 

5794 

5795 origin : {'upper', 'lower'}, default: :rc:`image.origin` 

5796 Place the [0, 0] index of the array in the upper left or lower 

5797 left corner of the Axes. The convention (the default) 'upper' is 

5798 typically used for matrices and images. 

5799 

5800 Note that the vertical axis points upward for 'lower' 

5801 but downward for 'upper'. 

5802 

5803 See the :ref:`imshow_extent` tutorial for 

5804 examples and a more detailed description. 

5805 

5806 extent : floats (left, right, bottom, top), optional 

5807 The bounding box in data coordinates that the image will fill. 

5808 These values may be unitful and match the units of the Axes. 

5809 The image is stretched individually along x and y to fill the box. 

5810 

5811 The default extent is determined by the following conditions. 

5812 Pixels have unit size in data coordinates. Their centers are on 

5813 integer coordinates, and their center coordinates range from 0 to 

5814 columns-1 horizontally and from 0 to rows-1 vertically. 

5815 

5816 Note that the direction of the vertical axis and thus the default 

5817 values for top and bottom depend on *origin*: 

5818 

5819 - For ``origin == 'upper'`` the default is 

5820 ``(-0.5, numcols-0.5, numrows-0.5, -0.5)``. 

5821 - For ``origin == 'lower'`` the default is 

5822 ``(-0.5, numcols-0.5, -0.5, numrows-0.5)``. 

5823 

5824 See the :ref:`imshow_extent` tutorial for 

5825 examples and a more detailed description. 

5826 

5827 filternorm : bool, default: True 

5828 A parameter for the antigrain image resize filter (see the 

5829 antigrain documentation). If *filternorm* is set, the filter 

5830 normalizes integer values and corrects the rounding errors. It 

5831 doesn't do anything with the source floating point values, it 

5832 corrects only integers according to the rule of 1.0 which means 

5833 that any sum of pixel weights must be equal to 1.0. So, the 

5834 filter function must produce a graph of the proper shape. 

5835 

5836 filterrad : float > 0, default: 4.0 

5837 The filter radius for filters that have a radius parameter, i.e. 

5838 when interpolation is one of: 'sinc', 'lanczos' or 'blackman'. 

5839 

5840 resample : bool, default: :rc:`image.resample` 

5841 When *True*, use a full resampling method. When *False*, only 

5842 resample when the output image is larger than the input image. 

5843 

5844 url : str, optional 

5845 Set the url of the created `.AxesImage`. See `.Artist.set_url`. 

5846 

5847 Returns 

5848 ------- 

5849 `~matplotlib.image.AxesImage` 

5850 

5851 Other Parameters 

5852 ---------------- 

5853 data : indexable object, optional 

5854 DATA_PARAMETER_PLACEHOLDER 

5855 

5856 **kwargs : `~matplotlib.artist.Artist` properties 

5857 These parameters are passed on to the constructor of the 

5858 `.AxesImage` artist. 

5859 

5860 See Also 

5861 -------- 

5862 matshow : Plot a matrix or an array as an image. 

5863 

5864 Notes 

5865 ----- 

5866 Unless *extent* is used, pixel centers will be located at integer 

5867 coordinates. In other words: the origin will coincide with the center 

5868 of pixel (0, 0). 

5869 

5870 There are two common representations for RGB images with an alpha 

5871 channel: 

5872 

5873 - Straight (unassociated) alpha: R, G, and B channels represent the 

5874 color of the pixel, disregarding its opacity. 

5875 - Premultiplied (associated) alpha: R, G, and B channels represent 

5876 the color of the pixel, adjusted for its opacity by multiplication. 

5877 

5878 `~matplotlib.pyplot.imshow` expects RGB images adopting the straight 

5879 (unassociated) alpha representation. 

5880 """ 

5881 im = mimage.AxesImage(self, cmap=cmap, norm=norm, 

5882 interpolation=interpolation, origin=origin, 

5883 extent=extent, filternorm=filternorm, 

5884 filterrad=filterrad, resample=resample, 

5885 interpolation_stage=interpolation_stage, 

5886 **kwargs) 

5887 

5888 if aspect is None and not ( 

5889 im.is_transform_set() 

5890 and not im.get_transform().contains_branch(self.transData)): 

5891 aspect = mpl.rcParams['image.aspect'] 

5892 if aspect is not None: 

5893 self.set_aspect(aspect) 

5894 

5895 im.set_data(X) 

5896 im.set_alpha(alpha) 

5897 if im.get_clip_path() is None: 

5898 # image does not already have clipping set, clip to Axes patch 

5899 im.set_clip_path(self.patch) 

5900 im._scale_norm(norm, vmin, vmax) 

5901 im.set_url(url) 

5902 

5903 # update ax.dataLim, and, if autoscaling, set viewLim 

5904 # to tightly fit the image, regardless of dataLim. 

5905 im.set_extent(im.get_extent()) 

5906 

5907 self.add_image(im) 

5908 return im 

5909 

5910 def _pcolorargs(self, funcname, *args, shading='auto', **kwargs): 

5911 # - create X and Y if not present; 

5912 # - reshape X and Y as needed if they are 1-D; 

5913 # - check for proper sizes based on `shading` kwarg; 

5914 # - reset shading if shading='auto' to flat or nearest 

5915 # depending on size; 

5916 

5917 _valid_shading = ['gouraud', 'nearest', 'flat', 'auto'] 

5918 try: 

5919 _api.check_in_list(_valid_shading, shading=shading) 

5920 except ValueError: 

5921 _api.warn_external(f"shading value '{shading}' not in list of " 

5922 f"valid values {_valid_shading}. Setting " 

5923 "shading='auto'.") 

5924 shading = 'auto' 

5925 

5926 if len(args) == 1: 

5927 C = np.asanyarray(args[0]) 

5928 nrows, ncols = C.shape[:2] 

5929 if shading in ['gouraud', 'nearest']: 

5930 X, Y = np.meshgrid(np.arange(ncols), np.arange(nrows)) 

5931 else: 

5932 X, Y = np.meshgrid(np.arange(ncols + 1), np.arange(nrows + 1)) 

5933 shading = 'flat' 

5934 C = cbook.safe_masked_invalid(C, copy=True) 

5935 return X, Y, C, shading 

5936 

5937 if len(args) == 3: 

5938 # Check x and y for bad data... 

5939 C = np.asanyarray(args[2]) 

5940 # unit conversion allows e.g. datetime objects as axis values 

5941 X, Y = args[:2] 

5942 X, Y = self._process_unit_info([("x", X), ("y", Y)], kwargs) 

5943 X, Y = [cbook.safe_masked_invalid(a, copy=True) for a in [X, Y]] 

5944 

5945 if funcname == 'pcolormesh': 

5946 if np.ma.is_masked(X) or np.ma.is_masked(Y): 

5947 raise ValueError( 

5948 'x and y arguments to pcolormesh cannot have ' 

5949 'non-finite values or be of type ' 

5950 'numpy.ma.MaskedArray with masked values') 

5951 nrows, ncols = C.shape[:2] 

5952 else: 

5953 raise _api.nargs_error(funcname, takes="1 or 3", given=len(args)) 

5954 

5955 Nx = X.shape[-1] 

5956 Ny = Y.shape[0] 

5957 if X.ndim != 2 or X.shape[0] == 1: 

5958 x = X.reshape(1, Nx) 

5959 X = x.repeat(Ny, axis=0) 

5960 if Y.ndim != 2 or Y.shape[1] == 1: 

5961 y = Y.reshape(Ny, 1) 

5962 Y = y.repeat(Nx, axis=1) 

5963 if X.shape != Y.shape: 

5964 raise TypeError(f'Incompatible X, Y inputs to {funcname}; ' 

5965 f'see help({funcname})') 

5966 

5967 if shading == 'auto': 

5968 if ncols == Nx and nrows == Ny: 

5969 shading = 'nearest' 

5970 else: 

5971 shading = 'flat' 

5972 

5973 if shading == 'flat': 

5974 if (Nx, Ny) != (ncols + 1, nrows + 1): 

5975 raise TypeError(f"Dimensions of C {C.shape} should" 

5976 f" be one smaller than X({Nx}) and Y({Ny})" 

5977 f" while using shading='flat'" 

5978 f" see help({funcname})") 

5979 else: # ['nearest', 'gouraud']: 

5980 if (Nx, Ny) != (ncols, nrows): 

5981 raise TypeError('Dimensions of C %s are incompatible with' 

5982 ' X (%d) and/or Y (%d); see help(%s)' % ( 

5983 C.shape, Nx, Ny, funcname)) 

5984 if shading == 'nearest': 

5985 # grid is specified at the center, so define corners 

5986 # at the midpoints between the grid centers and then use the 

5987 # flat algorithm. 

5988 def _interp_grid(X): 

5989 # helper for below 

5990 if np.shape(X)[1] > 1: 

5991 dX = np.diff(X, axis=1) * 0.5 

5992 if not (np.all(dX >= 0) or np.all(dX <= 0)): 

5993 _api.warn_external( 

5994 f"The input coordinates to {funcname} are " 

5995 "interpreted as cell centers, but are not " 

5996 "monotonically increasing or decreasing. " 

5997 "This may lead to incorrectly calculated cell " 

5998 "edges, in which case, please supply " 

5999 f"explicit cell edges to {funcname}.") 

6000 

6001 hstack = np.ma.hstack if np.ma.isMA(X) else np.hstack 

6002 X = hstack((X[:, [0]] - dX[:, [0]], 

6003 X[:, :-1] + dX, 

6004 X[:, [-1]] + dX[:, [-1]])) 

6005 else: 

6006 # This is just degenerate, but we can't reliably guess 

6007 # a dX if there is just one value. 

6008 X = np.hstack((X, X)) 

6009 return X 

6010 

6011 if ncols == Nx: 

6012 X = _interp_grid(X) 

6013 Y = _interp_grid(Y) 

6014 if nrows == Ny: 

6015 X = _interp_grid(X.T).T 

6016 Y = _interp_grid(Y.T).T 

6017 shading = 'flat' 

6018 

6019 C = cbook.safe_masked_invalid(C, copy=True) 

6020 return X, Y, C, shading 

6021 

6022 @_preprocess_data() 

6023 @_docstring.dedent_interpd 

6024 def pcolor(self, *args, shading=None, alpha=None, norm=None, cmap=None, 

6025 vmin=None, vmax=None, **kwargs): 

6026 r""" 

6027 Create a pseudocolor plot with a non-regular rectangular grid. 

6028 

6029 Call signature:: 

6030 

6031 pcolor([X, Y,] C, **kwargs) 

6032 

6033 *X* and *Y* can be used to specify the corners of the quadrilaterals. 

6034 

6035 .. hint:: 

6036 

6037 ``pcolor()`` can be very slow for large arrays. In most 

6038 cases you should use the similar but much faster 

6039 `~.Axes.pcolormesh` instead. See 

6040 :ref:`Differences between pcolor() and pcolormesh() 

6041 <differences-pcolor-pcolormesh>` for a discussion of the 

6042 differences. 

6043 

6044 Parameters 

6045 ---------- 

6046 C : 2D array-like 

6047 The color-mapped values. Color-mapping is controlled by *cmap*, 

6048 *norm*, *vmin*, and *vmax*. 

6049 

6050 X, Y : array-like, optional 

6051 The coordinates of the corners of quadrilaterals of a pcolormesh:: 

6052 

6053 (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1]) 

6054 ●╶───╴● 

6055 │ │ 

6056 ●╶───╴● 

6057 (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1]) 

6058 

6059 Note that the column index corresponds to the x-coordinate, and 

6060 the row index corresponds to y. For details, see the 

6061 :ref:`Notes <axes-pcolormesh-grid-orientation>` section below. 

6062 

6063 If ``shading='flat'`` the dimensions of *X* and *Y* should be one 

6064 greater than those of *C*, and the quadrilateral is colored due 

6065 to the value at ``C[i, j]``. If *X*, *Y* and *C* have equal 

6066 dimensions, a warning will be raised and the last row and column 

6067 of *C* will be ignored. 

6068 

6069 If ``shading='nearest'``, the dimensions of *X* and *Y* should be 

6070 the same as those of *C* (if not, a ValueError will be raised). The 

6071 color ``C[i, j]`` will be centered on ``(X[i, j], Y[i, j])``. 

6072 

6073 If *X* and/or *Y* are 1-D arrays or column vectors they will be 

6074 expanded as needed into the appropriate 2D arrays, making a 

6075 rectangular grid. 

6076 

6077 shading : {'flat', 'nearest', 'auto'}, default: :rc:`pcolor.shading` 

6078 The fill style for the quadrilateral. Possible values: 

6079 

6080 - 'flat': A solid color is used for each quad. The color of the 

6081 quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by 

6082 ``C[i, j]``. The dimensions of *X* and *Y* should be 

6083 one greater than those of *C*; if they are the same as *C*, 

6084 then a deprecation warning is raised, and the last row 

6085 and column of *C* are dropped. 

6086 - 'nearest': Each grid point will have a color centered on it, 

6087 extending halfway between the adjacent grid centers. The 

6088 dimensions of *X* and *Y* must be the same as *C*. 

6089 - 'auto': Choose 'flat' if dimensions of *X* and *Y* are one 

6090 larger than *C*. Choose 'nearest' if dimensions are the same. 

6091 

6092 See :doc:`/gallery/images_contours_and_fields/pcolormesh_grids` 

6093 for more description. 

6094 

6095 %(cmap_doc)s 

6096 

6097 %(norm_doc)s 

6098 

6099 %(vmin_vmax_doc)s 

6100 

6101 edgecolors : {'none', None, 'face', color, color sequence}, optional 

6102 The color of the edges. Defaults to 'none'. Possible values: 

6103 

6104 - 'none' or '': No edge. 

6105 - *None*: :rc:`patch.edgecolor` will be used. Note that currently 

6106 :rc:`patch.force_edgecolor` has to be True for this to work. 

6107 - 'face': Use the adjacent face color. 

6108 - A color or sequence of colors will set the edge color. 

6109 

6110 The singular form *edgecolor* works as an alias. 

6111 

6112 alpha : float, default: None 

6113 The alpha blending value of the face color, between 0 (transparent) 

6114 and 1 (opaque). Note: The edgecolor is currently not affected by 

6115 this. 

6116 

6117 snap : bool, default: False 

6118 Whether to snap the mesh to pixel boundaries. 

6119 

6120 Returns 

6121 ------- 

6122 `matplotlib.collections.PolyQuadMesh` 

6123 

6124 Other Parameters 

6125 ---------------- 

6126 antialiaseds : bool, default: False 

6127 The default *antialiaseds* is False if the default 

6128 *edgecolors*\ ="none" is used. This eliminates artificial lines 

6129 at patch boundaries, and works regardless of the value of alpha. 

6130 If *edgecolors* is not "none", then the default *antialiaseds* 

6131 is taken from :rc:`patch.antialiased`. 

6132 Stroking the edges may be preferred if *alpha* is 1, but will 

6133 cause artifacts otherwise. 

6134 

6135 data : indexable object, optional 

6136 DATA_PARAMETER_PLACEHOLDER 

6137 

6138 **kwargs 

6139 Additionally, the following arguments are allowed. They are passed 

6140 along to the `~matplotlib.collections.PolyQuadMesh` constructor: 

6141 

6142 %(PolyCollection:kwdoc)s 

6143 

6144 See Also 

6145 -------- 

6146 pcolormesh : for an explanation of the differences between 

6147 pcolor and pcolormesh. 

6148 imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a 

6149 faster alternative. 

6150 

6151 Notes 

6152 ----- 

6153 **Masked arrays** 

6154 

6155 *X*, *Y* and *C* may be masked arrays. If either ``C[i, j]``, or one 

6156 of the vertices surrounding ``C[i, j]`` (*X* or *Y* at 

6157 ``[i, j], [i+1, j], [i, j+1], [i+1, j+1]``) is masked, nothing is 

6158 plotted. 

6159 

6160 .. _axes-pcolor-grid-orientation: 

6161 

6162 **Grid orientation** 

6163 

6164 The grid orientation follows the standard matrix convention: An array 

6165 *C* with shape (nrows, ncolumns) is plotted with the column number as 

6166 *X* and the row number as *Y*. 

6167 """ 

6168 

6169 if shading is None: 

6170 shading = mpl.rcParams['pcolor.shading'] 

6171 shading = shading.lower() 

6172 X, Y, C, shading = self._pcolorargs('pcolor', *args, shading=shading, 

6173 kwargs=kwargs) 

6174 linewidths = (0.25,) 

6175 if 'linewidth' in kwargs: 

6176 kwargs['linewidths'] = kwargs.pop('linewidth') 

6177 kwargs.setdefault('linewidths', linewidths) 

6178 

6179 if 'edgecolor' in kwargs: 

6180 kwargs['edgecolors'] = kwargs.pop('edgecolor') 

6181 ec = kwargs.setdefault('edgecolors', 'none') 

6182 

6183 # aa setting will default via collections to patch.antialiased 

6184 # unless the boundary is not stroked, in which case the 

6185 # default will be False; with unstroked boundaries, aa 

6186 # makes artifacts that are often disturbing. 

6187 if 'antialiaseds' in kwargs: 

6188 kwargs['antialiased'] = kwargs.pop('antialiaseds') 

6189 if 'antialiased' not in kwargs and cbook._str_lower_equal(ec, "none"): 

6190 kwargs['antialiased'] = False 

6191 

6192 kwargs.setdefault('snap', False) 

6193 

6194 if np.ma.isMaskedArray(X) or np.ma.isMaskedArray(Y): 

6195 stack = np.ma.stack 

6196 X = np.ma.asarray(X) 

6197 Y = np.ma.asarray(Y) 

6198 # For bounds collections later 

6199 x = X.compressed() 

6200 y = Y.compressed() 

6201 else: 

6202 stack = np.stack 

6203 x = X 

6204 y = Y 

6205 coords = stack([X, Y], axis=-1) 

6206 

6207 collection = mcoll.PolyQuadMesh( 

6208 coords, array=C, cmap=cmap, norm=norm, alpha=alpha, **kwargs) 

6209 collection._scale_norm(norm, vmin, vmax) 

6210 

6211 # Transform from native to data coordinates? 

6212 t = collection._transform 

6213 if (not isinstance(t, mtransforms.Transform) and 

6214 hasattr(t, '_as_mpl_transform')): 

6215 t = t._as_mpl_transform(self.axes) 

6216 

6217 if t and any(t.contains_branch_seperately(self.transData)): 

6218 trans_to_data = t - self.transData 

6219 pts = np.vstack([x, y]).T.astype(float) 

6220 transformed_pts = trans_to_data.transform(pts) 

6221 x = transformed_pts[..., 0] 

6222 y = transformed_pts[..., 1] 

6223 

6224 self.add_collection(collection, autolim=False) 

6225 

6226 minx = np.min(x) 

6227 maxx = np.max(x) 

6228 miny = np.min(y) 

6229 maxy = np.max(y) 

6230 collection.sticky_edges.x[:] = [minx, maxx] 

6231 collection.sticky_edges.y[:] = [miny, maxy] 

6232 corners = (minx, miny), (maxx, maxy) 

6233 self.update_datalim(corners) 

6234 self._request_autoscale_view() 

6235 return collection 

6236 

6237 @_preprocess_data() 

6238 @_docstring.dedent_interpd 

6239 def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None, 

6240 vmax=None, shading=None, antialiased=False, **kwargs): 

6241 """ 

6242 Create a pseudocolor plot with a non-regular rectangular grid. 

6243 

6244 Call signature:: 

6245 

6246 pcolormesh([X, Y,] C, **kwargs) 

6247 

6248 *X* and *Y* can be used to specify the corners of the quadrilaterals. 

6249 

6250 .. hint:: 

6251 

6252 `~.Axes.pcolormesh` is similar to `~.Axes.pcolor`. It is much faster 

6253 and preferred in most cases. For a detailed discussion on the 

6254 differences see :ref:`Differences between pcolor() and pcolormesh() 

6255 <differences-pcolor-pcolormesh>`. 

6256 

6257 Parameters 

6258 ---------- 

6259 C : array-like 

6260 The mesh data. Supported array shapes are: 

6261 

6262 - (M, N) or M*N: a mesh with scalar data. The values are mapped to 

6263 colors using normalization and a colormap. See parameters *norm*, 

6264 *cmap*, *vmin*, *vmax*. 

6265 - (M, N, 3): an image with RGB values (0-1 float or 0-255 int). 

6266 - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int), 

6267 i.e. including transparency. 

6268 

6269 The first two dimensions (M, N) define the rows and columns of 

6270 the mesh data. 

6271 

6272 X, Y : array-like, optional 

6273 The coordinates of the corners of quadrilaterals of a pcolormesh:: 

6274 

6275 (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1]) 

6276 ●╶───╴● 

6277 │ │ 

6278 ●╶───╴● 

6279 (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1]) 

6280 

6281 Note that the column index corresponds to the x-coordinate, and 

6282 the row index corresponds to y. For details, see the 

6283 :ref:`Notes <axes-pcolormesh-grid-orientation>` section below. 

6284 

6285 If ``shading='flat'`` the dimensions of *X* and *Y* should be one 

6286 greater than those of *C*, and the quadrilateral is colored due 

6287 to the value at ``C[i, j]``. If *X*, *Y* and *C* have equal 

6288 dimensions, a warning will be raised and the last row and column 

6289 of *C* will be ignored. 

6290 

6291 If ``shading='nearest'`` or ``'gouraud'``, the dimensions of *X* 

6292 and *Y* should be the same as those of *C* (if not, a ValueError 

6293 will be raised). For ``'nearest'`` the color ``C[i, j]`` is 

6294 centered on ``(X[i, j], Y[i, j])``. For ``'gouraud'``, a smooth 

6295 interpolation is carried out between the quadrilateral corners. 

6296 

6297 If *X* and/or *Y* are 1-D arrays or column vectors they will be 

6298 expanded as needed into the appropriate 2D arrays, making a 

6299 rectangular grid. 

6300 

6301 %(cmap_doc)s 

6302 

6303 %(norm_doc)s 

6304 

6305 %(vmin_vmax_doc)s 

6306 

6307 edgecolors : {'none', None, 'face', color, color sequence}, optional 

6308 The color of the edges. Defaults to 'none'. Possible values: 

6309 

6310 - 'none' or '': No edge. 

6311 - *None*: :rc:`patch.edgecolor` will be used. Note that currently 

6312 :rc:`patch.force_edgecolor` has to be True for this to work. 

6313 - 'face': Use the adjacent face color. 

6314 - A color or sequence of colors will set the edge color. 

6315 

6316 The singular form *edgecolor* works as an alias. 

6317 

6318 alpha : float, default: None 

6319 The alpha blending value, between 0 (transparent) and 1 (opaque). 

6320 

6321 shading : {'flat', 'nearest', 'gouraud', 'auto'}, optional 

6322 The fill style for the quadrilateral; defaults to 

6323 :rc:`pcolor.shading`. Possible values: 

6324 

6325 - 'flat': A solid color is used for each quad. The color of the 

6326 quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by 

6327 ``C[i, j]``. The dimensions of *X* and *Y* should be 

6328 one greater than those of *C*; if they are the same as *C*, 

6329 then a deprecation warning is raised, and the last row 

6330 and column of *C* are dropped. 

6331 - 'nearest': Each grid point will have a color centered on it, 

6332 extending halfway between the adjacent grid centers. The 

6333 dimensions of *X* and *Y* must be the same as *C*. 

6334 - 'gouraud': Each quad will be Gouraud shaded: The color of the 

6335 corners (i', j') are given by ``C[i', j']``. The color values of 

6336 the area in between is interpolated from the corner values. 

6337 The dimensions of *X* and *Y* must be the same as *C*. When 

6338 Gouraud shading is used, *edgecolors* is ignored. 

6339 - 'auto': Choose 'flat' if dimensions of *X* and *Y* are one 

6340 larger than *C*. Choose 'nearest' if dimensions are the same. 

6341 

6342 See :doc:`/gallery/images_contours_and_fields/pcolormesh_grids` 

6343 for more description. 

6344 

6345 snap : bool, default: False 

6346 Whether to snap the mesh to pixel boundaries. 

6347 

6348 rasterized : bool, optional 

6349 Rasterize the pcolormesh when drawing vector graphics. This can 

6350 speed up rendering and produce smaller files for large data sets. 

6351 See also :doc:`/gallery/misc/rasterization_demo`. 

6352 

6353 Returns 

6354 ------- 

6355 `matplotlib.collections.QuadMesh` 

6356 

6357 Other Parameters 

6358 ---------------- 

6359 data : indexable object, optional 

6360 DATA_PARAMETER_PLACEHOLDER 

6361 

6362 **kwargs 

6363 Additionally, the following arguments are allowed. They are passed 

6364 along to the `~matplotlib.collections.QuadMesh` constructor: 

6365 

6366 %(QuadMesh:kwdoc)s 

6367 

6368 See Also 

6369 -------- 

6370 pcolor : An alternative implementation with slightly different 

6371 features. For a detailed discussion on the differences see 

6372 :ref:`Differences between pcolor() and pcolormesh() 

6373 <differences-pcolor-pcolormesh>`. 

6374 imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a 

6375 faster alternative. 

6376 

6377 Notes 

6378 ----- 

6379 **Masked arrays** 

6380 

6381 *C* may be a masked array. If ``C[i, j]`` is masked, the corresponding 

6382 quadrilateral will be transparent. Masking of *X* and *Y* is not 

6383 supported. Use `~.Axes.pcolor` if you need this functionality. 

6384 

6385 .. _axes-pcolormesh-grid-orientation: 

6386 

6387 **Grid orientation** 

6388 

6389 The grid orientation follows the standard matrix convention: An array 

6390 *C* with shape (nrows, ncolumns) is plotted with the column number as 

6391 *X* and the row number as *Y*. 

6392 

6393 .. _differences-pcolor-pcolormesh: 

6394 

6395 **Differences between pcolor() and pcolormesh()** 

6396 

6397 Both methods are used to create a pseudocolor plot of a 2D array 

6398 using quadrilaterals. 

6399 

6400 The main difference lies in the created object and internal data 

6401 handling: 

6402 While `~.Axes.pcolor` returns a `.PolyQuadMesh`, `~.Axes.pcolormesh` 

6403 returns a `.QuadMesh`. The latter is more specialized for the given 

6404 purpose and thus is faster. It should almost always be preferred. 

6405 

6406 There is also a slight difference in the handling of masked arrays. 

6407 Both `~.Axes.pcolor` and `~.Axes.pcolormesh` support masked arrays 

6408 for *C*. However, only `~.Axes.pcolor` supports masked arrays for *X* 

6409 and *Y*. The reason lies in the internal handling of the masked values. 

6410 `~.Axes.pcolor` leaves out the respective polygons from the 

6411 PolyQuadMesh. `~.Axes.pcolormesh` sets the facecolor of the masked 

6412 elements to transparent. You can see the difference when using 

6413 edgecolors. While all edges are drawn irrespective of masking in a 

6414 QuadMesh, the edge between two adjacent masked quadrilaterals in 

6415 `~.Axes.pcolor` is not drawn as the corresponding polygons do not 

6416 exist in the PolyQuadMesh. Because PolyQuadMesh draws each individual 

6417 polygon, it also supports applying hatches and linestyles to the collection. 

6418 

6419 Another difference is the support of Gouraud shading in 

6420 `~.Axes.pcolormesh`, which is not available with `~.Axes.pcolor`. 

6421 

6422 """ 

6423 if shading is None: 

6424 shading = mpl.rcParams['pcolor.shading'] 

6425 shading = shading.lower() 

6426 kwargs.setdefault('edgecolors', 'none') 

6427 

6428 X, Y, C, shading = self._pcolorargs('pcolormesh', *args, 

6429 shading=shading, kwargs=kwargs) 

6430 coords = np.stack([X, Y], axis=-1) 

6431 

6432 kwargs.setdefault('snap', mpl.rcParams['pcolormesh.snap']) 

6433 

6434 collection = mcoll.QuadMesh( 

6435 coords, antialiased=antialiased, shading=shading, 

6436 array=C, cmap=cmap, norm=norm, alpha=alpha, **kwargs) 

6437 collection._scale_norm(norm, vmin, vmax) 

6438 

6439 coords = coords.reshape(-1, 2) # flatten the grid structure; keep x, y 

6440 

6441 # Transform from native to data coordinates? 

6442 t = collection._transform 

6443 if (not isinstance(t, mtransforms.Transform) and 

6444 hasattr(t, '_as_mpl_transform')): 

6445 t = t._as_mpl_transform(self.axes) 

6446 

6447 if t and any(t.contains_branch_seperately(self.transData)): 

6448 trans_to_data = t - self.transData 

6449 coords = trans_to_data.transform(coords) 

6450 

6451 self.add_collection(collection, autolim=False) 

6452 

6453 minx, miny = np.min(coords, axis=0) 

6454 maxx, maxy = np.max(coords, axis=0) 

6455 collection.sticky_edges.x[:] = [minx, maxx] 

6456 collection.sticky_edges.y[:] = [miny, maxy] 

6457 corners = (minx, miny), (maxx, maxy) 

6458 self.update_datalim(corners) 

6459 self._request_autoscale_view() 

6460 return collection 

6461 

6462 @_preprocess_data() 

6463 @_docstring.dedent_interpd 

6464 def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None, 

6465 vmax=None, **kwargs): 

6466 """ 

6467 Create a pseudocolor plot with a non-regular rectangular grid. 

6468 

6469 Call signature:: 

6470 

6471 ax.pcolorfast([X, Y], C, /, **kwargs) 

6472 

6473 This method is similar to `~.Axes.pcolor` and `~.Axes.pcolormesh`. 

6474 It's designed to provide the fastest pcolor-type plotting with the 

6475 Agg backend. To achieve this, it uses different algorithms internally 

6476 depending on the complexity of the input grid (regular rectangular, 

6477 non-regular rectangular or arbitrary quadrilateral). 

6478 

6479 .. warning:: 

6480 

6481 This method is experimental. Compared to `~.Axes.pcolor` or 

6482 `~.Axes.pcolormesh` it has some limitations: 

6483 

6484 - It supports only flat shading (no outlines) 

6485 - It lacks support for log scaling of the axes. 

6486 - It does not have a pyplot wrapper. 

6487 

6488 Parameters 

6489 ---------- 

6490 C : array-like 

6491 The image data. Supported array shapes are: 

6492 

6493 - (M, N): an image with scalar data. Color-mapping is controlled 

6494 by *cmap*, *norm*, *vmin*, and *vmax*. 

6495 - (M, N, 3): an image with RGB values (0-1 float or 0-255 int). 

6496 - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int), 

6497 i.e. including transparency. 

6498 

6499 The first two dimensions (M, N) define the rows and columns of 

6500 the image. 

6501 

6502 This parameter can only be passed positionally. 

6503 

6504 X, Y : tuple or array-like, default: ``(0, N)``, ``(0, M)`` 

6505 *X* and *Y* are used to specify the coordinates of the 

6506 quadrilaterals. There are different ways to do this: 

6507 

6508 - Use tuples ``X=(xmin, xmax)`` and ``Y=(ymin, ymax)`` to define 

6509 a *uniform rectangular grid*. 

6510 

6511 The tuples define the outer edges of the grid. All individual 

6512 quadrilaterals will be of the same size. This is the fastest 

6513 version. 

6514 

6515 - Use 1D arrays *X*, *Y* to specify a *non-uniform rectangular 

6516 grid*. 

6517 

6518 In this case *X* and *Y* have to be monotonic 1D arrays of length 

6519 *N+1* and *M+1*, specifying the x and y boundaries of the cells. 

6520 

6521 The speed is intermediate. Note: The grid is checked, and if 

6522 found to be uniform the fast version is used. 

6523 

6524 - Use 2D arrays *X*, *Y* if you need an *arbitrary quadrilateral 

6525 grid* (i.e. if the quadrilaterals are not rectangular). 

6526 

6527 In this case *X* and *Y* are 2D arrays with shape (M + 1, N + 1), 

6528 specifying the x and y coordinates of the corners of the colored 

6529 quadrilaterals. 

6530 

6531 This is the most general, but the slowest to render. It may 

6532 produce faster and more compact output using ps, pdf, and 

6533 svg backends, however. 

6534 

6535 These arguments can only be passed positionally. 

6536 

6537 %(cmap_doc)s 

6538 

6539 This parameter is ignored if *C* is RGB(A). 

6540 

6541 %(norm_doc)s 

6542 

6543 This parameter is ignored if *C* is RGB(A). 

6544 

6545 %(vmin_vmax_doc)s 

6546 

6547 This parameter is ignored if *C* is RGB(A). 

6548 

6549 alpha : float, default: None 

6550 The alpha blending value, between 0 (transparent) and 1 (opaque). 

6551 

6552 snap : bool, default: False 

6553 Whether to snap the mesh to pixel boundaries. 

6554 

6555 Returns 

6556 ------- 

6557 `.AxesImage` or `.PcolorImage` or `.QuadMesh` 

6558 The return type depends on the type of grid: 

6559 

6560 - `.AxesImage` for a regular rectangular grid. 

6561 - `.PcolorImage` for a non-regular rectangular grid. 

6562 - `.QuadMesh` for a non-rectangular grid. 

6563 

6564 Other Parameters 

6565 ---------------- 

6566 data : indexable object, optional 

6567 DATA_PARAMETER_PLACEHOLDER 

6568 

6569 **kwargs 

6570 Supported additional parameters depend on the type of grid. 

6571 See return types of *image* for further description. 

6572 """ 

6573 

6574 C = args[-1] 

6575 nr, nc = np.shape(C)[:2] 

6576 if len(args) == 1: 

6577 style = "image" 

6578 x = [0, nc] 

6579 y = [0, nr] 

6580 elif len(args) == 3: 

6581 x, y = args[:2] 

6582 x = np.asarray(x) 

6583 y = np.asarray(y) 

6584 if x.ndim == 1 and y.ndim == 1: 

6585 if x.size == 2 and y.size == 2: 

6586 style = "image" 

6587 else: 

6588 dx = np.diff(x) 

6589 dy = np.diff(y) 

6590 if (np.ptp(dx) < 0.01 * abs(dx.mean()) and 

6591 np.ptp(dy) < 0.01 * abs(dy.mean())): 

6592 style = "image" 

6593 else: 

6594 style = "pcolorimage" 

6595 elif x.ndim == 2 and y.ndim == 2: 

6596 style = "quadmesh" 

6597 else: 

6598 raise TypeError( 

6599 f"When 3 positional parameters are passed to pcolorfast, the first " 

6600 f"two (X and Y) must be both 1D or both 2D; the given X was " 

6601 f"{x.ndim}D and the given Y was {y.ndim}D") 

6602 else: 

6603 raise _api.nargs_error('pcolorfast', '1 or 3', len(args)) 

6604 

6605 if style == "quadmesh": 

6606 # data point in each cell is value at lower left corner 

6607 coords = np.stack([x, y], axis=-1) 

6608 if np.ndim(C) not in {2, 3}: 

6609 raise ValueError("C must be 2D or 3D") 

6610 collection = mcoll.QuadMesh( 

6611 coords, array=C, 

6612 alpha=alpha, cmap=cmap, norm=norm, 

6613 antialiased=False, edgecolors="none") 

6614 self.add_collection(collection, autolim=False) 

6615 xl, xr, yb, yt = x.min(), x.max(), y.min(), y.max() 

6616 ret = collection 

6617 

6618 else: # It's one of the two image styles. 

6619 extent = xl, xr, yb, yt = x[0], x[-1], y[0], y[-1] 

6620 if style == "image": 

6621 im = mimage.AxesImage( 

6622 self, cmap=cmap, norm=norm, 

6623 data=C, alpha=alpha, extent=extent, 

6624 interpolation='nearest', origin='lower', 

6625 **kwargs) 

6626 elif style == "pcolorimage": 

6627 im = mimage.PcolorImage( 

6628 self, x, y, C, 

6629 cmap=cmap, norm=norm, alpha=alpha, extent=extent, 

6630 **kwargs) 

6631 self.add_image(im) 

6632 ret = im 

6633 

6634 if np.ndim(C) == 2: # C.ndim == 3 is RGB(A) so doesn't need scaling. 

6635 ret._scale_norm(norm, vmin, vmax) 

6636 

6637 if ret.get_clip_path() is None: 

6638 # image does not already have clipping set, clip to Axes patch 

6639 ret.set_clip_path(self.patch) 

6640 

6641 ret.sticky_edges.x[:] = [xl, xr] 

6642 ret.sticky_edges.y[:] = [yb, yt] 

6643 self.update_datalim(np.array([[xl, yb], [xr, yt]])) 

6644 self._request_autoscale_view(tight=True) 

6645 return ret 

6646 

6647 @_preprocess_data() 

6648 @_docstring.dedent_interpd 

6649 def contour(self, *args, **kwargs): 

6650 """ 

6651 Plot contour lines. 

6652 

6653 Call signature:: 

6654 

6655 contour([X, Y,] Z, [levels], **kwargs) 

6656 %(contour_doc)s 

6657 """ 

6658 kwargs['filled'] = False 

6659 contours = mcontour.QuadContourSet(self, *args, **kwargs) 

6660 self._request_autoscale_view() 

6661 return contours 

6662 

6663 @_preprocess_data() 

6664 @_docstring.dedent_interpd 

6665 def contourf(self, *args, **kwargs): 

6666 """ 

6667 Plot filled contours. 

6668 

6669 Call signature:: 

6670 

6671 contourf([X, Y,] Z, [levels], **kwargs) 

6672 %(contour_doc)s 

6673 """ 

6674 kwargs['filled'] = True 

6675 contours = mcontour.QuadContourSet(self, *args, **kwargs) 

6676 self._request_autoscale_view() 

6677 return contours 

6678 

6679 def clabel(self, CS, levels=None, **kwargs): 

6680 """ 

6681 Label a contour plot. 

6682 

6683 Adds labels to line contours in given `.ContourSet`. 

6684 

6685 Parameters 

6686 ---------- 

6687 CS : `.ContourSet` instance 

6688 Line contours to label. 

6689 

6690 levels : array-like, optional 

6691 A list of level values, that should be labeled. The list must be 

6692 a subset of ``CS.levels``. If not given, all levels are labeled. 

6693 

6694 **kwargs 

6695 All other parameters are documented in `~.ContourLabeler.clabel`. 

6696 """ 

6697 return CS.clabel(levels, **kwargs) 

6698 

6699 #### Data analysis 

6700 

6701 @_preprocess_data(replace_names=["x", 'weights'], label_namer="x") 

6702 def hist(self, x, bins=None, range=None, density=False, weights=None, 

6703 cumulative=False, bottom=None, histtype='bar', align='mid', 

6704 orientation='vertical', rwidth=None, log=False, 

6705 color=None, label=None, stacked=False, **kwargs): 

6706 """ 

6707 Compute and plot a histogram. 

6708 

6709 This method uses `numpy.histogram` to bin the data in *x* and count the 

6710 number of values in each bin, then draws the distribution either as a 

6711 `.BarContainer` or `.Polygon`. The *bins*, *range*, *density*, and 

6712 *weights* parameters are forwarded to `numpy.histogram`. 

6713 

6714 If the data has already been binned and counted, use `~.bar` or 

6715 `~.stairs` to plot the distribution:: 

6716 

6717 counts, bins = np.histogram(x) 

6718 plt.stairs(counts, bins) 

6719 

6720 Alternatively, plot pre-computed bins and counts using ``hist()`` by 

6721 treating each bin as a single point with a weight equal to its count:: 

6722 

6723 plt.hist(bins[:-1], bins, weights=counts) 

6724 

6725 The data input *x* can be a singular array, a list of datasets of 

6726 potentially different lengths ([*x0*, *x1*, ...]), or a 2D ndarray in 

6727 which each column is a dataset. Note that the ndarray form is 

6728 transposed relative to the list form. If the input is an array, then 

6729 the return value is a tuple (*n*, *bins*, *patches*); if the input is a 

6730 sequence of arrays, then the return value is a tuple 

6731 ([*n0*, *n1*, ...], *bins*, [*patches0*, *patches1*, ...]). 

6732 

6733 Masked arrays are not supported. 

6734 

6735 Parameters 

6736 ---------- 

6737 x : (n,) array or sequence of (n,) arrays 

6738 Input values, this takes either a single array or a sequence of 

6739 arrays which are not required to be of the same length. 

6740 

6741 bins : int or sequence or str, default: :rc:`hist.bins` 

6742 If *bins* is an integer, it defines the number of equal-width bins 

6743 in the range. 

6744 

6745 If *bins* is a sequence, it defines the bin edges, including the 

6746 left edge of the first bin and the right edge of the last bin; 

6747 in this case, bins may be unequally spaced. All but the last 

6748 (righthand-most) bin is half-open. In other words, if *bins* is:: 

6749 

6750 [1, 2, 3, 4] 

6751 

6752 then the first bin is ``[1, 2)`` (including 1, but excluding 2) and 

6753 the second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which 

6754 *includes* 4. 

6755 

6756 If *bins* is a string, it is one of the binning strategies 

6757 supported by `numpy.histogram_bin_edges`: 'auto', 'fd', 'doane', 

6758 'scott', 'stone', 'rice', 'sturges', or 'sqrt'. 

6759 

6760 range : tuple or None, default: None 

6761 The lower and upper range of the bins. Lower and upper outliers 

6762 are ignored. If not provided, *range* is ``(x.min(), x.max())``. 

6763 Range has no effect if *bins* is a sequence. 

6764 

6765 If *bins* is a sequence or *range* is specified, autoscaling 

6766 is based on the specified bin range instead of the 

6767 range of x. 

6768 

6769 density : bool, default: False 

6770 If ``True``, draw and return a probability density: each bin 

6771 will display the bin's raw count divided by the total number of 

6772 counts *and the bin width* 

6773 (``density = counts / (sum(counts) * np.diff(bins))``), 

6774 so that the area under the histogram integrates to 1 

6775 (``np.sum(density * np.diff(bins)) == 1``). 

6776 

6777 If *stacked* is also ``True``, the sum of the histograms is 

6778 normalized to 1. 

6779 

6780 weights : (n,) array-like or None, default: None 

6781 An array of weights, of the same shape as *x*. Each value in 

6782 *x* only contributes its associated weight towards the bin count 

6783 (instead of 1). If *density* is ``True``, the weights are 

6784 normalized, so that the integral of the density over the range 

6785 remains 1. 

6786 

6787 cumulative : bool or -1, default: False 

6788 If ``True``, then a histogram is computed where each bin gives the 

6789 counts in that bin plus all bins for smaller values. The last bin 

6790 gives the total number of datapoints. 

6791 

6792 If *density* is also ``True`` then the histogram is normalized such 

6793 that the last bin equals 1. 

6794 

6795 If *cumulative* is a number less than 0 (e.g., -1), the direction 

6796 of accumulation is reversed. In this case, if *density* is also 

6797 ``True``, then the histogram is normalized such that the first bin 

6798 equals 1. 

6799 

6800 bottom : array-like, scalar, or None, default: None 

6801 Location of the bottom of each bin, i.e. bins are drawn from 

6802 ``bottom`` to ``bottom + hist(x, bins)`` If a scalar, the bottom 

6803 of each bin is shifted by the same amount. If an array, each bin 

6804 is shifted independently and the length of bottom must match the 

6805 number of bins. If None, defaults to 0. 

6806 

6807 histtype : {'bar', 'barstacked', 'step', 'stepfilled'}, default: 'bar' 

6808 The type of histogram to draw. 

6809 

6810 - 'bar' is a traditional bar-type histogram. If multiple data 

6811 are given the bars are arranged side by side. 

6812 - 'barstacked' is a bar-type histogram where multiple 

6813 data are stacked on top of each other. 

6814 - 'step' generates a lineplot that is by default unfilled. 

6815 - 'stepfilled' generates a lineplot that is by default filled. 

6816 

6817 align : {'left', 'mid', 'right'}, default: 'mid' 

6818 The horizontal alignment of the histogram bars. 

6819 

6820 - 'left': bars are centered on the left bin edges. 

6821 - 'mid': bars are centered between the bin edges. 

6822 - 'right': bars are centered on the right bin edges. 

6823 

6824 orientation : {'vertical', 'horizontal'}, default: 'vertical' 

6825 If 'horizontal', `~.Axes.barh` will be used for bar-type histograms 

6826 and the *bottom* kwarg will be the left edges. 

6827 

6828 rwidth : float or None, default: None 

6829 The relative width of the bars as a fraction of the bin width. If 

6830 ``None``, automatically compute the width. 

6831 

6832 Ignored if *histtype* is 'step' or 'stepfilled'. 

6833 

6834 log : bool, default: False 

6835 If ``True``, the histogram axis will be set to a log scale. 

6836 

6837 color : :mpltype:`color` or list of :mpltype:`color` or None, default: None 

6838 Color or sequence of colors, one per dataset. Default (``None``) 

6839 uses the standard line color sequence. 

6840 

6841 label : str or list of str, optional 

6842 String, or sequence of strings to match multiple datasets. Bar 

6843 charts yield multiple patches per dataset, but only the first gets 

6844 the label, so that `~.Axes.legend` will work as expected. 

6845 

6846 stacked : bool, default: False 

6847 If ``True``, multiple data are stacked on top of each other If 

6848 ``False`` multiple data are arranged side by side if histtype is 

6849 'bar' or on top of each other if histtype is 'step' 

6850 

6851 Returns 

6852 ------- 

6853 n : array or list of arrays 

6854 The values of the histogram bins. See *density* and *weights* for a 

6855 description of the possible semantics. If input *x* is an array, 

6856 then this is an array of length *nbins*. If input is a sequence of 

6857 arrays ``[data1, data2, ...]``, then this is a list of arrays with 

6858 the values of the histograms for each of the arrays in the same 

6859 order. The dtype of the array *n* (or of its element arrays) will 

6860 always be float even if no weighting or normalization is used. 

6861 

6862 bins : array 

6863 The edges of the bins. Length nbins + 1 (nbins left edges and right 

6864 edge of last bin). Always a single array even when multiple data 

6865 sets are passed in. 

6866 

6867 patches : `.BarContainer` or list of a single `.Polygon` or list of \ 

6868such objects 

6869 Container of individual artists used to create the histogram 

6870 or list of such containers if there are multiple input datasets. 

6871 

6872 Other Parameters 

6873 ---------------- 

6874 data : indexable object, optional 

6875 DATA_PARAMETER_PLACEHOLDER 

6876 

6877 **kwargs 

6878 `~matplotlib.patches.Patch` properties 

6879 

6880 See Also 

6881 -------- 

6882 hist2d : 2D histogram with rectangular bins 

6883 hexbin : 2D histogram with hexagonal bins 

6884 stairs : Plot a pre-computed histogram 

6885 bar : Plot a pre-computed histogram 

6886 

6887 Notes 

6888 ----- 

6889 For large numbers of bins (>1000), plotting can be significantly 

6890 accelerated by using `~.Axes.stairs` to plot a pre-computed histogram 

6891 (``plt.stairs(*np.histogram(data))``), or by setting *histtype* to 

6892 'step' or 'stepfilled' rather than 'bar' or 'barstacked'. 

6893 """ 

6894 # Avoid shadowing the builtin. 

6895 bin_range = range 

6896 from builtins import range 

6897 

6898 if np.isscalar(x): 

6899 x = [x] 

6900 

6901 if bins is None: 

6902 bins = mpl.rcParams['hist.bins'] 

6903 

6904 # Validate string inputs here to avoid cluttering subsequent code. 

6905 _api.check_in_list(['bar', 'barstacked', 'step', 'stepfilled'], 

6906 histtype=histtype) 

6907 _api.check_in_list(['left', 'mid', 'right'], align=align) 

6908 _api.check_in_list(['horizontal', 'vertical'], orientation=orientation) 

6909 

6910 if histtype == 'barstacked' and not stacked: 

6911 stacked = True 

6912 

6913 # Massage 'x' for processing. 

6914 x = cbook._reshape_2D(x, 'x') 

6915 nx = len(x) # number of datasets 

6916 

6917 # Process unit information. _process_unit_info sets the unit and 

6918 # converts the first dataset; then we convert each following dataset 

6919 # one at a time. 

6920 if orientation == "vertical": 

6921 convert_units = self.convert_xunits 

6922 x = [*self._process_unit_info([("x", x[0])], kwargs), 

6923 *map(convert_units, x[1:])] 

6924 else: # horizontal 

6925 convert_units = self.convert_yunits 

6926 x = [*self._process_unit_info([("y", x[0])], kwargs), 

6927 *map(convert_units, x[1:])] 

6928 

6929 if bin_range is not None: 

6930 bin_range = convert_units(bin_range) 

6931 

6932 if not cbook.is_scalar_or_string(bins): 

6933 bins = convert_units(bins) 

6934 

6935 # We need to do to 'weights' what was done to 'x' 

6936 if weights is not None: 

6937 w = cbook._reshape_2D(weights, 'weights') 

6938 else: 

6939 w = [None] * nx 

6940 

6941 if len(w) != nx: 

6942 raise ValueError('weights should have the same shape as x') 

6943 

6944 input_empty = True 

6945 for xi, wi in zip(x, w): 

6946 len_xi = len(xi) 

6947 if wi is not None and len(wi) != len_xi: 

6948 raise ValueError('weights should have the same shape as x') 

6949 if len_xi: 

6950 input_empty = False 

6951 

6952 if color is None: 

6953 colors = [self._get_lines.get_next_color() for i in range(nx)] 

6954 else: 

6955 colors = mcolors.to_rgba_array(color) 

6956 if len(colors) != nx: 

6957 raise ValueError(f"The 'color' keyword argument must have one " 

6958 f"color per dataset, but {nx} datasets and " 

6959 f"{len(colors)} colors were provided") 

6960 

6961 hist_kwargs = dict() 

6962 

6963 # if the bin_range is not given, compute without nan numpy 

6964 # does not do this for us when guessing the range (but will 

6965 # happily ignore nans when computing the histogram). 

6966 if bin_range is None: 

6967 xmin = np.inf 

6968 xmax = -np.inf 

6969 for xi in x: 

6970 if len(xi): 

6971 # python's min/max ignore nan, 

6972 # np.minnan returns nan for all nan input 

6973 xmin = min(xmin, np.nanmin(xi)) 

6974 xmax = max(xmax, np.nanmax(xi)) 

6975 if xmin <= xmax: # Only happens if we have seen a finite value. 

6976 bin_range = (xmin, xmax) 

6977 

6978 # If bins are not specified either explicitly or via range, 

6979 # we need to figure out the range required for all datasets, 

6980 # and supply that to np.histogram. 

6981 if not input_empty and len(x) > 1: 

6982 if weights is not None: 

6983 _w = np.concatenate(w) 

6984 else: 

6985 _w = None 

6986 bins = np.histogram_bin_edges( 

6987 np.concatenate(x), bins, bin_range, _w) 

6988 else: 

6989 hist_kwargs['range'] = bin_range 

6990 

6991 density = bool(density) 

6992 if density and not stacked: 

6993 hist_kwargs['density'] = density 

6994 

6995 # List to store all the top coordinates of the histograms 

6996 tops = [] # Will have shape (n_datasets, n_bins). 

6997 # Loop through datasets 

6998 for i in range(nx): 

6999 # this will automatically overwrite bins, 

7000 # so that each histogram uses the same bins 

7001 m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs) 

7002 tops.append(m) 

7003 tops = np.array(tops, float) # causes problems later if it's an int 

7004 bins = np.array(bins, float) # causes problems if float16 

7005 if stacked: 

7006 tops = tops.cumsum(axis=0) 

7007 # If a stacked density plot, normalize so the area of all the 

7008 # stacked histograms together is 1 

7009 if density: 

7010 tops = (tops / np.diff(bins)) / tops[-1].sum() 

7011 if cumulative: 

7012 slc = slice(None) 

7013 if isinstance(cumulative, Number) and cumulative < 0: 

7014 slc = slice(None, None, -1) 

7015 if density: 

7016 tops = (tops * np.diff(bins))[:, slc].cumsum(axis=1)[:, slc] 

7017 else: 

7018 tops = tops[:, slc].cumsum(axis=1)[:, slc] 

7019 

7020 patches = [] 

7021 

7022 if histtype.startswith('bar'): 

7023 

7024 totwidth = np.diff(bins) 

7025 

7026 if rwidth is not None: 

7027 dr = np.clip(rwidth, 0, 1) 

7028 elif (len(tops) > 1 and 

7029 ((not stacked) or mpl.rcParams['_internal.classic_mode'])): 

7030 dr = 0.8 

7031 else: 

7032 dr = 1.0 

7033 

7034 if histtype == 'bar' and not stacked: 

7035 width = dr * totwidth / nx 

7036 dw = width 

7037 boffset = -0.5 * dr * totwidth * (1 - 1 / nx) 

7038 elif histtype == 'barstacked' or stacked: 

7039 width = dr * totwidth 

7040 boffset, dw = 0.0, 0.0 

7041 

7042 if align == 'mid': 

7043 boffset += 0.5 * totwidth 

7044 elif align == 'right': 

7045 boffset += totwidth 

7046 

7047 if orientation == 'horizontal': 

7048 _barfunc = self.barh 

7049 bottom_kwarg = 'left' 

7050 else: # orientation == 'vertical' 

7051 _barfunc = self.bar 

7052 bottom_kwarg = 'bottom' 

7053 

7054 for top, color in zip(tops, colors): 

7055 if bottom is None: 

7056 bottom = np.zeros(len(top)) 

7057 if stacked: 

7058 height = top - bottom 

7059 else: 

7060 height = top 

7061 bars = _barfunc(bins[:-1]+boffset, height, width, 

7062 align='center', log=log, 

7063 color=color, **{bottom_kwarg: bottom}) 

7064 patches.append(bars) 

7065 if stacked: 

7066 bottom = top 

7067 boffset += dw 

7068 # Remove stickies from all bars but the lowest ones, as otherwise 

7069 # margin expansion would be unable to cross the stickies in the 

7070 # middle of the bars. 

7071 for bars in patches[1:]: 

7072 for patch in bars: 

7073 patch.sticky_edges.x[:] = patch.sticky_edges.y[:] = [] 

7074 

7075 elif histtype.startswith('step'): 

7076 # these define the perimeter of the polygon 

7077 x = np.zeros(4 * len(bins) - 3) 

7078 y = np.zeros(4 * len(bins) - 3) 

7079 

7080 x[0:2*len(bins)-1:2], x[1:2*len(bins)-1:2] = bins, bins[:-1] 

7081 x[2*len(bins)-1:] = x[1:2*len(bins)-1][::-1] 

7082 

7083 if bottom is None: 

7084 bottom = 0 

7085 

7086 y[1:2*len(bins)-1:2] = y[2:2*len(bins):2] = bottom 

7087 y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1] 

7088 

7089 if log: 

7090 if orientation == 'horizontal': 

7091 self.set_xscale('log', nonpositive='clip') 

7092 else: # orientation == 'vertical' 

7093 self.set_yscale('log', nonpositive='clip') 

7094 

7095 if align == 'left': 

7096 x -= 0.5*(bins[1]-bins[0]) 

7097 elif align == 'right': 

7098 x += 0.5*(bins[1]-bins[0]) 

7099 

7100 # If fill kwarg is set, it will be passed to the patch collection, 

7101 # overriding this 

7102 fill = (histtype == 'stepfilled') 

7103 

7104 xvals, yvals = [], [] 

7105 for top in tops: 

7106 if stacked: 

7107 # top of the previous polygon becomes the bottom 

7108 y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1] 

7109 # set the top of this polygon 

7110 y[1:2*len(bins)-1:2] = y[2:2*len(bins):2] = top + bottom 

7111 

7112 # The starting point of the polygon has not yet been 

7113 # updated. So far only the endpoint was adjusted. This 

7114 # assignment closes the polygon. The redundant endpoint is 

7115 # later discarded (for step and stepfilled). 

7116 y[0] = y[-1] 

7117 

7118 if orientation == 'horizontal': 

7119 xvals.append(y.copy()) 

7120 yvals.append(x.copy()) 

7121 else: 

7122 xvals.append(x.copy()) 

7123 yvals.append(y.copy()) 

7124 

7125 # stepfill is closed, step is not 

7126 split = -1 if fill else 2 * len(bins) 

7127 # add patches in reverse order so that when stacking, 

7128 # items lower in the stack are plotted on top of 

7129 # items higher in the stack 

7130 for x, y, color in reversed(list(zip(xvals, yvals, colors))): 

7131 patches.append(self.fill( 

7132 x[:split], y[:split], 

7133 closed=True if fill else None, 

7134 facecolor=color, 

7135 edgecolor=None if fill else color, 

7136 fill=fill if fill else None, 

7137 zorder=None if fill else mlines.Line2D.zorder)) 

7138 for patch_list in patches: 

7139 for patch in patch_list: 

7140 if orientation == 'vertical': 

7141 patch.sticky_edges.y.append(0) 

7142 elif orientation == 'horizontal': 

7143 patch.sticky_edges.x.append(0) 

7144 

7145 # we return patches, so put it back in the expected order 

7146 patches.reverse() 

7147 

7148 # If None, make all labels None (via zip_longest below); otherwise, 

7149 # cast each element to str, but keep a single str as it. 

7150 labels = [] if label is None else np.atleast_1d(np.asarray(label, str)) 

7151 for patch, lbl in itertools.zip_longest(patches, labels): 

7152 if patch: 

7153 p = patch[0] 

7154 p._internal_update(kwargs) 

7155 if lbl is not None: 

7156 p.set_label(lbl) 

7157 for p in patch[1:]: 

7158 p._internal_update(kwargs) 

7159 p.set_label('_nolegend_') 

7160 

7161 if nx == 1: 

7162 return tops[0], bins, patches[0] 

7163 else: 

7164 patch_type = ("BarContainer" if histtype.startswith("bar") 

7165 else "list[Polygon]") 

7166 return tops, bins, cbook.silent_list(patch_type, patches) 

7167 

7168 @_preprocess_data() 

7169 def stairs(self, values, edges=None, *, 

7170 orientation='vertical', baseline=0, fill=False, **kwargs): 

7171 """ 

7172 Draw a stepwise constant function as a line or a filled plot. 

7173 

7174 *edges* define the x-axis positions of the steps. *values* the function values 

7175 between these steps. Depending on *fill*, the function is drawn either as a 

7176 continuous line with vertical segments at the edges, or as a filled area. 

7177 

7178 Parameters 

7179 ---------- 

7180 values : array-like 

7181 The step heights. 

7182 

7183 edges : array-like 

7184 The step positions, with ``len(edges) == len(vals) + 1``, 

7185 between which the curve takes on vals values. 

7186 

7187 orientation : {'vertical', 'horizontal'}, default: 'vertical' 

7188 The direction of the steps. Vertical means that *values* are along 

7189 the y-axis, and edges are along the x-axis. 

7190 

7191 baseline : float, array-like or None, default: 0 

7192 The bottom value of the bounding edges or when 

7193 ``fill=True``, position of lower edge. If *fill* is 

7194 True or an array is passed to *baseline*, a closed 

7195 path is drawn. 

7196 

7197 fill : bool, default: False 

7198 Whether the area under the step curve should be filled. 

7199 

7200 Returns 

7201 ------- 

7202 StepPatch : `~matplotlib.patches.StepPatch` 

7203 

7204 Other Parameters 

7205 ---------------- 

7206 data : indexable object, optional 

7207 DATA_PARAMETER_PLACEHOLDER 

7208 

7209 **kwargs 

7210 `~matplotlib.patches.StepPatch` properties 

7211 

7212 """ 

7213 

7214 if 'color' in kwargs: 

7215 _color = kwargs.pop('color') 

7216 else: 

7217 _color = self._get_lines.get_next_color() 

7218 if fill: 

7219 kwargs.setdefault('linewidth', 0) 

7220 kwargs.setdefault('facecolor', _color) 

7221 else: 

7222 kwargs.setdefault('edgecolor', _color) 

7223 

7224 if edges is None: 

7225 edges = np.arange(len(values) + 1) 

7226 

7227 edges, values, baseline = self._process_unit_info( 

7228 [("x", edges), ("y", values), ("y", baseline)], kwargs) 

7229 

7230 patch = mpatches.StepPatch(values, 

7231 edges, 

7232 baseline=baseline, 

7233 orientation=orientation, 

7234 fill=fill, 

7235 **kwargs) 

7236 self.add_patch(patch) 

7237 if baseline is None: 

7238 baseline = 0 

7239 if orientation == 'vertical': 

7240 patch.sticky_edges.y.append(np.min(baseline)) 

7241 self.update_datalim([(edges[0], np.min(baseline))]) 

7242 else: 

7243 patch.sticky_edges.x.append(np.min(baseline)) 

7244 self.update_datalim([(np.min(baseline), edges[0])]) 

7245 self._request_autoscale_view() 

7246 return patch 

7247 

7248 @_preprocess_data(replace_names=["x", "y", "weights"]) 

7249 @_docstring.dedent_interpd 

7250 def hist2d(self, x, y, bins=10, range=None, density=False, weights=None, 

7251 cmin=None, cmax=None, **kwargs): 

7252 """ 

7253 Make a 2D histogram plot. 

7254 

7255 Parameters 

7256 ---------- 

7257 x, y : array-like, shape (n, ) 

7258 Input values 

7259 

7260 bins : None or int or [int, int] or array-like or [array, array] 

7261 

7262 The bin specification: 

7263 

7264 - If int, the number of bins for the two dimensions 

7265 (``nx = ny = bins``). 

7266 - If ``[int, int]``, the number of bins in each dimension 

7267 (``nx, ny = bins``). 

7268 - If array-like, the bin edges for the two dimensions 

7269 (``x_edges = y_edges = bins``). 

7270 - If ``[array, array]``, the bin edges in each dimension 

7271 (``x_edges, y_edges = bins``). 

7272 

7273 The default value is 10. 

7274 

7275 range : array-like shape(2, 2), optional 

7276 The leftmost and rightmost edges of the bins along each dimension 

7277 (if not specified explicitly in the bins parameters): ``[[xmin, 

7278 xmax], [ymin, ymax]]``. All values outside of this range will be 

7279 considered outliers and not tallied in the histogram. 

7280 

7281 density : bool, default: False 

7282 Normalize histogram. See the documentation for the *density* 

7283 parameter of `~.Axes.hist` for more details. 

7284 

7285 weights : array-like, shape (n, ), optional 

7286 An array of values w_i weighing each sample (x_i, y_i). 

7287 

7288 cmin, cmax : float, default: None 

7289 All bins that has count less than *cmin* or more than *cmax* will not be 

7290 displayed (set to NaN before passing to `~.Axes.pcolormesh`) and these count 

7291 values in the return value count histogram will also be set to nan upon 

7292 return. 

7293 

7294 Returns 

7295 ------- 

7296 h : 2D array 

7297 The bi-dimensional histogram of samples x and y. Values in x are 

7298 histogrammed along the first dimension and values in y are 

7299 histogrammed along the second dimension. 

7300 xedges : 1D array 

7301 The bin edges along the x-axis. 

7302 yedges : 1D array 

7303 The bin edges along the y-axis. 

7304 image : `~.matplotlib.collections.QuadMesh` 

7305 

7306 Other Parameters 

7307 ---------------- 

7308 %(cmap_doc)s 

7309 

7310 %(norm_doc)s 

7311 

7312 %(vmin_vmax_doc)s 

7313 

7314 alpha : ``0 <= scalar <= 1`` or ``None``, optional 

7315 The alpha blending value. 

7316 

7317 data : indexable object, optional 

7318 DATA_PARAMETER_PLACEHOLDER 

7319 

7320 **kwargs 

7321 Additional parameters are passed along to the 

7322 `~.Axes.pcolormesh` method and `~matplotlib.collections.QuadMesh` 

7323 constructor. 

7324 

7325 See Also 

7326 -------- 

7327 hist : 1D histogram plotting 

7328 hexbin : 2D histogram with hexagonal bins 

7329 

7330 Notes 

7331 ----- 

7332 - Currently ``hist2d`` calculates its own axis limits, and any limits 

7333 previously set are ignored. 

7334 - Rendering the histogram with a logarithmic color scale is 

7335 accomplished by passing a `.colors.LogNorm` instance to the *norm* 

7336 keyword argument. Likewise, power-law normalization (similar 

7337 in effect to gamma correction) can be accomplished with 

7338 `.colors.PowerNorm`. 

7339 """ 

7340 

7341 h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range, 

7342 density=density, weights=weights) 

7343 

7344 if cmin is not None: 

7345 h[h < cmin] = None 

7346 if cmax is not None: 

7347 h[h > cmax] = None 

7348 

7349 pc = self.pcolormesh(xedges, yedges, h.T, **kwargs) 

7350 self.set_xlim(xedges[0], xedges[-1]) 

7351 self.set_ylim(yedges[0], yedges[-1]) 

7352 

7353 return h, xedges, yedges, pc 

7354 

7355 @_preprocess_data(replace_names=["x", "weights"], label_namer="x") 

7356 @_docstring.dedent_interpd 

7357 def ecdf(self, x, weights=None, *, complementary=False, 

7358 orientation="vertical", compress=False, **kwargs): 

7359 """ 

7360 Compute and plot the empirical cumulative distribution function of *x*. 

7361 

7362 .. versionadded:: 3.8 

7363 

7364 Parameters 

7365 ---------- 

7366 x : 1d array-like 

7367 The input data. Infinite entries are kept (and move the relevant 

7368 end of the ecdf from 0/1), but NaNs and masked values are errors. 

7369 

7370 weights : 1d array-like or None, default: None 

7371 The weights of the entries; must have the same shape as *x*. 

7372 Weights corresponding to NaN data points are dropped, and then the 

7373 remaining weights are normalized to sum to 1. If unset, all 

7374 entries have the same weight. 

7375 

7376 complementary : bool, default: False 

7377 Whether to plot a cumulative distribution function, which increases 

7378 from 0 to 1 (the default), or a complementary cumulative 

7379 distribution function, which decreases from 1 to 0. 

7380 

7381 orientation : {"vertical", "horizontal"}, default: "vertical" 

7382 Whether the entries are plotted along the x-axis ("vertical", the 

7383 default) or the y-axis ("horizontal"). This parameter takes the 

7384 same values as in `~.Axes.hist`. 

7385 

7386 compress : bool, default: False 

7387 Whether multiple entries with the same values are grouped together 

7388 (with a summed weight) before plotting. This is mainly useful if 

7389 *x* contains many identical data points, to decrease the rendering 

7390 complexity of the plot. If *x* contains no duplicate points, this 

7391 has no effect and just uses some time and memory. 

7392 

7393 Other Parameters 

7394 ---------------- 

7395 data : indexable object, optional 

7396 DATA_PARAMETER_PLACEHOLDER 

7397 

7398 **kwargs 

7399 Keyword arguments control the `.Line2D` properties: 

7400 

7401 %(Line2D:kwdoc)s 

7402 

7403 Returns 

7404 ------- 

7405 `.Line2D` 

7406 

7407 Notes 

7408 ----- 

7409 The ecdf plot can be thought of as a cumulative histogram with one bin 

7410 per data entry; i.e. it reports on the entire dataset without any 

7411 arbitrary binning. 

7412 

7413 If *x* contains NaNs or masked entries, either remove them first from 

7414 the array (if they should not taken into account), or replace them by 

7415 -inf or +inf (if they should be sorted at the beginning or the end of 

7416 the array). 

7417 """ 

7418 _api.check_in_list(["horizontal", "vertical"], orientation=orientation) 

7419 if "drawstyle" in kwargs or "ds" in kwargs: 

7420 raise TypeError("Cannot pass 'drawstyle' or 'ds' to ecdf()") 

7421 if np.ma.getmask(x).any(): 

7422 raise ValueError("ecdf() does not support masked entries") 

7423 x = np.asarray(x) 

7424 if np.isnan(x).any(): 

7425 raise ValueError("ecdf() does not support NaNs") 

7426 argsort = np.argsort(x) 

7427 x = x[argsort] 

7428 if weights is None: 

7429 # Ensure that we end at exactly 1, avoiding floating point errors. 

7430 cum_weights = (1 + np.arange(len(x))) / len(x) 

7431 else: 

7432 weights = np.take(weights, argsort) # Reorder weights like we reordered x. 

7433 cum_weights = np.cumsum(weights / np.sum(weights)) 

7434 if compress: 

7435 # Get indices of unique x values. 

7436 compress_idxs = [0, *(x[:-1] != x[1:]).nonzero()[0] + 1] 

7437 x = x[compress_idxs] 

7438 cum_weights = cum_weights[compress_idxs] 

7439 if orientation == "vertical": 

7440 if not complementary: 

7441 line, = self.plot([x[0], *x], [0, *cum_weights], 

7442 drawstyle="steps-post", **kwargs) 

7443 else: 

7444 line, = self.plot([*x, x[-1]], [1, *1 - cum_weights], 

7445 drawstyle="steps-pre", **kwargs) 

7446 line.sticky_edges.y[:] = [0, 1] 

7447 else: # orientation == "horizontal": 

7448 if not complementary: 

7449 line, = self.plot([0, *cum_weights], [x[0], *x], 

7450 drawstyle="steps-pre", **kwargs) 

7451 else: 

7452 line, = self.plot([1, *1 - cum_weights], [*x, x[-1]], 

7453 drawstyle="steps-post", **kwargs) 

7454 line.sticky_edges.x[:] = [0, 1] 

7455 return line 

7456 

7457 @_preprocess_data(replace_names=["x"]) 

7458 @_docstring.dedent_interpd 

7459 def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, 

7460 window=None, noverlap=None, pad_to=None, 

7461 sides=None, scale_by_freq=None, return_line=None, **kwargs): 

7462 r""" 

7463 Plot the power spectral density. 

7464 

7465 The power spectral density :math:`P_{xx}` by Welch's average 

7466 periodogram method. The vector *x* is divided into *NFFT* length 

7467 segments. Each segment is detrended by function *detrend* and 

7468 windowed by function *window*. *noverlap* gives the length of 

7469 the overlap between segments. The :math:`|\mathrm{fft}(i)|^2` 

7470 of each segment :math:`i` are averaged to compute :math:`P_{xx}`, 

7471 with a scaling to correct for power loss due to windowing. 

7472 

7473 If len(*x*) < *NFFT*, it will be zero padded to *NFFT*. 

7474 

7475 Parameters 

7476 ---------- 

7477 x : 1-D array or sequence 

7478 Array or sequence containing the data 

7479 

7480 %(Spectral)s 

7481 

7482 %(PSD)s 

7483 

7484 noverlap : int, default: 0 (no overlap) 

7485 The number of points of overlap between segments. 

7486 

7487 Fc : int, default: 0 

7488 The center frequency of *x*, which offsets the x extents of the 

7489 plot to reflect the frequency range used when a signal is acquired 

7490 and then filtered and downsampled to baseband. 

7491 

7492 return_line : bool, default: False 

7493 Whether to include the line object plotted in the returned values. 

7494 

7495 Returns 

7496 ------- 

7497 Pxx : 1-D array 

7498 The values for the power spectrum :math:`P_{xx}` before scaling 

7499 (real valued). 

7500 

7501 freqs : 1-D array 

7502 The frequencies corresponding to the elements in *Pxx*. 

7503 

7504 line : `~matplotlib.lines.Line2D` 

7505 The line created by this function. 

7506 Only returned if *return_line* is True. 

7507 

7508 Other Parameters 

7509 ---------------- 

7510 data : indexable object, optional 

7511 DATA_PARAMETER_PLACEHOLDER 

7512 

7513 **kwargs 

7514 Keyword arguments control the `.Line2D` properties: 

7515 

7516 %(Line2D:kwdoc)s 

7517 

7518 See Also 

7519 -------- 

7520 specgram 

7521 Differs in the default overlap; in not returning the mean of the 

7522 segment periodograms; in returning the times of the segments; and 

7523 in plotting a colormap instead of a line. 

7524 magnitude_spectrum 

7525 Plots the magnitude spectrum. 

7526 csd 

7527 Plots the spectral density between two signals. 

7528 

7529 Notes 

7530 ----- 

7531 For plotting, the power is plotted as 

7532 :math:`10\log_{10}(P_{xx})` for decibels, though *Pxx* itself 

7533 is returned. 

7534 

7535 References 

7536 ---------- 

7537 Bendat & Piersol -- Random Data: Analysis and Measurement Procedures, 

7538 John Wiley & Sons (1986) 

7539 """ 

7540 if Fc is None: 

7541 Fc = 0 

7542 

7543 pxx, freqs = mlab.psd(x=x, NFFT=NFFT, Fs=Fs, detrend=detrend, 

7544 window=window, noverlap=noverlap, pad_to=pad_to, 

7545 sides=sides, scale_by_freq=scale_by_freq) 

7546 freqs += Fc 

7547 

7548 if scale_by_freq in (None, True): 

7549 psd_units = 'dB/Hz' 

7550 else: 

7551 psd_units = 'dB' 

7552 

7553 line = self.plot(freqs, 10 * np.log10(pxx), **kwargs) 

7554 self.set_xlabel('Frequency') 

7555 self.set_ylabel('Power Spectral Density (%s)' % psd_units) 

7556 self.grid(True) 

7557 

7558 vmin, vmax = self.get_ybound() 

7559 step = max(10 * int(np.log10(vmax - vmin)), 1) 

7560 ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step) 

7561 self.set_yticks(ticks) 

7562 

7563 if return_line is None or not return_line: 

7564 return pxx, freqs 

7565 else: 

7566 return pxx, freqs, line 

7567 

7568 @_preprocess_data(replace_names=["x", "y"], label_namer="y") 

7569 @_docstring.dedent_interpd 

7570 def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None, 

7571 window=None, noverlap=None, pad_to=None, 

7572 sides=None, scale_by_freq=None, return_line=None, **kwargs): 

7573 r""" 

7574 Plot the cross-spectral density. 

7575 

7576 The cross spectral density :math:`P_{xy}` by Welch's average 

7577 periodogram method. The vectors *x* and *y* are divided into 

7578 *NFFT* length segments. Each segment is detrended by function 

7579 *detrend* and windowed by function *window*. *noverlap* gives 

7580 the length of the overlap between segments. The product of 

7581 the direct FFTs of *x* and *y* are averaged over each segment 

7582 to compute :math:`P_{xy}`, with a scaling to correct for power 

7583 loss due to windowing. 

7584 

7585 If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero 

7586 padded to *NFFT*. 

7587 

7588 Parameters 

7589 ---------- 

7590 x, y : 1-D arrays or sequences 

7591 Arrays or sequences containing the data. 

7592 

7593 %(Spectral)s 

7594 

7595 %(PSD)s 

7596 

7597 noverlap : int, default: 0 (no overlap) 

7598 The number of points of overlap between segments. 

7599 

7600 Fc : int, default: 0 

7601 The center frequency of *x*, which offsets the x extents of the 

7602 plot to reflect the frequency range used when a signal is acquired 

7603 and then filtered and downsampled to baseband. 

7604 

7605 return_line : bool, default: False 

7606 Whether to include the line object plotted in the returned values. 

7607 

7608 Returns 

7609 ------- 

7610 Pxy : 1-D array 

7611 The values for the cross spectrum :math:`P_{xy}` before scaling 

7612 (complex valued). 

7613 

7614 freqs : 1-D array 

7615 The frequencies corresponding to the elements in *Pxy*. 

7616 

7617 line : `~matplotlib.lines.Line2D` 

7618 The line created by this function. 

7619 Only returned if *return_line* is True. 

7620 

7621 Other Parameters 

7622 ---------------- 

7623 data : indexable object, optional 

7624 DATA_PARAMETER_PLACEHOLDER 

7625 

7626 **kwargs 

7627 Keyword arguments control the `.Line2D` properties: 

7628 

7629 %(Line2D:kwdoc)s 

7630 

7631 See Also 

7632 -------- 

7633 psd : is equivalent to setting ``y = x``. 

7634 

7635 Notes 

7636 ----- 

7637 For plotting, the power is plotted as 

7638 :math:`10 \log_{10}(P_{xy})` for decibels, though :math:`P_{xy}` itself 

7639 is returned. 

7640 

7641 References 

7642 ---------- 

7643 Bendat & Piersol -- Random Data: Analysis and Measurement Procedures, 

7644 John Wiley & Sons (1986) 

7645 """ 

7646 if Fc is None: 

7647 Fc = 0 

7648 

7649 pxy, freqs = mlab.csd(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend, 

7650 window=window, noverlap=noverlap, pad_to=pad_to, 

7651 sides=sides, scale_by_freq=scale_by_freq) 

7652 # pxy is complex 

7653 freqs += Fc 

7654 

7655 line = self.plot(freqs, 10 * np.log10(np.abs(pxy)), **kwargs) 

7656 self.set_xlabel('Frequency') 

7657 self.set_ylabel('Cross Spectrum Magnitude (dB)') 

7658 self.grid(True) 

7659 

7660 vmin, vmax = self.get_ybound() 

7661 step = max(10 * int(np.log10(vmax - vmin)), 1) 

7662 ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step) 

7663 self.set_yticks(ticks) 

7664 

7665 if return_line is None or not return_line: 

7666 return pxy, freqs 

7667 else: 

7668 return pxy, freqs, line 

7669 

7670 @_preprocess_data(replace_names=["x"]) 

7671 @_docstring.dedent_interpd 

7672 def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None, 

7673 pad_to=None, sides=None, scale=None, 

7674 **kwargs): 

7675 """ 

7676 Plot the magnitude spectrum. 

7677 

7678 Compute the magnitude spectrum of *x*. Data is padded to a 

7679 length of *pad_to* and the windowing function *window* is applied to 

7680 the signal. 

7681 

7682 Parameters 

7683 ---------- 

7684 x : 1-D array or sequence 

7685 Array or sequence containing the data. 

7686 

7687 %(Spectral)s 

7688 

7689 %(Single_Spectrum)s 

7690 

7691 scale : {'default', 'linear', 'dB'} 

7692 The scaling of the values in the *spec*. 'linear' is no scaling. 

7693 'dB' returns the values in dB scale, i.e., the dB amplitude 

7694 (20 * log10). 'default' is 'linear'. 

7695 

7696 Fc : int, default: 0 

7697 The center frequency of *x*, which offsets the x extents of the 

7698 plot to reflect the frequency range used when a signal is acquired 

7699 and then filtered and downsampled to baseband. 

7700 

7701 Returns 

7702 ------- 

7703 spectrum : 1-D array 

7704 The values for the magnitude spectrum before scaling (real valued). 

7705 

7706 freqs : 1-D array 

7707 The frequencies corresponding to the elements in *spectrum*. 

7708 

7709 line : `~matplotlib.lines.Line2D` 

7710 The line created by this function. 

7711 

7712 Other Parameters 

7713 ---------------- 

7714 data : indexable object, optional 

7715 DATA_PARAMETER_PLACEHOLDER 

7716 

7717 **kwargs 

7718 Keyword arguments control the `.Line2D` properties: 

7719 

7720 %(Line2D:kwdoc)s 

7721 

7722 See Also 

7723 -------- 

7724 psd 

7725 Plots the power spectral density. 

7726 angle_spectrum 

7727 Plots the angles of the corresponding frequencies. 

7728 phase_spectrum 

7729 Plots the phase (unwrapped angle) of the corresponding frequencies. 

7730 specgram 

7731 Can plot the magnitude spectrum of segments within the signal in a 

7732 colormap. 

7733 """ 

7734 if Fc is None: 

7735 Fc = 0 

7736 

7737 spec, freqs = mlab.magnitude_spectrum(x=x, Fs=Fs, window=window, 

7738 pad_to=pad_to, sides=sides) 

7739 freqs += Fc 

7740 

7741 yunits = _api.check_getitem( 

7742 {None: 'energy', 'default': 'energy', 'linear': 'energy', 

7743 'dB': 'dB'}, 

7744 scale=scale) 

7745 if yunits == 'energy': 

7746 Z = spec 

7747 else: # yunits == 'dB' 

7748 Z = 20. * np.log10(spec) 

7749 

7750 line, = self.plot(freqs, Z, **kwargs) 

7751 self.set_xlabel('Frequency') 

7752 self.set_ylabel('Magnitude (%s)' % yunits) 

7753 

7754 return spec, freqs, line 

7755 

7756 @_preprocess_data(replace_names=["x"]) 

7757 @_docstring.dedent_interpd 

7758 def angle_spectrum(self, x, Fs=None, Fc=None, window=None, 

7759 pad_to=None, sides=None, **kwargs): 

7760 """ 

7761 Plot the angle spectrum. 

7762 

7763 Compute the angle spectrum (wrapped phase spectrum) of *x*. 

7764 Data is padded to a length of *pad_to* and the windowing function 

7765 *window* is applied to the signal. 

7766 

7767 Parameters 

7768 ---------- 

7769 x : 1-D array or sequence 

7770 Array or sequence containing the data. 

7771 

7772 %(Spectral)s 

7773 

7774 %(Single_Spectrum)s 

7775 

7776 Fc : int, default: 0 

7777 The center frequency of *x*, which offsets the x extents of the 

7778 plot to reflect the frequency range used when a signal is acquired 

7779 and then filtered and downsampled to baseband. 

7780 

7781 Returns 

7782 ------- 

7783 spectrum : 1-D array 

7784 The values for the angle spectrum in radians (real valued). 

7785 

7786 freqs : 1-D array 

7787 The frequencies corresponding to the elements in *spectrum*. 

7788 

7789 line : `~matplotlib.lines.Line2D` 

7790 The line created by this function. 

7791 

7792 Other Parameters 

7793 ---------------- 

7794 data : indexable object, optional 

7795 DATA_PARAMETER_PLACEHOLDER 

7796 

7797 **kwargs 

7798 Keyword arguments control the `.Line2D` properties: 

7799 

7800 %(Line2D:kwdoc)s 

7801 

7802 See Also 

7803 -------- 

7804 magnitude_spectrum 

7805 Plots the magnitudes of the corresponding frequencies. 

7806 phase_spectrum 

7807 Plots the unwrapped version of this function. 

7808 specgram 

7809 Can plot the angle spectrum of segments within the signal in a 

7810 colormap. 

7811 """ 

7812 if Fc is None: 

7813 Fc = 0 

7814 

7815 spec, freqs = mlab.angle_spectrum(x=x, Fs=Fs, window=window, 

7816 pad_to=pad_to, sides=sides) 

7817 freqs += Fc 

7818 

7819 lines = self.plot(freqs, spec, **kwargs) 

7820 self.set_xlabel('Frequency') 

7821 self.set_ylabel('Angle (radians)') 

7822 

7823 return spec, freqs, lines[0] 

7824 

7825 @_preprocess_data(replace_names=["x"]) 

7826 @_docstring.dedent_interpd 

7827 def phase_spectrum(self, x, Fs=None, Fc=None, window=None, 

7828 pad_to=None, sides=None, **kwargs): 

7829 """ 

7830 Plot the phase spectrum. 

7831 

7832 Compute the phase spectrum (unwrapped angle spectrum) of *x*. 

7833 Data is padded to a length of *pad_to* and the windowing function 

7834 *window* is applied to the signal. 

7835 

7836 Parameters 

7837 ---------- 

7838 x : 1-D array or sequence 

7839 Array or sequence containing the data 

7840 

7841 %(Spectral)s 

7842 

7843 %(Single_Spectrum)s 

7844 

7845 Fc : int, default: 0 

7846 The center frequency of *x*, which offsets the x extents of the 

7847 plot to reflect the frequency range used when a signal is acquired 

7848 and then filtered and downsampled to baseband. 

7849 

7850 Returns 

7851 ------- 

7852 spectrum : 1-D array 

7853 The values for the phase spectrum in radians (real valued). 

7854 

7855 freqs : 1-D array 

7856 The frequencies corresponding to the elements in *spectrum*. 

7857 

7858 line : `~matplotlib.lines.Line2D` 

7859 The line created by this function. 

7860 

7861 Other Parameters 

7862 ---------------- 

7863 data : indexable object, optional 

7864 DATA_PARAMETER_PLACEHOLDER 

7865 

7866 **kwargs 

7867 Keyword arguments control the `.Line2D` properties: 

7868 

7869 %(Line2D:kwdoc)s 

7870 

7871 See Also 

7872 -------- 

7873 magnitude_spectrum 

7874 Plots the magnitudes of the corresponding frequencies. 

7875 angle_spectrum 

7876 Plots the wrapped version of this function. 

7877 specgram 

7878 Can plot the phase spectrum of segments within the signal in a 

7879 colormap. 

7880 """ 

7881 if Fc is None: 

7882 Fc = 0 

7883 

7884 spec, freqs = mlab.phase_spectrum(x=x, Fs=Fs, window=window, 

7885 pad_to=pad_to, sides=sides) 

7886 freqs += Fc 

7887 

7888 lines = self.plot(freqs, spec, **kwargs) 

7889 self.set_xlabel('Frequency') 

7890 self.set_ylabel('Phase (radians)') 

7891 

7892 return spec, freqs, lines[0] 

7893 

7894 @_preprocess_data(replace_names=["x", "y"]) 

7895 @_docstring.dedent_interpd 

7896 def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, 

7897 window=mlab.window_hanning, noverlap=0, pad_to=None, 

7898 sides='default', scale_by_freq=None, **kwargs): 

7899 r""" 

7900 Plot the coherence between *x* and *y*. 

7901 

7902 Coherence is the normalized cross spectral density: 

7903 

7904 .. math:: 

7905 

7906 C_{xy} = \frac{|P_{xy}|^2}{P_{xx}P_{yy}} 

7907 

7908 Parameters 

7909 ---------- 

7910 %(Spectral)s 

7911 

7912 %(PSD)s 

7913 

7914 noverlap : int, default: 0 (no overlap) 

7915 The number of points of overlap between blocks. 

7916 

7917 Fc : int, default: 0 

7918 The center frequency of *x*, which offsets the x extents of the 

7919 plot to reflect the frequency range used when a signal is acquired 

7920 and then filtered and downsampled to baseband. 

7921 

7922 Returns 

7923 ------- 

7924 Cxy : 1-D array 

7925 The coherence vector. 

7926 

7927 freqs : 1-D array 

7928 The frequencies for the elements in *Cxy*. 

7929 

7930 Other Parameters 

7931 ---------------- 

7932 data : indexable object, optional 

7933 DATA_PARAMETER_PLACEHOLDER 

7934 

7935 **kwargs 

7936 Keyword arguments control the `.Line2D` properties: 

7937 

7938 %(Line2D:kwdoc)s 

7939 

7940 References 

7941 ---------- 

7942 Bendat & Piersol -- Random Data: Analysis and Measurement Procedures, 

7943 John Wiley & Sons (1986) 

7944 """ 

7945 cxy, freqs = mlab.cohere(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend, 

7946 window=window, noverlap=noverlap, 

7947 scale_by_freq=scale_by_freq, sides=sides, 

7948 pad_to=pad_to) 

7949 freqs += Fc 

7950 

7951 self.plot(freqs, cxy, **kwargs) 

7952 self.set_xlabel('Frequency') 

7953 self.set_ylabel('Coherence') 

7954 self.grid(True) 

7955 

7956 return cxy, freqs 

7957 

7958 @_preprocess_data(replace_names=["x"]) 

7959 @_docstring.dedent_interpd 

7960 def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, 

7961 window=None, noverlap=None, 

7962 cmap=None, xextent=None, pad_to=None, sides=None, 

7963 scale_by_freq=None, mode=None, scale=None, 

7964 vmin=None, vmax=None, **kwargs): 

7965 """ 

7966 Plot a spectrogram. 

7967 

7968 Compute and plot a spectrogram of data in *x*. Data are split into 

7969 *NFFT* length segments and the spectrum of each section is 

7970 computed. The windowing function *window* is applied to each 

7971 segment, and the amount of overlap of each segment is 

7972 specified with *noverlap*. The spectrogram is plotted as a colormap 

7973 (using imshow). 

7974 

7975 Parameters 

7976 ---------- 

7977 x : 1-D array or sequence 

7978 Array or sequence containing the data. 

7979 

7980 %(Spectral)s 

7981 

7982 %(PSD)s 

7983 

7984 mode : {'default', 'psd', 'magnitude', 'angle', 'phase'} 

7985 What sort of spectrum to use. Default is 'psd', which takes the 

7986 power spectral density. 'magnitude' returns the magnitude 

7987 spectrum. 'angle' returns the phase spectrum without unwrapping. 

7988 'phase' returns the phase spectrum with unwrapping. 

7989 

7990 noverlap : int, default: 128 

7991 The number of points of overlap between blocks. 

7992 

7993 scale : {'default', 'linear', 'dB'} 

7994 The scaling of the values in the *spec*. 'linear' is no scaling. 

7995 'dB' returns the values in dB scale. When *mode* is 'psd', 

7996 this is dB power (10 * log10). Otherwise, this is dB amplitude 

7997 (20 * log10). 'default' is 'dB' if *mode* is 'psd' or 

7998 'magnitude' and 'linear' otherwise. This must be 'linear' 

7999 if *mode* is 'angle' or 'phase'. 

8000 

8001 Fc : int, default: 0 

8002 The center frequency of *x*, which offsets the x extents of the 

8003 plot to reflect the frequency range used when a signal is acquired 

8004 and then filtered and downsampled to baseband. 

8005 

8006 cmap : `.Colormap`, default: :rc:`image.cmap` 

8007 

8008 xextent : *None* or (xmin, xmax) 

8009 The image extent along the x-axis. The default sets *xmin* to the 

8010 left border of the first bin (*spectrum* column) and *xmax* to the 

8011 right border of the last bin. Note that for *noverlap>0* the width 

8012 of the bins is smaller than those of the segments. 

8013 

8014 data : indexable object, optional 

8015 DATA_PARAMETER_PLACEHOLDER 

8016 

8017 **kwargs 

8018 Additional keyword arguments are passed on to `~.axes.Axes.imshow` 

8019 which makes the specgram image. The origin keyword argument 

8020 is not supported. 

8021 

8022 Returns 

8023 ------- 

8024 spectrum : 2D array 

8025 Columns are the periodograms of successive segments. 

8026 

8027 freqs : 1-D array 

8028 The frequencies corresponding to the rows in *spectrum*. 

8029 

8030 t : 1-D array 

8031 The times corresponding to midpoints of segments (i.e., the columns 

8032 in *spectrum*). 

8033 

8034 im : `.AxesImage` 

8035 The image created by imshow containing the spectrogram. 

8036 

8037 See Also 

8038 -------- 

8039 psd 

8040 Differs in the default overlap; in returning the mean of the 

8041 segment periodograms; in not returning times; and in generating a 

8042 line plot instead of colormap. 

8043 magnitude_spectrum 

8044 A single spectrum, similar to having a single segment when *mode* 

8045 is 'magnitude'. Plots a line instead of a colormap. 

8046 angle_spectrum 

8047 A single spectrum, similar to having a single segment when *mode* 

8048 is 'angle'. Plots a line instead of a colormap. 

8049 phase_spectrum 

8050 A single spectrum, similar to having a single segment when *mode* 

8051 is 'phase'. Plots a line instead of a colormap. 

8052 

8053 Notes 

8054 ----- 

8055 The parameters *detrend* and *scale_by_freq* do only apply when *mode* 

8056 is set to 'psd'. 

8057 """ 

8058 if NFFT is None: 

8059 NFFT = 256 # same default as in mlab.specgram() 

8060 if Fc is None: 

8061 Fc = 0 # same default as in mlab._spectral_helper() 

8062 if noverlap is None: 

8063 noverlap = 128 # same default as in mlab.specgram() 

8064 if Fs is None: 

8065 Fs = 2 # same default as in mlab._spectral_helper() 

8066 

8067 if mode == 'complex': 

8068 raise ValueError('Cannot plot a complex specgram') 

8069 

8070 if scale is None or scale == 'default': 

8071 if mode in ['angle', 'phase']: 

8072 scale = 'linear' 

8073 else: 

8074 scale = 'dB' 

8075 elif mode in ['angle', 'phase'] and scale == 'dB': 

8076 raise ValueError('Cannot use dB scale with angle or phase mode') 

8077 

8078 spec, freqs, t = mlab.specgram(x=x, NFFT=NFFT, Fs=Fs, 

8079 detrend=detrend, window=window, 

8080 noverlap=noverlap, pad_to=pad_to, 

8081 sides=sides, 

8082 scale_by_freq=scale_by_freq, 

8083 mode=mode) 

8084 

8085 if scale == 'linear': 

8086 Z = spec 

8087 elif scale == 'dB': 

8088 if mode is None or mode == 'default' or mode == 'psd': 

8089 Z = 10. * np.log10(spec) 

8090 else: 

8091 Z = 20. * np.log10(spec) 

8092 else: 

8093 raise ValueError(f'Unknown scale {scale!r}') 

8094 

8095 Z = np.flipud(Z) 

8096 

8097 if xextent is None: 

8098 # padding is needed for first and last segment: 

8099 pad_xextent = (NFFT-noverlap) / Fs / 2 

8100 xextent = np.min(t) - pad_xextent, np.max(t) + pad_xextent 

8101 xmin, xmax = xextent 

8102 freqs += Fc 

8103 extent = xmin, xmax, freqs[0], freqs[-1] 

8104 

8105 if 'origin' in kwargs: 

8106 raise _api.kwarg_error("specgram", "origin") 

8107 

8108 im = self.imshow(Z, cmap, extent=extent, vmin=vmin, vmax=vmax, 

8109 origin='upper', **kwargs) 

8110 self.axis('auto') 

8111 

8112 return spec, freqs, t, im 

8113 

8114 @_docstring.dedent_interpd 

8115 def spy(self, Z, precision=0, marker=None, markersize=None, 

8116 aspect='equal', origin="upper", **kwargs): 

8117 """ 

8118 Plot the sparsity pattern of a 2D array. 

8119 

8120 This visualizes the non-zero values of the array. 

8121 

8122 Two plotting styles are available: image and marker. Both 

8123 are available for full arrays, but only the marker style 

8124 works for `scipy.sparse.spmatrix` instances. 

8125 

8126 **Image style** 

8127 

8128 If *marker* and *markersize* are *None*, `~.Axes.imshow` is used. Any 

8129 extra remaining keyword arguments are passed to this method. 

8130 

8131 **Marker style** 

8132 

8133 If *Z* is a `scipy.sparse.spmatrix` or *marker* or *markersize* are 

8134 *None*, a `.Line2D` object will be returned with the value of marker 

8135 determining the marker type, and any remaining keyword arguments 

8136 passed to `~.Axes.plot`. 

8137 

8138 Parameters 

8139 ---------- 

8140 Z : (M, N) array-like 

8141 The array to be plotted. 

8142 

8143 precision : float or 'present', default: 0 

8144 If *precision* is 0, any non-zero value will be plotted. Otherwise, 

8145 values of :math:`|Z| > precision` will be plotted. 

8146 

8147 For `scipy.sparse.spmatrix` instances, you can also 

8148 pass 'present'. In this case any value present in the array 

8149 will be plotted, even if it is identically zero. 

8150 

8151 aspect : {'equal', 'auto', None} or float, default: 'equal' 

8152 The aspect ratio of the Axes. This parameter is particularly 

8153 relevant for images since it determines whether data pixels are 

8154 square. 

8155 

8156 This parameter is a shortcut for explicitly calling 

8157 `.Axes.set_aspect`. See there for further details. 

8158 

8159 - 'equal': Ensures an aspect ratio of 1. Pixels will be square. 

8160 - 'auto': The Axes is kept fixed and the aspect is adjusted so 

8161 that the data fit in the Axes. In general, this will result in 

8162 non-square pixels. 

8163 - *None*: Use :rc:`image.aspect`. 

8164 

8165 origin : {'upper', 'lower'}, default: :rc:`image.origin` 

8166 Place the [0, 0] index of the array in the upper left or lower left 

8167 corner of the Axes. The convention 'upper' is typically used for 

8168 matrices and images. 

8169 

8170 Returns 

8171 ------- 

8172 `~matplotlib.image.AxesImage` or `.Line2D` 

8173 The return type depends on the plotting style (see above). 

8174 

8175 Other Parameters 

8176 ---------------- 

8177 **kwargs 

8178 The supported additional parameters depend on the plotting style. 

8179 

8180 For the image style, you can pass the following additional 

8181 parameters of `~.Axes.imshow`: 

8182 

8183 - *cmap* 

8184 - *alpha* 

8185 - *url* 

8186 - any `.Artist` properties (passed on to the `.AxesImage`) 

8187 

8188 For the marker style, you can pass any `.Line2D` property except 

8189 for *linestyle*: 

8190 

8191 %(Line2D:kwdoc)s 

8192 """ 

8193 if marker is None and markersize is None and hasattr(Z, 'tocoo'): 

8194 marker = 's' 

8195 _api.check_in_list(["upper", "lower"], origin=origin) 

8196 if marker is None and markersize is None: 

8197 Z = np.asarray(Z) 

8198 mask = np.abs(Z) > precision 

8199 

8200 if 'cmap' not in kwargs: 

8201 kwargs['cmap'] = mcolors.ListedColormap(['w', 'k'], 

8202 name='binary') 

8203 if 'interpolation' in kwargs: 

8204 raise _api.kwarg_error("spy", "interpolation") 

8205 if 'norm' not in kwargs: 

8206 kwargs['norm'] = mcolors.NoNorm() 

8207 ret = self.imshow(mask, interpolation='nearest', 

8208 aspect=aspect, origin=origin, 

8209 **kwargs) 

8210 else: 

8211 if hasattr(Z, 'tocoo'): 

8212 c = Z.tocoo() 

8213 if precision == 'present': 

8214 y = c.row 

8215 x = c.col 

8216 else: 

8217 nonzero = np.abs(c.data) > precision 

8218 y = c.row[nonzero] 

8219 x = c.col[nonzero] 

8220 else: 

8221 Z = np.asarray(Z) 

8222 nonzero = np.abs(Z) > precision 

8223 y, x = np.nonzero(nonzero) 

8224 if marker is None: 

8225 marker = 's' 

8226 if markersize is None: 

8227 markersize = 10 

8228 if 'linestyle' in kwargs: 

8229 raise _api.kwarg_error("spy", "linestyle") 

8230 ret = mlines.Line2D( 

8231 x, y, linestyle='None', marker=marker, markersize=markersize, 

8232 **kwargs) 

8233 self.add_line(ret) 

8234 nr, nc = Z.shape 

8235 self.set_xlim(-0.5, nc - 0.5) 

8236 if origin == "upper": 

8237 self.set_ylim(nr - 0.5, -0.5) 

8238 else: 

8239 self.set_ylim(-0.5, nr - 0.5) 

8240 self.set_aspect(aspect) 

8241 self.title.set_y(1.05) 

8242 if origin == "upper": 

8243 self.xaxis.tick_top() 

8244 else: # lower 

8245 self.xaxis.tick_bottom() 

8246 self.xaxis.set_ticks_position('both') 

8247 self.xaxis.set_major_locator( 

8248 mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True)) 

8249 self.yaxis.set_major_locator( 

8250 mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True)) 

8251 return ret 

8252 

8253 def matshow(self, Z, **kwargs): 

8254 """ 

8255 Plot the values of a 2D matrix or array as color-coded image. 

8256 

8257 The matrix will be shown the way it would be printed, with the first 

8258 row at the top. Row and column numbering is zero-based. 

8259 

8260 Parameters 

8261 ---------- 

8262 Z : (M, N) array-like 

8263 The matrix to be displayed. 

8264 

8265 Returns 

8266 ------- 

8267 `~matplotlib.image.AxesImage` 

8268 

8269 Other Parameters 

8270 ---------------- 

8271 **kwargs : `~matplotlib.axes.Axes.imshow` arguments 

8272 

8273 See Also 

8274 -------- 

8275 imshow : More general function to plot data on a 2D regular raster. 

8276 

8277 Notes 

8278 ----- 

8279 This is just a convenience function wrapping `.imshow` to set useful 

8280 defaults for displaying a matrix. In particular: 

8281 

8282 - Set ``origin='upper'``. 

8283 - Set ``interpolation='nearest'``. 

8284 - Set ``aspect='equal'``. 

8285 - Ticks are placed to the left and above. 

8286 - Ticks are formatted to show integer indices. 

8287 

8288 """ 

8289 Z = np.asanyarray(Z) 

8290 kw = {'origin': 'upper', 

8291 'interpolation': 'nearest', 

8292 'aspect': 'equal', # (already the imshow default) 

8293 **kwargs} 

8294 im = self.imshow(Z, **kw) 

8295 self.title.set_y(1.05) 

8296 self.xaxis.tick_top() 

8297 self.xaxis.set_ticks_position('both') 

8298 self.xaxis.set_major_locator( 

8299 mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True)) 

8300 self.yaxis.set_major_locator( 

8301 mticker.MaxNLocator(nbins=9, steps=[1, 2, 5, 10], integer=True)) 

8302 return im 

8303 

8304 @_preprocess_data(replace_names=["dataset"]) 

8305 def violinplot(self, dataset, positions=None, vert=True, widths=0.5, 

8306 showmeans=False, showextrema=True, showmedians=False, 

8307 quantiles=None, points=100, bw_method=None, side='both'): 

8308 """ 

8309 Make a violin plot. 

8310 

8311 Make a violin plot for each column of *dataset* or each vector in 

8312 sequence *dataset*. Each filled area extends to represent the 

8313 entire data range, with optional lines at the mean, the median, 

8314 the minimum, the maximum, and user-specified quantiles. 

8315 

8316 Parameters 

8317 ---------- 

8318 dataset : Array or a sequence of vectors. 

8319 The input data. 

8320 

8321 positions : array-like, default: [1, 2, ..., n] 

8322 The positions of the violins; i.e. coordinates on the x-axis for 

8323 vertical violins (or y-axis for horizontal violins). 

8324 

8325 vert : bool, default: True. 

8326 If true, creates a vertical violin plot. 

8327 Otherwise, creates a horizontal violin plot. 

8328 

8329 widths : float or array-like, default: 0.5 

8330 The maximum width of each violin in units of the *positions* axis. 

8331 The default is 0.5, which is half the available space when using default 

8332 *positions*. 

8333 

8334 showmeans : bool, default: False 

8335 Whether to show the mean with a line. 

8336 

8337 showextrema : bool, default: True 

8338 Whether to show extrema with a line. 

8339 

8340 showmedians : bool, default: False 

8341 Whether to show the median with a line. 

8342 

8343 quantiles : array-like, default: None 

8344 If not None, set a list of floats in interval [0, 1] for each violin, 

8345 which stands for the quantiles that will be rendered for that 

8346 violin. 

8347 

8348 points : int, default: 100 

8349 The number of points to evaluate each of the gaussian kernel density 

8350 estimations at. 

8351 

8352 bw_method : {'scott', 'silverman'} or float or callable, default: 'scott' 

8353 The method used to calculate the estimator bandwidth. If a 

8354 float, this will be used directly as `kde.factor`. If a 

8355 callable, it should take a `matplotlib.mlab.GaussianKDE` instance as 

8356 its only parameter and return a float. 

8357 

8358 side : {'both', 'low', 'high'}, default: 'both' 

8359 'both' plots standard violins. 'low'/'high' only 

8360 plots the side below/above the positions value. 

8361 

8362 data : indexable object, optional 

8363 DATA_PARAMETER_PLACEHOLDER 

8364 

8365 Returns 

8366 ------- 

8367 dict 

8368 A dictionary mapping each component of the violinplot to a 

8369 list of the corresponding collection instances created. The 

8370 dictionary has the following keys: 

8371 

8372 - ``bodies``: A list of the `~.collections.PolyCollection` 

8373 instances containing the filled area of each violin. 

8374 

8375 - ``cmeans``: A `~.collections.LineCollection` instance that marks 

8376 the mean values of each of the violin's distribution. 

8377 

8378 - ``cmins``: A `~.collections.LineCollection` instance that marks 

8379 the bottom of each violin's distribution. 

8380 

8381 - ``cmaxes``: A `~.collections.LineCollection` instance that marks 

8382 the top of each violin's distribution. 

8383 

8384 - ``cbars``: A `~.collections.LineCollection` instance that marks 

8385 the centers of each violin's distribution. 

8386 

8387 - ``cmedians``: A `~.collections.LineCollection` instance that 

8388 marks the median values of each of the violin's distribution. 

8389 

8390 - ``cquantiles``: A `~.collections.LineCollection` instance created 

8391 to identify the quantile values of each of the violin's 

8392 distribution. 

8393 

8394 See Also 

8395 -------- 

8396 .Axes.violin : Draw a violin from pre-computed statistics. 

8397 boxplot : Draw a box and whisker plot. 

8398 """ 

8399 

8400 def _kde_method(X, coords): 

8401 # Unpack in case of e.g. Pandas or xarray object 

8402 X = cbook._unpack_to_numpy(X) 

8403 # fallback gracefully if the vector contains only one value 

8404 if np.all(X[0] == X): 

8405 return (X[0] == coords).astype(float) 

8406 kde = mlab.GaussianKDE(X, bw_method) 

8407 return kde.evaluate(coords) 

8408 

8409 vpstats = cbook.violin_stats(dataset, _kde_method, points=points, 

8410 quantiles=quantiles) 

8411 return self.violin(vpstats, positions=positions, vert=vert, 

8412 widths=widths, showmeans=showmeans, 

8413 showextrema=showextrema, showmedians=showmedians, side=side) 

8414 

8415 def violin(self, vpstats, positions=None, vert=True, widths=0.5, 

8416 showmeans=False, showextrema=True, showmedians=False, side='both'): 

8417 """ 

8418 Draw a violin plot from pre-computed statistics. 

8419 

8420 Draw a violin plot for each column of *vpstats*. Each filled area 

8421 extends to represent the entire data range, with optional lines at the 

8422 mean, the median, the minimum, the maximum, and the quantiles values. 

8423 

8424 Parameters 

8425 ---------- 

8426 vpstats : list of dicts 

8427 A list of dictionaries containing stats for each violin plot. 

8428 Required keys are: 

8429 

8430 - ``coords``: A list of scalars containing the coordinates that 

8431 the violin's kernel density estimate were evaluated at. 

8432 

8433 - ``vals``: A list of scalars containing the values of the 

8434 kernel density estimate at each of the coordinates given 

8435 in *coords*. 

8436 

8437 - ``mean``: The mean value for this violin's dataset. 

8438 

8439 - ``median``: The median value for this violin's dataset. 

8440 

8441 - ``min``: The minimum value for this violin's dataset. 

8442 

8443 - ``max``: The maximum value for this violin's dataset. 

8444 

8445 Optional keys are: 

8446 

8447 - ``quantiles``: A list of scalars containing the quantile values 

8448 for this violin's dataset. 

8449 

8450 positions : array-like, default: [1, 2, ..., n] 

8451 The positions of the violins; i.e. coordinates on the x-axis for 

8452 vertical violins (or y-axis for horizontal violins). 

8453 

8454 vert : bool, default: True. 

8455 If true, plots the violins vertically. 

8456 Otherwise, plots the violins horizontally. 

8457 

8458 widths : float or array-like, default: 0.5 

8459 The maximum width of each violin in units of the *positions* axis. 

8460 The default is 0.5, which is half available space when using default 

8461 *positions*. 

8462 

8463 showmeans : bool, default: False 

8464 Whether to show the mean with a line. 

8465 

8466 showextrema : bool, default: True 

8467 Whether to show extrema with a line. 

8468 

8469 showmedians : bool, default: False 

8470 Whether to show the median with a line. 

8471 

8472 side : {'both', 'low', 'high'}, default: 'both' 

8473 'both' plots standard violins. 'low'/'high' only 

8474 plots the side below/above the positions value. 

8475 

8476 Returns 

8477 ------- 

8478 dict 

8479 A dictionary mapping each component of the violinplot to a 

8480 list of the corresponding collection instances created. The 

8481 dictionary has the following keys: 

8482 

8483 - ``bodies``: A list of the `~.collections.PolyCollection` 

8484 instances containing the filled area of each violin. 

8485 

8486 - ``cmeans``: A `~.collections.LineCollection` instance that marks 

8487 the mean values of each of the violin's distribution. 

8488 

8489 - ``cmins``: A `~.collections.LineCollection` instance that marks 

8490 the bottom of each violin's distribution. 

8491 

8492 - ``cmaxes``: A `~.collections.LineCollection` instance that marks 

8493 the top of each violin's distribution. 

8494 

8495 - ``cbars``: A `~.collections.LineCollection` instance that marks 

8496 the centers of each violin's distribution. 

8497 

8498 - ``cmedians``: A `~.collections.LineCollection` instance that 

8499 marks the median values of each of the violin's distribution. 

8500 

8501 - ``cquantiles``: A `~.collections.LineCollection` instance created 

8502 to identify the quantiles values of each of the violin's 

8503 distribution. 

8504 

8505 See Also 

8506 -------- 

8507 violin : 

8508 Draw a violin plot from data instead of pre-computed statistics. 

8509 """ 

8510 

8511 # Statistical quantities to be plotted on the violins 

8512 means = [] 

8513 mins = [] 

8514 maxes = [] 

8515 medians = [] 

8516 quantiles = [] 

8517 

8518 qlens = [] # Number of quantiles in each dataset. 

8519 

8520 artists = {} # Collections to be returned 

8521 

8522 N = len(vpstats) 

8523 datashape_message = ("List of violinplot statistics and `{0}` " 

8524 "values must have the same length") 

8525 

8526 # Validate positions 

8527 if positions is None: 

8528 positions = range(1, N + 1) 

8529 elif len(positions) != N: 

8530 raise ValueError(datashape_message.format("positions")) 

8531 

8532 # Validate widths 

8533 if np.isscalar(widths): 

8534 widths = [widths] * N 

8535 elif len(widths) != N: 

8536 raise ValueError(datashape_message.format("widths")) 

8537 

8538 # Validate side 

8539 _api.check_in_list(["both", "low", "high"], side=side) 

8540 

8541 # Calculate ranges for statistics lines (shape (2, N)). 

8542 line_ends = [[-0.25 if side in ['both', 'low'] else 0], 

8543 [0.25 if side in ['both', 'high'] else 0]] \ 

8544 * np.array(widths) + positions 

8545 

8546 # Colors. 

8547 if mpl.rcParams['_internal.classic_mode']: 

8548 fillcolor = 'y' 

8549 linecolor = 'r' 

8550 else: 

8551 fillcolor = linecolor = self._get_lines.get_next_color() 

8552 

8553 # Check whether we are rendering vertically or horizontally 

8554 if vert: 

8555 fill = self.fill_betweenx 

8556 if side in ['low', 'high']: 

8557 perp_lines = functools.partial(self.hlines, colors=linecolor, 

8558 capstyle='projecting') 

8559 par_lines = functools.partial(self.vlines, colors=linecolor, 

8560 capstyle='projecting') 

8561 else: 

8562 perp_lines = functools.partial(self.hlines, colors=linecolor) 

8563 par_lines = functools.partial(self.vlines, colors=linecolor) 

8564 else: 

8565 fill = self.fill_between 

8566 if side in ['low', 'high']: 

8567 perp_lines = functools.partial(self.vlines, colors=linecolor, 

8568 capstyle='projecting') 

8569 par_lines = functools.partial(self.hlines, colors=linecolor, 

8570 capstyle='projecting') 

8571 else: 

8572 perp_lines = functools.partial(self.vlines, colors=linecolor) 

8573 par_lines = functools.partial(self.hlines, colors=linecolor) 

8574 

8575 # Render violins 

8576 bodies = [] 

8577 for stats, pos, width in zip(vpstats, positions, widths): 

8578 # The 0.5 factor reflects the fact that we plot from v-p to v+p. 

8579 vals = np.array(stats['vals']) 

8580 vals = 0.5 * width * vals / vals.max() 

8581 bodies += [fill(stats['coords'], 

8582 -vals + pos if side in ['both', 'low'] else pos, 

8583 vals + pos if side in ['both', 'high'] else pos, 

8584 facecolor=fillcolor, alpha=0.3)] 

8585 means.append(stats['mean']) 

8586 mins.append(stats['min']) 

8587 maxes.append(stats['max']) 

8588 medians.append(stats['median']) 

8589 q = stats.get('quantiles') # a list of floats, or None 

8590 if q is None: 

8591 q = [] 

8592 quantiles.extend(q) 

8593 qlens.append(len(q)) 

8594 artists['bodies'] = bodies 

8595 

8596 if showmeans: # Render means 

8597 artists['cmeans'] = perp_lines(means, *line_ends) 

8598 if showextrema: # Render extrema 

8599 artists['cmaxes'] = perp_lines(maxes, *line_ends) 

8600 artists['cmins'] = perp_lines(mins, *line_ends) 

8601 artists['cbars'] = par_lines(positions, mins, maxes) 

8602 if showmedians: # Render medians 

8603 artists['cmedians'] = perp_lines(medians, *line_ends) 

8604 if quantiles: # Render quantiles: each width is repeated qlen times. 

8605 artists['cquantiles'] = perp_lines( 

8606 quantiles, *np.repeat(line_ends, qlens, axis=1)) 

8607 

8608 return artists 

8609 

8610 # Methods that are entirely implemented in other modules. 

8611 

8612 table = _make_axes_method(mtable.table) 

8613 

8614 # args can be either Y or y1, y2, ... and all should be replaced 

8615 stackplot = _preprocess_data()(_make_axes_method(mstack.stackplot)) 

8616 

8617 streamplot = _preprocess_data( 

8618 replace_names=["x", "y", "u", "v", "start_points"])( 

8619 _make_axes_method(mstream.streamplot)) 

8620 

8621 tricontour = _make_axes_method(mtri.tricontour) 

8622 tricontourf = _make_axes_method(mtri.tricontourf) 

8623 tripcolor = _make_axes_method(mtri.tripcolor) 

8624 triplot = _make_axes_method(mtri.triplot) 

8625 

8626 def _get_aspect_ratio(self): 

8627 """ 

8628 Convenience method to calculate the aspect ratio of the Axes in 

8629 the display coordinate system. 

8630 """ 

8631 figure_size = self.get_figure().get_size_inches() 

8632 ll, ur = self.get_position() * figure_size 

8633 width, height = ur - ll 

8634 return height / (width * self.get_data_ratio())