Add a point to a graph

Good morning,

I wrote a procedure that print a graph every time I call it using the values given as a list. This is the code:

def GuideGraphDraw(self, frm, data1, data2, data3, data4):

client = plot.PlotCanvas(frm)

client.SetEnableGrid(True)

frame_size = frm.GetClientSize()

client.SetInitialSize(size=frame_size)

client.SetBackgroundColour("#401010")

client.SetForegroundColour("#ADD8E6")

line1 = plot.PolyLine(data1, legend=’’, colour=‘red’, width=1)

line2 = plot.PolyLine(data2, legend=’’, colour=‘blue’, width=1)

line3 = plot.PolyLine(data3, legend=’’, colour=‘orange’, width=1)

line4 = plot.PolyLine(data4, legend=’’, colour=‘lightblue’, width=1)

data = data1+data2+data3+data4

x = map(lambda c: c[0] , data)

y = map(lambda c: c[1] , data)

gc = plot.PlotGraphics([line1, line2, line3, line4])

try:

client.Draw(gc, xAxis= (min(x),max(x+[10])), yAxis= (min(y)-0.1,max(y)+0.1))

except:

pass

My problem is that I need to add a point at the end of the graph every 2 seconds and, only on windows (not on Linux), I see the whole graph being repainted and this is very annoying.

How could I improve my code? Thanks

Hello, the following code snippet demonstrates redrawing of a
wx.lib.plot.PlotCanvas and it does *not* flicker on Win7 and WinXP.
Because your code sample is incomplete, it is not possible to
reproduce the flickering-on-redraw issue.
Maybe this happens because you create a new PlotCanval all over again
(instead of reusing it).

Your range-determining algorithm is duplicating the work done by the
range-finding-algorithm in wx.lib.plot, therefore I removed it.

# -*- coding: utf-8 -*-

import wx
import wx.lib.plot
import math

class plotframe(wx.Frame):
    def __init__(self, *args, **kwds):
        wx.Frame.__init__(self, *args, **kwds)

        pnl = wx.Panel(self, -1)
        self.pnl = pnl

        # add another control to show the sizing behaviour of the
PlotCanvas
        self.btn = wx.Button(pnl, -1, 'Some Button')

        # self.client is the plot canvas on which the plot is drawn
        self.client = wx.lib.plot.PlotCanvas(pnl)
        # if this line is ommitted, the PlotCanvas assumes a MinSize
of (20, 20)
# self.client.SetMinSize((400,300))

        # experiment with this to check for responsiveness with more
datapoints
        # more than 10000 get sluggish, but much more can be handled
by a decent machine
        self.numpoints = 100

···

#
        self.min = 0
        self.step = math.pi * 2.0 / float(self.numpoints)

        self.mydata = [(i * self.step, math.sin(i * self.step)) for i
in range(0, self.numpoints + 1)]
        self.myi = self.numpoints
        self.initplot()

        sz = wx.BoxSizer(wx.VERTICAL)
        sz.Add(self.client, 1, wx.EXPAND|wx.ALL, 0)
        sz.Add(self.btn, 0, wx.EXPAND|wx.ALL, 4)

        pnl.SetSizer(sz)
# sz.Fit(self)

        # we use our button to make our data grow
        self.Bind(wx.EVT_BUTTON, self.addpoint, self.btn)

        # we also use a timer to make the data grow
        self.poller = wx.Timer(self, wx.NewId())
        self.Bind(wx.EVT_TIMER, self.addpoint)
        # time is given in miliseconds
        # WARNING: Set it too low and the app will become unresponsive
        self.poller.Start(2000, wx.TIMER_CONTINUOUS)

    def initplot(self):
        client = self.client
        client.SetEnableGrid(True)
# frm = self
# frame_size = frm.GetClientSize()
# client.SetInitialSize(size=frame_size)
# client.SetBackgroundColour("#401010")
# client.SetForegroundColour("#ADD8E6")
        self.doplot()

    def addpoint(self, evt):
        self.myi += 1
