Skip to content

Commit 8798ab0

Browse files
authored
Merge pull request #21266 from Kislovskiy/fix-21101
Fix #21101 Add validator to errorbar method
2 parents 07a0444 + 4710e31 commit 8798ab0

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import math
55
from numbers import Integral, Number
6+
from datetime import timedelta
67

78
import numpy as np
89
from numpy import ma
@@ -3180,7 +3181,7 @@ def errorbar(self, x, y, yerr=None, xerr=None,
31803181
errors.
31813182
- *None*: No errorbar.
31823183
3183-
Note that all error arrays should have *positive* values.
3184+
Note that all error arrays should have *non-negative* values.
31843185
31853186
See :doc:`/gallery/statistics/errorbar_features`
31863187
for an example on the usage of ``xerr`` and ``yerr``.
@@ -3284,6 +3285,18 @@ def errorbar(self, x, y, yerr=None, xerr=None,
32843285
if len(x) != len(y):
32853286
raise ValueError("'x' and 'y' must have the same size")
32863287

3288+
def has_negative_values(array):
3289+
if array is None:
3290+
return False
3291+
try:
3292+
return np.any(array < 0)
3293+
except TypeError: # if array contains 'datetime.timedelta' types
3294+
return np.any(array < timedelta(0))
3295+
3296+
if has_negative_values(xerr) or has_negative_values(yerr):
3297+
raise ValueError(
3298+
"'xerr' and 'yerr' must have non-negative values")
3299+
32873300
if isinstance(errorevery, Integral):
32883301
errorevery = (0, errorevery)
32893302
if isinstance(errorevery, tuple):

lib/matplotlib/tests/test_axes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3513,6 +3513,25 @@ def test_errorbar_every_invalid():
35133513
ax.errorbar(x, y, yerr, errorevery='foobar')
35143514

35153515

3516+
def test_xerr_yerr_positive():
3517+
ax = plt.figure().subplots()
3518+
3519+
error_message = "'xerr' and 'yerr' must have non-negative values"
3520+
3521+
with pytest.raises(ValueError, match=error_message):
3522+
ax.errorbar(x=[0], y=[0], xerr=[[-0.5], [1]], yerr=[[-0.5], [1]])
3523+
with pytest.raises(ValueError, match=error_message):
3524+
ax.errorbar(x=[0], y=[0], xerr=[[-0.5], [1]])
3525+
with pytest.raises(ValueError, match=error_message):
3526+
ax.errorbar(x=[0], y=[0], yerr=[[-0.5], [1]])
3527+
with pytest.raises(ValueError, match=error_message):
3528+
x = np.arange(5)
3529+
y = [datetime.datetime(2021, 9, i * 2 + 1) for i in x]
3530+
ax.errorbar(x=x,
3531+
y=y,
3532+
yerr=datetime.timedelta(days=-10))
3533+
3534+
35163535
@check_figures_equal()
35173536
def test_errorbar_every(fig_test, fig_ref):
35183537
x = np.linspace(0, 1, 15)

0 commit comments

Comments
 (0)