moving wxPyPlot

OOPS, forgot the attachment...here it is

Peter Wurmsdobler wrote:

as maybe many people, I want to make some oscilloscope type of plot. I
assume that some vector is updated by removing the first value and
appending a new value. Then that vector should be plotted which gives
the impression of a moving curve.

I tried to implement the moving plot using, or perhaps mis-using
wxPyPlot with the following code. But I am convinced that there must be
a more elegant way, by just updating the data in the PolyLine and
calling a redraw method. Any ideas?

While the comments indicate that "all methods are private", the wonder
of PYthon is that attributes are not truly private, so, just as you
suspected, this works just fine:

     def OnTimer(self,event):
         self.count += self.dT
         self.data1[:,1] = Numeric.sin(self.time+self.count) #fake move
         self.lines1.points = self.data1
         self.client.Draw(self.pg)

However, it's not really well optimised. One difficultly is that the
Draw() method currently contians all sorts of code for setting up and
drawing the axes. In your case, you want a Draw() function that just
re-draws the data, with all the Axis, zoom, etc all the same. It
shouldn't be too hard to separate those functions, however.

Someone else on this list was trying to optimize drawing in wxPyPlot,
and found that they could access the wxPyPlot dc directly, and draw to
that. It was a little messy, but it worked. Personlly, I'd just add the
functionality to wxPyPlot.

Another problem is that as you re-draw your data, you need to erase the
previous version, and restore the gridlines or whatever. This could sap
performance a little. In my FloatCanvas (which may be distributed with
the next version of wxPython...thanks, Robin) I solved this by triple
buffering... If an obejct get an "Foreground" flag, it gets drawn on top
of the usual off-screen buffer. THis way, you can have something
changing on top of a complex background, and not have to re-draw the
background each frame.

