zorder is not respected by all parts of `errorbar` #1622

Open
tacaswell opened this Issue Dec 22, 2012 · 9 comments

Projects

None yet

5 participants

Owner

This was found by via a SO question (http://stackoverflow.com/questions/14003572/how-to-force-errorbars-to-render-last-with-matplotlib)

It looks like the root cause of this issue is that LineCollections do not take zorder as a parameter.

The hacky work around is to put negative zorder on the lines you want to be below the error bars.

import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.gca()
[ax.plot(rand(50),color='0.75') for j in range(122)];
ax.errorbar(range(50),rand(50),yerr=.3*rand(50))
plt.draw()

eb_wrong

fig = plt.figure()
ax = plt.gca()
[ax.plot(rand(50),color='0.75',zorder=-32) for j in range(122)];
ax.errorbar(range(50),rand(50),yerr=.3*rand(50))
plt.draw()

eb_hack

Member

@tacaswell Commit 6dd3204 looks fine to me. It doesn't look like it's currently a pull request. Would you be able to create one against v1.2.x? Then Travis can do its magic.

@dmcdougall dmcdougall was assigned Dec 30, 2012
@tacaswell tacaswell added a commit to tacaswell/matplotlib that referenced this issue Dec 30, 2012
@tacaswell tacaswell first pass at getting fixing Issue #1622 aa476d8
Owner

Done.

I was not sure the best place to make this fix. I looked at pushing support for zorder all the way down to Collection but went with what I thought was the minimal change instead.

Member

I looked at pushing support for zorder all the way down to Collection...

This is the 'correct' solution, in my opinion.

...but went with what I thought was the minimal change instead.

This is the solution most appropriate for the maintenance branch, in my opinion.

Member

Fixed in #1628.

@dmcdougall dmcdougall closed this Jan 2, 2013

I just encountered the same problem with mpl 1.4.2:

rand

Has this problem resurfaced? I haven't seen any mention of it in the changelog up to 1.4.3.

Owner

@agbuckley This isn't a bug that we can easily fix. If you give a z-order to the errorbar (which is greater than 2) it will now behave correctly.

The underlying issue here is that the errorbar is rendered as three artists, and the lines are rendered as 522 artists. The vertical lines are drawn as a collection, everything else is a line. The collection and lines are stored in different internal lists which are then concatenated and sorted (in a stable manner) by zorder which determines the draw order. The stable part is important because as the lists are appended too in the order they are added to the axes. Hence, in this case the vertical lines (which are a collection) are drawn first, then the gray lines, then blue line and the caps.

I have thoughts on how to fix this, but they involve a rather major refactoring of the internals and are at least a year out.

Ah, I see: the bug that was fixed was non-passing of the z-order to rendering of errorbar verticals, but the counterintuitive implicit ordering (with no zorder argument) is still just part of how mpl is, for now? Good to know... and best of luck for finding time & enthusiasm for that internal refactoring! Thanks.

This bug is back in matplotlib 2.0.0!

@dstansby dstansby reopened this Feb 16, 2017
Contributor

The minimal example at the top of this bug still doesn't work, so I'll reopen to reflect that. In the meantime, passing zorder=3 to plt.errorbar seems to do the trick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment