patch for adding manual label location selection to clabel

Another option would be to create a start_event_loop function like Paul
suggested and overload that function in those backends that aren't
interactive so that it returns an error, but this requires writing one
such function for each non-interactive backend.

Either create a deeper hierarchy:

   FigureCanvasBase:
       def start_event_loop(self, ...):
           raise NotImplemented
   FigureCanvasInteractive:
       def start_event_loop(self, ...):
           generic interactive using time.sleep
   MyInteractiveBackend(FigureCanvasInteractive):
       def start_event_loop(self, ...):
           specialized interactive code using GUI

or a mix-in class:

   FigureCanvasBase:
       def start_event_loop(self, ...):
           raise NotImplemented
   FigureCanvasEventLoopMixin:
       def start_event_loop(self, ...):
           generic interactive using time.sleep
   MyInteractiveBackend(FigureCanvasBase,FigureCanvasEventLoopMixin):
       ... no start_event_loop since using the generic mixin ...

I prefer the latter, particularly since it won't be needed once the
existing interactive backends are implemented.

Also, is there any case
where an event loop would be useful for a graphically non-interactive
backend? If so, this would again mean that this problem would be easier
to deal with once in the Blocking* classes.

No reason to. While you could prompt for graph coordinates at the
command line on a call to ginput, you could also simply prompt for
the coordinates without bothering with ginput.

    - Paul

···

On Thu, Jul 17, 2008 at 09:44:48PM +0200, David M. Kaplan wrote:

+1 one that.

Also, I don't think a exception is a good idea. Simply a warnings.warn
should be enough.

Ga�l

···

On Thu, Jul 17, 2008 at 04:55:42PM -0400, Paul Kienzle wrote:

On Thu, Jul 17, 2008 at 09:44:48PM +0200, David M. Kaplan wrote:
> Another option would be to create a start_event_loop function like Paul
> suggested and overload that function in those backends that aren't
> interactive so that it returns an error, but this requires writing one
> such function for each non-interactive backend.

Either create a deeper hierarchy:

   FigureCanvasBase:
       def start_event_loop(self, ...):
           raise NotImplemented
   FigureCanvasInteractive:
       def start_event_loop(self, ...):
           generic interactive using time.sleep
   MyInteractiveBackend(FigureCanvasInteractive):
       def start_event_loop(self, ...):
           specialized interactive code using GUI

or a mix-in class:

   FigureCanvasBase:
       def start_event_loop(self, ...):
           raise NotImplemented
   FigureCanvasEventLoopMixin:
       def start_event_loop(self, ...):
           generic interactive using time.sleep
   MyInteractiveBackend(FigureCanvasBase,FigureCanvasEventLoopMixin):
       ... no start_event_loop since using the generic mixin ...

I prefer the latter, particularly since it won't be needed once the
existing interactive backends are implemented.

Hi,

   FigureCanvasBase:
       def start_event_loop(self, ...):
           raise NotImplemented
   FigureCanvasEventLoopMixin:
       def start_event_loop(self, ...):
           generic interactive using time.sleep
   MyInteractiveBackend(FigureCanvasBase,FigureCanvasEventLoopMixin):
       ... no start_event_loop since using the generic mixin ...

So just to make sure that I understand this, "MyInteractiveBackend"
would be any backend canvas class for whom we want to implement the
standard generic mixin. For example, the class FigureCanvasGTK would
inherit FigureCanvasEventLoopMixin until we get around to writing
something specific for GTK. On the other hand, FigureCanvasWx wouldn't
inherit the mixin, but would use the WX specific code you sent
yesterday. And FigureCanvasPs wouldn't get anything at all. Am I
getting this?

If so, then I will go ahead and make the appropriate modifications.
Looking at the list of backends, I think it suffices to inherit the
mixin for the following backends: cairo, cocoagg, fltkagg?, gdk?, gtk,
qt4, qt, tkagg (wx covered with its own code). All other interactive
backends should inherit from these. The ones with the question marks I
am not really sure about, but will assume true unless told otherwise.

I agree with Gael that warning is probably sufficient. This will allow
code running in the background to pass over interactive commands such as
ginput. This may be better than an immediate error, but could cause
problems later in the script when data is expected, but one gets [].

Cheers,
David

···

On Thu, 2008-07-17 at 16:55 -0400, Paul Kienzle wrote:

--
**********************************
David M. Kaplan
Charge de Recherche 1
Institut de Recherche pour le Developpement
Centre de Recherche Halieutique Mediterraneenne et Tropicale
av. Jean Monnet
B.P. 171
34203 Sete cedex
France

Phone: +33 (0)4 99 57 32 27
Fax: +33 (0)4 99 57 32 95
http://www.ur097.ird.fr/team/dkaplan/index.html
**********************************

I'm not a huge fan of mixins. We use them occassionally, eg for
FigureCanvasGtkAgg and their are some good uses for them, but they can
quickly lead to overly complex code so should be avoided where
possible. I find the "deeper hierarchy" approach more appealing here,
but am not sure if it is viable. For example

  class FigureCanvasGTKAgg(FigureCanvasGTK, FigureCanvasAgg)

inherits from an interactive and a non-interactive backend, which is a
good example of how quickly multiple mixin inheritance can get tricky.
I think perhaps it is best to create no new classes, put the base
methods in the FigureCanvasBase, make the default behavior
non-interactive, and then overrride them for the GUI backends. Any
problems with this?

Finally, the term "interactive" is a bit confusing and overloaded
here, since "is_interactive" in mpl means someone is working from the
interactive shell and we want to update the figure on every command
(if draw_if_interactive). For clarity, I think we should refer to
this as a "user interface" backend or something like that,. I know in
parts of the backend code we have the designation of interactive
backends, but these variables should probably be renamed to avoid
further confusion, since the other use of interactive is already
enshrined in the frontend api and rc file.

JDH

···

On Fri, Jul 18, 2008 at 4:27 AM, David M. Kaplan <David.Kaplan@...622...> wrote:

So just to make sure that I understand this, "MyInteractiveBackend"
would be any backend canvas class for whom we want to implement the
standard generic mixin. For example, the class FigureCanvasGTK would
inherit FigureCanvasEventLoopMixin until we get around to writing
something specific for GTK. On the other hand, FigureCanvasWx wouldn't
inherit the mixin, but would use the WX specific code you sent
yesterday. And FigureCanvasPs wouldn't get anything at all. Am I
getting this?

If so, then I will go ahead and make the appropriate modifications.
Looking at the list of backends, I think it suffices to inherit the
mixin for the following backends: cairo, cocoagg, fltkagg?, gdk?, gtk,
qt4, qt, tkagg (wx covered with its own code). All other interactive
backends should inherit from these. The ones with the question marks I
am not really sure about, but will assume true unless told otherwise.

Hi,

I'm not a huge fan of mixins. We use them occassionally, eg for
FigureCanvasGtkAgg and their are some good uses for them, but they can
quickly lead to overly complex code so should be avoided where
possible. I find the "deeper hierarchy" approach more appealing here,
but am not sure if it is viable. For example

  class FigureCanvasGTKAgg(FigureCanvasGTK, FigureCanvasAgg)

Actually the case of GTKAgg is an interesting one. I have
FigureCanvasGTK inherit the mixin, but this doesn't cascade to GTKAgg
because it gets overloaded with the non-user-interface versions from
FigureCanvasAgg leading calls to ginput to produce an error. Adding the
mixin to the end of GTKAgg's inheritance list didn't work because it
seems that python decides that Agg has already overwritten the same
mixin included by GTK and ignores the mixin inheritance at the end of
the list (this surprised me, but it appears to work that way). One
could always force it to use the right ones by adding functions that
point to the mixin versions, but this seems less elegant than
inheritance.

In this and similar cases, is the order of inheritance important?
Changing it to (FigureCanvasAgg, FigureCanvasGTK) should fix the
problem.

inherits from an interactive and a non-interactive backend, which is a
good example of how quickly multiple mixin inheritance can get tricky.
I think perhaps it is best to create no new classes, put the base
methods in the FigureCanvasBase, make the default behavior
non-interactive, and then overrride them for the GUI backends. Any
problems with this?

Well, yeah. I think this would mean a lot of the same code in many
backends. I also like the idea of a deeper hierarchy with a
FigureCanvasUserInterface class that inherits FigureCanvasBase but adds
functional start/stop_loop_events because it would allow for a simple
cbook test for a working user interface:
isinstance(mycanvas,FigureCanvasUserInterface)

A deeper hierarchy won't help the inheritance problem for GTKAgg though.

Finally, the term "interactive" is a bit confusing and overloaded
here, since "is_interactive" in mpl means someone is working from the
interactive shell and we want to update the figure on every command
(if draw_if_interactive). For clarity, I think we should refer to
this as a "user interface" backend or something like that,. I know in
parts of the backend code we have the designation of interactive
backends, but these variables should probably be renamed to avoid
further confusion, since the other use of interactive is already
enshrined in the frontend api and rc file.

I agree.

···

On Fri, 2008-07-18 at 09:24 -0500, John Hunter wrote:

On Fri, Jul 18, 2008 at 4:27 AM, David M. Kaplan <David.Kaplan@...622...> wrote:

JDH

--
**********************************
David M. Kaplan
Charge de Recherche 1
Institut de Recherche pour le Developpement
Centre de Recherche Halieutique Mediterraneenne et Tropicale
av. Jean Monnet
B.P. 171
34203 Sete cedex
France

Phone: +33 (0)4 99 57 32 27
Fax: +33 (0)4 99 57 32 95
http://www.ur097.ird.fr/team/dkaplan/index.html
**********************************