I've enclosed FloatCanvas.py and test_Plot.py, which produces something
very similar to your example. I'm not sure using FloatCanvas is right
for you (I havn't built an axis drawing or anything like that into it),
but you can get ideas from it.

-Chris

FloatCanvas.py (52.8 KB)

test_Plot.py (7.39 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Peter Wurmsdobler wrote:

In effect, using PyPlot for moving pictures with the Draw() method
comsumes quite a lot of CPU resources, 70% for xfs ??? for my
pyplottest.py running (attached, with many pyplot featues such as zoom
and print).

Well, zooming doesn't seem to work. It immediatedly re-sets itself at
the next time step.

> It shouldn't be too hard to separate those functions, however.
Well, I tried, but no too hard. I removed more or less randomly some
calls, all the axis update in the Draw() method of PlotGraphics, but it
did not work properly.

It will take some re-structuring. It wasn't designed with this kind of
animation in mind.

Is there a chance that the printing features will be worked in, as they
are currently available in pyplot ?

I'd like to add printing. It would be a bit of work. ONe thing that
would be easy is to save the image as a PNG. GIF, or whatever I will
certainly add that soon.

The rubber band zoom?

It has a Rubber band zoom, but it's different, as it zooms in on the
whole thing, axes and all. Did you try it?

Fancy axis?

That's going to take some work, and I'm not sure I'll do it. What I
would do is to subclass FloatCanvas, and add the axes, etc.
Functionality in the subclass. I did have this in mind, but I may just
use wxPyPlot instead.

How could I help to copy those features from pyplot? Or is there some
co-operation between FloatCanvas and PyPlot?

There is none now. The only similarity at all is that I added double
buffering to wxPyPlot, and did it essentially the same way as
FLoatCanvas.

Merging the FloatCanvas capability into pyplot?

Building a new PLotCanvas from FloatCAnvs could certainly be done,
borrowing a lot of code from wxPyPlot, but I'm not sure it's worth it.
It depends on what your goals are, but if what you want is essentially
wxPyPlot, but with better support for quickly updating the data, I'd
jsut do a littel re-structuring of wxPyPlot. That would be less work
than adding all the extra stuff to FloatCanvas.

A attached another version of you test file, called floatcanvastest.py.
There the Timer() function calculates sin/cos values (simulating data
input from some DAQ board), appends them to a list and passes the list
as array to the data object for drawing (Perhaps there is a nicer way to
do that).

Well, there's no reason for the separate list, you can jsut update the
data array.

You will notice one thing: The sin/cos functions are not
scaled correctly, they should be +-1, but are somewhere by 0.9 ?

Yes, they are. The axis box goes from -1.1 to 1.1. I added grid lines so
you can see better whats goin on. By the way, you can move the mouse
around the plot, and see the coordinates in the status box at the bottom
of the frame.

I've enclosed a version with grid lines and getting rid of the list in
Timer()

-Chris

floatcanvastest.py (8.85 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Gordon,

Peter Wurmsdobler has been trying to make wxPyPlot work better for
"moving" plots. I did a little re-working of wxPyPlot, and I thought you
might want to take a look. I've enclosed wxPyPlot2.py and pyplottest.py.

wxPyPlot2 is re-structured a little, adding a DrawData() method, that
can be used to draw just the data points, without re-drawing all the
axis and everything. This should make it more efficient. The problem now
is that it erases the plot area, so the old data gets erased, but also
any gridlines. I think to do this right, we should perhaps add another
buffer, so that we could store the axes, legend, and all that in a
buffer, then blit that into the main buffer, and draw the data on top.
THis way you could have grid lines, plus whatever fancy stuff you might
want in addition in the background. We might even want to kepp two sets
of data sets, one for the background, and one for the foreground. This
would allow you to have some data that was static, and some that could
be quickly re-plotted.

pyplottest is a little test program that Peter wrote. I altered it to
test the wxPyPlot2.

Let me know what you think, I may or may not get a chance to work on teh
triple buffer scheme, but even as it stands, I think it's an
improvement. We'll have to move the code that draws the grid to the
DrawData function, and I'm sure it could be cleaned up a little.

-Chris

wxPyPlot2.py (55.7 KB)

pyplottest.py (6.46 KB)

···

--
Christopher Barker, Ph.D.
Oceanographer
                                        
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Hi,
I am on the last step of installing wxPython on my Solaris machine (actually
running the python setup.py) and I am getting a weird error that I can
figure out:

c++ -shared -L/tools/python/gtk/lib -I/tools/python/gtk/include
build/temp.solaris-2.8-sun4u-2.2/src/gtk/help.o -L/usr/X11R6/lib -o
build/lib.solaris-2.8-sun4u-2.2/wxPython/helpc.so -L/tools/python/gtk/lib -p
threads -L/tools/python/gtk/lib -Wl,-rpath -Wl,/tools/python/gtk/lib -lwx_gt
kd-2.4

ld: elf error: file /tools/python/gtk/lib: elf_begin: I/O error: region
read: Is a directory

ld: fatal: File processing errors. No output written to
build/lib.solaris-2.8-sun4u-2.2/wxPython/helpc.so

collect2: ld returned 1 exit status

error: command 'c++' failed with exit status 1

Any ideas? I AM SO CLOSEEE!

Gilad

Chris,

Well, zooming doesn't seem to work. It immediatedly re-sets itself at
the next time step.

This is due to the way the plot is redrawn, its the full Draw() method.

It has a Rubber band zoom, but it's different, as it zooms in on the
whole thing, axes and all. Did you try it?

Yes, I saw, works great.

wxPyPlot, but with better support for quickly updating the data, I'd
jsut do a littel re-structuring of wxPyPlot. That would be less work
than adding all the extra stuff to FloatCanvas.

Either would be fine for me.

Well, there's no reason for the separate list, you can jsut update the
data array.

Thanks, I was not aware of the fact I can change arrays in the same way as lists.

I've enclosed a version with grid lines and getting rid of the list in
Timer()

Thanks, works fine !
peter