You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
matplotlib.pyplot.errorbar does follow the plot order, in particular the markers seem to be plot always last. Calls to other plot functions will thus be covered by the errobar markers.
@jklymak Thanks for the reply. I tried that earlier and I can confirm that plt.errorbar(range(10), range(10), fmt='o', zorder=-1) produces the expected result.
That is a good fix for now, but long term I think it would be good to fix this.
I agree this is a bug, and think that the correct fix is along the lines of
diff --git i/lib/matplotlib/axes/_axes.py w/lib/matplotlib/axes/_axes.py
index 3f9d7fede..3da0b40e8 100644
--- i/lib/matplotlib/axes/_axes.py+++ w/lib/matplotlib/axes/_axes.py@@ -3244,7 +3244,6 @@ class Axes(_AxesBase):
# anything that comes in as 'None', drop so the default thing
# happens down stream
kwargs = {k: v for k, v in kwargs.items() if v is not None}
- kwargs.setdefault('zorder', 2)
try:
offset, errorevery = errorevery
@@ -3306,8 +3305,6 @@ class Axes(_AxesBase):
plot_line_style = {
**base_style,
**kwargs,
- 'zorder': (kwargs['zorder'] - .1 if barsabove else- kwargs['zorder'] + .1),
}
# make the style dict for the line collections (the bars)
@@ -3352,7 +3349,6 @@ class Axes(_AxesBase):
data_line = None
if plot_line:
data_line = mlines.Line2D(x, y, **plot_line_style)
- self.add_line(data_line)
barcols = []
caplines = []
@@ -3510,8 +3506,15 @@ class Axes(_AxesBase):
xup, yup = xywhere(x, y, uplims & everymask)
caplines.append(mlines.Line2D(xup, yup, marker='_',
**eb_cap_style))
- for l in caplines:- self.add_line(l)++ if barsabove:+ self.add_line(data_line)+ for l in caplines:+ self.add_line(l)+ else:+ for l in caplines:+ self.add_line(l)+ self.add_line(data_line)
self._request_autoscale_view()
errorbar_container = ErrorbarContainer((data_line, tuple(caplines),
-- basically, achieve support for barsabove by just plotting the elements in the right order, rather than manipulating their zorder, as the latter misinteracts with other plot elements.
As usual, brownie points for whoever takes up this patch and turns it into a proper PR with tests/api_changes/etc.
I started to look into this, and it seems that the vertical errorbars (bar columns) are not following the plot order either, they use vlines which even can make them fall behind the last plot's markers.
I will try to work on this some more, maybe figure out a way to not use vlines.
The vertical bars also won't work together with the patch suggested by @anntzer
@anntzer: It should have worked before applying the patch, but with the changes you proposed above we remove all the zorder calls. I tried to add in eb_lines_style.defautl('zorder', 2.0) which still looks like they fall behind lines previously plotted and raising it to 2.1 means it will appear on top of everything.
Also the calls to vlines mean those objects are instantaneously plot, so that needs to be considered in the calls to add_lines, later on, otherwise the vertical bars will always fall behind the line markers.
Ah yes, so the zorder still needs to be put in the kwargs (but without the 0.1 offset), and the call to vlines needs to be done in the right order relative to the rest rather than immediately.
... except that I guess collections and lines are zsorted separately, argh.
@anntzer. The zsorted issue was kind of on my mind, I know where little about the internals of matplotlib but I was suspecting that might be the case. This seems to agree very well with what I observe.
@QuLogic Thanks for the link, that seems to be very much related.
I have to work right now, but will try to get back to it later today. I think the use of vlines is not optimal here maybe the error bars could be painted by something else?
Drawing the bar columns as Lines2D brings us pretty close to the expected result, but breaks a lot of other tests. It is pretty ugly and not very efficient but my personal opinion, I rather have something slow that does what I would expect than something that behaves oddly. Pushed the fix to my branch, updated the link above, it was broken.
Activity
jklymak commentedon Apr 15, 2020
You can probably workaround w zorder kwarg.
cosama commentedon Apr 15, 2020
@jklymak Thanks for the reply. I tried that earlier and I can confirm that
plt.errorbar(range(10), range(10), fmt='o', zorder=-1)produces the expected result.That is a good fix for now, but long term I think it would be good to fix this.
anntzer commentedon Apr 20, 2020
I agree this is a bug, and think that the correct fix is along the lines of
-- basically, achieve support for
barsaboveby just plotting the elements in the right order, rather than manipulating their zorder, as the latter misinteracts with other plot elements.As usual, brownie points for whoever takes up this patch and turns it into a proper PR with tests/api_changes/etc.
cosama commentedon Apr 22, 2020
I started to look into this, and it seems that the vertical errorbars (bar columns) are not following the plot order either, they use
vlineswhich even can make them fall behind the last plot's markers.I will try to work on this some more, maybe figure out a way to not use
vlines.The vertical bars also won't work together with the patch suggested by @anntzer
anntzer commentedon Apr 22, 2020
zordergets copied intoeb_lines_style, why doesn't that work? can you provide a repro?cosama commentedon Apr 22, 2020
@anntzer: It should have worked before applying the patch, but with the changes you proposed above we remove all the
zordercalls. I tried to add ineb_lines_style.defautl('zorder', 2.0)which still looks like they fall behind lines previously plotted and raising it to2.1means it will appear on top of everything.Also the calls to
vlinesmean those objects are instantaneously plot, so that needs to be considered in the calls toadd_lines, later on, otherwise the vertical bars will always fall behind the line markers.I work on it on https://github.com/cosama/matplotlib/tree/fix-errobar-order, I added a test
lib/matplotlib/tests/test_axes.py::test_errorbar_default_orderwhich illustrates how I would imagine it.anntzer commentedon Apr 22, 2020
Ah yes, so the zorder still needs to be put in the kwargs (but without the 0.1 offset), and the call to vlines needs to be done in the right order relative to the rest rather than immediately.
... except that I guess collections and lines are zsorted separately, argh.
QuLogic commentedon Apr 22, 2020
See also #1622.
cosama commentedon Apr 22, 2020
@anntzer. The zsorted issue was kind of on my mind, I know where little about the internals of matplotlib but I was suspecting that might be the case. This seems to agree very well with what I observe.
@QuLogic Thanks for the link, that seems to be very much related.
I have to work right now, but will try to get back to it later today. I think the use of
vlinesis not optimal here maybe the error bars could be painted by something else?cosama commentedon Apr 22, 2020
Drawing the bar columns as
Lines2Dbrings us pretty close to the expected result, but breaks a lot of other tests. It is pretty ugly and not very efficient but my personal opinion, I rather have something slow that does what I would expect than something that behaves oddly. Pushed the fix to my branch, updated the link above, it was broken.tacaswell commentedon Apr 6, 2021
Closed by #18216