scipy.xplt to matplotlib

One word of caution: you'll notice that in the above,

    > the xplt script runs very fast, while the mpl one is
    > unacceptably slow (and it consumes a TON of cpu). There
    > may be a trick to provide acceptable update speeds for
    > dynamically resized plots, but unfortunately I don't use
    > that kind of plotting much, so I can't really offer much
    > help there.

Yes, this will run extremely slow, because each plot command creates a
new matplotlib.lines.Line2D object, which at draw time means a new
transformation, a new graphics context, etc. By the time you reach
the end of the loop, you'll have a ton of extra overhead in object
creation and function calls.

If possible, I suggest creating just two line objects and manipulating
their data directly, as in

from math import sin, cos
import matplotlib.numerix as nx
import pylab
pylab.ion() # interactive on, so each plot updates the window

pylab.hold('on')
allt = [0] # grow these lists and set the line data with them
allsin = [sin(0)]
allcos = [cos(0)]
lsin, = pylab.plot(allt, allsin, 'g+') # lsin is a Line2D instance
lcos, = pylab.plot(allt, allcos, 'ro') # lcos is a Line2D instance
pylab.xlabel('Time t[s]')
pylab.ylabel('Response')
pylab.axis([0,10,-1,1])
for t in nx.arange(0.1,10,0.1):
    allt.append(t)
    allsin.append(sin(t))
    allcos.append(cos(t))
    lsin.set_data(allt, allsin)
    lcos.set_data(allt, allcos)
    pylab.draw()

# to prevent the window from closing
raw_input()

    > I get the feeling that there's an O(N^2) problem
    > somewhere in there, because it seems to me that the plot
    > update slows down worse than linearly as more points are
    > added. But I didn't really measure it, it's just a gut
    > feeling.

This will still be slower than xplt, but shouldn't be mind-numbingly
slow. I have some concrete ideas on how to make animation faster, and
have started working on them, but don't have anything ready yet.

JDH

1. This is indeed much faster.
2. It still slows to a crawl as t grows. Should it?
3. The only thing that slows down is draw(), so the problem
   does not lie with the updating of the line instances.

Alan Isaac

P.S. Suppose I run the script and then press enter in the
shell before closing the graph window. I get the following
'NULL tstate' error:
    Fatal Python error: PyEval_RestoreThread: Null tstate
    abnormal program termination
Perhaps this is to be expected.

···

On Mon, 30 May 2005, John Hunter apparently wrote:

If possible, I suggest creating just two line objects and
manipulating their data directly, as in

from math import sin, cos
import matplotlib.numerix as nx
import pylab
pylab.ion() # interactive on, so each plot updates the window

pylab.hold('on')
allt = [0] # grow these lists and set the line data with them
allsin = [sin(0)]
allcos = [cos(0)]
lsin, = pylab.plot(allt, allsin, 'g+') # lsin is a Line2D instance
lcos, = pylab.plot(allt, allcos, 'ro') # lcos is a Line2D instance
pylab.xlabel('Time t[s]')
pylab.ylabel('Response')
pylab.axis([0,10,-1,1])
for t in nx.arange(0.1,10,0.1):
    allt.append(t)
    allsin.append(sin(t))
    allcos.append(cos(t))
    lsin.set_data(allt, allsin)
    lcos.set_data(allt, allcos)
    pylab.draw()

# to prevent the window from closing
raw_input()

There is another point:
For me the y-axis label does not show up in Fernando's example.

Changing the end of the code to:

···

On Mon, 30 May 2005, John Hunter wrote:

##############################
raw_input("before x-label")
pylab.xlabel('Time t[s]')
raw_input("after x-label, before y-label")
pylab.ylabel('Response')
raw_input("after y-label")
#####################
shows that the xlabel is shown after the pylab.ylabel line
and the ylabel is never shown.
This is on debian linux, python 2.3, matplotlib.__version__ 0.80

    > One word of caution: you'll notice that in the above,
    > the xplt script runs very fast, while the mpl one is
    > unacceptably slow (and it consumes a TON of cpu). There
    > may be a trick to provide acceptable update speeds for
    > dynamically resized plots, but unfortunately I don't use
    > that kind of plotting much, so I can't really offer much
    > help there.

