 # Controlling zorder of individual elements of the same type...

Hi all, I am having a bit of a problem with the order

> things get drawn. I looked at the zorder example and
> the docs, but I can't seem to find a solution. Here's
> an illustration:

> The red wiggly line is drawn first, by a loglog() call,
> and then the green one is an axhline() call. However,
> the green line ends up below the red one. It turns out
> that in cases where the range of the red stuff is above
> the green cutoff, this causes the green line to be
> totally obscured. And for my plots, it's important that
> the green line is clearly visible always.

> My naive expectation was that whatever was called last
> on the plot would end up on top, but that doesn't seem
> to be the case. I did a few experiments:

> x=frange(0,2*pi,npts=100) figure()
> plot(x,sin(x),x,cos(x),linewidth=10)
> plot(x,sin(2*x),linewidth=10) axhline(0,linewidth=10)

Hmm, seems to work for me -- you didn't specify the colors in your
example which makes it hard to test, so I'll add them

from pylab import *
x=frange(0,2*pi,npts=100)
figure()
plot(x,sin(x),x,cos(x),linewidth=10, color='red')
plot(x,sin(2*x),linewidth=10, color='green')
axhline(0,linewidth=10, color='blue')
show()

with results at http://matplotlib.sf.net/jdh.png

> And I can't really figure out what determines the zorder
> of all the line objects.

Well the zorder kwarg is your friend -- did you see
examples/zorder_demo.py ? Eg

plot(x,y, zorder=100) # I'm on top!

I think I have an idea of what may be causing the plot order problem
you are experiencing

From axes.py draw method

artists = []
artists.extend(self.collections)
artists.extend(self.patches)
artists.extend(self.lines)
artists.extend(self.texts)

dsu = [ (a.zorder, a) for a in artists]
dsu.sort()

for zorder, a in dsu:
a.draw(renderer)

Now, if I recall correctly, python sort doesn't guarantee preserving
order for equal element. Since the order in the respective list
(patches, lines, etc) *is* determined by the order of the plot
commands, we might be better off with

dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)]
dsu.sort()

for zorder, i, a in dsu:
a.draw(renderer)

to guarantee relative order for artists with the same zorder.

Or is sort relative order preserving for equal elements?

JDH

John Hunter wrote:

Hmm, seems to work for me -- you didn't specify the colors in your
example which makes it hard to test, so I'll add them

Weird. I ran this a ton of times, and in _most_ cases I get your same results. And yet a _few_ times, and only when I pasted the code in an interactive window, the horizontal line ends below the sine/cosine plots. Very, very strange.

Well the zorder kwarg is your friend -- did you see
examples/zorder_demo.py ? Eg

plot(x,y, zorder=100) # I'm on top!

I did read it, but I guess I misunderstood the docstring on top. I understood it as meaning that you could only reorder classes of objects relative to one another (lines, text, patches), but not individual lines within the class of all lines.

Now, if I recall correctly, python sort doesn't guarantee preserving
order for equal element. Since the order in the respective list
(patches, lines, etc) *is* determined by the order of the plot
commands, we might be better off with

dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)]
dsu.sort()
for zorder, i, a in dsu:
a.draw(renderer)

to guarantee relative order for artists with the same zorder.

Or is sort relative order preserving for equal elements?

Well, the funny thing about my sometimes-odd results, is that in python 2.3, list.sort _is_ stable:

So I'm not quite sure why I get odd results in a few cases. And I can't seem to find a reliable way to repeat the behavior.

But thanks for the clarification on the zorder argument, that's enough for me to get the behavior I need.

I'll update the zorder_demo example with a more explicit docstring so others don't fall into the same confusion.

Cheers,

f