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 22 from serialselect import selectserial
23 23 from colours import *
24 24 from series import Series
  25 +from plot import Plot
25 26  
26 27 logging.basicConfig(format='%(levelname)s:\t%(message)s', level=logging.DEBUG)
27 28 logging.info("Logging system active")
... ... @@ -39,128 +40,6 @@ else:
39 40 os='Other'
40 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 43 testseries = Series()
165 44 logging.info("Series created")
166 45 plots = []
... ...
robots/little_john/telemetry/code/monitor/version1/plot.py 0 โ†’ 100644
... ... @@ -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()
... ...