Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 25778c6

Browse filesBrowse files
authored
Merge branch 'matplotlib:main' into subfigure-clear
2 parents 6e4b1d9 + 4784ffa commit 25778c6
Copy full SHA for 25778c6

File tree

Expand file treeCollapse file tree

13 files changed

+152
-13
lines changed
Filter options
Expand file treeCollapse file tree

13 files changed

+152
-13
lines changed

‎.pre-commit-config.yaml

Copy file name to clipboard
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
ci:
2+
autofix_prs: false
3+
autoupdate_schedule: 'quarterly'
4+
exclude: |
5+
(?x)^(
6+
extern|
7+
lib/matplotlib/mpl-data|
8+
doc/devel/gitwash|
9+
doc/users/prev|
10+
doc/api/prev|
11+
lib/matplotlib/tests/tinypages
12+
)
13+
repos:
14+
- repo: https://github.com/pre-commit/pre-commit-hooks
15+
rev: v4.0.1
16+
hooks:
17+
- id: check-added-large-files
18+
- id: check-docstring-first
19+
- id: end-of-file-fixer
20+
exclude_types: [svg]
21+
- id: mixed-line-ending
22+
- id: trailing-whitespace
23+
exclude_types: [svg]
24+
- repo: https://github.com/pycqa/flake8
25+
rev: 3.9.2
26+
hooks:
27+
- id: flake8
28+
additional_dependencies: [pydocstyle>5.1.0, flake8-docstrings>1.4.0]
29+
args: ["--docstring-convention=all"]

‎doc/devel/development_setup.rst

Copy file name to clipboardExpand all lines: doc/devel/development_setup.rst
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ true for ``*.py`` files. If you change the C-extension source (which might
6060
also happen if you change branches) you will have to re-run
6161
``python -m pip install -ve .``
6262

63+
Installing pre-commit hooks
64+
===========================
65+
You can optionally install `pre-commit <https://pre-commit.com/>`_ hooks.
66+
These will automatically check flake8 and other style issues when you run
67+
``git commit``. The hooks are defined in the top level
68+
``.pre-commit-config.yaml`` file. To install the hooks ::
69+
70+
pip install pre-commit
71+
pre-commit install
72+
6373
Installing additional dependencies for development
6474
==================================================
6575
See :ref:`development-dependencies`.
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Custom cap widths in box and whisker plots in bxp() and boxplot()
2+
-----------------------------------------------------------------
3+
4+
New bxp() and boxplot() parameter capwidths allows to control the
5+
widths of the caps in box and whisker plots.
6+
7+
.. plot::
8+
:include-source: true
9+
10+
import matplotlib.pyplot as plt
11+
import numpy as np
12+
x = np.linspace(-7, 7, 140)
13+
x = np.hstack([-25, x, 25])
14+
fig, ax = plt.subplots()
15+
ax.boxplot([x, x], notch=1, capwidths=[0.01, 0.2])
16+
plt.show()

‎environment.yml

Copy file name to clipboardExpand all lines: environment.yml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ dependencies:
4747
- nbformat!=5.0.0,!=5.0.1
4848
- pandas!=0.25.0
4949
- pikepdf
50+
- pre-commit
5051
- pydocstyle>=5.1.0
5152
- pytest!=4.6.0,!=5.4.0
5253
- pytest-cov

‎examples/statistics/boxplot_demo.py

Copy file name to clipboardExpand all lines: examples/statistics/boxplot_demo.py
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,18 @@ def fake_bootstrapper(n):
231231
plt.setp(bp['fliers'], markersize=3.0)
232232
plt.show()
233233

