Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9f28318

Browse files
committed
Merge pull request #2452 from larrybradley/limitfix
Fixed issues with errorbar limits
2 parents f93ab9b + 7cc983d commit 9f28318

File tree

8 files changed

+2240
-90
lines changed

8 files changed

+2240
-90
lines changed

doc/api/api_changes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ original location:
4747
- mstream -> `from matplotlib import stream as mstream`
4848
- mtable -> `from matplotlib import table as mtable`
4949

50+
* The :func:`~matplotlib.pyplot.errorbar` method has been changed such that
51+
the upper and lower limits (*lolims*, *uplims*, *xlolims*, *xuplims*) now
52+
point in the correct direction.
53+
5054
* The Sphinx extensions `ipython_directive` and
5155
`ipython_console_highlighting` have been moved to the IPython
5256
project itself. While they remain in matplotlib for this release,

doc/users/whats_new.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ specify wedgeprops = {'linewidth':3} to specify the width of the borders of
139139
the wedges in the pie. For more properties that the user can specify, look at
140140
the docs for the wedge and text objects.
141141

142+
Fixed the direction of errorbar upper/lower limits
143+
``````````````````````````````````````````````````
144+
Larry Bradley fixed the :func:`~matplotlib.pyplot.errorbar` method such
145+
that the upper and lower limits (*lolims*, *uplims*, *xlolims*,
146+
*xuplims*) now point in the correct direction.
142147

