##// END OF EJS Templates
Update sender plots when loosing conn
Juan C. Espinoza -
r1302:5d9cc9fa8a36
parent child
Show More
@@ -1,704 +1,705
1 1
2 2 import os
3 3 import sys
4 4 import zmq
5 5 import time
6 6 import numpy
7 7 import datetime
8 from queue import Queue
8 9 from functools import wraps
9 10 from threading import Thread
10 11 import matplotlib
11 12
12 13 if 'BACKEND' in os.environ:
13 14 matplotlib.use(os.environ['BACKEND'])
14 15 elif 'linux' in sys.platform:
15 16 matplotlib.use("TkAgg")
16 17 elif 'darwin' in sys.platform:
17 18 matplotlib.use('WxAgg')
18 19 else:
19 20 from schainpy.utils import log
20 21 log.warning('Using default Backend="Agg"', 'INFO')
21 22 matplotlib.use('Agg')
22 23
23 24 import matplotlib.pyplot as plt
24 25 from matplotlib.patches import Polygon
25 26 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 27 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27 28
28 29 from schainpy.model.data.jrodata import PlotterData
29 30 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 31 from schainpy.utils import log
31 32
32 33 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 34 blu_values = matplotlib.pyplot.get_cmap(
34 35 'seismic_r', 20)(numpy.arange(20))[10:15]
35 36 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 37 'jro', numpy.vstack((blu_values, jet_values)))
37 38 matplotlib.pyplot.register_cmap(cmap=ncmap)
38 39
39 40 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 41 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41 42
42 43 EARTH_RADIUS = 6.3710e3
43 44
44 45 def ll2xy(lat1, lon1, lat2, lon2):
45 46
46 47 p = 0.017453292519943295
47 48 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 49 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 50 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 51 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 52 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 53 theta = -theta + numpy.pi/2
53 54 return r*numpy.cos(theta), r*numpy.sin(theta)
54 55
55 56
56 57 def km2deg(km):
57 58 '''
58 59 Convert distance in km to degrees
59 60 '''
60 61
61 62 return numpy.rad2deg(km/EARTH_RADIUS)
62 63
63 64
64 65 def figpause(interval):
65 66 backend = plt.rcParams['backend']
66 67 if backend in matplotlib.rcsetup.interactive_bk:
67 68 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 69 if figManager is not None:
69 70 canvas = figManager.canvas
70 71 if canvas.figure.stale:
71 72 canvas.draw()
72 73 try:
73 74 canvas.start_event_loop(interval)
74 75 except:
75 76 pass
76 77 return
77 78
78 79
79 80 def popup(message):
80 81 '''
81 82 '''
82 83
83 84 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 85 text = '\n'.join([s.strip() for s in message.split(':')])
85 86 fig.text(0.01, 0.5, text, ha='left', va='center',
86 87 size='20', weight='heavy', color='w')
87 88 fig.show()
88 89 figpause(1000)
89 90
90 91
91 92 class Throttle(object):
92 93 '''
93 94 Decorator that prevents a function from being called more than once every
94 95 time period.
95 96 To create a function that cannot be called more than once a minute, but
96 97 will sleep until it can be called:
97 98 @Throttle(minutes=1)
98 99 def foo():
99 100 pass
100 101
101 102 for i in range(10):
102 103 foo()
103 104 print "This function has run %s times." % i
104 105 '''
105 106
106 107 def __init__(self, seconds=0, minutes=0, hours=0):
107 108 self.throttle_period = datetime.timedelta(
108 109 seconds=seconds, minutes=minutes, hours=hours
109 110 )
110 111
111 112 self.time_of_last_call = datetime.datetime.min
112 113
113 114 def __call__(self, fn):
114 115 @wraps(fn)
115 116 def wrapper(*args, **kwargs):
116 117 coerce = kwargs.pop('coerce', None)
117 118 if coerce:
118 119 self.time_of_last_call = datetime.datetime.now()
119 120 return fn(*args, **kwargs)
120 121 else:
121 122 now = datetime.datetime.now()
122 123 time_since_last_call = now - self.time_of_last_call
123 124 time_left = self.throttle_period - time_since_last_call
124 125
125 126 if time_left > datetime.timedelta(seconds=0):
126 127 return
127 128
128 129 self.time_of_last_call = datetime.datetime.now()
129 130 return fn(*args, **kwargs)
130 131
131 132 return wrapper
132 133
133 134 def apply_throttle(value):
134 135
135 136 @Throttle(seconds=value)
136 137 def fnThrottled(fn):
137 138 fn()
138 139
139 140 return fnThrottled
140 141
141 142
142 143 @MPDecorator
143 144 class Plot(Operation):
144 145 '''
145 146 Base class for Schain plotting operations
146 147 '''
147 148
148 149 CODE = 'Figure'
149 150 colormap = 'jet'
150 151 bgcolor = 'white'
151 152 buffering = True
152 153 __missing = 1E30
153 154
154 155 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
155 156 'showprofile']
156 157
157 158 def __init__(self):
158 159
159 160 Operation.__init__(self)
160 161 self.isConfig = False
161 162 self.isPlotConfig = False
162 163 self.save_counter = 1
163 164 self.sender_time = 0
164 165 self.data = None
165 166 self.firsttime = True
167 self.sender_queue = Queue(maxsize=10)
166 168 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
167 169
168 170 def __fmtTime(self, x, pos):
169 171 '''
170 172 '''
171 173
172 174 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
173 175
174 176 def __setup(self, **kwargs):
175 177 '''
176 178 Initialize variables
177 179 '''
178 180
179 181 self.figures = []
180 182 self.axes = []
181 183 self.cb_axes = []
182 184 self.localtime = kwargs.pop('localtime', True)
183 185 self.show = kwargs.get('show', True)
184 186 self.save = kwargs.get('save', False)
185 187 self.save_period = kwargs.get('save_period', 1)
186 188 self.ftp = kwargs.get('ftp', False)
187 189 self.colormap = kwargs.get('colormap', self.colormap)
188 190 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
189 191 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
190 192 self.colormaps = kwargs.get('colormaps', None)
191 193 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
192 194 self.showprofile = kwargs.get('showprofile', False)
193 195 self.title = kwargs.get('wintitle', self.CODE.upper())
194 196 self.cb_label = kwargs.get('cb_label', None)
195 197 self.cb_labels = kwargs.get('cb_labels', None)
196 198 self.labels = kwargs.get('labels', None)
197 199 self.xaxis = kwargs.get('xaxis', 'frequency')
198 200 self.zmin = kwargs.get('zmin', None)
199 201 self.zmax = kwargs.get('zmax', None)
200 202 self.zlimits = kwargs.get('zlimits', None)
201 203 self.xmin = kwargs.get('xmin', None)
202 204 self.xmax = kwargs.get('xmax', None)
203 205 self.xrange = kwargs.get('xrange', 24)
204 206 self.xscale = kwargs.get('xscale', None)
205 207 self.ymin = kwargs.get('ymin', None)
206 208 self.ymax = kwargs.get('ymax', None)
207 209 self.yscale = kwargs.get('yscale', None)
208 210 self.xlabel = kwargs.get('xlabel', None)
209 211 self.attr_time = kwargs.get('attr_time', 'utctime')
210 212 self.decimation = kwargs.get('decimation', None)
211 213 self.showSNR = kwargs.get('showSNR', False)
212 214 self.oneFigure = kwargs.get('oneFigure', True)
213 215 self.width = kwargs.get('width', None)
214 216 self.height = kwargs.get('height', None)
215 217 self.colorbar = kwargs.get('colorbar', True)
216 218 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
217 219 self.channels = kwargs.get('channels', None)
218 220 self.titles = kwargs.get('titles', [])
219 221 self.polar = False
220 222 self.type = kwargs.get('type', 'iq')
221 223 self.grid = kwargs.get('grid', False)
222 224 self.pause = kwargs.get('pause', False)
223 225 self.save_code = kwargs.get('save_code', None)
224 226 self.realtime = kwargs.get('realtime', True)
225 227 self.throttle = kwargs.get('throttle', 0)
226 228 self.exp_code = kwargs.get('exp_code', None)
227 229 self.plot_server = kwargs.get('plot_server', False)
228 230 self.sender_period = kwargs.get('sender_period', 60)
229 231 self.height_index = kwargs.get('height_index', None)
230 232 self.__throttle_plot = apply_throttle(self.throttle)
231 233 self.data = PlotterData(
232 234 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
233 235
234 236 if self.plot_server:
235 237 if not self.plot_server.startswith('tcp://'):
236 238 self.plot_server = 'tcp://{}'.format(self.plot_server)
237 239 log.success(
238 240 'Sending to server: {}'.format(self.plot_server),
239 241 self.name
240 242 )
241 243 if 'plot_name' in kwargs:
242 244 self.plot_name = kwargs['plot_name']
243 245
244 246 def __setup_plot(self):
245 247 '''
246 248 Common setup for all figures, here figures and axes are created
247 249 '''
248 250
249 251 self.setup()
250 252
251 253 self.time_label = 'LT' if self.localtime else 'UTC'
252 254
253 255 if self.width is None:
254 256 self.width = 8
255 257
256 258 self.figures = []
257 259 self.axes = []
258 260 self.cb_axes = []
259 261 self.pf_axes = []
260 262 self.cmaps = []
261 263
262 264 size = '15%' if self.ncols == 1 else '30%'
263 265 pad = '4%' if self.ncols == 1 else '8%'
264 266
265 267 if self.oneFigure:
266 268 if self.height is None:
267 269 self.height = 1.4 * self.nrows + 1
268 270 fig = plt.figure(figsize=(self.width, self.height),
269 271 edgecolor='k',
270 272 facecolor='w')
271 273 self.figures.append(fig)
272 274 for n in range(self.nplots):
273 275 ax = fig.add_subplot(self.nrows, self.ncols,
274 276 n + 1, polar=self.polar)
275 277 ax.tick_params(labelsize=8)
276 278 ax.firsttime = True
277 279 ax.index = 0
278 280 ax.press = None
279 281 self.axes.append(ax)
280 282 if self.showprofile:
281 283 cax = self.__add_axes(ax, size=size, pad=pad)
282 284 cax.tick_params(labelsize=8)
283 285 self.pf_axes.append(cax)
284 286 else:
285 287 if self.height is None:
286 288 self.height = 3
287 289 for n in range(self.nplots):
288 290 fig = plt.figure(figsize=(self.width, self.height),
289 291 edgecolor='k',
290 292 facecolor='w')
291 293 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
292 294 ax.tick_params(labelsize=8)
293 295 ax.firsttime = True
294 296 ax.index = 0
295 297 ax.press = None
296 298 self.figures.append(fig)
297 299 self.axes.append(ax)
298 300 if self.showprofile:
299 301 cax = self.__add_axes(ax, size=size, pad=pad)
300 302 cax.tick_params(labelsize=8)
301 303 self.pf_axes.append(cax)
302 304
303 305 for n in range(self.nrows):
304 306 if self.colormaps is not None:
305 307 cmap = plt.get_cmap(self.colormaps[n])
306 308 else:
307 309 cmap = plt.get_cmap(self.colormap)
308 310 cmap.set_bad(self.bgcolor, 1.)
309 311 self.cmaps.append(cmap)
310 312
311 313 def __add_axes(self, ax, size='30%', pad='8%'):
312 314 '''
313 315 Add new axes to the given figure
314 316 '''
315 317 divider = make_axes_locatable(ax)
316 318 nax = divider.new_horizontal(size=size, pad=pad)
317 319 ax.figure.add_axes(nax)
318 320 return nax
319 321
320 322 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
321 323 '''
322 324 Create a masked array for missing data
323 325 '''
324 326 if x_buffer.shape[0] < 2:
325 327 return x_buffer, y_buffer, z_buffer
326 328
327 329 deltas = x_buffer[1:] - x_buffer[0:-1]
328 330 x_median = numpy.median(deltas)
329 331
330 332 index = numpy.where(deltas > 5 * x_median)
331 333
332 334 if len(index[0]) != 0:
333 335 z_buffer[::, index[0], ::] = self.__missing
334 336 z_buffer = numpy.ma.masked_inside(z_buffer,
335 337 0.99 * self.__missing,
336 338 1.01 * self.__missing)
337 339
338 340 return x_buffer, y_buffer, z_buffer
339 341
340 342 def decimate(self):
341 343
342 344 # dx = int(len(self.x)/self.__MAXNUMX) + 1
343 345 dy = int(len(self.y) / self.decimation) + 1
344 346
345 347 # x = self.x[::dx]
346 348 x = self.x
347 349 y = self.y[::dy]
348 350 z = self.z[::, ::, ::dy]
349 351
350 352 return x, y, z
351 353
352 354 def format(self):
353 355 '''
354 356 Set min and max values, labels, ticks and titles
355 357 '''
356 358
357 359 if self.xmin is None:
358 360 xmin = self.data.min_time
359 361 else:
360 362 if self.xaxis is 'time':
361 363 dt = self.getDateTime(self.data.min_time)
362 364 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
363 365 datetime.datetime(1970, 1, 1)).total_seconds()
364 366 if self.data.localtime:
365 367 xmin += time.timezone
366 368 else:
367 369 xmin = self.xmin
368 370
369 371 if self.xmax is None:
370 372 xmax = xmin + self.xrange * 60 * 60
371 373 else:
372 374 if self.xaxis is 'time':
373 375 dt = self.getDateTime(self.data.max_time)
374 376 xmax = self.xmax - 1
375 377 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
376 378 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
377 379 if self.data.localtime:
378 380 xmax += time.timezone
379 381 else:
380 382 xmax = self.xmax
381 383
382 384 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
383 385 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
384 386
385 387 for n, ax in enumerate(self.axes):
386 388 if ax.firsttime:
387 389
388 390 dig = int(numpy.log10(ymax))
389 391 if dig == 0:
390 392 digD = len(str(ymax)) - 2
391 393 ydec = ymax*(10**digD)
392 394
393 395 dig = int(numpy.log10(ydec))
394 396 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
395 397 ystep = ystep/5
396 398 ystep = ystep/(10**digD)
397 399
398 400 else:
399 401 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
400 402 ystep = ystep/5
401 403
402 404 if self.xaxis is not 'time':
403 405
404 406 dig = int(numpy.log10(xmax))
405 407
406 408 if dig <= 0:
407 409 digD = len(str(xmax)) - 2
408 410 xdec = xmax*(10**digD)
409 411
410 412 dig = int(numpy.log10(xdec))
411 413 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
412 414 xstep = xstep*0.5
413 415 xstep = xstep/(10**digD)
414 416
415 417 else:
416 418 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
417 419 xstep = xstep/5
418 420
419 421 ax.set_facecolor(self.bgcolor)
420 422 ax.yaxis.set_major_locator(MultipleLocator(ystep))
421 423 if self.xscale:
422 424 ax.xaxis.set_major_formatter(FuncFormatter(
423 425 lambda x, pos: '{0:g}'.format(x*self.xscale)))
424 426 if self.xscale:
425 427 ax.yaxis.set_major_formatter(FuncFormatter(
426 428 lambda x, pos: '{0:g}'.format(x*self.yscale)))
427 429 if self.xaxis is 'time':
428 430 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
429 431 ax.xaxis.set_major_locator(LinearLocator(9))
430 432 else:
431 433 ax.xaxis.set_major_locator(MultipleLocator(xstep))
432 434 if self.xlabel is not None:
433 435 ax.set_xlabel(self.xlabel)
434 436 ax.set_ylabel(self.ylabel)
435 437 ax.firsttime = False
436 438 if self.showprofile:
437 439 self.pf_axes[n].set_ylim(ymin, ymax)
438 440 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
439 441 self.pf_axes[n].set_xlabel('dB')
440 442 self.pf_axes[n].grid(b=True, axis='x')
441 443 [tick.set_visible(False)
442 444 for tick in self.pf_axes[n].get_yticklabels()]
443 445 if self.colorbar:
444 446 ax.cbar = plt.colorbar(
445 447 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
446 448 ax.cbar.ax.tick_params(labelsize=8)
447 449 ax.cbar.ax.press = None
448 450 if self.cb_label:
449 451 ax.cbar.set_label(self.cb_label, size=8)
450 452 elif self.cb_labels:
451 453 ax.cbar.set_label(self.cb_labels[n], size=8)
452 454 else:
453 455 ax.cbar = None
454 456 if self.grid:
455 457 ax.grid(True)
456 458
457 459 if not self.polar:
458 460 ax.set_xlim(xmin, xmax)
459 461 ax.set_ylim(ymin, ymax)
460 462 ax.set_title('{} {} {}'.format(
461 463 self.titles[n],
462 464 self.getDateTime(self.data.max_time).strftime(
463 465 '%Y-%m-%d %H:%M:%S'),
464 466 self.time_label),
465 467 size=8)
466 468 else:
467 469 ax.set_title('{}'.format(self.titles[n]), size=8)
468 470 ax.set_ylim(0, 90)
469 471 ax.set_yticks(numpy.arange(0, 90, 20))
470 472 ax.yaxis.labelpad = 40
471 473
472 474 if self.firsttime:
473 475 for n, fig in enumerate(self.figures):
474 476 fig.subplots_adjust(**self.plots_adjust)
475 477 self.firsttime = False
476 478
477 479 def clear_figures(self):
478 480 '''
479 481 Reset axes for redraw plots
480 482 '''
481 483
482 484 for ax in self.axes+self.pf_axes+self.cb_axes:
483 485 ax.clear()
484 486 ax.firsttime = True
485 487 if ax.cbar:
486 488 ax.cbar.remove()
487 489
488 490 def __plot(self):
489 491 '''
490 492 Main function to plot, format and save figures
491 493 '''
492 494
493 495 self.plot()
494 496 self.format()
495 497
496 498 for n, fig in enumerate(self.figures):
497 499 if self.nrows == 0 or self.nplots == 0:
498 500 log.warning('No data', self.name)
499 501 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
500 502 fig.canvas.manager.set_window_title(self.CODE)
501 503 continue
502 504
503 505 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
504 506 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
505 507 fig.canvas.draw()
506 508 if self.show:
507 509 fig.show()
508 510 figpause(0.01)
509 511
510 512 if self.save:
511 513 self.save_figure(n)
512 514
513 515 if self.plot_server:
514 516 self.send_to_server()
515 517
516 518 def save_figure(self, n):
517 519 '''
518 520 '''
519 521
520 522 if self.save_counter < self.save_period:
521 523 self.save_counter += 1
522 524 return
523 525
524 526 self.save_counter = 1
525 527
526 528 fig = self.figures[n]
527 529
528 530 if self.save_code:
529 531 if isinstance(self.save_code, str):
530 532 labels = [self.save_code for x in self.figures]
531 533 else:
532 534 labels = self.save_code
533 535 else:
534 536 labels = [self.CODE for x in self.figures]
535 537
536 538 figname = os.path.join(
537 539 self.save,
538 540 labels[n],
539 541 '{}_{}.png'.format(
540 542 labels[n],
541 543 self.getDateTime(self.data.max_time).strftime(
542 544 '%Y%m%d_%H%M%S'
543 545 ),
544 546 )
545 547 )
546 548 log.log('Saving figure: {}'.format(figname), self.name)
547 549 if not os.path.isdir(os.path.dirname(figname)):
548 550 os.makedirs(os.path.dirname(figname))
549 551 fig.savefig(figname)
550 552
551 553 if self.throttle == 0:
552 554 figname = os.path.join(
553 555 self.save,
554 556 '{}_{}.png'.format(
555 557 labels[n],
556 558 self.getDateTime(self.data.min_time).strftime(
557 559 '%Y%m%d'
558 560 ),
559 561 )
560 562 )
561 563 fig.savefig(figname)
562 564
563 565 def send_to_server(self):
564 566 '''
565 567 '''
566 568
567 569 interval = self.data.tm - self.sender_time
568 570 if interval < self.sender_period:
569 571 return
570 572
571 573 self.sender_time = self.data.tm
572 574
573 attrs = ['titles', 'zmin', 'zmax']
575 attrs = ['titles', 'zmin', 'zmax', 'colormap']
574 576 for attr in attrs:
575 self.data.meta[attr] = getattr(self, attr)
577 value = getattr(self, attr)
578 if value is not None:
579 self.data.meta[attr] = getattr(self, attr)
576 580 self.data.meta['interval'] = int(interval)
577 retries = 2
581 msg = self.data.jsonify(self.plot_name, self.plot_type)
582 self.sender_queue.put(msg)
583
578 584 while True:
579 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
585 if self.sender_queue.empty():
586 break
587 self.socket.send_string(self.sender_queue.get())
580 588 socks = dict(self.poll.poll(5000))
581 589 if socks.get(self.socket) == zmq.POLLIN:
582 590 reply = self.socket.recv_string()
583 591 if reply == 'ok':
584 592 log.log("Response from server ok", self.name)
585 break
593 time.sleep(0.1)
594 continue
586 595 else:
587 596 log.warning(
588 597 "Malformed reply from server: {}".format(reply), self.name)
589
590 598 else:
591 599 log.warning(
592 600 "No response from server, retrying...", self.name)
601 self.sender_queue.put(msg)
593 602 self.socket.setsockopt(zmq.LINGER, 0)
594 603 self.socket.close()
595 604 self.poll.unregister(self.socket)
596 retries -= 1
597 if retries == 0:
598 log.error(
599 "Server seems to be offline, abandoning", self.name)
600 self.socket = self.context.socket(zmq.REQ)
601 self.socket.connect(self.plot_server)
602 self.poll.register(self.socket, zmq.POLLIN)
603 time.sleep(1)
604 break
605 time.sleep(0.1)
605 606 self.socket = self.context.socket(zmq.REQ)
606 607 self.socket.connect(self.plot_server)
607 608 self.poll.register(self.socket, zmq.POLLIN)
608 time.sleep(0.5)
609 break
609 610
610 611 def setup(self):
611 612 '''
612 613 This method should be implemented in the child class, the following
613 614 attributes should be set:
614 615
615 616 self.nrows: number of rows
616 617 self.ncols: number of cols
617 618 self.nplots: number of plots (channels or pairs)
618 619 self.ylabel: label for Y axes
619 620 self.titles: list of axes title
620 621
621 622 '''
622 623 raise NotImplementedError
623 624
624 625 def plot(self):
625 626 '''
626 627 Must be defined in the child class
627 628 '''
628 629 raise NotImplementedError
629 630
630 631 def run(self, dataOut, **kwargs):
631 632 '''
632 633 Main plotting routine
633 634 '''
634 635
635 636 if self.isConfig is False:
636 637 self.__setup(**kwargs)
637 638
638 639 t = getattr(dataOut, self.attr_time)
639 640
640 641 if dataOut.useLocalTime:
641 642 self.getDateTime = datetime.datetime.fromtimestamp
642 643 if not self.localtime:
643 644 t += time.timezone
644 645 else:
645 646 self.getDateTime = datetime.datetime.utcfromtimestamp
646 647 if self.localtime:
647 648 t -= time.timezone
648 649
649 650 if 'buffer' in self.plot_type:
650 651 if self.xmin is None:
651 652 self.tmin = t
652 653 self.xmin = self.getDateTime(t).hour
653 654 else:
654 655 self.tmin = (
655 656 self.getDateTime(t).replace(
656 657 hour=int(self.xmin),
657 658 minute=0,
658 659 second=0) - self.getDateTime(0)).total_seconds()
659 660
660 661 self.data.setup()
661 662 self.isConfig = True
662 663 if self.plot_server:
663 664 self.context = zmq.Context()
664 665 self.socket = self.context.socket(zmq.REQ)
665 666 self.socket.connect(self.plot_server)
666 667 self.poll = zmq.Poller()
667 668 self.poll.register(self.socket, zmq.POLLIN)
668 669
669 670 tm = getattr(dataOut, self.attr_time)
670 671
671 672 if not dataOut.useLocalTime and self.localtime:
672 673 tm -= time.timezone
673 674 if dataOut.useLocalTime and not self.localtime:
674 675 tm += time.timezone
675 676
676 677 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
677 678 self.save_counter = self.save_period
678 679 self.__plot()
679 680 self.xmin += self.xrange
680 681 if self.xmin >= 24:
681 682 self.xmin -= 24
682 683 self.tmin += self.xrange*60*60
683 684 self.data.setup()
684 685 self.clear_figures()
685 686
686 687 self.data.update(dataOut, tm)
687 688
688 689 if self.isPlotConfig is False:
689 690 self.__setup_plot()
690 691 self.isPlotConfig = True
691 692
692 693 if self.throttle == 0:
693 694 self.__plot()
694 695 else:
695 696 self.__throttle_plot(self.__plot)#, coerce=coerce)
696 697
697 698 def close(self):
698 699
699 700 if self.data and not self.data.flagNoData:
700 701 self.save_counter = self.save_period
701 702 self.__plot()
702 703 if self.data and not self.data.flagNoData and self.pause:
703 704 figpause(10)
704 705
General Comments 0
You need to be logged in to leave comments. Login now