how to make matplotlib faster?

John Hunter Wrote:>

    >> Aside from the aforementioned "run" mode of ipython, which does
    >> just this, the basic incantation is
    >>
    >> >>> from matplotlib import interactive, is_interactive >>> b =
    >> is_interactive() # store the current interactive state >>>
    >> plot(blah, blah) # make some plots >>> interactive(False) #
    >> turn interactive off >>> for i in arange(1e4096):
    >> plot(arange(i), arange(i)**2) # don't try this at home >>>
    >> interactive(b) # restore previous interactive state
    >>
    >> Basically, this is what ipython does. This is wrapped into a
    >> single function "run", called like
    >>
    >> >>> x = 1 # some fluff >>> run ~/myexamples/simple_demo.py #
    >> turn interactive off for run >>> x = 2 # interactive setting is
    >> restored
    >>
    >> But of course, you can use the interactive / is_interactive
    >> functions in any script or interactive session.
    >>
    >> To make this more accessible, perhaps we should add an
    >> interactive (or update) kwarg to plot and friends, in the same
    >> vein that we discussed a kwarg for hold, so you can easily do
    >> things like
    >>
    >> plot(x, y, hold=False) # add plot, clearing previous plot(x, y,
    >> update=False) # add plot but do not update
    >>
    >> But the question arises, does the additional complexity in the
    >> matplotlib internals required to support this justify the
    >> savings for the occasional user who would otherwise have to
    >> type a couple of extra lines?
    >>
    > In this case I don't think so. the function interactive()
    > is what I was looking for, not a keyword argument. Unlike
    > overplotting, I think interactive() is likely to be used
    > almost entirely in scripts and functions and that is by far
    > the better approach. So it's already good enough as far as
    > I'm concerned.

Following these discussions, I just added ion and ioff to the pylab
interface, and updated the web site interaction page with (not
uploaded yet) with the following. Let me know if you have anything to
add here.

By default, matplotlib defers drawing until the end of the script
because drawing can be an expensive opertation, and you may not
want to update the plot every time a single property is changed, only
once after all the properties have changed.

But in interactive mode, eg from the python shell, you usually do want
to update the plot with every command, eg, after changing the xlabel
or the marker style of a line. With the TkAgg backend, you can use
matplotlib from an arbitrary python shell. Just set TkAgg to be your
default backend and interactive to be True in your matplotlibrc file
and fire up python. Then

from pylab import *
plot([1,2,3])
xlabel('hi mom')

should work out of the box. Note, in batch mode, ie when making
figures from scripts, interactive mode can be slow since it redraws
the figure with each command. So you may want to think carefully
before making this the default behavior. TkAgg sets interactive mode
to True when you issue the show command.

Unfortunately, due to the 'mainloop' cycle of GUI toolkits, it is not
yet possible to use matplotlib from an arbitrary python shell with the
other GUI backends. You must use a custom python shell that runs the
GUI is a separate thread.

The recommended way to use matplotlib interactively from a shell is
with ipython, which has an pylab mode that detects your matplotlib
.matplotlibrc file and makes the right settings to run matplotlib with
your GUI of choice in interactive mode using threading. gtk users
will need to make sure that they have compiled gtk with threading for
this to work. Using ipython in pylab mode is basically a nobrainer
because it knows enough about matplotlib internals to make all the
right settings for you internally

  peds-pc311:~> ipython -pylab
  Python 2.3.3 (#2, Apr 13 2004, 17:41:29)
  Type "copyright", "credits" or "license" for more information.

  IPython 0.6.5 -- An enhanced Interactive Python.
  ? -> Introduction to IPython's features.
  %magic -> Information about IPython's 'magic' % functions.
  help -> Python's own help system.
  object? -> Details about 'object'. ?object also works, ?? prints more.

  Welcome to pylab, a matplotlib-based Python environment.
    help(matplotlib) -> generic matplotlib information.
    help(matlab) -> matlab-compatible commands from matplotlib.
    help(plotting) -> plotting commands.

  >>> plot( rand(20), rand(20), 'go' )

Note that you did not need to import any matplotlib names because in
pylab mode ipython will import them for you. ipython turns on
interactive mode for you, and also provides a "run" command so you can
run matplotlib scripts from the matplotlib shell and then
interactively update your figure. ipython will turn off interactive
mode during a run command for efficiency, and then restore the
interactive state at the end of the run.

  >>> cd python/projects/matplotlib/examples/
  /home/jdhunter/python/projects/matplotlib/examples
  >>> run simple_plot.py
  >>> title('a new title', color='r')

The pylab interface provides 4 commands that are useful for
interactive control. Note again that the interactgive setting
primarily controls whether the figure is redrawn with each plotting
command. is_interactive returns the interactive setting, ion turns
interactive on, ioff turns it off, and draw forces a redraw of the
entire figure. Thus when working with a big figure in which drawing
is expensive, you may want to turn matplotlib's interactive setting
off temporarily to avoid the performance hit

···

run mybigfatfigure.py

  >>> ioff() # turn updates off
  >>> title('now how much would you pay?')
  >>> xticklabels(fontsize=20, color='green')
  >>> draw() # force a draw
  >>> savefig('alldone', dpi=300)
  >>> close()
  >>> ion() # turn updates back on
  >>> plot(rand(20), mfc='g', mec='r', ms=40, mew=4, ls='--', lw=3)

John Hunter wrote:
[...]

By default, matplotlib defers drawing until the end of the script
because drawing can be an expensive opertation, and you may not
want to update the plot every time a single property is changed, only
once after all the properties have changed.

But in interactive mode, eg from the python shell, you usually do want
to update the plot with every command, eg, after changing the xlabel
or the marker style of a line. With the TkAgg backend, you can use
matplotlib from an arbitrary python shell. Just set TkAgg to be your
default backend and interactive to be True in your matplotlibrc file
and fire up python. Then

>>> from pylab import *
>>> plot([1,2,3])
>>> xlabel('hi mom')

should work out of the box. Note, in batch mode, ie when making
figures from scripts, interactive mode can be slow since it redraws
the figure with each command. So you may want to think carefully
before making this the default behavior. TkAgg sets interactive mode
to True when you issue the show command.

[...]

I'd just add that we may want to recommend that using ioff(), ion()
be part of the matplotlib idiom for writing demos and larger, more
involved plotting programs and scripts particularly where the
author of the script or function is unsure of what context it
will be run in. That way it always runs efficiently. Does that
seem a reasonable thing to recommend?

Perry

In thinking about the ioff(), ion() approach it occurs to me that
it may not be quite so simple for scripts. I think a common
desire is for a script or function to turn off interactive mode
if it is on, but at the end, restore the previous interactive
state. In this case a push/pop approach to interactive mode may
be more appropriate rather than stop/start. In particular, if
interactive mode happended to be off, you wouldn't want to turn
it on at the end of the script.

Perry