Skip to content

zorder is not respected by all parts of errorbar #1622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tacaswell opened this issue Dec 22, 2012 · 10 comments
Closed

zorder is not respected by all parts of errorbar #1622

tacaswell opened this issue Dec 22, 2012 · 10 comments
Assignees
Milestone

Comments

@tacaswell
Copy link
Member

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

@dmcdougall
Copy link
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.

@ghost ghost assigned dmcdougall Dec 30, 2012
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Dec 30, 2012
@tacaswell
Copy link
Member Author

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.

@dmcdougall
Copy link
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.

@dmcdougall
Copy link
Member

Fixed in #1628.

@agbuckley
Copy link

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.

@tacaswell
Copy link
Member Author

@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.

@agbuckley
Copy link

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.

@fkbreitl
Copy link

This bug is back in matplotlib 2.0.0!

@dstansby
Copy link
Member

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.

@tacaswell
Copy link
Member Author

image

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

fixed by #18216

@QuLogic QuLogic modified the milestones: needs sorting, v3.5.0 Apr 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants