Example #1
0
 def configure(self):
     if self.configWindow:
         self.configWindow.closeWindow()
     self.configWindow = ScopeConfigWindow(self)
Example #2
0
 def configure(self):
     if self.configWindow:
         self.configWindow.closeWindow()
     self.configWindow = ScopeConfigWindow(self)
Example #3
0
class Oscilloscope():
    def __init__(self, geom=None):
        self.window = None
        self.configWindow = None
        self.canvasInited = False
        # add more lines by adding colors
        self.colors = ["blue", "green", "red", "cyan", "magenta"]
        self.probes = []
        self.numActiveProbes = 0
        # range for the data (xaxis always starts at zero)
        self.maxNumelems = 60
        self.setTimeAxis(100)
        self.yrange = (None, None)
        self.opts = {'Title':'Untitled',
                     'X Label':'Cycles Past (Sample Period='+
                     str(self.samplesPerElem)+')',
                     'Y Label':'Value',
                     'X Scale':self.xrange,
                     'Y Scale':'auto'}
        self.ymin, self.ymax = None, None
        self.ybounds = None, None
        self.ptRadius = 2
        self.legend = True
        # just pay attention to the position part, since the canvas is a 
        # fixed size
        self.geom = None
        if geom:
            self.geom = geom[geom.find('+'):]

    def openWindow(self):
        # already open; don't open again
        if self.window:
            return
        self.window = Tkinter.Toplevel()
        self.window.wm_title("Soar Oscilloscope")
        self.window.protocol("WM_DELETE_WINDOW", self.closeWindow)
        if self.geom:
            self.window.geometry(self.geom)
        self.canvWidth, self.canvHeight = 600, 400
        self.canvas = Tkinter.Canvas(self.window,
                                     width = self.canvWidth, 
                                     height = self.canvHeight,
                                     background = "white")
        self.canvas.pack()
        self.button = Tkinter.Button(self.window, 
                                     text="Configure Oscilloscope",
                                     command = self.configure)
        self.button.pack()
        self.makeCanvasObjects()
        self.canvas.wait_visibility()
        self.setStaticObjects()

    def configure(self):
        if self.configWindow:
            self.configWindow.closeWindow()
        self.configWindow = ScopeConfigWindow(self)

    def doneConfiguring(self):
        self.configWindow = None
        self.setStaticObjects()
        
    def deleteScalingCanvasObjects(self):
        def deleteTask():
            for i in range(self.lines):
                for j in range(self.lines[i]):
                    self.canvas.delete(self.lines[i][j])
                for j in range(self.points[i]):
                    self.canvas.delete(self.points[i][j])
        form.main.tk_enqueue(deleteTask)

    def makeCanvasObjects(self):
        if not self.window:
            return
        if self.canvasInited:
            self.deleteScalingCanvasObjects()
        # number of text objects doesn't change with rescale
        else:
            self.canvasInited = True
            # clear rect comes first so everything else shows up
            #self.clearRect = self.canvas.create_rectangle(0,0,
            #                                              self.canvWidth,
            #                                              self.canvHeight,
            #                                              fill="white")
            # outline rect needs to come first (don't draw over pts)
            self.outlineRect = self.canvas.create_rectangle(0,0,1,1,
                                                            fill="white")
            self.xminText = self.canvas.create_text(0, 0, text="")
            self.xmaxText = self.canvas.create_text(0, 0, text="")
            self.yminText = self.canvas.create_text(0, 0, text="")
            self.ymaxText = self.canvas.create_text(0, 0, text="")
            self.yLabelText = self.canvas.create_text(0, 0, text="")
            self.xLabelText = self.canvas.create_text(0, 0, text="")
            self.titleText = self.canvas.create_text(0, 0, text="")
            if self.legend:
                self.legendLines = []
                self.legendText = []
                self.legendPoints = []
                for color in self.colors:
                    l = self.canvas.create_line(-2, -1, -1, -1,
                                                 fill=color, smooth=1, width=3)
                    self.legendLines.append(l)
                    t = self.canvas.create_text(0, 0, text="")
                    self.legendText.append(t)
                    p = self.canvas.create_oval(-2, -2, -1, -1,
                                                 fill=color, outline=color)
                    self.legendPoints.append(p)

        self.lines = []
        self.points = []
        rad = self.ptRadius
        # make all the objects off the canvas
        x0,y0 = -2, -1
        x1,y1 = -1, -1
        for i in range(len(self.colors)):
            color = self.colors[i]
            self.lines.append([])
            self.points.append([])
            for j in range(self.numelems):
                if j < self.numelems-1:
                    l = self.canvas.create_line(x0,y0,x1,y1, fill=color,
                                                smooth=1, width=3)
                    self.lines[i].append(l)
                p = self.canvas.create_oval(x1-rad, y1-rad, x1+rad, x1+rad,
                                            fill=color, outline=color)
                self.points[i].append(p)

    def setCanvasText(self, item, x, y, **opts):
        self.canvas.coords(item, x, y)
        self.canvas.itemconfig(item, opts)

    def closeWindow(self):
        if self.window:
            self.geom = self.window.geometry()
            app.soar.scope_geom = self.geom
            self.window.destroy()
            self.window = None
        if self.configWindow:
            self.configWindow.closeWindow()
            self.configWindow = None

    def setTimeAxis(self, desiredRange=None):
        if not desiredRange:
            desiredRange = self.opts['X Scale']
        if desiredRange < 1:
            return
        self.numelems = desiredRange + 1
        self.samplesPerElem = 1
        while self.numelems > self.maxNumelems:
            self.samplesPerElem += 1
            self.numelems = int((desiredRange+1)/self.samplesPerElem)
        # TODO: put appropriate label on graph
        self.xrange = desiredRange
        for p in self.probes:
            if p:
                p.resize(self.numelems, self.samplesPerElem)
        self.makeCanvasObjects()
        self.setStaticObjects()

    def clearProbes(self):
        self.probes = []
        self.ymin, self.ymax = None, None

    def makeFunc(self, func, i=None):
        if func.func_code.co_argcount == 0:
            if i is not None: return lambda inp: func()[i]
            else: return lambda inp: func()
        elif func.func_code.co_argcount == 1:
            if i is not None: return lambda inp: func(inp)[i]
            else: return lambda inp: func(inp)
        else:
            sys.stderr.write("Dynamic plot function takes too many arguments")
            return lambda inp: 0.0

    def addProbeFunction(self, names, func, functext=None, initVal=0):
        numavail = len(self.colors) - len(self.probes)
        if numavail == 0:
            sys.stderr.write("All available probes are in use.  Signal will not be plotted")
            return
        if type(names) == list or type(names) == tuple:
            numprobes = min(numavail, len(names))
            if numprobes < len(names):
                sys.stderr.write("Not enough available probes for all signals.  Only "+str(numprobes)+" signals will be plotted.")
            for i in range(numprobes):
                text = functext if functext else str(func)
                text = text+"["+str(i)+"]"
                self.addProbe(names[i], self.makeFunc(func, i), text, initVal)
        else:
            self.addProbe(names, self.makeFunc(func), 
                          functext if functext else str(func), initVal)
        self.setStaticObjects()

    def addProbe(self, name, functext, initVal=0):
        func = lambda: eval(functext)
        self.addProbeFunction(name, func, functext, initVal)

    def setProbeText(self, probeidx, name, functext):
        func = lambda: eval(functext)
        self.setProbe(probeidx, name, func, functext)

    def addProbe(self, name, func, functext, initVal=0):
        self.probes.append(Probe(name, func, functext, self.numelems,
                                 self.samplesPerElem, initVal))
        self.setStaticObjects()
                                      
    def setExtremes(self, (minv, maxv)):
        self.ymin = minv if self.ymin==None else min(self.ymin, minv)
        self.ymax = maxv if self.ymax==None else max(self.ymax, maxv)
