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

Skip to content

Commit 52e93d1

Browse files
committed
Sync caps of errorbar3d with 2d.
There are a few differences that cause some image changes: * When both upper and lower limits are True, `errorbar3d` incorrectly used full errorbar length for them. They should both have 0 errorbar with the arrow-head cap. * The arrow-head cap should use `eb_cap_style`, not `eb_lines_style`. This meant that the capsize defaulted to 0, so this was made explicitly non-zero in the test. * The baseline of the triangle (bottom/top for caps above/below a line) in 2D is aligned with the end of the errorbar, *not* the tip of the triangle, so all quivers in 3D shifted outward to match. * The quiver would preferably not overlap the existing errorbar, which I've hopefully achieved by setting the length based on `capsize`, and using the above positioning. Consequently, `arrow_length_ratio` is no longer exposed.
1 parent bfc744d commit 52e93d1

File tree

4 files changed

+17
-35
lines changed

4 files changed

+17
-35
lines changed

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,10 +2999,6 @@ def errorbar(self, x, y, z, zerr=None, yerr=None, xerr=None, fmt='',
29992999
Used to avoid overlapping error bars when two series share x-axis
30003000
values.
30013001
3002-
arrow_length_ratio : float, default: 0.4
3003-
Passed to :meth:`quiver`, the ratio of the arrow head with respect
3004-
to the quiver.
3005-
30063002
Returns
30073003
-------
30083004
errlines : list
@@ -3143,14 +3139,8 @@ def _extract_errs(err, data, lomask, himask):
31433139
else:
31443140
low_err, high_err = err, err
31453141

3146-
# for compatibility with the 2d errorbar function, when both upper
3147-
# and lower limits specified, we need to draw the markers / line
3148-
common_mask = (lomask == himask) & everymask
3149-
_lomask = lomask | common_mask
3150-
_himask = himask | common_mask
3151-
3152-
lows = np.where(_lomask, data - low_err, data)
3153-
highs = np.where(_himask, data + high_err, data)
3142+
lows = np.where(lomask | ~everymask, data, data - low_err)
3143+
highs = np.where(himask | ~everymask, data, data + high_err)
31543144

31553145
return lows, highs
31563146

@@ -3185,18 +3175,16 @@ def _extract_errs(err, data, lomask, himask):
31853175
lolims = np.broadcast_to(lolims, len(data)).astype(bool)
31863176
uplims = np.broadcast_to(uplims, len(data)).astype(bool)
31873177

3188-
nolims = ~(lolims | uplims)
3189-
31903178
# a nested list structure that expands to (xl,xh),(yl,yh),(zl,zh),
31913179
# where x/y/z and l/h correspond to dimensions and low/high
31923180
# positions of errorbars in a dimension we're looping over
31933181
coorderr = [
3194-
_extract_errs(err * dir_vector[i], coord,
3195-
~lolims & everymask, ~uplims & everymask)
3182+
_extract_errs(err * dir_vector[i], coord, lolims, uplims)
31963183
for i, coord in enumerate([x, y, z])]
31973184
(xl, xh), (yl, yh), (zl, zh) = coorderr
31983185

31993186
# draws capmarkers - flat caps orthogonal to the error bars
3187+
nolims = ~(lolims | uplims)
32003188
if nolims.any() and capsize > 0:
32013189
lo_caps_xyz = _apply_mask([xl, yl, zl], nolims & everymask)
32023190
hi_caps_xyz = _apply_mask([xh, yh, zh], nolims & everymask)
@@ -3214,24 +3202,18 @@ def _extract_errs(err, data, lomask, himask):
32143202
caplines.append(cap_lo)
32153203
caplines.append(cap_hi)
32163204

3217-
if (lolims | uplims).any():
3218-
limits = [
3219-
_extract_errs(err*dir_vector[i], coord, uplims, lolims)
3220-
for i, coord in enumerate([x, y, z])]
3221-
3222-
(xlo, xup), (ylo, yup), (zlo, zup) = limits
3223-
lomask = lolims & everymask
3224-
upmask = uplims & everymask
3225-
lolims_xyz = np.array(_apply_mask([xlo, ylo, zlo], upmask))
3226-
uplims_xyz = np.array(_apply_mask([xup, yup, zup], lomask))
3227-
lo_xyz = np.array(_apply_mask([x, y, z], upmask))
3228-
up_xyz = np.array(_apply_mask([x, y, z], lomask))
3229-
x0, y0, z0 = np.concatenate([lo_xyz, up_xyz], axis=-1)
3230-
dx, dy, dz = np.concatenate([lolims_xyz - lo_xyz,
3231-
uplims_xyz - up_xyz], axis=-1)
3232-
self.quiver(x0, y0, z0, dx, dy, dz,
3233-
arrow_length_ratio=arrow_length_ratio,
3234-
**eb_lines_style)
3205+
if lolims.any():
3206+
xh0, yh0, zh0 = _apply_mask([xh, yh, zh], lolims & everymask)
3207+
self.quiver(xh0, yh0, zh0, *dir_vector,
3208+
length=eb_cap_style.get('markersize', 0) / 30,
3209+
arrow_length_ratio=1,
3210+
**eb_cap_style)
3211+
if uplims.any():
3212+
xl0, yl0, zl0 = _apply_mask([xl, yl, zl], uplims & everymask)
3213+
self.quiver(xl0, yl0, zl0, *-dir_vector,
3214+
length=eb_cap_style.get('markersize', 0) / 30,
3215+
arrow_length_ratio=1,
3216+
**eb_cap_style)
32353217

32363218
errline = art3d.Line3DCollection(np.array(coorderr).T,
32373219
**eb_lines_style)

lib/mpl_toolkits/tests/test_mplot3d.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,7 @@ def test_errorbar3d_errorevery():
11041104
zlolims = (i % estep == 0) & (i // estep % 3 == 2)
11051105

11061106
ax.errorbar(x, y, z, 0.2, zuplims=zuplims, zlolims=zlolims,
1107-
errorevery=estep)
1107+
errorevery=estep, capsize=1)
11081108

11091109

11101110
@mpl3d_image_comparison(['errorbar3d.png'])

0 commit comments

Comments
 (0)