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 31d5636

Browse filesBrowse files
authored
Merge pull request #19869 from anntzer/errorbarxy
Factor out x/y lo/hi handling in errorbar.
2 parents ab07898 + 9113e53 commit 31d5636
Copy full SHA for 31d5636

File tree

Expand file treeCollapse file tree

1 file changed

+50
-100
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+50
-100
lines changed

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+50-100Lines changed: 50 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -3409,116 +3409,66 @@ def errorbar(self, x, y, yerr=None, xerr=None,
34093409
barcols = []
34103410
caplines = []
34113411

3412-
# arrays fine here, they are booleans and hence not units
3413-
lolims = np.broadcast_to(lolims, len(x)).astype(bool)
3414-
uplims = np.broadcast_to(uplims, len(x)).astype(bool)
3415-
xlolims = np.broadcast_to(xlolims, len(x)).astype(bool)
3416-
xuplims = np.broadcast_to(xuplims, len(x)).astype(bool)
3417-
34183412
# Vectorized fancy-indexer.
34193413
def apply_mask(arrays, mask): return [array[mask] for array in arrays]
34203414

3421-
def extract_err(name, err, data, lolims, uplims):
3422-
"""
3423-
Private function to compute error bars.
3424-
3425-
Parameters
3426-
----------
3427-
name : {'x', 'y'}
3428-
Name used in the error message.
3429-
err : array-like
3430-
xerr or yerr from errorbar().
3431-
data : array-like
3432-
x or y from errorbar().
3433-
lolims : array-like
3434-
Error is only applied on **upper** side when this is True. See
3435-
the note in the main docstring about this parameter's name.
3436-
uplims : array-like
3437-
Error is only applied on **lower** side when this is True. See
3438-
the note in the main docstring about this parameter's name.
3439-
"""
3415+
# dep: dependent dataset, indep: independent dataset
3416+
for (dep_axis, dep, err, lolims, uplims, indep, lines_func,
3417+
marker, lomarker, himarker) in [
3418+
("x", x, xerr, xlolims, xuplims, y, self.hlines,
3419+
"|", mlines.CARETRIGHTBASE, mlines.CARETLEFTBASE),
3420+
("y", y, yerr, lolims, uplims, x, self.vlines,
3421+
"_", mlines.CARETUPBASE, mlines.CARETDOWNBASE),
3422+
]:
3423+
if err is None:
3424+
continue
3425+
lolims = np.broadcast_to(lolims, len(dep)).astype(bool)
3426+
uplims = np.broadcast_to(uplims, len(dep)).astype(bool)
34403427
try:
3441-
np.broadcast_to(err, (2, len(data)))
3428+
np.broadcast_to(err, (2, len(dep)))
34423429
except ValueError:
34433430
raise ValueError(
3444-
f"'{name}err' (shape: {np.shape(err)}) must be a scalar "
3445-
f"or a 1D or (2, n) array-like whose shape matches "
3446-
f"'{name}' (shape: {np.shape(data)})") from None
3431+
f"'{dep_axis}err' (shape: {np.shape(err)}) must be a "
3432+
f"scalar or a 1D or (2, n) array-like whose shape matches "
3433+
f"'{dep_axis}' (shape: {np.shape(dep)})") from None
34473434
# This is like
3448-
# low, high = np.broadcast_to(...)
3449-
# return data - low * ~lolims, data + high * ~uplims
3435+
# elow, ehigh = np.broadcast_to(...)
3436+
# return dep - elow * ~lolims, dep + ehigh * ~uplims
34503437
# except that broadcast_to would strip units.
3451-
return data + np.row_stack([-(1 - lolims), 1 - uplims]) * err
3452-
3453-
if xerr is not None:
3454-
left, right = extract_err('x', xerr, x, xlolims, xuplims)
3455-
barcols.append(self.hlines(
3456-
*apply_mask([y, left, right], everymask), **eb_lines_style))
3457-
# select points without upper/lower limits in x and
3458-
# draw normal errorbars for these points
3459-
noxlims = ~(xlolims | xuplims)
3460-
if noxlims.any() and capsize > 0:
3461-
yo, lo, ro = apply_mask([y, left, right], noxlims & everymask)
3462-
caplines.extend([
3463-
mlines.Line2D(lo, yo, marker='|', **eb_cap_style),
3464-
mlines.Line2D(ro, yo, marker='|', **eb_cap_style)])
3465-
if xlolims.any():
3466-
xo, yo, ro = apply_mask([x, y, right], xlolims & everymask)
3467-
if self.xaxis_inverted():
3468-
marker = mlines.CARETLEFTBASE
3469-
else:
3470-
marker = mlines.CARETRIGHTBASE
3471-
caplines.append(mlines.Line2D(
3472-
ro, yo, ls='None', marker=marker, **eb_cap_style))
3473-
if capsize > 0:
3474-
caplines.append(mlines.Line2D(
3475-
xo, yo, marker='|', **eb_cap_style))
3476-
if xuplims.any():
3477-
xo, yo, lo = apply_mask([x, y, left], xuplims & everymask)
3478-
if self.xaxis_inverted():
3479-
marker = mlines.CARETRIGHTBASE
3480-
else:
3481-
marker = mlines.CARETLEFTBASE
3482-
caplines.append(mlines.Line2D(
3483-
lo, yo, ls='None', marker=marker, **eb_cap_style))
3484-
if capsize > 0:
3485-
caplines.append(mlines.Line2D(
3486-
xo, yo, marker='|', **eb_cap_style))
3487-
3488-
if yerr is not None:
3489-
lower, upper = extract_err('y', yerr, y, lolims, uplims)
3490-
barcols.append(self.vlines(
3491-
*apply_mask([x, lower, upper], everymask), **eb_lines_style))
3492-
# select points without upper/lower limits in y and
3493-
# draw normal errorbars for these points
3494-
noylims = ~(lolims | uplims)
3495-
if noylims.any() and capsize > 0:
3496-
xo, lo, uo = apply_mask([x, lower, upper], noylims & everymask)
3497-
caplines.extend([
3498-
mlines.Line2D(xo, lo, marker='_', **eb_cap_style),
3499-
mlines.Line2D(xo, uo, marker='_', **eb_cap_style)])
3500-
if lolims.any():
3501-
xo, yo, uo = apply_mask([x, y, upper], lolims & everymask)
3502-
if self.yaxis_inverted():
3503-
marker = mlines.CARETDOWNBASE
3504-
else:
3505-
marker = mlines.CARETUPBASE
3506-
caplines.append(mlines.Line2D(
3507-
xo, uo, ls='None', marker=marker, **eb_cap_style))
3508-
if capsize > 0:
3509-
caplines.append(mlines.Line2D(
3510-
xo, yo, marker='_', **eb_cap_style))
3511-
if uplims.any():
3512-
xo, yo, lo = apply_mask([x, y, lower], uplims & everymask)
3513-
if self.yaxis_inverted():
3514-
marker = mlines.CARETUPBASE
3515-
else:
3516-
marker = mlines.CARETDOWNBASE
3517-
caplines.append(mlines.Line2D(
3518-
xo, lo, ls='None', marker=marker, **eb_cap_style))
3438+
low, high = dep + np.row_stack([-(1 - lolims), 1 - uplims]) * err
3439+
3440+
barcols.append(lines_func(
3441+
*apply_mask([indep, low, high], everymask), **eb_lines_style))
3442+
# Normal errorbars for points without upper/lower limits.
3443+
nolims = ~(lolims | uplims)
3444+
if nolims.any() and capsize > 0:
3445+
indep_masked, lo_masked, hi_masked = apply_mask(
3446+
[indep, low, high], nolims & everymask)
3447+
for lh_masked in [lo_masked, hi_masked]:
3448+
# Since this has to work for x and y as dependent data, we
3449+
# first set both x and y to the independent variable and
3450+
# overwrite the respective dependent data in a second step.
3451+
line = mlines.Line2D(indep_masked, indep_masked,
3452+
marker=marker, **eb_cap_style)
3453+
line.set(**{f"{dep_axis}data": lh_masked})
3454+
caplines.append(line)
3455+
for idx, (lims, hl) in enumerate([(lolims, high), (uplims, low)]):
3456+
if not lims.any():
3457+
continue
3458+
hlmarker = (
3459+
himarker
3460+
if getattr(self, f"{dep_axis}axis").get_inverted() ^ idx
3461+
else lomarker)
3462+
x_masked, y_masked, hl_masked = apply_mask(
3463+
[x, y, hl], lims & everymask)
3464+
# As above, we set the dependent data in a second step.
3465+
line = mlines.Line2D(x_masked, y_masked,
3466+
marker=hlmarker, **eb_cap_style)
3467+
line.set(**{f"{dep_axis}data": hl_masked})
3468+
caplines.append(line)
35193469
if capsize > 0:
35203470
caplines.append(mlines.Line2D(
3521-
xo, yo, marker='_', **eb_cap_style))
3471+
x_masked, y_masked, marker=marker, **eb_cap_style))
35223472

35233473
for l in caplines:
35243474
self.add_line(l)

0 commit comments

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