Package joy :: Module scope
[hide private]
[frames] | no frames]

Source Code for Module joy.scope

  1  import pygame as pg 
  2  import numpy as np 
  3   
4 -class DataWindow( object ):
5 """ 6 Concrete class DataWindow represents a sliding window of data through time 7 """
8 - def __init__(self,duration=1):
9 self.clear() 10 self.duration = duration
11
12 - def clear( self ):
13 """ 14 Empty the window. 15 """ 16 self.push = self._firstPush 17 self.t = [] 18 self.data = []
19
20 - def setDuration( self, duration ):
21 """ 22 Change the duration of data allowed in the window. 23 This may discard existing data if duration was made smaller 24 """ 25 assert duration>=0 26 self.duration = duration 27 if self.t: 28 self._trim()
29
30 - def _trim( self ):
31 """ 32 (private) trim any entries outside the most recent window of 33 self.duration time units 34 """ 35 t = self.t[-1] 36 while t-self.t[0]>self.duration: 37 self.t.pop(0) 38 self.data.pop(0)
39
40 - def _firstPush( self, t, val ):
41 """ 42 Push data at the end of the window 43 INPUTS: 44 t -- timestamp 45 val -- data record to append / replace 46 47 If t equals last timestamp, last entry in window is replaced. Otherwise, 48 entry is appended and window is trimmed to duration limit. 49 50 (private) first push operation on an empty window 51 """ 52 self.t = [t] 53 self.data = [val] 54 self.push = self._push
55
56 - def _push( self, t, val ):
57 """ 58 Push data at the end of the window 59 INPUTS: 60 t -- timestamp 61 val -- data record to append / replace 62 63 If t equals last timestamp, last entry in window is replaced. Otherwise, 64 entry is appended and window is trimmed to duration limit. 65 """ 66 if t>self.t[-1]: 67 self.t.append(t) 68 self.data.append(val) 69 self._trim() 70 elif t==self.t[-1]: 71 self.data[-1] = val 72 else: 73 raise IndexError('Time %g < last entry %g' % (t,self.t[-1]))
74
75 - def push( self, t, val ):
76 """Fake placeholder -- modified by __init__, _firstPush""" 77 pass
78
79 -def planBoxes( grid, bw=0.1 ):
80 """ 81 Convenience function for creating a figure layout 82 INPUT: 83 grid -- ASCII art layout (see example below) 84 bw -- border width in grids; either scalar or (horizontal,vertical) 85 OUTPUT: 86 Boxes for regions, sorted by region id chars. 87 Regions marked with space, '-' or '|' are ignored 88 Example: 89 p=''' 90 xxxxx yyy 91 xxxxx yyy 92 xxxxx yyy 93 94 zzzzzzzzz 95 zzzzzzzzz 96 ''' 97 box_x,box_y,box_z = planAxes(p,bw=0.5) 98 """ 99 # Convert border to 2 entry array 100 bw = np.asarray(bw) 101 if bw.size==1: 102 bw = np.array([bw,bw]) 103 else: 104 assert bw.size==2 105 # Split lines 106 g0 = grid.strip().split("\n") 107 l = max([len(r) for r in g0]) 108 # Pad lines to constant length 109 pad = " "*l 110 # Create grid of chars 111 g = np.array([ [y for y in (x+pad)[:l]] for x in g0][::-1]) 112 xs = 1.0/g.shape[1] 113 ys = 1.0/g.shape[0] 114 lst = np.unique(g.flatten()) 115 res = [] 116 bx,by = bw 117 for nm in lst: 118 if nm in ' -|': 119 continue 120 ind = (g==nm) 121 xi = np.any(ind,axis=0).ravel().nonzero()[0] 122 yi = np.any(ind,axis=1).ravel().nonzero()[0] 123 box = np.array(( 124 (xi[0]+bx)*xs,(yi[0]+by)*ys, 125 xs*(xi[-1]-xi[0]+1-2*bx),ys*(yi[-1]-yi[0]+1-2*by) 126 )) 127 res.append(box) 128 return res
129
130 -class Glyph( object ):
131 """ 132 Concrete class representing a bitmap that is placed at multiple 133 locations on an image. Each Glyph has an image and a basepoint 134 offset (which defaults to its center). The image is RGBA, so 135 pixels may be made transparent. 136 137 By default, a Glyph contains a blue cross of the specified size, 138 with lines 3 pixels wide. With size 5, this makes a good circular 139 dot. 140 """
141 - def __init__(self, size, color=(0,0,128) ):
142 """ 143 Create a glyph of the specified size and color. 144 145 INPUTS: 146 size -- number or pair -- size of glyph image 147 148 ATTRIBUTES: 149 .ofs -- len 2 -- offset of basepoint into image 150 .img -- pygame image of size size, mode RGBA -- the Glyph itself 151 """ 152 try: 153 len(size) 154 except: 155 size = (size,size) 156 self.img = pg.image.fromstring( 157 ' ' * (size[0]*size[1]*4), size,"RGBA" ) 158 self.ofs = (size[0]/2, size[1]/2) 159 self.img.fill((0,0,0,0)) 160 pg.draw.line(self.img, color, (0,self.ofs[1]),(size[0],self.ofs[1]),3) 161 pg.draw.line(self.img, color, (self.ofs[0],0),(self.ofs[1],size[1]),3)
162
163 - def put( self, surf, x, y ):
164 """ 165 Put copies of the image at the specified points on the surface 166 167 INPUTS: 168 surf -- pygame.Surface to draw on 169 x,y -- sequences of equal length of x and y coordinates 170 """ 171 sz = self.img.get_size() 172 for xi,yi in zip(x,y): 173 surf.blit( self.img, (xi-self.ofs[0],yi-self.ofs[1],sz[0],sz[1]))
174
175 -class LinePlotter( object ):
176 """ 177 Concrete class LinePlotter implements simple line plotting functionality 178 (including coordinate scaling and line markers) on a box within a 179 pygame.Surface 180 """ 181 color = np.array([0,0,255]) 182
183 - def __init__(self, surf, box = (0,0,1,1) ):
184 """ 185 INPUTS: 186 surf -- the pygame.Surface on which to plot 187 box -- bounding box, in range (0,0) to (1,1) 188 189 ATTRIBUTES (public): 190 .c -- color -- line color to use; autogenerated 191 .mrk -- Glyph -- line symbols; default is dot with the color .c 192 .bg -- color -- background color used for clearing plot area 193 .axes -- 4-list -- (xmin,ymin,width,height) 194 """ 195 w,h = surf.get_size() 196 x0,y0,x1,y1 = box 197 self._surf = surf.subsurface( (w*x0, h*y0, w*x1, h*y1) ) 198 self.c = LinePlotter.color 199 self.mrk = Glyph((5,5),color=LinePlotter.color) 200 LinePlotter.color = (LinePlotter.color + np.array([0x85,0x05,0x50])) % 255 201 self.bg = (255,255,255) 202 self.axes = [0,0,1,1]
203
204 - def plot( self, x, y=None ):
205 """ 206 Plot a line with the specified points 207 208 INPUTS: 209 x -- numbers -- x coordinates, in plot(x,y) form, or y coordinates 210 in plot(y) form. 211 y -- numbers or None -- y coordinates of points 212 """ 213 W,H = self._surf.get_size() 214 x0,y0,xs,ys = tuple(( float(x) for x in self.axes )) 215 if y is None: 216 py = (np.asarray(x)-x0)/xs * H 217 px = np.arange(0,W,float(W)/len(py)) 218 else: 219 px = (np.asarray(x)-x0)/xs * W 220 py = (np.asarray(y)-y0)/ys * H 221 if self.mrk: 222 self.mrk.put(self._surf,px,py) 223 if len(px)>1: 224 pg.draw.aalines( self._surf, self.c, False, zip(px,py))
225
226 - def cla( self ):
227 """ 228 Clear the plot area to background color 229 """ 230 self._surf.fill(self.bg)
231 232 if __name__=="__main__": 233 from pygame.locals import * 234 pg.init() 235 screen = pg.display.set_mode((640,480)) 236 clock = pg.time.Clock() 237 bx = planBoxes('abc\ndef') 238 plt = [ 239 [LinePlotter( screen, b ),DataWindow( 2000 )] 240 for b in bx 241 ] 242 while True: 243 clock.tick(60) 244 pg.event.pump() 245 event = pg.event.poll() 246 if event.type == QUIT: 247 break 248 if event.type == KEYDOWN and event.key == K_ESCAPE: 249 break 250 t = pg.time.get_ticks() 251 screen.fill(0) 252 for lp,dw in plt: 253 lp.cla() 254 dw.push(t,np.random.rand()) 255 lp.axes[2] = float(dw.duration) 256 lp.plot( dw.data ) 257 pg.display.flip() 258