-
Notifications
You must be signed in to change notification settings - Fork 21
/
plot_manager_D3S.py
411 lines (338 loc) · 12.6 KB
/
plot_manager_D3S.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
from globalvalues import RPI
if RPI:
import RPi.GPIO as GPIO
import time
import traceback
import argparse
import kromek
import numpy as np
import signal
import sys
from auxiliaries import set_verbosity
#from sender import ServerSender
from data_handler_d3s import Data_Handler_D3S
from Real_Time_Spectra import Real_Time_Spectra
# import spectra_fitter
from globalvalues import DEFAULT_CALIBRATIONLOG_D3S, DEFAULT_LOGFILE_D3S
from globalvalues import DEFAULT_CALIBRATIONLOG_TIME
from globalvalues import DEFAULT_DATALOG_D3S
def signal_term_handler(signal, frame):
# If SIGTERM signal is intercepted, the SystemExit exception routines
# get run
print('Got Sigterm!')
sys.exit(0)
signal.signal(signal.SIGTERM, signal_term_handler)
class Manager_D3S(object):
"""
Master object for D3S device operation.
Prints out spectra for every interval, stores each spectra, and
sums the spectra together.
Interval is in seconds with the default being 30 seconds.
"""
def __init__(self,
interval=5,
maxspectra=20,
count=0,
transport='usb',
device='all',
log_bytes=False,
verbosity=None,
datalog=None,
datalogflag=False,
calibrationlog=None,
calibrationlogflag=False,
calibrationlogtime=None,
test=None,
logfile=None,
log=False,
running=False,
plot=True
):
self.running = running
self.total = None
self.lst = None
self.create_structures = True
self.interval = interval
self.maxspectra = maxspectra
self.count = count
self.config = None
self.publickey = None
self.transport = transport
self.device = device
self.log_bytes = log_bytes
self.calibrationlog = calibrationlog
self.calibrationlogflag = calibrationlogflag
self.c_timer = 0
self.calibrationlogtime = calibrationlogtime
self.z_flag()
self.y_flag()
self.x_flag()
self.make_calibration_log(self.calibrationlog)
self.datalog = datalog
self.datalogflag = datalogflag
self.a_flag()
self.d_flag()
self.make_data_log(self.datalog)
self.test = test
self.handle_input(
log, logfile, verbosity, interval)
self.plot = plot
self.data_handler = Data_Handler_D3S(
manager=self,
verbosity=self.v,
logfile=self.logfile)
# self.sender = ServerSender(
# manager=self,
# mode=sender_mode,
# port=port,
# verbosity=self.v,
# logfile=self.logfile,)
# DEFAULT_UDP_PORT and DEFAULT_TCP_PORT are assigned in sender
self.data_handler.backlog_to_queue()
print('creating plotter')
self.rt_plot = Real_Time_Spectra(
manager=self,
verbosity=self.v)
def z_flag(self):
"""
Checks if the -z from_argparse is called.
If it is called, sets the path of the calibration-log to
DEFAULT_CALIBRATIONLOG_D3S.
"""
if self.calibrationlogflag:
self.calibrationlog = DEFAULT_CALIBRATIONLOG_D3S
def y_flag(self):
"""
Checks if the -y from_argparse is called.
If it is called, sets calibrationlogflag to True.
Also sets calibrationlogtime to DEFAULT_CALIBRATIONLOG_TIME.
"""
if self.calibrationlog:
self.calibrationlogflag = True
self.calibrationlogtime = DEFAULT_CALIBRATIONLOG_TIME
def x_flag(self):
"""
Checks if -x is called.
If it is called, sets calibrationlogflag to True.
Also sets calibrationlog to DEFAULT_CALIBRATIONLOG_D3S.
"""
if self.calibrationlogtime and (
self.calibrationlogtime != DEFAULT_CALIBRATIONLOG_TIME):
self.calibrationlog = DEFAULT_CALIBRATIONLOG_D3S
self.calibrationlogflag = True
def make_calibration_log(self, file):
if self.calibrationlogflag:
with open(file, 'a') as f:
pass
def a_flag(self):
"""
Checks if the -a from_argparse is called.
If it is called, sets the path of the data-log to
DEFAULT_DATALOG_D3S.
"""
if self.datalogflag:
self.datalog = DEFAULT_DATALOG_D3S
def d_flag(self):
"""
Checks if the -d from_argparse is called.
If it is called, sets datalogflag to True.
"""
if self.datalog:
self.datalogflag = True
def make_data_log(self, file):
if self.datalogflag:
with open(file, 'a') as f:
pass
def handle_input(self, log, logfile, verbosity, interval):
"""
Sets up logging, verbosity, interval, config, and publickey
"""
# resolve logging defaults
if log and logfile is None:
# use default file if logging is enabled
logfile = DEFAULT_LOGFILE_D3S
if logfile and not log:
# enable logging if logfile is specified
# (this overrides a log=False input which wouldn't make sense)
log = True
if log:
self.logfile = logfile
else:
self.logfile = None
if verbosity is None:
verbosity = 1
self.v = verbosity
set_verbosity(self, logfile=logfile)
if log:
self.vprint(1, '')
self.vprint(1, 'Writing to logfile at {}'.format(self.logfile))
self.running = True
if interval is None:
self.vprint(
2, "No interval given, using interval at 30 seconds")
interval = DEFAULT_INTERVAL_NORMAL_D3S
self.interval = int(interval)
def close(self, plot_id):
self.rt_plot.close(plot_id)
def run(self):
"""
Main method. Currently also stores and sum the spectra as well.
Current way to stop is only using a keyboard interrupt.
"""
if self.transport == 'any':
devs = kromek.discover()
else:
devs = kromek.discover(self.transport)
print('Discovered %s' % devs)
if len(devs) <= 0:
return
filtered = []
for dev in devs:
if self.device == 'all' or dev[0] in self.device:
filtered.append(dev)
devs = filtered
if len(devs) <= 0:
return
done_devices = set()
try:
while self.running:
print("Plot_manager.run: getting data")
with kromek.Controller(devs, self.interval) as controller:
for reading in controller.read():
if self.create_structures:
self.total = np.array(reading[4])
self.lst = np.array([reading[4]])
self.create_structures = False
else:
self.total += np.array(reading[4])
self.lst = np.concatenate(
(self.lst, [np.array(reading[4])]))
serial = reading[0]
dev_count = reading[1]
if serial not in done_devices:
this_start, this_end = self.get_interval(
time.time() - self.interval)
self.handle_spectra(
this_start, this_end, reading[4])
if dev_count >= self.count > 0:
done_devices.add(serial)
controller.stop_collector(serial)
if len(done_devices) >= len(devs):
break
except KeyboardInterrupt:
self.vprint(1, '\nKeyboardInterrupt: stopping Manager run')
self.takedown()
except SystemExit:
self.vprint(1, '\nSystemExit: taking down Manager')
self.takedown()
def get_interval(self, start_time):
"""
Return start and end time for interval, based on given start_time.
"""
end_time = start_time + self.interval
return start_time, end_time
def data_log(self, file, spectra):
"""
Writes spectra to data-log.
"""
if self.datalogflag:
with open(file, 'a') as f:
f.write('{0}, '.format(spectra))
self.vprint(
2, 'Writing spectra to data log at {}'.format(file))
def calibration_log(self, file, spectra):
"""
Writes spectra to calibration-log.
"""
if self.calibrationlogflag:
with open(file, 'a') as f:
f.write('{0}, '.format(spectra))
self.vprint(
2, 'Writing spectra to calibration log at {}'.format(file))
self.c_timer += self.interval
if self.c_timer >= self.calibrationlogtime:
self.vprint(1, 'Calibration Complete')
self.takedown()
def plot_waterfall(self, plot_id):
"""Wrapper around waterfall plotter in Real_Time_Spectra class"""
self.rt_plot.plot_waterfall(plot_id)
def plot_spectrum(self,plot_id):
"""Wrapper around spectrum plotter in Real_Time_Spectra class"""
self.rt_plot.plot_sum(plot_id)
def plot_fitter(self):
"""
Wrapper around spectrum-fitter data acquisition plotter in
spectra_fitter class
"""
total_time=self.interval*self.maxspectra
times = np.linspace(self.interval,total_time + 1,self.interval)
spectra_fitter.main(self.rt_plot.sum_data, times)
def handle_spectra(self, this_start, this_end, spectra):
"""
Get spectra from sensor, display text, send to server.
"""
self.rt_plot.add_data(self.rt_plot.queue, spectra, self.maxspectra)
if self.plot:
'''
Plot the data.
'''
self.plot_waterfall(1)
self.plot_spectrum(2)
# self.plot_fitter()
'''
Uncomment 3 lines below to plot the spectra fitter plots.
'''
else:
self.data_handler.main(
self.datalog, self.calibrationlog, spectra, this_start, this_end)
def takedown(self):
"""
Sets self.running to False and deletes self. Also turns off LEDs
"""
GPIO.cleanup()
self.running = False
self.data_handler.send_all_to_backlog()
del(self)
@classmethod
def from_argparse(cls):
parser = argparse.ArgumentParser()
parser.add_argument('--datalog', '-d', default=None)
parser.add_argument(
'--datalogflag', '-a', action='store_true', default=True)
parser.add_argument('--verbosity', '-v', type=int, default=None)
parser.add_argument('--test', '-t', action='store_true', default=None)
parser.add_argument('--transport', '-n', default= 'usb')
parser.add_argument('--interval', '-i', type=int, default=5)
parser.add_argument('--maxspectra', '-s', type = int, default=20)
parser.add_argument('--count', '-o', dest='count', default=0)
parser.add_argument('--device', '-e', dest='device', default='all')
parser.add_argument(
'--log-bytes', '-b', dest='log_bytes', default=False,
action='store_true')
parser.add_argument('--log', '-l', action='store_true', default=False)
parser.add_argument('--logfile', '-f', type=str, default=None)
parser.add_argument('--calibrationlogtime', '-x', type=int, default=None)
parser.add_argument('--calibrationlog', '-y', default=None)
parser.add_argument(
'--calibrationlogflag', '-z', action='store_true', default=False)
parser.add_argument('--plot', '-p', action='store_true', default=True)
args = parser.parse_args()
arg_dict = vars(args)
mgr = Manager_D3S(**arg_dict)
return mgr
def main():
mgr = Manager_D3S.from_argparse()
try:
mgr.run()
except:
if mgr.logfile:
# print exception info to logfile
with open(mgr.logfile, 'a') as f:
traceback.print_exc(15, f)
# regardless, re-raise the error which will print to stderr
raise
if __name__ == '__main__':
'''
Execute the main method with argument parsing enabled.
'''
main()