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