1
2
3 import datetime
4 import dics
5 import gamin
6 import logging
7 import re
8 import tc08
9 import time
10
11 import matplotlib
12 matplotlib.use('GTKAgg')
13 from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as \
14 FigureCanvas
15 from matplotlib.backends.backend_gtk import NavigationToolbar2GTK as \
16 NavigationToolbar
17 from matplotlib.axes import Subplot
18 from matplotlib.figure import Figure
19
20 import pygtk
21 pygtk.require('2.0')
22 import gobject
23 import gtk
24
26 """
27 First stab at a gui element. To begin with it's just a temperature
28 monitor display. The GTK main loop will block, so to retain
29 ability to use the python console we'll want to make this a seperate
30 thread at some point.
31 """
32 colours = ('b', 'r', 'c', 'm', 'y', 'k')
33 styles = ('-', '--', '-.', ':')
34
35
37 gtk.main_quit()
38 return False
39
41 """
42 Initialises the gui. Takes a dics.instrument object as an argument,
43 which it scans through for tc08 instances from which it polls
44 temperatures for display.
45 """
46 if not isinstance(instrument, dics.instrument):
47 raise TypeError('Expected dics.instrument, got %s!' % \
48 type(instrument))
49
50 self.logger = logging.getLogger('gui')
51
52
53 self.pattern = re.compile(\
54 r'(?:(?<=:\d{2})\s+)|(?:(?<=\.\d{2})\s+(?!$))')
55 self.timefmt = '%d%b%y %H:%M:%S'
56
57
58 self.tc08s = [value for value in instrument.__dict__.values() if \
59 isinstance(value, tc08.tc08)]
60
61
62 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
63 self.window.set_title('DICS - Temperature monitor')
64 self.window.set_default_size(700,500)
65
66
67 self.window.connect("delete_event", self.delete_event)
68
69
70 self.hbox = gtk.HBox(homogeneous=False, spacing=10)
71 self.window.add(self.hbox)
72
73
74 num_rows = sum([len(temp_logger.getNames()) for temp_logger in \
75 self.tc08s])
76 self.table = gtk.Table(num_rows, 4, homogeneous=False)
77 self.table.set_row_spacings(0)
78 self.table.set_col_spacings(0)
79 self.hbox.pack_start(self.table, expand=False, fill=False, \
80 padding=10)
81
82
83
84 self.labels_name = []
85 self.labels_temp = []
86 self.labels_unit = []
87 self.checks_plot = []
88 row = 0
89
90 for temp_logger in self.tc08s:
91 for name in temp_logger.getNames():
92
93 label_name = gtk.Label(name)
94 label_temp = gtk.Label('****.**')
95 label_unit = gtk.Label(temp_logger.units)
96 check_plot = gtk.CheckButton()
97
98 self.table.attach(label_name, 0, 1, row, row + 1, \
99 xoptions=0, yoptions=0, \
100 xpadding=0, ypadding=0)
101 self.table.attach(label_temp, 1, 2, row, row + 1, \
102 xoptions=0, yoptions=0, \
103 xpadding=0, ypadding=0)
104 self.table.attach(label_unit, 2, 3, row, row + 1, \
105 xoptions=0, yoptions=0, \
106 xpadding=0, ypadding=0)
107 self.table.attach(check_plot, 3, 4, row, row + 1, \
108 xoptions=0, yoptions=0, \
109 xpadding=0, ypadding=0)
110
111 label_name.set_alignment(0,0.5)
112 check_plot.set_active(True)
113
114 label_name.show()
115 label_temp.show()
116 label_unit.show()
117 check_plot.show()
118
119 self.labels_name += [label_name]
120 self.labels_temp += [label_temp]
121 self.labels_unit += [label_unit]
122 self.checks_plot += [check_plot]
123 row += 1
124
125
126 self.vbox_plot = gtk.VBox(homogeneous=False, spacing=0)
127 self.hbox.pack_start(self.vbox_plot, expand=True, fill=True, \
128 padding=0)
129
130
131 self.logfiles = []
132 self.logs = []
133 for temp_logger in self.tc08s:
134 filename = temp_logger.filename
135 self.logfiles.append(filename)
136 try:
137 logfile = file(filename, 'r')
138 except IOError:
139 self.logger.warning("Couldn't open temperature logfile %s!" % \
140 filename)
141 continue
142 log = logfile.readlines()
143 logfile.close()
144 self.logs.append(self.parse_log(log))
145
146
147 self.figure = Figure(figsize=(5,4), dpi=100)
148 self.axes = self.figure.add_subplot(111)
149
150
151 self.make_plot()
152
153
154 self.canvas = FigureCanvas(self.figure)
155 self.vbox_plot.pack_start(self.canvas, expand=True, fill=True, \
156 padding=0)
157
158 self.toolbar = NavigationToolbar(self.canvas, self.window)
159 self.vbox_plot.pack_start(self.toolbar, expand=False, fill=False, \
160 padding=0)
161
162 self.canvas.show()
163 self.toolbar.show()
164
165
166 self.table.show()
167 self.vbox_plot.show()
168 self.hbox.show()
169 self.window.show()
170
172 """
173 Given an integer, returns a matplotlib line colour character. As the
174 number is increased the line colour cycles through blue, green,
175 red, cyan, magenta, yellow, black.
176 """
177 index = int(number) % len(gui.colours)
178 return gui.colours[index]
179
181 """
182 Given an integer, returns a matplotlib line style character. As the
183 number is increased the line style cycles through solid line, dashed
184 line, dot-dashed line and dotted line.
185 """
186 index = int(number) % len(gui.styles)
187 return gui.styles[index]
188
190
191 self.axes.clear()
192
193 for index1 in range(0, len(self.tc08s)):
194 log = self.logs[index1]
195 temp_logger = self.tc08s[index1]
196 names = temp_logger.getNames()
197 style = self.line_style(index1)
198 for index2 in range(1, len(log)):
199 channel = log[index2]
200 name = names[index2-1]
201 colour = self.line_colour(index2-2)
202 self.axes.plot_date(matplotlib.dates.date2num(log[0]), \
203 channel, colour + style, label=name)
204
205 self.axes.legend(numpoints=2)
206 self.axes.set_xlabel('Date/time')
207 self.axes.set_ylabel('Temperature')
208
210 """
211 Parses a temperature log file, and returns a tuple containing a list
212 of datetime.datetime objects and a one list of temperatures per
213 channel.
214 """
215
216 splits = [self.pattern.split(line) for line in temp_log if \
217 line[0] != '#']
218
219
220
221
222 data = [\
223 [datetime.datetime.fromtimestamp(\
224 time.mktime(time.strptime(split[0], self.timefmt)))] + \
225 [float(temp) for temp in split[2:]]
226 for split in splits]
227
228 data = zip(*data)
229
230 return data
231
233 """
234 Callback function that gets the current temperatures from the tc08
235 objects in self.tc08s and updates the temperature display.
236 """
237
238 newTemps = []
239 for temp_logger in self.tc08s:
240 newTemps += temp_logger.getTemps()
241
242 for label, temp in zip(self.labels_temp, newTemps):
243 label.set_text('%7.2f' % temp)
244
245 return True
246
248
249
250 self.timer_id = gobject.timeout_add(5000, self.updateDisplay)
251
252 gtk.main()
253
254
255
256 del self.tc08s
257 return 0
258