Commit 58501ed77f5937cac4036858ce0c7bcce62b9c13

Authored by Christopher Stone
1 parent 8ffbc4ad
Exists in master

Split class plot into separate module, as part of attempt to declutter main

robots/little_john/telemetry/code/monitor/version1/main.py
@@ -22,6 +22,7 @@ import logging @@ -22,6 +22,7 @@ import logging
22 from serialselect import selectserial 22 from serialselect import selectserial
23 from colours import * 23 from colours import *
24 from series import Series 24 from series import Series
  25 +from plot import Plot
25 26
26 logging.basicConfig(format='%(levelname)s:\t%(message)s', level=logging.DEBUG) 27 logging.basicConfig(format='%(levelname)s:\t%(message)s', level=logging.DEBUG)
27 logging.info("Logging system active") 28 logging.info("Logging system active")
@@ -39,128 +40,6 @@ else: @@ -39,128 +40,6 @@ else:
39 os='Other' 40 os='Other'
40 logging.info('OS = ' + os) 41 logging.info('OS = ' + os)
41 42
42 -class Plot(pyglet.window.Window):  
43 - def __init__(self, series):  
44 - """Setup a the details of a plot, and create a corresponding window"""  
45 - pyglet.window.Window.__init__(self, resizable=True)  
46 - self.set_icon(pyglet.image.load('32x32.png'))  
47 - self.set_minimum_size(320,320)  
48 - self.series = series  
49 - self.font = 'Arkhip'  
50 - self.margins = (0.09, 0.08) # Fractions of window size  
51 - self.lines = (10, 8)  
52 - #self.resizable = True  
53 - self.set_caption(self.series.title)  
54 -  
55 - def on_resize(self, width, height):  
56 - """Handle a resize event from the pyglet event loop"""  
57 - try:  
58 - self.bounds = ((int(self.width * self.margins[0]), int(self.width * (1 - self.margins[0]))),  
59 - (int(self.height * self.margins[1]), int(self.height * (1 - self.margins[1]))))  
60 - except Exception as e:  
61 - logging.critical(str(e))  
62 - self.close()  
63 - logging.critical('Instance closed')  
64 - sys.exit()  
65 - self.tag_size = min(self.height*self.margins[1]*0.3,self.width*self.margins[0]*0.3)  
66 - # This sometimes seems to throw an error ('AttributeError: 'Plot' object has no attribute 'margins') when started for a second time from the same instance. Interesting. Causes the plot windows to freeze  
67 - pyglet.window.Window.on_resize(self, width, height)  
68 -  
69 - def on_draw(self):  
70 - """Draw all the components of the graph"""  
71 - self.drawBackground()  
72 - self.drawHeading()  
73 - self.drawAxis(0)  
74 - self.drawAxis(1)  
75 - self.drawLine(self.series)  
76 -  
77 - def drawBackground(self):  
78 - """Draw the graph background, currently a plain colour"""  
79 - pyglet.image.SolidColorImagePattern(WHITE).create_image(self.width, self.height).blit(0, 0)  
80 -  
81 - def drawHeading(self):  
82 - """Draw a title for the graph (duplicated in the window titlebar, if present"""  
83 - heading = pyglet.text.Label(self.series.title, color=BLACK,  
84 - font_name=self.font, font_size=self.height*self.margins[0]*0.5,  
85 - x=self.width/2, y=self.height-(self.margins[1]),  
86 - anchor_x='center', anchor_y='top')  
87 - heading.draw()  
88 -  
89 - def drawLine(self, series):  
90 - xscale = float(self.series.xlimits[1]-self.series.xlimits[0])/(self.bounds[0][1]-self.bounds[0][0])  
91 - yscale = float(self.series.ylimits[1]-self.series.ylimits[0])/(self.bounds[1][1]-self.bounds[1][0])  
92 - logging.debug("xscale = " + str(xscale) + ", yscale = " + str(yscale))  
93 - lmar = int(self.width * self.margins[0])  
94 - rmar = int(self.width * self.margins[1])  
95 - tmar = int(self.height * self.margins[0])  
96 - bmar = int(self.height * self.margins[1])  
97 -  
98 - pyglet.gl.glLineWidth(2)  
99 -  
100 - for n in range(len(series.data) - 1):  
101 - x1, y1 = series.data[n][0]-series.xlimits[0], series.data[n][1]-series.ylimits[0]  
102 - x2, y2 = series.data[n+1][0]-series.xlimits[0], series.data[n+1][1]-series.ylimits[0]  
103 - x1 = int((x1/xscale)+lmar)  
104 - y1 = int((y1/yscale)+bmar)  
105 - x2 = int((x2/xscale)+lmar)  
106 - y2 = int((y2/yscale)+bmar)  
107 - pyglet.graphics.draw(2, pyglet.gl.GL_LINES,  
108 - ('v2i', (x1, y1, x2, y2)),  
109 - ('c3B', (255, 0, 0, 255, 0, 0)))  
110 - pyglet.gl.glLineWidth(1)  
111 -  
112 -  
113 -  
114 - def drawAxis(self, axis): # axis=0 is x, 1 is y  
115 - """Draw the gridlines and labels for one axis, specified in the last argument"""  
116 - limita = self.bounds[1-axis][1]  
117 - limitb = self.bounds[1-axis][0]  
118 - start = self.bounds[axis][0]  
119 - stop = self.bounds[axis][1]  
120 - increment = float(stop-start)/self.lines[axis]  
121 - for pos in numpy.arange(start, stop+1, increment):  
122 - # Using fp arithmetic to avoid intermittent fencepost errors  
123 - pos = int(pos)  
124 - if axis==0: # x axis, vertical lines  
125 - scale = float(self.series.xlimits[1]-self.series.xlimits[0])/(stop-start)  
126 - tagvalue = ((pos-start) * scale) + self.series.xlimits[0]  
127 - tagtext = str(int(tagvalue))  
128 - pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2i', (pos, limita, pos, limitb)),  
129 - ('c3B', (0, 0, 0, 0, 0, 0)))  
130 - tag = pyglet.text.Label(tagtext, color=BLACK,  
131 - font_name=self.font, font_size=self.tag_size,  
132 - x=pos, y=self.height*self.margins[1],  
133 - anchor_x='left', anchor_y='top')  
134 - axistitle = pyglet.text.Label(self.series.xname, color=BLACK,  
135 - font_name=self.font, font_size=self.tag_size,  
136 - x=self.width/2, y=0,  
137 - anchor_x='center', anchor_y='bottom')  
138 - axistitle.draw()  
139 - if axis==1: # y axis, horizontal lines  
140 - scale = float(self.series.ylimits[1]-self.series.ylimits[0])/(stop-start)  
141 - tagvalue = ((pos-start) * scale) + self.series.ylimits[0]  
142 - tagtext = str(int(tagvalue))  
143 - pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2i', (limita, pos, limitb, pos)),  
144 - ('c3B', (0, 0, 0, 0, 0, 0)))  
145 - tag = pyglet.text.Label(tagtext, color=BLACK,  
146 - font_name=self.font, font_size=self.tag_size,  
147 - x=self.width*self.margins[0]*0.9, y=pos,  
148 - anchor_x='right', anchor_y='center')  
149 - axistitle = pyglet.text.Label(self.series.yname, color=BLACK,  
150 - font_name=self.font, font_size=self.tag_size,  
151 - x=0, y=self.height/2,  
152 - anchor_x='center', anchor_y='top')  
153 - pyglet.gl.glPushMatrix() # Set up a new context to avoid confusing the main one  
154 - # Tranformation to rotate label, and ensure it ends up in the right place  
155 - pyglet.gl.glTranslatef(self.height//2, self.height//2, 0.0)  
156 - pyglet.gl.glRotatef(90.0, 0.0, 0.0, 1.0)  
157 - # Draw the axis title using the rotated coordinate system  
158 - axistitle.draw()  
159 - # Return everything to its previous state  
160 - pyglet.gl.glPopMatrix()  
161 -  
162 - tag.draw()  
163 -  
164 testseries = Series() 43 testseries = Series()
165 logging.info("Series created") 44 logging.info("Series created")
166 plots = [] 45 plots = []
robots/little_john/telemetry/code/monitor/version1/plot.py 0 โ†’ 100644
@@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
  1 +# Class representing a single 2D plot window and its properties
  2 +# Written as a telemetry tool by:
  3 +# The UoN Robot Wars Project, 2018
  4 +
  5 +import pyglet
  6 +import numpy
  7 +import logging
  8 +from colours import *
  9 +
  10 +class Plot(pyglet.window.Window):
  11 + def __init__(self, series):
  12 + """Setup a the details of a plot, and create a corresponding window"""
  13 + pyglet.window.Window.__init__(self, resizable=True)
  14 + self.set_icon(pyglet.image.load('32x32.png'))
  15 + self.set_minimum_size(320,320)
  16 + self.series = series
  17 + self.font = 'Arkhip'
  18 + self.margins = (0.09, 0.08) # Fractions of window size
  19 + self.lines = (10, 8)
  20 + #self.resizable = True
  21 + self.set_caption(self.series.title)
  22 +
  23 + def on_resize(self, width, height):
  24 + """Handle a resize event from the pyglet event loop"""
  25 + try:
  26 + self.bounds = ((int(self.width * self.margins[0]), int(self.width * (1 - self.margins[0]))),
  27 + (int(self.height * self.margins[1]), int(self.height * (1 - self.margins[1]))))
  28 + except Exception as e:
  29 + logging.critical(str(e))
  30 + self.close()
  31 + logging.critical('Instance closed')
  32 + sys.exit()
  33 + self.tag_size = min(self.height*self.margins[1]*0.3,self.width*self.margins[0]*0.3)
  34 + # This sometimes seems to throw an error ('AttributeError: 'Plot' object has no attribute 'margins') when started for a second time from the same instance. Interesting. Causes the plot windows to freeze
  35 + pyglet.window.Window.on_resize(self, width, height)
  36 +
  37 + def on_draw(self):
  38 + """Draw all the components of the graph"""
  39 + self.drawBackground()
  40 + self.drawHeading()
  41 + self.drawAxis(0)
  42 + self.drawAxis(1)
  43 + self.drawLine(self.series)
  44 +
  45 + def drawBackground(self):
  46 + """Draw the graph background, currently a plain colour"""
  47 + pyglet.image.SolidColorImagePattern(WHITE).create_image(self.width, self.height).blit(0, 0)
  48 +
  49 + def drawHeading(self):
  50 + """Draw a title for the graph (duplicated in the window titlebar, if present"""
  51 + heading = pyglet.text.Label(self.series.title, color=BLACK,
  52 + font_name=self.font, font_size=self.height*self.margins[0]*0.5,
  53 + x=self.width/2, y=self.height-(self.margins[1]),
  54 + anchor_x='center', anchor_y='top')
  55 + heading.draw()
  56 +
  57 + def drawLine(self, series):
  58 + xscale = float(self.series.xlimits[1]-self.series.xlimits[0])/(self.bounds[0][1]-self.bounds[0][0])
  59 + yscale = float(self.series.ylimits[1]-self.series.ylimits[0])/(self.bounds[1][1]-self.bounds[1][0])
  60 + logging.debug("xscale = " + str(xscale) + ", yscale = " + str(yscale))
  61 + lmar = int(self.width * self.margins[0])
  62 + rmar = int(self.width * self.margins[1])
  63 + tmar = int(self.height * self.margins[0])
  64 + bmar = int(self.height * self.margins[1])
  65 +
  66 + pyglet.gl.glLineWidth(2)
  67 +
  68 + for n in range(len(series.data) - 1):
  69 + x1, y1 = series.data[n][0]-series.xlimits[0], series.data[n][1]-series.ylimits[0]
  70 + x2, y2 = series.data[n+1][0]-series.xlimits[0], series.data[n+1][1]-series.ylimits[0]
  71 + x1 = int((x1/xscale)+lmar)
  72 + y1 = int((y1/yscale)+bmar)
  73 + x2 = int((x2/xscale)+lmar)
  74 + y2 = int((y2/yscale)+bmar)
  75 + pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
  76 + ('v2i', (x1, y1, x2, y2)),
  77 + ('c3B', (255, 0, 0, 255, 0, 0)))
  78 + pyglet.gl.glLineWidth(1)
  79 +
  80 +
  81 +
  82 + def drawAxis(self, axis): # axis=0 is x, 1 is y
  83 + """Draw the gridlines and labels for one axis, specified in the last argument"""
  84 + limita = self.bounds[1-axis][1]
  85 + limitb = self.bounds[1-axis][0]
  86 + start = self.bounds[axis][0]
  87 + stop = self.bounds[axis][1]
  88 + increment = float(stop-start)/self.lines[axis]
  89 + for pos in numpy.arange(start, stop+1, increment):
  90 + # Using fp arithmetic to avoid intermittent fencepost errors
  91 + pos = int(pos)
  92 + if axis==0: # x axis, vertical lines
  93 + scale = float(self.series.xlimits[1]-self.series.xlimits[0])/(stop-start)
  94 + tagvalue = ((pos-start) * scale) + self.series.xlimits[0]
  95 + tagtext = str(int(tagvalue))
  96 + pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2i', (pos, limita, pos, limitb)),
  97 + ('c3B', (0, 0, 0, 0, 0, 0)))
  98 + tag = pyglet.text.Label(tagtext, color=BLACK,
  99 + font_name=self.font, font_size=self.tag_size,
  100 + x=pos, y=self.height*self.margins[1],
  101 + anchor_x='left', anchor_y='top')
  102 + axistitle = pyglet.text.Label(self.series.xname, color=BLACK,
  103 + font_name=self.font, font_size=self.tag_size,
  104 + x=self.width/2, y=0,
  105 + anchor_x='center', anchor_y='bottom')
  106 + axistitle.draw()
  107 + if axis==1: # y axis, horizontal lines
  108 + scale = float(self.series.ylimits[1]-self.series.ylimits[0])/(stop-start)
  109 + tagvalue = ((pos-start) * scale) + self.series.ylimits[0]
  110 + tagtext = str(int(tagvalue))
  111 + pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2i', (limita, pos, limitb, pos)),
  112 + ('c3B', (0, 0, 0, 0, 0, 0)))
  113 + tag = pyglet.text.Label(tagtext, color=BLACK,
  114 + font_name=self.font, font_size=self.tag_size,
  115 + x=self.width*self.margins[0]*0.9, y=pos,
  116 + anchor_x='right', anchor_y='center')
  117 + axistitle = pyglet.text.Label(self.series.yname, color=BLACK,
  118 + font_name=self.font, font_size=self.tag_size,
  119 + x=0, y=self.height/2,
  120 + anchor_x='center', anchor_y='top')
  121 + pyglet.gl.glPushMatrix() # Set up a new context to avoid confusing the main one
  122 + # Tranformation to rotate label, and ensure it ends up in the right place
  123 + pyglet.gl.glTranslatef(self.height//2, self.height//2, 0.0)
  124 + pyglet.gl.glRotatef(90.0, 0.0, 0.0, 1.0)
  125 + # Draw the axis title using the rotated coordinate system
  126 + axistitle.draw()
  127 + # Return everything to its previous state
  128 + pyglet.gl.glPopMatrix()
  129 +
  130 + tag.draw()