143148
Date handling
144149
-------------
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
Demo of the errorbar function, including upper and lower limits
3+
"""
4+
import numpy as np
5+
import matplotlib.pyplot as plt
6+
7+
# example data
8+
x = np.arange(0.5, 5.5, 0.5)
9+
y = np.exp(-x)
10+
xerr = 0.1
11+
yerr = 0.2
12+
ls = 'dotted'
13+
14+
fig = plt.figure()
15+
ax = fig.add_subplot(1, 1, 1)
16+
17+
# standard error bars
18+
plt.errorbar(x, y, xerr=xerr, yerr=yerr, ls=ls, color='blue')
19+
20+
# including upper limits
21+
uplims = np.zeros(x.shape)
22+
uplims[[1, 5, 9]] = True
23+
plt.errorbar(x, y+0.5, xerr=xerr, yerr=yerr, uplims=uplims, ls=ls,
24+
color='green')
25+
26+
# including lower limits
27+
lolims = np.zeros(x.shape)
28+
lolims[[2, 4, 8]] = True
29+
plt.errorbar(x, y+1.0, xerr=xerr, yerr=yerr, lolims=lolims, ls=ls,
30+
color='red')
31+
32+
# including upper and lower limits
33+
plt.errorbar(x, y+1.5, marker='o', ms=8, xerr=xerr, yerr=yerr,
34+
lolims=lolims, uplims=uplims, ls=ls, color='magenta')
35+
36+
# including xlower and xupper limits
37+
xerr = 0.2
38+
yerr = np.zeros(x.shape) + 0.2
39+
yerr[[3, 6]] = 0.3
40+
xlolims = lolims
41+
xuplims = uplims
42+
lolims = np.zeros(x.shape)
43+
uplims = np.zeros(x.shape)
44+
lolims[[6]] = True
45+
uplims[[3]] = True
46+
plt.errorbar(x, y+2.1, marker='o', ms=8, xerr=xerr, yerr=yerr,
47+
xlolims=xlolims, xuplims=xuplims, uplims=uplims, lolims=lolims,
48+
ls='none', mec='blue', capsize=0, color='cyan')
49+
50+
ax.set_xlim((0, 5.5))
51+
ax.set_title('Errorbar upper and lower limits')
52+
plt.show()
53+

lib/matplotlib/axes/_axes.py

Lines changed: 103 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2602,7 +2602,9 @@ def errorbar(self, x, y, yerr=None, xerr=None,
26022602
These arguments can be used to indicate that a value gives
26032603
only upper/lower limits. In that case a caret symbol is
26042604
used to indicate this. lims-arguments may be of the same
2605-
type as *xerr* and *yerr*.
2605+
type as *xerr* and *yerr*. To use limits with inverted
2606+
axes, :meth:`set_xlim` or :meth:`set_ylim` must be called
2607+
before :meth:`errorbar`.
26062608
26072609
*errorevery*: positive integer
26082610
subsamples the errorbars. e.g., if everyerror=5, errorbars for
@@ -2682,16 +2684,12 @@ def errorbar(self, x, y, yerr=None, xerr=None,
26822684
if elinewidth:
26832685
lines_kw['linewidth'] = elinewidth
26842686
else:
2685-
if 'linewidth' in kwargs:
2686-
lines_kw['linewidth'] = kwargs['linewidth']
2687-
if 'lw' in kwargs:
2688-
lines_kw['lw'] = kwargs['lw']
2689-
if 'transform' in kwargs:
2690-
lines_kw['transform'] = kwargs['transform']
2691-
if 'alpha' in kwargs:
2692-
lines_kw['alpha'] = kwargs['alpha']
2693-
if 'zorder' in kwargs:
2694-
lines_kw['zorder'] = kwargs['zorder']
2687+
for key in ('linewidth', 'lw'):
2688+
if key in kwargs:
2689+
lines_kw[key] = kwargs[key]
2690+
for key in ('transform', 'alpha', 'zorder'):
2691+
if key in kwargs:
2692+
lines_kw[key] = kwargs[key]
26952693

26962694
# arrays fine here, they are booleans and hence not units
26972695
if not iterable(lolims):
@@ -2727,29 +2725,21 @@ def xywhere(xs, ys, mask):
27272725
ys = [thisy for thisy, b in zip(ys, mask) if b]
27282726
return xs, ys
27292727

2728+
plot_kw = {'label': '_nolegend_'}
27302729
if capsize > 0:
2731-
plot_kw = {
2732-
'ms': 2 * capsize,
2733-
'label': '_nolegend_'}
2734-
if capthick is not None:
2735-
# 'mew' has higher priority, I believe,
2736-
# if both 'mew' and 'markeredgewidth' exists.
2737-
# So, save capthick to markeredgewidth so that
2738-
# explicitly setting mew or markeredgewidth will
2739-
# over-write capthick.
2740-
plot_kw['markeredgewidth'] = capthick
2741-
# For backwards-compat, allow explicit setting of
2742-
# 'mew' or 'markeredgewidth' to over-ride capthick.
2743-
if 'markeredgewidth' in kwargs:
2744-
plot_kw['markeredgewidth'] = kwargs['markeredgewidth']
2745-
if 'mew' in kwargs:
2746-
plot_kw['mew'] = kwargs['mew']
2747-
if 'transform' in kwargs:
2748-
plot_kw['transform'] = kwargs['transform']
2749-
if 'alpha' in kwargs:
2750-
plot_kw['alpha'] = kwargs['alpha']
2751-
if 'zorder' in kwargs:
2752-
plot_kw['zorder'] = kwargs['zorder']
2730+
plot_kw['ms'] = 2. * capsize
2731+
if capthick is not None:
2732+
# 'mew' has higher priority, I believe,
2733+
# if both 'mew' and 'markeredgewidth' exists.
2734+
# So, save capthick to markeredgewidth so that
2735+
# explicitly setting mew or markeredgewidth will
2736+
# over-write capthick.
2737+
plot_kw['markeredgewidth'] = capthick
2738+
# For backwards-compat, allow explicit setting of
2739+
# 'mew' or 'markeredgewidth' to over-ride capthick.
2740+
for key in ('markeredgewidth', 'mew', 'transform', 'alpha', 'zorder'):
2741+
if key in kwargs:
2742+
plot_kw[key] = kwargs[key]
27532743

27542744
if xerr is not None:
27552745
if (iterable(xerr) and len(xerr) == 2 and
@@ -2766,38 +2756,48 @@ def xywhere(xs, ys, mask):
27662756
right = [thisx + thiserr for (thisx, thiserr)
27672757
in cbook.safezip(x, xerr)]
27682758

2769-
yo, _ = xywhere(y, right, everymask)
2770-
lo, ro = xywhere(left, right, everymask)
2771-
barcols.append(self.hlines(yo, lo, ro, **lines_kw))
2772-
if capsize > 0:
2773-
if xlolims.any():
2774-
# can't use numpy logical indexing since left and
2775-
# y are lists
2776-
leftlo, ylo = xywhere(left, y, xlolims & everymask)
2777-
2778-
caplines.extend(
2779-
self.plot(leftlo, ylo, ls='None',
2780-
marker=mlines.CARETLEFT, **plot_kw))
2781-
xlolims = ~xlolims
2782-
leftlo, ylo = xywhere(left, y, xlolims & everymask)
2783-
caplines.extend(self.plot(leftlo, ylo, 'k|', **plot_kw))
2759+
# select points without upper/lower limits in x and
2760+
# draw normal errorbars for these points
2761+
noxlims = ~(xlolims | xuplims)
2762+
if noxlims.any():
2763+
yo, _ = xywhere(y, right, noxlims & everymask)
2764+
lo, ro = xywhere(left, right, noxlims & everymask)
2765+
barcols.append(self.hlines(yo, lo, ro, **lines_kw))
2766+
if capsize > 0:
2767+
caplines.extend(self.plot(lo, yo, 'k|', **plot_kw))
2768+
caplines.extend(self.plot(ro, yo, 'k|', **plot_kw))
2769+
2770+
if xlolims.any():
2771+
yo, _ = xywhere(y, right, xlolims & everymask)
2772+
lo, ro = xywhere(x, right, xlolims & everymask)
2773+
barcols.append(self.hlines(yo, lo, ro, **lines_kw))
2774+
rightup, yup = xywhere(right, y, xlolims & everymask)
2775+
if self.xaxis_inverted():
2776+
marker = mlines.CARETLEFT
27842777
else:
2785-
2786-
leftlo, ylo = xywhere(left, y, everymask)
2787-
caplines.extend(self.plot(leftlo, ylo, 'k|', **plot_kw))
2788-
2789-
if xuplims.any():
2790-
2791-
rightup, yup = xywhere(right, y, xuplims & everymask)
2792-
caplines.extend(
2793-
self.plot(rightup, yup, ls='None',
2794-
marker=mlines.CARETRIGHT, **plot_kw))
2795-
xuplims = ~xuplims
2796-
rightup, yup = xywhere(right, y, xuplims & everymask)
2797-
caplines.extend(self.plot(rightup, yup, 'k|', **plot_kw))
2778+
marker = mlines.CARETRIGHT
2779+
caplines.extend(
2780+
self.plot(rightup, yup, ls='None', marker=marker,
2781+
**plot_kw))
2782+
if capsize > 0:
2783+
xlo, ylo = xywhere(x, y, xlolims & everymask)
2784+
caplines.extend(self.plot(xlo, ylo, 'k|', **plot_kw))
2785+
2786+
if xuplims.any():
2787+
yo, _ = xywhere(y, right, xuplims & everymask)
2788+
lo, ro = xywhere(left, x, xuplims & everymask)
2789+
barcols.append(self.hlines(yo, lo, ro, **lines_kw))
2790+
leftlo, ylo = xywhere(left, y, xuplims & everymask)
2791+
if self.xaxis_inverted():
2792+
marker = mlines.CARETRIGHT
27982793
else:
2799-
rightup, yup = xywhere(right, y, everymask)
2800-
caplines.extend(self.plot(rightup, yup, 'k|', **plot_kw))
2794+
marker = mlines.CARETLEFT
2795+
caplines.extend(
2796+
self.plot(leftlo, ylo, ls='None', marker=marker,
2797+
**plot_kw))
2798+
if capsize > 0:
2799+
xup, yup = xywhere(x, y, xuplims & everymask)
2800+
caplines.extend(self.plot(xup, yup, 'k|', **plot_kw))
28012801

28022802
if yerr is not None:
28032803
if (iterable(yerr) and len(yerr) == 2 and
@@ -2814,35 +2814,48 @@ def xywhere(xs, ys, mask):
28142814
upper = [thisy + thiserr for (thisy, thiserr)
28152815
in cbook.safezip(y, yerr)]
28162816

2817-
xo, _ = xywhere(x, lower, everymask)
2818-
lo, uo = xywhere(lower, upper, everymask)
2819-
barcols.append(self.vlines(xo, lo, uo, **lines_kw))
2820-
if capsize > 0:
2821-
2822-
if lolims.any():
2823-
xlo, lowerlo = xywhere(x, lower, lolims & everymask)
2824-
caplines.extend(
2825-
self.plot(xlo, lowerlo, ls='None',
2826-
marker=mlines.CARETDOWN, **plot_kw))
2827-
lolims = ~lolims
2828-
xlo, lowerlo = xywhere(x, lower, lolims & everymask)
2829-
caplines.extend(self.plot(xlo, lowerlo, 'k_', **plot_kw))
2817+
# select points without upper/lower limits in y and
2818+
# draw normal errorbars for these points
2819+
noylims = ~(lolims | uplims)
2820+
if noylims.any():
2821+
xo, _ = xywhere(x, lower, noylims & everymask)
2822+
lo, uo = xywhere(lower, upper, noylims & everymask)
2823+
barcols.append(self.vlines(xo, lo, uo, **lines_kw))
2824+
if capsize > 0:
2825+
caplines.extend(self.plot(xo, lo, 'k_', **plot_kw))
2826+
caplines.extend(self.plot(xo, uo, 'k_', **plot_kw))
2827+
2828+
if lolims.any():
2829+
xo, _ = xywhere(x, lower, lolims & everymask)
2830+
lo, uo = xywhere(y, upper, lolims & everymask)
2831+
barcols.append(self.vlines(xo, lo, uo, **lines_kw))
2832+
xup, upperup = xywhere(x, upper, lolims & everymask)
2833+
if self.yaxis_inverted():
2834+
marker = mlines.CARETDOWN
28302835
else:
2831-
xlo, lowerlo = xywhere(x, lower, everymask)
2832-
caplines.extend(self.plot(xlo, lowerlo, 'k_', **plot_kw))
2833-
2834-
if uplims.any():
2835-
xup, upperup = xywhere(x, upper, uplims & everymask)
2836-
2837-
caplines.extend(
2838-
self.plot(xup, upperup, ls='None',
2839-
marker=mlines.CARETUP, **plot_kw))
2840-
uplims = ~uplims
2841-
xup, upperup = xywhere(x, upper, uplims & everymask)
2842-
caplines.extend(self.plot(xup, upperup, 'k_', **plot_kw))
2836+
marker = mlines.CARETUP
2837+
caplines.extend(
2838+
self.plot(xup, upperup, ls='None', marker=marker,
2839+
**plot_kw))
2840+
if capsize > 0:
2841+
xlo, ylo = xywhere(x, y, lolims & everymask)
2842+
caplines.extend(self.plot(xlo, ylo, 'k_', **plot_kw))
2843+
2844+
if uplims.any():
2845+
xo, _ = xywhere(x, lower, uplims & everymask)
2846+
lo, uo = xywhere(lower, y, uplims & everymask)
2847+
barcols.append(self.vlines(xo, lo, uo, **lines_kw))
2848+
xlo, lowerlo = xywhere(x, lower, uplims & everymask)
2849+
if self.yaxis_inverted():
2850+
marker = mlines.CARETUP
28432851
else:
2844-
xup, upperup = xywhere(x, upper, everymask)
2845-
caplines.extend(self.plot(xup, upperup, 'k_', **plot_kw))
2852+
marker = mlines.CARETDOWN
2853+
caplines.extend(
2854+
self.plot(xlo, lowerlo, ls='None', marker=marker,
2855+
**plot_kw))
2856+
if capsize > 0:
2857+
xup, yup = xywhere(x, y, uplims & everymask)
2858+
caplines.extend(self.plot(xup, yup, 'k_', **plot_kw))
28462859

28472860
if not barsabove and fmt is not None:
28482861
l0, = self.plot(x, y, fmt, **kwargs)
Binary file not shown.

0 commit comments

Comments
 (0)