234+
235+
###############################################################################
236+
# Here we customize the widths of the caps .
237+
238+
x = np.linspace(-7, 7, 140)
239+
x = np.hstack([-25, x, 25])
240+
fig, ax = plt.subplots()
241+
242+
ax.boxplot([x, x], notch=1, capwidths=[0.01, 0.2])
243+
244+
plt.show()
245+
234246
#############################################################################
235247
#
236248
# .. admonition:: References

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+30-10Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3525,7 +3525,8 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
35253525
showbox=None, showfliers=None, boxprops=None,
35263526
labels=None, flierprops=None, medianprops=None,
35273527
meanprops=None, capprops=None, whiskerprops=None,
3528-
manage_ticks=True, autorange=False, zorder=None):
3528+
manage_ticks=True, autorange=False, zorder=None,
3529+
capwidths=None):
35293530
"""
35303531
Draw a box and whisker plot.
35313532
@@ -3692,6 +3693,8 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
36923693
Show the arithmetic means.
36933694
capprops : dict, default: None
36943695
The style of the caps.
3696+
capwidths : float or array, default: None
3697+
The widths of the caps.
36953698
boxprops : dict, default: None
36963699
The style of the box.
36973700
whiskerprops : dict, default: None
@@ -3820,15 +3823,17 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
38203823
medianprops=medianprops, meanprops=meanprops,
38213824
meanline=meanline, showfliers=showfliers,
38223825
capprops=capprops, whiskerprops=whiskerprops,
3823-
manage_ticks=manage_ticks, zorder=zorder)
3826+
manage_ticks=manage_ticks, zorder=zorder,
3827+
capwidths=capwidths)
38243828
return artists
38253829

38263830
def bxp(self, bxpstats, positions=None, widths=None, vert=True,
38273831
patch_artist=False, shownotches=False, showmeans=False,
38283832
showcaps=True, showbox=True, showfliers=True,
38293833
boxprops=None, whiskerprops=None, flierprops=None,
38303834
medianprops=None, capprops=None, meanprops=None,
3831-
meanline=False, manage_ticks=True, zorder=None):
3835+
meanline=False, manage_ticks=True, zorder=None,
3836+
capwidths=None):
38323837
"""
38333838
Drawing function for box and whisker plots.
38343839
@@ -3866,6 +3871,10 @@ def bxp(self, bxpstats, positions=None, widths=None, vert=True,
38663871
The widths of the boxes. The default is
38673872
``clip(0.15*(distance between extreme positions), 0.15, 0.5)``.
38683873
3874+
capwidths : float or array-like, default: None
3875+
Either a scalar or a vector and sets the width of each cap.
3876+
The default is ``0.5*(with of the box)``, see *widths*.
3877+
38693878
vert : bool, default: True
38703879
If `True` (default), makes the boxes vertical.
38713880
If `False`, makes horizontal boxes.
@@ -3998,7 +4007,16 @@ def do_patch(xs, ys, **kwargs):
39984007
elif len(widths) != N:
39994008
raise ValueError(datashape_message.format("widths"))
40004009

4001-
for pos, width, stats in zip(positions, widths, bxpstats):
4010+
# capwidth
4011+
if capwidths is None:
4012+
capwidths = 0.5 * np.array(widths)
4013+
elif np.isscalar(capwidths):
4014+
capwidths = [capwidths] * N
4015+
elif len(capwidths) != N:
4016+
raise ValueError(datashape_message.format("capwidths"))
4017+
4018+
for pos, width, stats, capwidth in zip(positions, widths, bxpstats,
4019+
capwidths):
40024020
# try to find a new label
40034021
datalabels.append(stats.get('label', pos))
40044022

@@ -4007,8 +4025,8 @@ def do_patch(xs, ys, **kwargs):
40074025
whislo_y = [stats['q1'], stats['whislo']]
40084026
whishi_y = [stats['q3'], stats['whishi']]
40094027
# cap coords
4010-
cap_left = pos - width * 0.25
4011-
cap_right = pos + width * 0.25
4028+
cap_left = pos - capwidth * 0.5
4029+
cap_right = pos + capwidth * 0.5
40124030
cap_x = [cap_left, cap_right]
40134031
cap_lo = np.full(2, stats['whislo'])
40144032
cap_hi = np.full(2, stats['whishi'])
@@ -4018,14 +4036,16 @@ def do_patch(xs, ys, **kwargs):
40184036
med_y = [stats['med'], stats['med']]
40194037
# notched boxes
40204038
if shownotches:
4021-
box_x = [box_left, box_right, box_right, cap_right, box_right,
4022-
box_right, box_left, box_left, cap_left, box_left,
4023-
box_left]
4039+
notch_left = pos - width * 0.25
4040+
notch_right = pos + width * 0.25
4041+
box_x = [box_left, box_right, box_right, notch_right,
4042+
box_right, box_right, box_left, box_left, notch_left,
4043+
box_left, box_left]
40244044
box_y = [stats['q1'], stats['q1'], stats['cilo'],
40254045
stats['med'], stats['cihi'], stats['q3'],
40264046
stats['q3'], stats['cihi'], stats['med'],
40274047
stats['cilo'], stats['q1']]
4028-
med_x = cap_x
4048+
med_x = [notch_left, notch_right]
40294049
# plain boxes
40304050
else:
40314051
box_x = [box_left, box_right, box_right, box_left, box_left]

‎lib/matplotlib/backends/_backend_tk.py

Copy file name to clipboardExpand all lines: lib/matplotlib/backends/_backend_tk.py
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ def blit(photoimage, aggimage, offsets, bbox=None):
7878
7979
If *bbox* is passed, it defines the region that gets blitted. That region
8080
will be composed with the previous data according to the alpha channel.
81+
Blitting will be clipped to pixels inside the canvas, including silently
82+
doing nothing if the *bbox* region is entirely outside the canvas.
8183
8284
Tcl events must be dispatched to trigger a blit from a non-Tcl thread.
8385
"""
@@ -90,6 +92,8 @@ def blit(photoimage, aggimage, offsets, bbox=None):
9092
x2 = min(math.ceil(x2), width)
9193
y1 = max(math.floor(y1), 0)
9294
y2 = min(math.ceil(y2), height)
95+
if (x1 > x2) or (y1 > y2):
96+
return
9397
bboxptr = (x1, x2, y1, y2)
9498
comp_rule = TK_PHOTO_COMPOSITE_OVERLAY
9599
else:

‎lib/matplotlib/pyplot.py

Copy file name to clipboardExpand all lines: lib/matplotlib/pyplot.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2431,7 +2431,7 @@ def boxplot(
24312431
showfliers=None, boxprops=None, labels=None, flierprops=None,
24322432
medianprops=None, meanprops=None, capprops=None,
24332433
whiskerprops=None, manage_ticks=True, autorange=False,
2434-
zorder=None, *, data=None):
2434+
zorder=None, capwidths=None, *, data=None):
24352435
return gca().boxplot(
24362436
x, notch=notch, sym=sym, vert=vert, whis=whis,
24372437
positions=positions, widths=widths, patch_artist=patch_artist,
@@ -2442,7 +2442,7 @@ def boxplot(
24422442
flierprops=flierprops, medianprops=medianprops,
24432443
meanprops=meanprops, capprops=capprops,
24442444
whiskerprops=whiskerprops, manage_ticks=manage_ticks,
2445-
autorange=autorange, zorder=zorder,
2445+
autorange=autorange, zorder=zorder, capwidths=capwidths,
24462446
**({"data": data} if data is not None else {}))
24472447

24482448

Loading
Loading
Loading

‎lib/matplotlib/tests/test_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_axes.py
+47Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1683,6 +1683,23 @@ def test_boxplot_dates_pandas(pd):
16831683
plt.boxplot(data, positions=years)
16841684

16851685

1686+
def test_boxplot_capwidths():
1687+
data = np.random.rand(5, 3)
1688+
fig, axs = plt.subplots(9)
1689+
1690+
axs[0].boxplot(data, capwidths=[0.3, 0.2, 0.1], widths=[0.1, 0.2, 0.3])
1691+
axs[1].boxplot(data, capwidths=[0.3, 0.2, 0.1], widths=0.2)
1692+
axs[2].boxplot(data, capwidths=[0.3, 0.2, 0.1])
1693+
1694+
axs[3].boxplot(data, capwidths=0.5, widths=[0.1, 0.2, 0.3])
1695+
axs[4].boxplot(data, capwidths=0.5, widths=0.2)
1696+
axs[5].boxplot(data, capwidths=0.5)
1697+
1698+
axs[6].boxplot(data, widths=[0.1, 0.2, 0.3])
1699+
axs[7].boxplot(data, widths=0.2)
1700+
axs[8].boxplot(data)
1701+
1702+
16861703
def test_pcolor_regression(pd):
16871704
from pandas.plotting import (
16881705
register_matplotlib_converters,
@@ -2860,6 +2877,25 @@ def test_bxp_bad_positions():
28602877
_bxp_test_helper(bxp_kwargs=dict(positions=[2, 3]))
28612878

28622879

2880+
@image_comparison(['bxp_custom_capwidths.png'],
2881+
savefig_kwarg={'dpi': 40},
2882+
style='default')
2883+
def test_bxp_custom_capwidths():
2884+
_bxp_test_helper(bxp_kwargs=dict(capwidths=[0.0, 0.1, 0.5, 1.0]))
2885+
2886+
2887+
@image_comparison(['bxp_custom_capwidth.png'],
2888+
savefig_kwarg={'dpi': 40},
2889+
style='default')
2890+
def test_bxp_custom_capwidth():
2891+
_bxp_test_helper(bxp_kwargs=dict(capwidths=0.6))
2892+
2893+
2894+
def test_bxp_bad_capwidths():
2895+
with pytest.raises(ValueError):
2896+
_bxp_test_helper(bxp_kwargs=dict(capwidths=[1]))
2897+
2898+
28632899
@image_comparison(['boxplot', 'boxplot'], tol=1.28, style='default')
28642900
def test_boxplot():
28652901
# Randomness used for bootstrapping.
@@ -2879,6 +2915,17 @@ def test_boxplot():
28792915
ax.set_ylim((-30, 30))
28802916

28812917

2918+
@image_comparison(['boxplot_custom_capwidths.png'],
2919+
savefig_kwarg={'dpi': 40}, style='default')
2920+
def test_boxplot_custom_capwidths():
2921+
2922+
x = np.linspace(-7, 7, 140)
2923+
x = np.hstack([-25, x, 25])
2924+
fig, ax = plt.subplots()
2925+
2926+
ax.boxplot([x, x], notch=1, capwidths=[0.01, 0.2])
2927+
2928+
28822929
@image_comparison(['boxplot_sym2.png'], remove_text=True, style='default')
28832930
def test_boxplot_sym2():
28842931
# Randomness used for bootstrapping.

‎requirements/testing/all.txt

Copy file name to clipboardExpand all lines: requirements/testing/all.txt
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# pip requirements for all the CI builds
22

33
certifi
4-
coverage
4+
coverage!=6.3
55
pytest!=4.6.0,!=5.4.0
66
pytest-cov
77
pytest-rerunfailures

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.