##// END OF EJS Templates
upgrade filterbyHeights, fix initial parameters. removeProfileSats2 improved debug
joabAM -
r1655:13a9a26f11d7
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

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