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