# print self.myi
        self.mydata.append((self.myi * self.step, math.sin(self.myi
*self.step)))
        self.doplot()

    def doplot(self):
        client = self.client
        plot = wx.lib.plot
        line1 = plot.PolyLine(self.mydata, legend='', colour='red',
width=1)
        line2 = plot.PolyLine([(el[0], el[1] + 0.1) for el in
self.mydata], legend='', colour='blue', width=1)
        line3 = plot.PolyLine([(el[0], el[1] + 0.2) for el in
self.mydata], legend='', colour='orange', width=1)
        line4 = plot.PolyLine([(el[0], el[1] + 0.3) for el in
self.mydata], legend='', colour='lightblue', width=1)
        gc = plot.PlotGraphics([line1, line2, line3, line4])

        # do not specify x/y ranges, the plot package can handle this
itself very well
        client.Draw(gc)

if __name__ == '__main__':
    app = wx.App(0)
    frame1 = plotframe(None, -1, 'myplotframe')
    frame1.Show()

# import wx.lib.inspection as wxli
# wxli.InspectionTool().Show()
    app.MainLoop()

Thank you very much, nepix32, you solved the problem!

My bad, I should have attached a complete and working snippet, but since I’m an occasional programmer, it would have taken me a lot of time… However I owe you a pizza, call me if you come to Rome :wink:
Just one more question: since it’s quite impossible to set the color of a togglebutton in Windows (I have togglebutton to show/hide everyone of the four graph), I’d like to use the legend to make the user understand which line is related to which togglebutton, but I don’t see the legend anywhere. Why?

···

2012/9/11 nepix32 nepix32@gmail.com

Hello, the following code snippet demonstrates redrawing of a

wx.lib.plot.PlotCanvas and it does not flicker on Win7 and WinXP.

Because your code sample is incomplete, it is not possible to

reproduce the flickering-on-redraw issue.

Maybe this happens because you create a new PlotCanval all over again

(instead of reusing it).

Your range-determining algorithm is duplicating the work done by the

range-finding-algorithm in wx.lib.plot, therefore I removed it.

Just one more question: since it's quite impossible to set the color of a
togglebutton in Windows (I have togglebutton to show/hide everyone of the

You could use
wx.lib.buttons.GenToggleButton
which also supports colored foreground

four graph), I'd like to use the legend to make the user understand which
line is related to which togglebutton, but I don't see the legend anywhere.
Why?

1) in
...
    def initplot(self):
        client = self.client
        # Turn on the legend
        client.SetEnableLegend(True)
...

2) in plot.PolyLine(..., legend = '', ...) the legend must not be an
empty string, otherwise you only get a colored blob for the legend

Thank you very much, nepix32, you solved the problem!
My bad, I should have attached a complete and working snippet, but since
I'm an occasional programmer, it would have taken me a lot of time...
However I owe you a pizza, call me if you come to Rome :wink:

I live nearer as you may think... I will bring Pumpkin seed oil when
visiting Rome for the Pizza :slight_smile:

···

On Sep 11, 9:31 pm, andrea console <andreacons...@gmail.com> wrote:

Everything works properly now, thanks a lot! See you in Rome

···

2012/9/12 nepix32 <nepix32@gmail.com>:

On Sep 11, 9:31 pm, andrea console <andreacons...@gmail.com> wrote:

Just one more question: since it's quite impossible to set the color of a
togglebutton in Windows (I have togglebutton to show/hide everyone of the

You could use
wx.lib.buttons.GenToggleButton
which also supports colored foreground

four graph), I'd like to use the legend to make the user understand which
line is related to which togglebutton, but I don't see the legend anywhere.
Why?

1) in
...
    def initplot(self):
        client = self.client
        # Turn on the legend
        client.SetEnableLegend(True)
...

2) in plot.PolyLine(..., legend = '', ...) the legend must not be an
empty string, otherwise you only get a colored blob for the legend

Thank you very much, nepix32, you solved the problem!
My bad, I should have attached a complete and working snippet, but since
I'm an occasional programmer, it would have taken me a lot of time...
However I owe you a pizza, call me if you come to Rome :wink:

I live nearer as you may think... I will bring Pumpkin seed oil when
visiting Rome for the Pizza :slight_smile: