John Hunter wrote:
> Hey Eric, I'm CC-ing the devel list because some of this has
> potentially far reaching consequences.
> 
>>>>>> "Eric" == Eric Firing <[EMAIL PROTECTED]> writes:
> 
>     Eric> In connection with the colorbar sizing problem I have been
>     Eric> thinking about adding a function list to axes, with the
>     Eric> functions to be executed early in the draw() method, to
>     Eric> handle this sort of thing.  Using this mechanism to handle
> 
> I think this is a very nice idea -- I saw a talk at pycon one year about
> the utility of adding hooks, eg before_somefunc_hook and after_somefunc_hook
> that are customizable *for every function in your API*.  The questions are
> 
>   1) what is the right data structure -- a single callable, a
>      sequence, or a dictionary registry with connect/disconnect
>      semantics (eg the backend event callback handler)
> 
>   2) what is the signature (see below)
> 
>   3) which artists should support it
> 
> Most elegant, but most expensive, is something like a ordered
> dictionary which is supported for every artist.  By renaming all the
> artist draw methods _draw, we can do this quite simply in
> backend_bases.Renderer with
> 
> def draw(self, renderer):
>     for func in self.before_draw_hook.ordered_values():
>         func(self, renderer)
> 
>     self._draw(renderer)
> 
>     for func in self.after_draw_hook.ordered_values():
>         func(self, renderer)
> 

Nice, simple, elegant, but it doesn't quite match what I had in mind for 
axes.  I was thinking that the place to put the hook call is inside the 
draw() method, so it can take advantage of the intial work done there: 
getting a cached renderer, checking for visibility.  Maybe this doesn't 
matter.

Also, looking at backend_bases, I can't figure out where this goes. 
There is a RendererBase class, but it doesn't have a draw method.  And 
there is a FigureCanvasBase, but its draw method is overridden by each 
backend.  What am I missing?

> 
> I think this could be really useful and would help handle problems
> that crop up all the time -- how to handle physical layout problems
> where we need the renderer to get size information like you are
> experiencing with colorbar.  This problem also crops up in a lot of
> text layout problems.  Unfortunately, draw time layout creates other
> problems (sometimes users want this info at the API level), and order
> effects becomes very important and potentially complicated.  But that
> said, given the current architecture, something like this would be a
> definite improvement.
> 
> I'm inclined to use an ordered dictionary because one wants the
> connect/disconnect semantics that keys make easy, and because ordering
> matters.  There is a python cookbook recipe for an ordered dictionary,
> and we could easily roll our own.  Because the calls are potentially
> expensive, we might want an optimization like
> 
I agree, an ordered dictionary is ideal if one needs the option of 
multiple functions being executed.  I would probably have it inherit 
from list and tack on the dictionary; I think this might make for the 
fastest cycling through the list, and that is the place where speed is 
needed.

> class MyOrderedDictionary:
>     def __init__(blah):
>         self.isempty = True
> 
> 
> so we can do
> 
> def draw(renderer):
>     if not self.before_draw_hook.isempty:
>         for func in self.before_draw_hook.ordered_values():
>             func(self, renderer)
> 
>     self._draw(renderer)
> 
>     if not self.after_draw_hook.isempty:
>         for func in self.after_draw_hook.ordered_values():
>             func(self, renderer)
> 
> Since 99% of the time I guess these will be empty and then we are just
> adding a few attribute lookups and a boolean check for each draw.

Detail:
Maybe it would be simpler and faster to initialize like this:

     self.before_draw_hook=None

and have
     def register_before_draw(self, name, func):
         if self.before_draw_hook is None:
             self.before_draw_hook = OrderedDictionary()
         self.before_draw_hook.append(name, func)

It saves one attribute lookup at draw time.     

Larger picture:

Looking at the axes draw method, I am wondering whether a more general 
application of an OrderedDictionary (or ListDict, or whatever) wouldn't 
be a better approach.  Why should there be before_draw_hook, draw, and 
after_draw_hook, with a big list generation and sorting operation at 
draw time?  Could everything be done by having artists register all 
draw-time functions in a single ListDict, with sufficient ordering 
information to keep everything straight?  That's pretty vague, and there 
is a lot I don't understand--but it just seems like there is an 
opportunity here for simplifying the overall structure with improved 
flexibility and no loss of speed.  (Again, some kind of result-caching 
and need-for-recomputation-signalling would be needed.)

Eric

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Matplotlib-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to