Suitable for high speed plotting?

I'm attempting my first wxPython program in years (I'm a long time
Python programmer, but typically do server side work that needs no
GUI), and having some trouble with performance.

The system we're developing is connected to a 3-axis accelerometer,
streaming data to us at 1Khz (ie 1000 times a second). Each of those
1000 times a second, we receive an X coordinate, a Y coordinate and a
Z.

What we'd like to do is display three plots, in realtime, at a
framerate of roughly 20fps. Three plots consisting of XvsY, YvsZ and
XvsZ, and three of the raw X, Y and Z data.

Our first run at it was using matplotlib with wx, but the update was
horrendous (roughly 2 fps).

I figure that's too much overhead, so I'm now trying a more "raw"
method. For now, I'm just drawing one graph, to see how things go. I'm
using a wx.Frame, and a separate thread posting events to it. My basic
drawing code is:

def Draw(self, DC):
        DC = wx.PaintDC(self)
        DC.SetBackground(wx.Brush("White"))
        DC.Clear()

        GC = wx.GraphicsContext.Create(DC)

        Pen = GC.CreatePen(wx.Pen("Black", 4))

        c1 = wx.Color(255, 0, 0, 255)
        c2 = wx.Color(255, 0, 0, 0)
        GC.SetPen(Pen)
        GC.Translate(60,75)
        GC.Scale(0.5,0.5)
        GC.DrawLines(self.points)

I update self.points in the event handler, and it will always consist
of 500 (X,Y) tuples. So essentially, I'm trying to draw a 500 point
line 20 times per second.

Is this the best way to do this? Anyone have any hints for going
faster, and using less CPU? Currently, I'm hitting 80% on one of my
processors. I'm running a 2GHz MacBook running OS X, with the latest
version of wxPython, and Python2.5.

Thanks in advance,
Jay P.

I'm attempting my first wxPython program in years (I'm a long time
Python programmer, but typically do server side work that needs no
GUI), and having some trouble with performance.

The system we're developing is connected to a 3-axis accelerometer,
streaming data to us at 1Khz (ie 1000 times a second). Each of those
1000 times a second, we receive an X coordinate, a Y coordinate and a
Z.

What we'd like to do is display three plots, in realtime, at a
framerate of roughly 20fps. Three plots consisting of XvsY, YvsZ and
XvsZ, and three of the raw X, Y and Z data.

Our first run at it was using matplotlib with wx, but the update was
horrendous (roughly 2 fps).

I figure that's too much overhead, so I'm now trying a more "raw"
method. For now, I'm just drawing one graph, to see how things go. I'm
using a wx.Frame, and a separate thread posting events to it. My basic
drawing code is:

def Draw(self, DC):
        DC = wx.PaintDC(self)
        DC.SetBackground(wx.Brush("White"))
        DC.Clear()

        GC = wx.GraphicsContext.Create(DC)

        Pen = GC.CreatePen(wx.Pen("Black", 4))

        c1 = wx.Color(255, 0, 0, 255)
        c2 = wx.Color(255, 0, 0, 0)
        GC.SetPen(Pen)
        GC.Translate(60,75)
        GC.Scale(0.5,0.5)
        GC.DrawLines(self.points)

I update self.points in the event handler, and it will always consist
of 500 (X,Y) tuples. So essentially, I'm trying to draw a 500 point
line 20 times per second.

Is this the best way to do this? Anyone have any hints for going
faster, and using less CPU? Currently, I'm hitting 80% on one of my
processors. I'm running a 2GHz MacBook running OS X, with the latest
version of wxPython, and Python2.5.

Use numpy (if you're not already).

Unless you really need anti-aliased display, try using a straight wxDC.
The overhead of anti-aliased drawing is significant. Also, thin lines
draw faster than fat ones. Small windows are faster to redraw than big
ones (!).

20 fps with 500 points per line should be doable with a wcDC. Windows
seems faster than wxGTK, usually (presuambly because of better HW
acceleration of GDI calls).

If things are still struggling, try (2D) drawing with OpenGL. This is
blazingly fast (assuming you've got accelerated OpenGL) and quite easy
to do (but you'll need to learn some OpenGL of course).

How about doing the drawing from the Idle event handler, and sending
wakeupIdle events at each new dataset. Thus, if data arrives faster than
the system can draw, you don't totally backup your event-queue (I'm
being a bit loose with my terminology here but hopefully you'll get the
idea).

HTH
BC

···

On Wed, 2007-09-26 at 20:27 -0400, Jay Parlar wrote:

Thanks in advance,
Jay P.

Our first run at it was using matplotlib with wx, but the update was
horrendous (roughly 2 fps).

I've had reasonable success using numpy and the PlotCanvas from
wx.lib.plot. It's certainly orders of magnitude faster than
matplotlib.

Rob

> Our first run at it was using matplotlib with wx, but the update was
> horrendous (roughly 2 fps).

I've had reasonable success using numpy and the PlotCanvas from
wx.lib.plot. It's certainly orders of magnitude faster than
matplotlib.

This prompted me to see if I could clean up my source code and turn it
into a little demo, which I was able to do. At least on my machines,
I can do 500 data points at 20fps with no problem.

Rob

plotter.py (12 KB)