John and Michael,

 Thanks for your detailed feedback about the mpl design philosophy. I'm
 not attached to my implementation details. I will scrap the
 draw_raster list and move to implement get/set_rasterized on the
 artists.


 > > Doing this in the axes.draw method may not be the most natural place
 > > to do this since it could be done in the artist.draw method, but it
 > > may be the most expedient.  This is an area where having support for
 > > before_draw and  after_draw hooks might be useful.

 How about providing a decorator for the draw method that would do the
 necessary check/start/draw/stop? Requires Python 2.4 for the nice
 syntax, but can still be done with 2.3.  A decorator would make adding
 the rasterize feature (and others) quite easy for any draw method.
 There are several draw methods in the chain (figure has one, axes has
 one, and line, collections, etc. all do), and this would be a fast,
 low-maintenance way of adding hooks to each artist subclass (I count
 16 2D draw methods). I have a proof-of-concept snippet if it would be
 helpful to understand what I mean.



 > > One potential
 > > problem with either of these approached is it looks like the mixed
 > > mode renderer is set up to handle multiple rasterized draws before
 > > dumping the aggregate image into the backend on a stop_renderer, so
 > > doing the start/stop in any of the approaches above would obviate this
 > > efficiency.
 > >   The axes could aggregate the rasterized artists before
 > > rendering and then do them all together, but making this play properly
 > > with zorder will be tricky.
 > >
 >  That's right.  To receive significant gains, you would generally want to
 > perform a number of drawing operations in a single raster buffer.  Given how
 > mpl is currently designed, that generally implies a Collection (which is
 > fairly easy to wrap start/stop_rasterizing calls around) -- it doesn't
 > necessarily have to mean a whole bunch of separate Artist objects (which
 > would be much harder to do given the current way things are drawn).  The
 > latter may be ultimately more optimal, but the former is an easy win.
 >
 >


>  As for the implementation, Eric's patch does appear to deal with the
 > z-order problem, (by interleaving rasterized and non-rasterized drawing
 > correctly base on zorder), but it doesn't combine adjacent rasterized
 > artists into a single buffer.  The drawing loop in Axes.draw could fairly
 > easily be modified to do that.  However, I think a better solution that
 > doesn't require an explicit "draw_raster" list, is to make
 > "stop_rasterizing" lazy.  At the moment, when "stop_rasterizing" is called,
 > the buffer is immediately flushed and written out.  If instead it just set a
 > flag, causing the buffer to be flushed when the next vector object is
 > written, then something like
 >
 >   start_rasterizing()
 >   draw_line()
 >   stop_rastering()
 >   start_rastering()
 >   draw_line()
 >   stop_rasterizing()
 >   draw_line()
 >
 >  would write out a single raster buffer with two lines, followed by a vector
 > line.  Of course, and here is the tricky bit, if the two rasterized objects
 > are really far apart spatially, you waste a lot of space on transparent
 > pixels between them.  We can let the user decide whether to rasterize each
 > individually with a nice clean API, but letting the user decide whether to
 > combine adjacent rasterizations gets tricky and I think is asking too much
 > of someone who doesn't know the mpl internals.  Perhaps that is an argument
 > against trying to implicitly combine adjacent rasterized draws -- it's
 > trying to be too smart?
 >

 I see the inefficiency in repeated start/stop/flush.  At the same
 time, generating a separate image in each start/stop is useful for
 later tweaking/composition in a vector drawing editor. For instance,
 if I overlay points (sometimes 10^5) on top of weather radar data
 (10^5 polys), I might want to turn the points off. So I'd argue that
 flush-per-artist is best because it creates a figure with maximal
 editability, which is one of the advantages of using a vector-based
 backend in the first place.

 In summary:
 1. On the artist base class, add get/set_rasterized( True | False | None )
 with the default for True to be rasterize-per-artist. Later (or now,
 if it's important to others), ('alone' | 'combine') could be added,
 with True defaulting to 'alone'.

 2. Starting / stopping the rasterizing:

> >   if a.get_rasterized():
 > >       renderer.start_rasterizing()
 > >       a.draw(renderer)
 > >       renderer.stop_rasterizing()
 > >   else:
 > >       a.draw(renderer)
 Put this in a draw method decorator. Decorate each artist subclass
individually.

 -Eric

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to