Progress on interactive backend detection

I have implemented a prototype of interactive backend detection. As I
proposed earlier, I added an extra rc parameter 'backend_fallback' that
allows pyplot to inspect sys.modules on load and try to redirect
interactive backends to the appropriate ones.

I am attaching a patch, not for inclusion, as I still want to check
different details on interactivity, and the behavior of the show command,
but for comments and triage. I have tested it in various apps, and I
think it is interesting to review the different mainstream apps
presenting a interactive shell in which pylab can be used interactively.

* wx apps. In mayavi2, my near-born ipython frontend the attached patch
works seamlessly, with or without the interactive switch. In SPE
(wx-based IDE) it does not work, and I suspect this is because of ugly
things SPE does to the wx image-loading, for theming reasons, as I see
totally unrelated errors.

* Qt: In Eric4 the qt detection does not work as it seems that Eric
  spawns a new python process. As a result, as long as you keep the
  interactive switch off, pylab works great, but you really have to use a
  blocking show. Does anybody now a Qt program that has an interactive
  Python prompt?

* In IDLE I can't figure out what is happening. I must confess that I do not
  know much about Tkinter, and I am not too sure how matplotlib is
  supposed to collaborate with an existing Tk mainloop.

* The only GTK program I could think of with an interactive python prompt
  was accerciser, an pylab now works out of the box there, in interactive
  mode or not.

Of course in ipython -q|q4|w|g-thread, my addition work seamlessly, but
that was too easy :).

Some remarks that came out of this extensive testing:

  - show starts a mainloop and is blocking even if there are not windows
    open. This basically leads to a deadlock where the user cannot
    interrupt the mainloop. This can probably be easily fixed, and I'll
    look into it.

  - we cannot guess whether the user want to be in interactive mode or
    not: there is a potential large cost of being in interactive mode due to
    continuous refreshing of the UI. Ipython gets it right by turning the
    interactive mode off when running a script, but when need the host
    environment to make this decision and we cannot make it in matplotlib.
    However, I believe it is important to expose more this
    functionality, as the user will now probably have to make this
    decision. This is why I have add the import of "interactive" in
    pyplot.

  - this brings up the fact that the user experience can be increased a
    lot if the host environment collaborates with matplotlib. This is why
    we discussed with John the idea of adding a "vendor registry", a
    light-weight module that an environment could import at little cost
    to tell matplotlib what backend to use, whether to put the
    interactive switch, and hopefully more, like maybe a factory to
    create new figure, as this would allow embedding these figures in an IDE.
    We do this with mayavi2, where the figures created by mlab are
    standalone windows when the fullblown environment is not running, but
    integrated windows when it is running.

I am sure there is more that we can learn. Please come up with ideas so
that we can see better what is the way forward for integrating matplotlib
to graphical shells and environments.

Cheers,

Ga�l

backend_detect.patch (701 Bytes)

I forgot to mention: fltk and cocoa did not get any love at all in this
patch. The reason being that I do not know of any program running the
first one, and for me to test and develop things for the second one,
somebody will have to offer me an apple computer :).

Cheers,

Ga�l

It turns out it was only in the GTK backend, and quite trivial to
correct. Attached is a new patch, including this correction.

Ga�l

detect_mainloop.patch (3.33 KB)

···

On Sat, Jul 19, 2008 at 07:31:19AM +0200, Gael Varoquaux wrote:

  - show starts a mainloop and is blocking even if there are not windows
    open. This basically leads to a deadlock where the user cannot
    interrupt the mainloop. This can probably be easily fixed, and I'll
    look into it.

Hey Gael, this is starting to look reasonable. I know implementing
these checks, such as detecting whether the mainloop is active, can be
a hassle, so thanks for taking the time to write against so many
environments. We may want to make take the logic you've provided and
encapsulate them in the backend methods to make them more easily
recognizable, fixable and reusable. Eg, each unser interface backend
would provide a "mainloop_running" method. You could then access this
in pyplot to support your fallback logic, and also we could use it in
"show" to make sure we don't try and start mainloops that are already
running.

One thing notice in your patch is that when it comes time to check for
tk, you import tkinter and then do nothing with it. I assume this is
a placeholder until you figure out what you want to do?

For a little background, Fernando, Gael and I talked about this
problem a bit over the phone yesterday. The use case they are trying
to address is that people may be wanting to use more than one
application, at different times or at the same time, that have
embedded python shells. With all the work going on making ipython
frontends for wx, qt and gtk, it is not unreasonable to assume that
there ill soon be multiple IDEs or other environment in which one
might want to import and use pylab. Since we only support one default
backend, and it is dificult and onerous for the user to constantly
modify their rc depending on what application they may be launching,
Fernando and Gael proposed supporting a backend fallback option so the
user could express the intention: use my default backend unless I
happen to be in an incompatible user interface environment and then
just choose the most sensible thing. Users who do not want this magic
can simply turn the fallback option off. This behavior will only be
triggered if

  1) the fallback option is on (it will be by default)
  2) the user is running mpl in an environment in which a user
interface already has a running mainloop
  3) the default backend is known to be incompatible. Eg, if the
default backend is PS, nothing will happen.

I think the proposed changes are reasonable.

JDH

···

On Sat, Jul 19, 2008 at 1:05 AM, Gael Varoquaux <gael.varoquaux@...427...> wrote:

It turns out it was only in the GTK backend, and quite trivial to
correct. Attached is a new patch, including this correction.

John Hunter wrote:

Fernando and Gael proposed supporting a backend fallback option so the
user could express the intention: use my default backend unless I
happen to be in an incompatible user interface environment and then
just choose the most sensible thing. Users who do not want this magic
can simply turn the fallback option off. This behavior will only be
triggered if

  1) the fallback option is on (it will be by default)
  2) the user is running mpl in an environment in which a user
interface already has a running mainloop
  3) the default backend is known to be incompatible. Eg, if the
default backend is PS, nothing will happen.

I think the proposed changes are reasonable.

+1

Ryan

···

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Ryan May wrote:

John Hunter wrote:

Fernando and Gael proposed supporting a backend fallback option so the
user could express the intention: use my default backend unless I
happen to be in an incompatible user interface environment and then
just choose the most sensible thing. Users who do not want this magic
can simply turn the fallback option off. This behavior will only be
triggered if

  1) the fallback option is on (it will be by default)
  2) the user is running mpl in an environment in which a user
interface already has a running mainloop
  3) the default backend is known to be incompatible. Eg, if the
default backend is PS, nothing will happen.

I think the proposed changes are reasonable.

+1

I agree. Sounds like progress.

Eric

···

Ryan

> It turns out it was only in the GTK backend, and quite trivial to
> correct. Attached is a new patch, including this correction.

Hey Gael, this is starting to look reasonable. I know implementing
these checks, such as detecting whether the mainloop is active, can be
a hassle, so thanks for taking the time to write against so many
environments. We may want to make take the logic you've provided and
encapsulate them in the backend methods to make them more easily
recognizable, fixable and reusable. Eg, each unser interface backend
would provide a "mainloop_running" method. You could then access this
in pyplot to support your fallback logic, and also we could use it in
"show" to make sure we don't try and start mainloops that are already
running.

In theory this could work, but the problem is that the logics for
selecting the backend gets executed when matplotlib.backends is imported,
ie before importing any backend. I tried implementing your suggestion,
but it failed because I had to imports from backends. Am I missing
something obvious?

One thing notice in your patch is that when it comes time to check for
tk, you import tkinter and then do nothing with it. I assume this is
a placeholder until you figure out what you want to do?

I have actually given up on that, so you should probably remove these two
lines. If somebody knows how to check accurately for tk, I am interested.

Cheers,

Ga�l

···

On Sat, Jul 19, 2008 at 03:42:27PM -0500, John Hunter wrote:

On Sat, Jul 19, 2008 at 1:05 AM, Gael Varoquaux > <gael.varoquaux@...427...> wrote:

Could somebody review this patch and possibly check it in? It is not
perfect but is, IMHO, a good start that works on everything I have thrown
at it. I have not been able to abstract in more by pushing the relevant
code in the backends, as in introduces coupling that induces the
selection of the wrong backend.

Debian freeze is close, and I would really like this to go in before. We
do need to work on a vendor registry for the long run, to allow
application builders to override this mechanism on a per-application
basis. However to be able to have a roper view of what this registry, I
need to wip up an app to use it. I am busy doing that, but it won't be
ready before Debian freeze, whereas the attached patch fixes all my
problems.

Cheers,

Ga�l

detect_mainloop.patch (3.33 KB)

···

On Sat, Jul 19, 2008 at 08:05:52AM +0200, Gael Varoquaux wrote:

On Sat, Jul 19, 2008 at 07:31:19AM +0200, Gael Varoquaux wrote:
> - show starts a mainloop and is blocking even if there are not windows
> open. This basically leads to a deadlock where the user cannot
> interrupt the mainloop. This can probably be easily fixed, and I'll
> look into it.

It turns out it was only in the GTK backend, and quite trivial to
correct. Attached is a new patch, including this correction.

OK, looks good; I've committed it to svn r5798. I have commented out
the tkinter import until we figure out what if anything we need to do
in that case.

Thanks for the patch.

JDH

···

On Mon, Jul 21, 2008 at 4:07 AM, Gael Varoquaux <gael.varoquaux@...427...> wrote:

Could somebody review this patch and possibly check it in? It is not
perfect but is, IMHO, a good start that works on everything I have thrown

Thanks John. Sorry for leaving the tk part behind. It should indeed be
commented out.

Ga�l

···

On Mon, Jul 21, 2008 at 05:30:00AM -0500, John Hunter wrote:

On Mon, Jul 21, 2008 at 4:07 AM, Gael Varoquaux > <gael.varoquaux@...427...> wrote:

> Could somebody review this patch and possibly check it in? It is not
> perfect but is, IMHO, a good start that works on everything I have thrown

OK, looks good; I've committed it to svn r5798. I have commented out
the tkinter import until we figure out what if anything we need to do
in that case.