Example #4
0
class Oscilloscope():
    def __init__(self, geom=None):
        self.window = None
        self.configWindow = None
        self.canvasInited = False
        # add more lines by adding colors
        self.colors = ["blue", "green", "red", "cyan", "magenta"]
        self.probes = []
        self.numActiveProbes = 0
        # range for the data (xaxis always starts at zero)
        self.maxNumelems = 60
        self.setTimeAxis(100)
        self.yrange = (None, None)
        self.opts = {'Title':'Untitled',
                     'X Label':'Cycles Past (Sample Period='+
                     str(self.samplesPerElem)+')',
                     'Y Label':'Value',
                     'X Scale':self.xrange,
                     'Y Scale':'auto'}
        self.ymin, self.ymax = None, None
        self.ybounds = None, None
        self.ptRadius = 2
        self.legend = True
        # just pay attention to the position part, since the canvas is a 
        # fixed size
        self.geom = None
        if geom:
            self.geom = geom[geom.find('+'):]

    def openWindow(self):
        # already open; don't open again
        if self.window:
            return
        self.window = Tkinter.Toplevel()
        self.window.wm_title("Soar Oscilloscope")
        self.window.protocol("WM_DELETE_WINDOW", self.closeWindow)
        if self.geom:
            self.window.geometry(self.geom)
        self.canvWidth, self.canvHeight = 600, 400
        self.canvas = Tkinter.Canvas(self.window,
                                     width = self.canvWidth, 
                                     height = self.canvHeight,
                                     background = "white")
        self.canvas.pack()
        self.button = Tkinter.Button(self.window, 
                                     text="Configure Oscilloscope",
                                     command = self.configure)
        self.button.pack()
        self.makeCanvasObjects()
        self.canvas.wait_visibility()
        self.setStaticObjects()

    def configure(self):
        if self.configWindow:
            self.configWindow.closeWindow()
        self.configWindow = ScopeConfigWindow(self)

    def doneConfiguring(self):
        self.configWindow = None
        self.setStaticObjects()
        
    def deleteScalingCanvasObjects(self):
        def deleteTask():
            for i in range(self.lines):
                for j in range(self.lines[i]):
                    self.canvas.delete(self.lines[i][j])
                for j in range(self.points[i]):
                    self.canvas.delete(self.points[i][j])
        form.main.tk_enqueue(deleteTask)

    def makeCanvasObjects(self):
        if not self.window:
            return
        if self.canvasInited:
            self.deleteScalingCanvasObjects()
        # number of text objects doesn't change with rescale
        else:
            self.canvasInited = True
            # clear rect comes first so everything else shows up
            #self.clearRect = self.canvas.create_rectangle(0,0,
            #                                              self.canvWidth,
            #                                              self.canvHeight,
            #                                              fill="white")
            # outline rect needs to come first (don't draw over pts)
            self.outlineRect = self.canvas.create_rectangle(0,0,1,1,
                                                            fill="white")
            self.xminText = self.canvas.create_text(0, 0, text="")
            self.xmaxText = self.canvas.create_text(0, 0, text="")
            self.yminText = self.canvas.create_text(0, 0, text="")
            self.ymaxText = self.canvas.create_text(0, 0, text="")
            self.yLabelText = self.canvas.create_text(0, 0, text="")
            self.xLabelText = self.canvas.create_text(0, 0, text="")
            self.titleText = self.canvas.create_text(0, 0, text="")
            if self.legend:
                self.legendLines = []
                self.legendText = []
                self.legendPoints = []
                for color in self.colors:
                    l = self.canvas.create_line(-2, -1, -1, -1,
                                                 fill=color, smooth=1, width=3)
                    self.legendLines.append(l)
                    t = self.canvas.create_text(0, 0, text="")
                    self.legendText.append(t)
                    p = self.canvas.create_oval(-2, -2, -1, -1,
                                                 fill=color, outline=color)
                    self.legendPoints.append(p)

        self.lines = []
        self.points = []
        rad = self.ptRadius
        # make all the objects off the canvas
        x0,y0 = -2, -1
        x1,y1 = -1, -1
        for i in range(len(self.colors)):
            color = self.colors[i]
            self.lines.append([])
            self.points.append([])
            for j in range(self.numelems):
                if j < self.numelems-1:
                    l = self.canvas.create_line(x0,y0,x1,y1, fill=color,
                                                smooth=1, width=3)
                    self.lines[i].append(l)
                p = self.canvas.create_oval(x1-rad, y1-rad, x1+rad, x1+rad,
                                            fill=color, outline=color)
                self.points[i].append(p)

    def setCanvasText(self, item, x, y, **opts):
        self.canvas.coords(item, x, y)
        self.canvas.itemconfig(item, opts)

    def closeWindow(self):
        if self.window:
            self.geom = self.window.geometry()
            app.soar.scope_geom = self.geom
            self.window.destroy()
            self.window = None
        if self.configWindow:
            self.configWindow.closeWindow()
            self.configWindow = None

    def setTimeAxis(self, desiredRange=None):
        if not desiredRange:
            desiredRange = self.opts['X Scale']
        if desiredRange < 1:
            return
        self.numelems = desiredRange + 1
        self.samplesPerElem = 1
        while self.numelems > self.maxNumelems:
            self.samplesPerElem += 1
            self.numelems = int((desiredRange+1)/self.samplesPerElem)
        # TODO: put appropriate label on graph
        self.xrange = desiredRange
        for p in self.probes:
            if p:
                p.resize(self.numelems, self.samplesPerElem)
        self.makeCanvasObjects()
        self.setStaticObjects()

    def clearProbes(self):
        self.probes = []
        self.ymin, self.ymax = None, None

    def makeFunc(self, func, i=None):
        if func.func_code.co_argcount == 0:
            if i is not None: return lambda inp: func()[i]
            else: return lambda inp: func()
        elif func.func_code.co_argcount == 1:
            if i is not None: return lambda inp: func(inp)[i]
            else: return lambda inp: func(inp)
        else:
            sys.stderr.write("Dynamic plot function takes too many arguments")
            return lambda inp: 0.0

    def addProbeFunction(self, names, func, functext=None, initVal=0):
        numavail = len(self.colors) - len(self.probes)
        if numavail == 0:
            sys.stderr.write("All available probes are in use.  Signal will not be plotted")
            return
        if type(names) == list or type(names) == tuple:
            numprobes = min(numavail, len(names))
            if numprobes < len(names):
                sys.stderr.write("Not enough available probes for all signals.  Only "+str(numprobes)+" signals will be plotted.")
            for i in range(numprobes):
                text = functext if functext else str(func)
                text = text+"["+str(i)+"]"
                self.addProbe(names[i], self.makeFunc(func, i), text, initVal)
        else:
            self.addProbe(names, self.makeFunc(func), 
                          functext if functext else str(func), initVal)
        self.setStaticObjects()

    def addProbe(self, name, functext, initVal=0):
        func = lambda: eval(functext)
        self.addProbeFunction(name, func, functext, initVal)

    def setProbeText(self, probeidx, name, functext):
        func = lambda: eval(functext)
        self.setProbe(probeidx, name, func, functext)

    def addProbe(self, name, func, functext, initVal=0):
        self.probes.append(Probe(name, func, functext, self.numelems,
                                 self.samplesPerElem, initVal))
        self.setStaticObjects()
                                      
    def setExtremes(self, (minv, maxv)):
        self.ymin = minv if self.ymin==None else min(self.ymin, minv)
        self.ymax = maxv if self.ymax==None else max(self.ymax, maxv)