Well, yeah. I think this would mean a lot of the same code in many
backends. I also like the idea of a deeper hierarchy with a
FigureCanvasUserInterface class that inherits FigureCanvasBase but adds
functional start/stop_loop_events because it would allow for a simple
cbook test for a working user interface:
isinstance(mycanvas,FigureCanvasUserInterface)

I'm not sure I see where the redundant code is coming in. In envision
the base class doing nothing in start_event_loop and stop_event_loop
which solves the problem for the non-UI backends, and all the UI
backends will have to be specialized to deal with their own event
loops. Basically, we would need to provide implementations for gtk,
tk, wx and qt (and maybe qt4?) since these are the four backends that
are actually maintained. Perhaps I am overly squeamish, but I am
uncomfortable with a default UI implementation here anyhow.

This is the paradigm we have used for the canvas draw_idle method and
it has worked fine. If we get consensus on this, I think we can bang
out the four methods quickly. tk requires nothing special and can be
based on the current sleep implementation. I can help with gtk if
need be. Paul has already done wx. qt anyone?

Also, are the names stop_event_loop and stop_event_loop good choices?
I find them confusing because I associate them with the UI event loop
which will always be running. Something like
wait_start and wait_stop is more intuitive to me.

A deeper hierarchy won't help the inheritance problem for GTKAgg though.

I believe this will solve the problem, because FigureCanvasGTK is
inherited first, so GTKAgg will get the specialized method. According
to Guido at
http://www.network-theory.co.uk/docs/pytut/MultipleInheritance.html

  The only rule necessary to explain the semantics is the resolution
rule used for class attribute
  references. This is depth-first, left-to-right. Thus, if an
attribute is not found in DerivedClassName,
  it is searched in Base1, then (recursively) in the base classes of
Base1, and only if it is not
  found there, it is searched in Base2, and so on.

···

On Fri, Jul 18, 2008 at 2:32 PM, David M. Kaplan <David.Kaplan@...622...> wrote:

Hi,

I have finally committed a changeset for moving the "event loop" stuff
into the backends. I have hopefully found a compromise that will please
most. Since this is close to release date, I suggest that everyone who
can give it a look (r5831) and if there is any problem, just role the
changes back and release with the old code.

My compromise was the following:

1) In FigureCanvasBase, create start/stop_event_loop that raise errors.
I kept these names instead of wait_start wait_stop because I think
things like start_event_loop is used in other programming contexts to
denote the same things. In the documentation string, I tried to make it
clear that this is not the overall GUI event loop. If people aren't
happy, changing is a fairly simple find and replace.

2) In FigureCanvasBase, I also created start/stop_event_loop_default.
These do the standard time.sleep thing. start_event_loop_default throws
a deprecated warning saying it should be replaced by a gui specific
version. Once we have the gui specific versions, I still think we
should keep this function around as this code is very simple and
straightforward and is likely to work on almost anything. For example,
if we ever had a problem with a backend, we could always use this till a
fix was found.

3) In cocoagg, fltkagg, gtk, qt, qt4, and tkagg, I implemented
fall-through functions for start/stop_event_loop that simply call the
default versions.

4) In WX, I used the code submitted by Paul, but was unable to check it
because when I tried to use the WX backend, I got an error about no
GraphicsContext (below). This looks bad. I am using wxPython: 2.6.3.2.

Again, any problem with this, just role the changes back until after the
release.

Cheers,
David

Traceback (most recent call last):
  File
"/usr/lib/python2.5/site-packages/matplotlib/backends/backend_wx.py",
line 1035, in _onPaint
    self.draw(repaint=False)
  File
"/usr/lib/python2.5/site-packages/matplotlib/backends/backend_wx.py",
line 903, in draw
    self.figure.draw(self.renderer)
  File "/usr/lib/python2.5/site-packages/matplotlib/figure.py", line
724, in draw
    if self.frameon: self.patch.draw(renderer)
  File "/usr/lib/python2.5/site-packages/matplotlib/patches.py", line
257, in draw
    gc = renderer.new_gc()
  File
"/usr/lib/python2.5/site-packages/matplotlib/backends/backend_wx.py",
line 360, in new_gc
    self.gc = GraphicsContextWx(self.bitmap, self)
  File
"/usr/lib/python2.5/site-packages/matplotlib/backends/backend_wx.py",
line 457, in __init__
    gfx_ctx = wx.GraphicsContext.Create(dc)
<type 'exceptions.AttributeError'>: 'module' object has no attribute
'GraphicsContext'

···

--
**********************************
David M. Kaplan
Charge de Recherche 1
Institut de Recherche pour le Developpement
Centre de Recherche Halieutique Mediterraneenne et Tropicale
av. Jean Monnet
B.P. 171
34203 Sete cedex
France

Phone: +33 (0)4 99 57 32 27
Fax: +33 (0)4 99 57 32 95
http://www.ur097.ird.fr/team/dkaplan/index.html
**********************************