Yes, this will run extremely slow, because each plot command creates a
new matplotlib.lines.Line2D object, which at draw time means a new
transformation, a new graphics context, etc. By the time you reach
the end of the loop, you'll have a ton of extra overhead in object
creation and function calls.

If possible, I suggest creating just two line objects and manipulating
their data directly, as in

from math import sin, cos
import matplotlib.numerix as nx
import pylab
pylab.ion() # interactive on, so each plot updates the window

pylab.hold('on')
allt = [0] # grow these lists and set the line data with them
allsin = [sin(0)]
allcos = [cos(0)]
lsin, = pylab.plot(allt, allsin, 'g+') # lsin is a Line2D instance
lcos, = pylab.plot(allt, allcos, 'ro') # lcos is a Line2D instance
pylab.xlabel('Time t[s]')
pylab.ylabel('Response')
pylab.axis([0,10,-1,1])
for t in nx.arange(0.1,10,0.1):
    allt.append(t)
    allsin.append(sin(t))
    allcos.append(cos(t))
    lsin.set_data(allt, allsin)
    lcos.set_data(allt, allcos)
    pylab.draw()

# to prevent the window from closing
raw_input()

    > I get the feeling that there's an O(N^2) problem
    > somewhere in there, because it seems to me that the plot
    > update slows down worse than linearly as more points are
    > added. But I didn't really measure it, it's just a gut
    > feeling.

This will still be slower than xplt, but shouldn't be mind-numbingly
slow.

On my machine it is slower by a factor 15
(import matplotlib ; matplotlib.rc.func_globals["get_backend"]()
gives 'GTKAgg').

As I am a speed fanatic :wink: I would surely like this
to be faster. But one should not forget
that matplotlib does quite a lot
(in particular antialising, sophisticated markers etc.).

I have some concrete ideas on how to make animation faster, and
have started working on them, but don't have anything ready yet.

That sounds great - looking very much forward to this!
Would this also result in a shorter code for the matplotlib example
(which is at the moment more than twice as long
than the scipy.xplt one)?

Best,

Arnd

Arnd Baecker wrote:

"Fernando" == Fernando Perez <Fernando.Perez@...179...> writes:

There is another point:
For me the y-axis label does not show up in Fernando's example.

Changing the end of the code to:
##############################
raw_input("before x-label")
pylab.xlabel('Time t[s]')
raw_input("after x-label, before y-label")
pylab.ylabel('Response')
raw_input("after y-label")
#####################
shows that the xlabel is shown after the pylab.ylabel line
and the ylabel is never shown.

Mmh, very strange. I can confirm that the labels do both (x/y) display correctly for me, on a Fedora Core 3 box using mpl 0.80 on Python 2.3.4 (the default), and the TkAgg backend.

However, on my box all other backends (WX, GTK, Qt) fail to even open the display window _at all_. The code runs (confirmed by some print statements), but it never opens a window at all. This, despite the fact that these backends all work just fine in 'ipython -pylab'.

Trying to get some info from matplotlib wasn't very enlightening:

[~/test]> ./pplot.py --verbose-helpful
matplotlib data path /usr/share/matplotlib
loaded rc file /usr/local/home/fperez/.matplotlibrc
matplotlib version 0.80
verbose.level helpful
interactive is False
platform is linux2
numerix Numeric 23.7
font search path ['/usr/share/matplotlib']
loaded ttfcache file /usr/local/home/fperez/.ttffont.cache
backend GTKAgg version 2.4.1
t 0.0
t 0.1
t 0.2
t 0.3
[...]

I haven't the foggiest idea what the problem may be...

Best,

f

···

On Mon, 30 May 2005, John Hunter wrote: