Welcome, guest | Sign In | My Account | Store | Cart
#!/usr/bin/env python
"""
Author: Flavio Codeco Coelho
License: GPL
Stripchart module for vpython
Features:
-user defined number of channels

"""

import psyco
import time
from visual import *
from visual.text import *
from RandomArray import random
from psyco.classes import *
psyco
.full()

class Strip:
   
"""
    Stripchart object.
    """

   
def __init__(self, nch=1, xlabel='t(s)',ylabel='V'):
       
self.scene = display(title="Stripchart Recorder",width=600,height=400, uniform=0, ambient=1,autoscale=1)
       
#create the curves
       
self.channels = self.addch(nch)
       
self.gridon = True
       
self.grid = frame() #collection of horizontal grid lines
       
self.ticklabels=frame()#collection of labels
       
self.xlabel = label(frame=self.grid,pos=(9,-9,0),text=xlabel,color=color.orange,box=0, line=0)
       
self.ylabel = label(frame=self.grid,pos=(-9,9,0),text=ylabel,color=color.orange,box=0,line=0)
       
self.drawGrid()
       
self.drawTickLabels(range(-10,10),range(-10,10))
       

   
def addch(self, nch=1):
       
"""
        Creates a channel object (curve)
        nch is the number of channels.
        """

        col
= [color.white,color.blue,color.red,color.green,color.yellow,color.cyan,color.magenta, color.orange]
        tplch
= tuple([curve(radius=0, color=col[n%len(col)])for n in xrange(nch)])

       
return tplch

   
def toggleGrid(self):
       
"""
        Toggle visibility of gridlines
        """

        r
= len(self.grid.objects)
       
if self.gridon:
           
for i in range(r):
               
self.grid.objects[0].visible = 0
           
self.gridon = False
       
else:
           
self.drawGrid()
           
self.gridon = True
           
       
pass
   
def drawGrid(self):
       
"""
        draw grid lines
        """

        hrng
= int(self.scene.range[1])
        vrng
= int(self.scene.range[0])
       
       
[curve(frame=self.grid,pos=[(-vrng,i),(vrng,i)],color=color.white) for i in  xrange(-hrng, hrng, hrng*2/10)]
       
       
[curve(frame=self.grid,pos=[(j,-hrng),(j,hrng)],color=color.white) for j in  xrange(-vrng, vrng, vrng*2/10)]
       
       
       
   
def drawTickLabels(self,xticks,yticks):
       
"""
        Draw x and y tick labels
        """

        xticks2
= array([round(i,2) for i in xticks])
        yticks2
= array([round(i,2) for i in yticks])
        labidx
= range(0,len(xticks2),len(xticks2)/10) #indices to the labels to be plotted
       
Pos = range(-10,10,2) #position of the ticklabels within the frame coordinates
       
       
#List comprehensions to draw ticklabels. [(xticks,yticks) for i in xrange(len(Pos))]
       
# Not as clear as a regular "for" but much faster...
       
[label(frame=self.ticklabels,pos=(Pos[i],-8,0),text=str(xticks2[labidx[i]]),color=color.orange,box=0,line=0) for i in xrange(len(Pos))] #x ticklables
       
       
[label(frame=self.ticklabels,pos=(-8,Pos[i],0),text=str(yticks2[labidx[i]]),color=color.orange,box=0,line=0) for i in xrange(len(Pos))] #y ticklabels
       
   
def updateTicks(self,xticks,yticks):
       
"""
        Update tick labels  values
        """

        xticks2
= array([round(i,2) for i in xticks])
        yticks2
= array([round(i,2) for i in yticks])
        labidx
= range(0,len(xticks2),len(xticks2)/10) #indices to the labels to be plotted
       
Pos = range(-10,10,2) #position of the ticklabels within the frame coordinates
        i
= j = 0
       
for l in self.ticklabels.objects:
           
if self.ticklabels.objects.index(l) < 10: #update x axis
                l
.text = str(xticks2[labidx[i]])
                i
+= 1
           
else:                       #update y axis
                l
.text = str(yticks2[labidx[j]])
                j
+= 1
       
       
   
def plot(self,ch,point):
       
"""
        Appends a point to the channel(curve) object ch.
        Fills the scene and after it is full,
        shifts the curve one step left, for each new point.
        If its the first point it creates the plot.
        """

       
#Adjust the scene and frames vertically to folow data
       
if point[1] > self.scene.range[1]:
           
self.scene.center[1] = point[1]-9
           
self.grid.y = point[1]-9
           
self.ticklabels.y = point[1]-9
       
elif  point[1] < -self.scene.range[1]:
           
self.scene.center[1] = point[1]+9
           
self.grid.y = point[1]+9
           
self.ticklabels.y = point[1]+9
       
#=========================================    
       
if self.scene.kb.keys:#key trap
            s
= self.scene.kb.getkey() # obtain keyboard information
           
if s == 'g' or s == 'G':
               
self.toggleGrid()
       
# Scroll scene center right to follow data        
       
if len(ch.x) > 0 and ch.x[-1] > 10:
           
# scroll center of the scene with x
            new_x_center
= (ch.x[0]+ch.x[-1])/2.
           
self.scene.center = (new_x_center,0,0)
           
self.updateTicks(ch.x,ch.y)
           
self.grid.x = new_x_center
           
self.ticklabels.x = new_x_center
           
           
# shift curve and append
           
            ch
.pos[:-1] = ch.pos[1:]
            ch
.pos[-1] = point
       
else:
            ch
.append(pos=point)

if __name__=='__main__':
    st
= Strip(2)
    ch1
= st.channels[0]
    ch2
= st.channels[1]
    start
= time.clock()
   
for i in arange(-10,200,.1):
        st
.plot(ch1,(i,10*sin(i),0))
        st
.plot(ch2,(i,10*cos(i)+random(),0))
       
#rate(50)#set maximum frame rate

   
print "frame rate: ", 1/((time.clock()-start)/210.)

History