Z-Order Sorting

All,

I have been looking at some of the recent z-order changes and have found an issue that breaks previous behavior. Previously when
items were added to a Figure or an Axes with the same z-order value, they were rendered in order of when they were added, so that
the first one added is 'underneath' the others and the last one added is rendered 'over' all the other items of the same z-order
value. This no longer is the case. The following snippet of code demonstrates the problem:

···

#===============================================================
class ZSortClass( object ):
   def __init__( self, name, zorder = 0 ):
      self.name = name
      self.zorder = zorder
   def doit( self ):
      print "z-order [%s] = %s" % (self.name, self.zorder)

# Instantiate out of order to prove a point
a = ZSortClass( 'a', 0 )
c = ZSortClass( 'c', 0 )
b = ZSortClass( 'b', 0 )

all = [ a, b, c ]
dsu = [ (x.zorder, x.doit, x.name) for x in all ]

print dsu
dsu.sort()
print dsu
#===============================================================

All three instances have the same 'zorder' value, which causes the sort command to resort to sorting on the memory address. This
can change from run to run. In simple cases the memory addresses typically increase in order of instantiation, but in larger blocks
of code, python can perform garbage collection at any time and this would no longer hold true, and cause the effect to appear random
(This is also affecting the rendering of filled continents in basemap). I couldn't think of an easy solution without making some
intrusive changes to what is already in place, so I thought that I'd post my findings for further discussion.

--James Evans

James Evans wrote:

All,

I have been looking at some of the recent z-order changes and have found an issue that breaks previous behavior. Previously when
items were added to a Figure or an Axes with the same z-order value, they were rendered in order of when they were added, so that
the first one added is 'underneath' the others and the last one added is rendered 'over' all the other items of the same z-order
value. This no longer is the case. The following snippet of code demonstrates the problem:

#===============================================================
class ZSortClass( object ):
   def __init__( self, name, zorder = 0 ):
      self.name = name
      self.zorder = zorder
   def doit( self ):
      print "z-order [%s] = %s" % (self.name, self.zorder)

# Instantiate out of order to prove a point
a = ZSortClass( 'a', 0 )
c = ZSortClass( 'c', 0 )
b = ZSortClass( 'b', 0 )

all = [ a, b, c ]
dsu = [ (x.zorder, x.doit, x.name) for x in all ]

print dsu
dsu.sort()
print dsu
#===============================================================

All three instances have the same 'zorder' value, which causes the sort command to resort to sorting on the memory address. This
can change from run to run. In simple cases the memory addresses typically increase in order of instantiation, but in larger blocks
of code, python can perform garbage collection at any time and this would no longer hold true, and cause the effect to appear random
(This is also affecting the rendering of filled continents in basemap). I couldn't think of an easy solution without making some
intrusive changes to what is already in place, so I thought that I'd post my findings for further discussion.

This is easy to fix by using the key kwarg (added in python 2.4) of the sort method, because python uses a stable sort. It looks like it only needs to be fixed in Axes.draw, because Figure.draw has never paid any attention to zorder anyway. I'll do it now.

Eric

···

--James Evans

------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing. Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

James Evans wrote:

All,

I have been looking at some of the recent z-order changes and have found an issue that breaks previous behavior. Previously when
items were added to a Figure or an Axes with the same z-order value, they were rendered in order of when they were added, so that
the first one added is 'underneath' the others and the last one added is rendered 'over' all the other items of the same z-order
value. This no longer is the case. The following snippet of code demonstrates the problem:

#===============================================================
class ZSortClass( object ):
   def __init__( self, name, zorder = 0 ):
      self.name = name
      self.zorder = zorder
   def doit( self ):
      print "z-order [%s] = %s" % (self.name, self.zorder)

# Instantiate out of order to prove a point
a = ZSortClass( 'a', 0 )
c = ZSortClass( 'c', 0 )
b = ZSortClass( 'b', 0 )

all = [ a, b, c ]
dsu = [ (x.zorder, x.doit, x.name) for x in all ]

print dsu
dsu.sort()
print dsu
#===============================================================

All three instances have the same 'zorder' value, which causes the sort command to resort to sorting on the memory address. This
can change from run to run. In simple cases the memory addresses typically increase in order of instantiation, but in larger blocks
of code, python can perform garbage collection at any time and this would no longer hold true, and cause the effect to appear random
(This is also affecting the rendering of filled continents in basemap). I couldn't think of an easy solution without making some
intrusive changes to what is already in place, so I thought that I'd post my findings for further discussion.

Try svn 8000. I think it fixes the problem in Axes and Figure.

Eric

It does now in svn HEAD -- I just added this yesterday.

JDH

···

On Tue, Dec 1, 2009 at 6:21 PM, Eric Firing <efiring@...229...> wrote:

This is easy to fix by using the key kwarg (added in python 2.4) of the
sort method, because python uses a stable sort. It looks like it only
needs to be fixed in Axes.draw, because Figure.draw has never paid any
attention to zorder anyway. I'll do it now.

John Hunter wrote:

···

On Tue, Dec 1, 2009 at 6:21 PM, Eric Firing <efiring@...229...> wrote:

This is easy to fix by using the key kwarg (added in python 2.4) of the
sort method, because python uses a stable sort. It looks like it only
needs to be fixed in Axes.draw, because Figure.draw has never paid any
attention to zorder anyway. I'll do it now.

It does now in svn HEAD -- I just added this yesterday.

Yes, I saw that after I sent the first message, so I stabilized the sort in Figure.draw also.

Eric

The recent zorder-related changes broke the some of the rasterization
feature, and I just committed a fix. In doing so, I replaced

        dsu.sort(key=lambda x: x[0])

to

        dsu.sort(key=itemgetter(0))

which I think is slightly faster (although speed is not much of concern here).

Regards,

-JJ

···

On Tue, Dec 1, 2009 at 11:17 PM, Eric Firing <efiring@...229...> wrote:

John Hunter wrote:

On Tue, Dec 1, 2009 at 6:21 PM, Eric Firing <efiring@...229...> wrote:

This is easy to fix by using the key kwarg (added in python 2.4) of the
sort method, because python uses a stable sort. It looks like it only
needs to be fixed in Axes.draw, because Figure.draw has never paid any
attention to zorder anyway. I'll do it now.

It does now in svn HEAD -- I just added this yesterday.

Yes, I saw that after I sent the first message, so I stabilized the sort
in Figure.draw also.

Eric

------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing.
Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Jae-Joon Lee wrote:

The recent zorder-related changes broke the some of the rasterization
feature, and I just committed a fix.

Thanks Jae-Joon.

Is it easy to turn this into a test so that it never unintentionally crops up again?

Thanks,
Andrew

Jae-Joon Lee wrote:

The recent zorder-related changes broke the some of the rasterization
feature, and I just committed a fix. In doing so, I replaced

        dsu.sort(key=lambda x: x[0])

to

        dsu.sort(key=itemgetter(0))

which I think is slightly faster (although speed is not much of concern here).

Jae-Joon,

Thanks for pointing that out. I didn't even know about itemgetter; I have never paid any attention to the operator module.

Eric