##// END OF EJS Templates
Update plot parameters
jespinoza -
r1336:fc3be1cf6768
parent child
Show More
@@ -1,665 +1,665
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 multiprocessing import Queue
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('WxAgg')
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
87 87 def popup(message):
88 88 '''
89 89 '''
90 90
91 91 fig = plt.figure(figsize=(12, 8), facecolor='r')
92 92 text = '\n'.join([s.strip() for s in message.split(':')])
93 93 fig.text(0.01, 0.5, text, ha='left', va='center',
94 94 size='20', weight='heavy', color='w')
95 95 fig.show()
96 96 figpause(1000)
97 97
98 98
99 99 class Throttle(object):
100 100 '''
101 101 Decorator that prevents a function from being called more than once every
102 102 time period.
103 103 To create a function that cannot be called more than once a minute, but
104 104 will sleep until it can be called:
105 105 @Throttle(minutes=1)
106 106 def foo():
107 107 pass
108 108
109 109 for i in range(10):
110 110 foo()
111 111 print "This function has run %s times." % i
112 112 '''
113 113
114 114 def __init__(self, seconds=0, minutes=0, hours=0):
115 115 self.throttle_period = datetime.timedelta(
116 116 seconds=seconds, minutes=minutes, hours=hours
117 117 )
118 118
119 119 self.time_of_last_call = datetime.datetime.min
120 120
121 121 def __call__(self, fn):
122 122 @wraps(fn)
123 123 def wrapper(*args, **kwargs):
124 124 coerce = kwargs.pop('coerce', None)
125 125 if coerce:
126 126 self.time_of_last_call = datetime.datetime.now()
127 127 return fn(*args, **kwargs)
128 128 else:
129 129 now = datetime.datetime.now()
130 130 time_since_last_call = now - self.time_of_last_call
131 131 time_left = self.throttle_period - time_since_last_call
132 132
133 133 if time_left > datetime.timedelta(seconds=0):
134 134 return
135 135
136 136 self.time_of_last_call = datetime.datetime.now()
137 137 return fn(*args, **kwargs)
138 138
139 139 return wrapper
140 140
141 141 def apply_throttle(value):
142 142
143 143 @Throttle(seconds=value)
144 144 def fnThrottled(fn):
145 145 fn()
146 146
147 147 return fnThrottled
148 148
149 149
150 150 @MPDecorator
151 151 class Plot(Operation):
152 152 """Base class for Schain plotting operations
153 153
154 154 This class should never be use directtly you must subclass a new operation,
155 155 children classes must be defined as follow:
156 156
157 157 ExamplePlot(Plot):
158 158
159 159 CODE = 'code'
160 160 colormap = 'jet'
161 161 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
162 162
163 163 def setup(self):
164 164 pass
165 165
166 166 def plot(self):
167 167 pass
168 168
169 169 """
170 170
171 171 CODE = 'Figure'
172 172 colormap = 'jet'
173 173 bgcolor = 'white'
174 174 buffering = True
175 175 __missing = 1E30
176 176
177 177 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
178 178 'showprofile']
179 179
180 180 def __init__(self):
181 181
182 182 Operation.__init__(self)
183 183 self.isConfig = False
184 184 self.isPlotConfig = False
185 185 self.save_time = 0
186 186 self.sender_time = 0
187 187 self.data = None
188 188 self.firsttime = True
189 189 self.sender_queue = Queue(maxsize=60)
190 190 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
191 191
192 192 def __fmtTime(self, x, pos):
193 193 '''
194 194 '''
195 195
196 196 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
197 197
198 198 def __setup(self, **kwargs):
199 199 '''
200 200 Initialize variables
201 201 '''
202 202
203 203 self.figures = []
204 204 self.axes = []
205 205 self.cb_axes = []
206 206 self.localtime = kwargs.pop('localtime', True)
207 207 self.show = kwargs.get('show', True)
208 208 self.save = kwargs.get('save', False)
209 self.save_period = kwargs.get('save_period', 60)
209 self.save_period = kwargs.get('save_period', 0)
210 210 self.colormap = kwargs.get('colormap', self.colormap)
211 211 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
212 212 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
213 213 self.colormaps = kwargs.get('colormaps', None)
214 214 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
215 215 self.showprofile = kwargs.get('showprofile', False)
216 216 self.title = kwargs.get('wintitle', self.CODE.upper())
217 217 self.cb_label = kwargs.get('cb_label', None)
218 218 self.cb_labels = kwargs.get('cb_labels', None)
219 219 self.labels = kwargs.get('labels', None)
220 220 self.xaxis = kwargs.get('xaxis', 'frequency')
221 221 self.zmin = kwargs.get('zmin', None)
222 222 self.zmax = kwargs.get('zmax', None)
223 223 self.zlimits = kwargs.get('zlimits', None)
224 224 self.xmin = kwargs.get('xmin', None)
225 225 self.xmax = kwargs.get('xmax', None)
226 226 self.xrange = kwargs.get('xrange', 12)
227 227 self.xscale = kwargs.get('xscale', None)
228 228 self.ymin = kwargs.get('ymin', None)
229 229 self.ymax = kwargs.get('ymax', None)
230 230 self.yscale = kwargs.get('yscale', None)
231 231 self.xlabel = kwargs.get('xlabel', None)
232 232 self.attr_time = kwargs.get('attr_time', 'utctime')
233 233 self.decimation = kwargs.get('decimation', None)
234 234 self.showSNR = kwargs.get('showSNR', False)
235 235 self.oneFigure = kwargs.get('oneFigure', True)
236 236 self.width = kwargs.get('width', None)
237 237 self.height = kwargs.get('height', None)
238 238 self.colorbar = kwargs.get('colorbar', True)
239 239 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
240 240 self.channels = kwargs.get('channels', None)
241 241 self.titles = kwargs.get('titles', [])
242 242 self.polar = False
243 243 self.type = kwargs.get('type', 'iq')
244 244 self.grid = kwargs.get('grid', False)
245 245 self.pause = kwargs.get('pause', False)
246 246 self.save_code = kwargs.get('save_code', self.CODE)
247 247 self.throttle = kwargs.get('throttle', 0)
248 248 self.exp_code = kwargs.get('exp_code', None)
249 self.plot_server = kwargs.get('plot_server', False)
249 self.server = kwargs.get('server', False)
250 250 self.sender_period = kwargs.get('sender_period', 60)
251 251 self.tag = kwargs.get('tag', '')
252 252 self.height_index = kwargs.get('height_index', None)
253 253 self.__throttle_plot = apply_throttle(self.throttle)
254 254 self.data = PlotterData(
255 255 self.CODE, self.throttle, self.exp_code, self.localtime, self.buffering, snr=self.showSNR)
256 256
257 if self.plot_server:
258 if not self.plot_server.startswith('tcp://'):
259 self.plot_server = 'tcp://{}'.format(self.plot_server)
257 if self.server:
258 if not self.server.startswith('tcp://'):
259 self.server = 'tcp://{}'.format(self.server)
260 260 log.success(
261 'Sending to server: {}'.format(self.plot_server),
261 'Sending to server: {}'.format(self.server),
262 262 self.name
263 263 )
264 264
265 265 def __setup_plot(self):
266 266 '''
267 267 Common setup for all figures, here figures and axes are created
268 268 '''
269 269
270 270 self.setup()
271 271
272 272 self.time_label = 'LT' if self.localtime else 'UTC'
273 273
274 274 if self.width is None:
275 275 self.width = 8
276 276
277 277 self.figures = []
278 278 self.axes = []
279 279 self.cb_axes = []
280 280 self.pf_axes = []
281 281 self.cmaps = []
282 282
283 283 size = '15%' if self.ncols == 1 else '30%'
284 284 pad = '4%' if self.ncols == 1 else '8%'
285 285
286 286 if self.oneFigure:
287 287 if self.height is None:
288 288 self.height = 1.4 * self.nrows + 1
289 289 fig = plt.figure(figsize=(self.width, self.height),
290 290 edgecolor='k',
291 291 facecolor='w')
292 292 self.figures.append(fig)
293 293 for n in range(self.nplots):
294 294 ax = fig.add_subplot(self.nrows, self.ncols,
295 295 n + 1, polar=self.polar)
296 296 ax.tick_params(labelsize=8)
297 297 ax.firsttime = True
298 298 ax.index = 0
299 299 ax.press = None
300 300 self.axes.append(ax)
301 301 if self.showprofile:
302 302 cax = self.__add_axes(ax, size=size, pad=pad)
303 303 cax.tick_params(labelsize=8)
304 304 self.pf_axes.append(cax)
305 305 else:
306 306 if self.height is None:
307 307 self.height = 3
308 308 for n in range(self.nplots):
309 309 fig = plt.figure(figsize=(self.width, self.height),
310 310 edgecolor='k',
311 311 facecolor='w')
312 312 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
313 313 ax.tick_params(labelsize=8)
314 314 ax.firsttime = True
315 315 ax.index = 0
316 316 ax.press = None
317 317 self.figures.append(fig)
318 318 self.axes.append(ax)
319 319 if self.showprofile:
320 320 cax = self.__add_axes(ax, size=size, pad=pad)
321 321 cax.tick_params(labelsize=8)
322 322 self.pf_axes.append(cax)
323 323
324 324 for n in range(self.nrows):
325 325 if self.colormaps is not None:
326 326 cmap = plt.get_cmap(self.colormaps[n])
327 327 else:
328 328 cmap = plt.get_cmap(self.colormap)
329 329 cmap.set_bad(self.bgcolor, 1.)
330 330 self.cmaps.append(cmap)
331 331
332 332 def __add_axes(self, ax, size='30%', pad='8%'):
333 333 '''
334 334 Add new axes to the given figure
335 335 '''
336 336 divider = make_axes_locatable(ax)
337 337 nax = divider.new_horizontal(size=size, pad=pad)
338 338 ax.figure.add_axes(nax)
339 339 return nax
340 340
341 341 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
342 342 '''
343 343 Create a masked array for missing data
344 344 '''
345 345 if x_buffer.shape[0] < 2:
346 346 return x_buffer, y_buffer, z_buffer
347 347
348 348 deltas = x_buffer[1:] - x_buffer[0:-1]
349 349 x_median = numpy.median(deltas)
350 350
351 351 index = numpy.where(deltas > 5 * x_median)
352 352
353 353 if len(index[0]) != 0:
354 354 z_buffer[::, index[0], ::] = self.__missing
355 355 z_buffer = numpy.ma.masked_inside(z_buffer,
356 356 0.99 * self.__missing,
357 357 1.01 * self.__missing)
358 358
359 359 return x_buffer, y_buffer, z_buffer
360 360
361 361 def decimate(self):
362 362
363 363 # dx = int(len(self.x)/self.__MAXNUMX) + 1
364 364 dy = int(len(self.y) / self.decimation) + 1
365 365
366 366 # x = self.x[::dx]
367 367 x = self.x
368 368 y = self.y[::dy]
369 369 z = self.z[::, ::, ::dy]
370 370
371 371 return x, y, z
372 372
373 373 def format(self):
374 374 '''
375 375 Set min and max values, labels, ticks and titles
376 376 '''
377 377
378 378 for n, ax in enumerate(self.axes):
379 379 if ax.firsttime:
380 380 if self.xaxis != 'time':
381 381 xmin = self.xmin
382 382 xmax = self.xmax
383 383 else:
384 384 xmin = self.tmin
385 385 xmax = self.tmin + self.xrange*60*60
386 386 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
387 387 ax.xaxis.set_major_locator(LinearLocator(9))
388 388 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
389 389 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
390 390 ax.set_facecolor(self.bgcolor)
391 391 if self.xscale:
392 392 ax.xaxis.set_major_formatter(FuncFormatter(
393 393 lambda x, pos: '{0:g}'.format(x*self.xscale)))
394 394 if self.yscale:
395 395 ax.yaxis.set_major_formatter(FuncFormatter(
396 396 lambda x, pos: '{0:g}'.format(x*self.yscale)))
397 397 if self.xlabel is not None:
398 398 ax.set_xlabel(self.xlabel)
399 399 if self.ylabel is not None:
400 400 ax.set_ylabel(self.ylabel)
401 401 if self.showprofile:
402 402 self.pf_axes[n].set_ylim(ymin, ymax)
403 403 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
404 404 self.pf_axes[n].set_xlabel('dB')
405 405 self.pf_axes[n].grid(b=True, axis='x')
406 406 [tick.set_visible(False)
407 407 for tick in self.pf_axes[n].get_yticklabels()]
408 408 if self.colorbar:
409 409 ax.cbar = plt.colorbar(
410 410 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
411 411 ax.cbar.ax.tick_params(labelsize=8)
412 412 ax.cbar.ax.press = None
413 413 if self.cb_label:
414 414 ax.cbar.set_label(self.cb_label, size=8)
415 415 elif self.cb_labels:
416 416 ax.cbar.set_label(self.cb_labels[n], size=8)
417 417 else:
418 418 ax.cbar = None
419 419 ax.set_xlim(xmin, xmax)
420 420 ax.set_ylim(ymin, ymax)
421 421 ax.firsttime = False
422 422 if self.grid:
423 423 ax.grid(True)
424 424 if not self.polar:
425 425 ax.set_title('{} {} {}'.format(
426 426 self.titles[n],
427 427 self.getDateTime(self.data.max_time).strftime(
428 428 '%Y-%m-%d %H:%M:%S'),
429 429 self.time_label),
430 430 size=8)
431 431 else:
432 432 ax.set_title('{}'.format(self.titles[n]), size=8)
433 433 ax.set_ylim(0, 90)
434 434 ax.set_yticks(numpy.arange(0, 90, 20))
435 435 ax.yaxis.labelpad = 40
436 436
437 437 if self.firsttime:
438 438 for n, fig in enumerate(self.figures):
439 439 fig.subplots_adjust(**self.plots_adjust)
440 440 self.firsttime = False
441 441
442 442 def clear_figures(self):
443 443 '''
444 444 Reset axes for redraw plots
445 445 '''
446 446
447 447 for ax in self.axes+self.pf_axes+self.cb_axes:
448 448 ax.clear()
449 449 ax.firsttime = True
450 450 if hasattr(ax, 'cbar') and ax.cbar:
451 451 ax.cbar.remove()
452 452
453 453 def __plot(self):
454 454 '''
455 455 Main function to plot, format and save figures
456 456 '''
457 457
458 458 self.plot()
459 459 self.format()
460 460
461 461 for n, fig in enumerate(self.figures):
462 462 if self.nrows == 0 or self.nplots == 0:
463 463 log.warning('No data', self.name)
464 464 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
465 465 fig.canvas.manager.set_window_title(self.CODE)
466 466 continue
467 467
468 468 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
469 469 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
470 470 fig.canvas.draw()
471 471 if self.show:
472 472 fig.show()
473 473 figpause(0.01)
474 474
475 475 if self.save:
476 476 self.save_figure(n)
477 477
478 if self.plot_server:
478 if self.server:
479 479 self.send_to_server()
480 480
481 481 def save_figure(self, n):
482 482 '''
483 483 '''
484 484
485 if (self.data.tm - self.save_time) < self.sender_period:
485 if (self.data.tm - self.save_time) <= self.save_period:
486 486 return
487 487
488 488 self.save_time = self.data.tm
489 489
490 490 fig = self.figures[n]
491 491
492 492 figname = os.path.join(
493 493 self.save,
494 494 self.save_code,
495 495 '{}_{}.png'.format(
496 496 self.save_code,
497 497 self.getDateTime(self.data.max_time).strftime(
498 498 '%Y%m%d_%H%M%S'
499 499 ),
500 500 )
501 501 )
502 502 log.log('Saving figure: {}'.format(figname), self.name)
503 503 if not os.path.isdir(os.path.dirname(figname)):
504 504 os.makedirs(os.path.dirname(figname))
505 505 fig.savefig(figname)
506 506
507 507 if self.throttle == 0:
508 508 figname = os.path.join(
509 509 self.save,
510 510 '{}_{}.png'.format(
511 511 self.save_code,
512 512 self.getDateTime(self.data.min_time).strftime(
513 513 '%Y%m%d'
514 514 ),
515 515 )
516 516 )
517 517 fig.savefig(figname)
518 518
519 519 def send_to_server(self):
520 520 '''
521 521 '''
522 522
523 523 interval = self.data.tm - self.sender_time
524 524 if interval < self.sender_period:
525 525 return
526 526
527 527 self.sender_time = self.data.tm
528 528
529 529 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
530 530 for attr in attrs:
531 531 value = getattr(self, attr)
532 532 if value:
533 533 if isinstance(value, (numpy.float32, numpy.float64)):
534 534 value = round(float(value), 2)
535 535 self.data.meta[attr] = value
536 536 if self.colormap == 'jet':
537 537 self.data.meta['colormap'] = 'Jet'
538 538 elif 'RdBu' in self.colormap:
539 539 self.data.meta['colormap'] = 'RdBu'
540 540 else:
541 541 self.data.meta['colormap'] = 'Viridis'
542 542 self.data.meta['interval'] = int(interval)
543 543
544 544 try:
545 545 self.sender_queue.put(self.data.tm, block=False)
546 546 except:
547 547 tm = self.sender_queue.get()
548 548 self.sender_queue.put(self.data.tm)
549 549
550 550 while True:
551 551 if self.sender_queue.empty():
552 552 break
553 553 tm = self.sender_queue.get()
554 554 try:
555 555 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
556 556 except:
557 557 continue
558 558 self.socket.send_string(msg)
559 559 socks = dict(self.poll.poll(5000))
560 560 if socks.get(self.socket) == zmq.POLLIN:
561 561 reply = self.socket.recv_string()
562 562 if reply == 'ok':
563 563 log.log("Response from server ok", self.name)
564 564 time.sleep(0.2)
565 565 continue
566 566 else:
567 567 log.warning(
568 568 "Malformed reply from server: {}".format(reply), self.name)
569 569 else:
570 570 log.warning(
571 571 "No response from server, retrying...", self.name)
572 572 self.sender_queue.put(self.data.tm)
573 573 self.socket.setsockopt(zmq.LINGER, 0)
574 574 self.socket.close()
575 575 self.poll.unregister(self.socket)
576 576 time.sleep(0.1)
577 577 self.socket = self.context.socket(zmq.REQ)
578 self.socket.connect(self.plot_server)
578 self.socket.connect(self.server)
579 579 self.poll.register(self.socket, zmq.POLLIN)
580 580 break
581 581
582 582 def setup(self):
583 583 '''
584 584 This method should be implemented in the child class, the following
585 585 attributes should be set:
586 586
587 587 self.nrows: number of rows
588 588 self.ncols: number of cols
589 589 self.nplots: number of plots (channels or pairs)
590 590 self.ylabel: label for Y axes
591 591 self.titles: list of axes title
592 592
593 593 '''
594 594 raise NotImplementedError
595 595
596 596 def plot(self):
597 597 '''
598 598 Must be defined in the child class
599 599 '''
600 600 raise NotImplementedError
601 601
602 602 def run(self, dataOut, **kwargs):
603 603 '''
604 604 Main plotting routine
605 605 '''
606 606
607 607 if self.isConfig is False:
608 608 self.__setup(**kwargs)
609 609
610 610 if self.localtime:
611 611 self.getDateTime = datetime.datetime.fromtimestamp
612 612 else:
613 613 self.getDateTime = datetime.datetime.utcfromtimestamp
614 614
615 615 self.data.setup()
616 616 self.isConfig = True
617 if self.plot_server:
617 if self.server:
618 618 self.context = zmq.Context()
619 619 self.socket = self.context.socket(zmq.REQ)
620 self.socket.connect(self.plot_server)
620 self.socket.connect(self.server)
621 621 self.poll = zmq.Poller()
622 622 self.poll.register(self.socket, zmq.POLLIN)
623 623
624 624 tm = getattr(dataOut, self.attr_time)
625 625
626 626 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
627 self.save_counter = self.save_period
627 self.save_time = tm
628 628 self.__plot()
629 629 self.tmin += self.xrange*60*60
630 630 self.data.setup()
631 631 self.clear_figures()
632 632
633 633 self.data.update(dataOut, tm)
634 634
635 635 if self.isPlotConfig is False:
636 636 self.__setup_plot()
637 637 self.isPlotConfig = True
638 638 if self.xaxis == 'time':
639 639 dt = self.getDateTime(tm)
640 640 if self.xmin is None:
641 641 self.tmin = tm
642 642 self.xmin = dt.hour
643 643 minutes = (self.xmin-int(self.xmin)) * 60
644 644 seconds = (minutes - int(minutes)) * 60
645 645 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
646 646 datetime.datetime(1970, 1, 1)).total_seconds()
647 647 if self.localtime:
648 648 self.tmin += time.timezone
649 649
650 650 if self.xmin is not None and self.xmax is not None:
651 651 self.xrange = self.xmax - self.xmin
652 652
653 653 if self.throttle == 0:
654 654 self.__plot()
655 655 else:
656 656 self.__throttle_plot(self.__plot)#, coerce=coerce)
657 657
658 658 def close(self):
659 659
660 660 if self.data and not self.data.flagNoData:
661 self.save_counter = self.save_period
661 self.save_time = self.data.tm
662 662 self.__plot()
663 663 if self.data and not self.data.flagNoData and self.pause:
664 664 figpause(10)
665 665
@@ -1,187 +1,187
1 1 import os
2 2 import datetime
3 3 import numpy
4 4 import copy
5 5 from schainpy.model.graphics.jroplot_base import Plot
6 6
7 7
8 8 class CorrelationPlot(Plot):
9 9 isConfig = None
10 10 __nsubplots = None
11 11
12 12 WIDTHPROF = None
13 13 HEIGHTPROF = None
14 14 PREFIX = 'corr'
15 15
16 16 def __init__(self, **kwargs):
17 17 Figure.__init__(self, **kwargs)
18 18 self.isConfig = False
19 19 self.__nsubplots = 1
20 20
21 21 self.WIDTH = 280
22 22 self.HEIGHT = 250
23 23 self.WIDTHPROF = 120
24 24 self.HEIGHTPROF = 0
25 25 self.counter_imagwr = 0
26 26
27 27 self.PLOT_CODE = 1
28 28 self.FTP_WEI = None
29 29 self.EXP_CODE = None
30 30 self.SUB_EXP_CODE = None
31 31 self.PLOT_POS = None
32 32
33 33 def getSubplots(self):
34 34
35 35 ncol = int(numpy.sqrt(self.nplots)+0.9)
36 36 nrow = int(self.nplots*1./ncol + 0.9)
37 37
38 38 return nrow, ncol
39 39
40 40 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
41 41
42 42 showprofile = False
43 43 self.__showprofile = showprofile
44 44 self.nplots = nplots
45 45
46 46 ncolspan = 1
47 47 colspan = 1
48 48 if showprofile:
49 49 ncolspan = 3
50 50 colspan = 2
51 51 self.__nsubplots = 2
52 52
53 53 self.createFigure(id = id,
54 54 wintitle = wintitle,
55 55 widthplot = self.WIDTH + self.WIDTHPROF,
56 56 heightplot = self.HEIGHT + self.HEIGHTPROF,
57 57 show=show)
58 58
59 59 nrow, ncol = self.getSubplots()
60 60
61 61 counter = 0
62 62 for y in range(nrow):
63 63 for x in range(ncol):
64 64
65 65 if counter >= self.nplots:
66 66 break
67 67
68 68 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
69 69
70 70 if showprofile:
71 71 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
72 72
73 73 counter += 1
74 74
75 75 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
76 76 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
77 77 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
78 78 server=None, folder=None, username=None, password=None,
79 79 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
80 80
81 81 """
82 82
83 83 Input:
84 84 dataOut :
85 85 id :
86 86 wintitle :
87 87 channelList :
88 88 showProfile :
89 89 xmin : None,
90 90 xmax : None,
91 91 ymin : None,
92 92 ymax : None,
93 93 zmin : None,
94 94 zmax : None
95 95 """
96 96
97 97 if dataOut.flagNoData:
98 98 return None
99 99
100 100 if realtime:
101 101 if not(isRealtime(utcdatatime = dataOut.utctime)):
102 102 print('Skipping this plot function')
103 103 return
104 104
105 105 if channelList == None:
106 106 channelIndexList = dataOut.channelIndexList
107 107 else:
108 108 channelIndexList = []
109 109 for channel in channelList:
110 110 if channel not in dataOut.channelList:
111 111 raise ValueError("Channel %d is not in dataOut.channelList")
112 112 channelIndexList.append(dataOut.channelList.index(channel))
113 113
114 114 factor = dataOut.normFactor
115 115 lenfactor = factor.shape[1]
116 116 x = dataOut.getLagTRange(1)
117 y = dataOut.getHeiRange()
117 y = dataOut.heightList
118 118
119 119 z = copy.copy(dataOut.data_corr[:,:,0,:])
120 120 for i in range(dataOut.data_corr.shape[0]):
121 121 z[i,:,:] = z[i,:,:]/factor[i,:]
122 122 zdB = numpy.abs(z)
123 123
124 124 avg = numpy.average(z, axis=1)
125 125 # avg = numpy.nanmean(z, axis=1)
126 126 # noise = dataOut.noise/factor
127 127
128 128 #thisDatetime = dataOut.datatime
129 129 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
130 130 title = wintitle + " Correlation"
131 131 xlabel = "Lag T (s)"
132 132 ylabel = "Range (Km)"
133 133
134 134 if not self.isConfig:
135 135
136 136 nplots = dataOut.data_corr.shape[0]
137 137
138 138 self.setup(id=id,
139 139 nplots=nplots,
140 140 wintitle=wintitle,
141 141 showprofile=showprofile,
142 142 show=show)
143 143
144 144 if xmin == None: xmin = numpy.nanmin(x)
145 145 if xmax == None: xmax = numpy.nanmax(x)
146 146 if ymin == None: ymin = numpy.nanmin(y)
147 147 if ymax == None: ymax = numpy.nanmax(y)
148 148 if zmin == None: zmin = 0
149 149 if zmax == None: zmax = 1
150 150
151 151 self.FTP_WEI = ftp_wei
152 152 self.EXP_CODE = exp_code
153 153 self.SUB_EXP_CODE = sub_exp_code
154 154 self.PLOT_POS = plot_pos
155 155
156 156 self.isConfig = True
157 157
158 158 self.setWinTitle(title)
159 159
160 160 for i in range(self.nplots):
161 161 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
162 162 title = "Channel %d and %d: : %s" %(dataOut.pairsList[i][0],dataOut.pairsList[i][1] , str_datetime)
163 163 axes = self.axesList[i*self.__nsubplots]
164 164 axes.pcolor(x, y, zdB[i,:,:],
165 165 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
166 166 xlabel=xlabel, ylabel=ylabel, title=title,
167 167 ticksize=9, cblabel='')
168 168
169 169 # if self.__showprofile:
170 170 # axes = self.axesList[i*self.__nsubplots +1]
171 171 # axes.pline(avgdB[i], y,
172 172 # xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
173 173 # xlabel='dB', ylabel='', title='',
174 174 # ytick_visible=False,
175 175 # grid='x')
176 176 #
177 177 # noiseline = numpy.repeat(noisedB[i], len(y))
178 178 # axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
179 179
180 180 self.draw()
181 181
182 182 self.save(figpath=figpath,
183 183 figfile=figfile,
184 184 save=save,
185 185 ftp=ftp,
186 186 wr_period=wr_period,
187 187 thisDatetime=thisDatetime) No newline at end of file
@@ -1,342 +1,342
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9
10 10 from schainpy.model.graphics.jroplot_base import Plot
11 11
12 12
13 13 class SpectraHeisScope(Plot):
14 14
15 15
16 16 isConfig = None
17 17 __nsubplots = None
18 18
19 19 WIDTHPROF = None
20 20 HEIGHTPROF = None
21 21 PREFIX = 'spc'
22 22
23 23 def __init__(self):#, **kwargs):
24 24
25 25 Plot.__init__(self)#, **kwargs)
26 26 self.isConfig = False
27 27 self.__nsubplots = 1
28 28
29 29 self.WIDTH = 230
30 30 self.HEIGHT = 250
31 31 self.WIDTHPROF = 120
32 32 self.HEIGHTPROF = 0
33 33 self.counter_imagwr = 0
34 34
35 35 self.PLOT_CODE = SPEC_CODE
36 36
37 37 def getSubplots(self):
38 38
39 39 ncol = int(numpy.sqrt(self.nplots)+0.9)
40 40 nrow = int(self.nplots*1./ncol + 0.9)
41 41
42 42 return nrow, ncol
43 43
44 44 def setup(self, id, nplots, wintitle, show):
45 45
46 46 showprofile = False
47 47 self.__showprofile = showprofile
48 48 self.nplots = nplots
49 49
50 50 ncolspan = 1
51 51 colspan = 1
52 52 if showprofile:
53 53 ncolspan = 3
54 54 colspan = 2
55 55 self.__nsubplots = 2
56 56
57 57 self.createFigure(id = id,
58 58 wintitle = wintitle,
59 59 widthplot = self.WIDTH + self.WIDTHPROF,
60 60 heightplot = self.HEIGHT + self.HEIGHTPROF,
61 61 show = show)
62 62
63 63 nrow, ncol = self.getSubplots()
64 64
65 65 counter = 0
66 66 for y in range(nrow):
67 67 for x in range(ncol):
68 68
69 69 if counter >= self.nplots:
70 70 break
71 71
72 72 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
73 73
74 74 if showprofile:
75 75 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
76 76
77 77 counter += 1
78 78
79 79
80 80 def run(self, dataOut, id, wintitle="", channelList=None,
81 81 xmin=None, xmax=None, ymin=None, ymax=None, save=False,
82 82 figpath='./', figfile=None, ftp=False, wr_period=1, show=True,
83 83 server=None, folder=None, username=None, password=None,
84 84 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
85 85
86 86 """
87 87
88 88 Input:
89 89 dataOut :
90 90 id :
91 91 wintitle :
92 92 channelList :
93 93 xmin : None,
94 94 xmax : None,
95 95 ymin : None,
96 96 ymax : None,
97 97 """
98 98
99 99 if dataOut.flagNoData:
100 100 return dataOut
101 101
102 102 if dataOut.realtime:
103 103 if not(isRealtime(utcdatatime = dataOut.utctime)):
104 104 print('Skipping this plot function')
105 105 return
106 106
107 107 if channelList == None:
108 108 channelIndexList = dataOut.channelIndexList
109 109 else:
110 110 channelIndexList = []
111 111 for channel in channelList:
112 112 if channel not in dataOut.channelList:
113 113 raise ValueError("Channel %d is not in dataOut.channelList")
114 114 channelIndexList.append(dataOut.channelList.index(channel))
115 115
116 116 # x = dataOut.heightList
117 117 c = 3E8
118 118 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
119 119 #deberia cambiar para el caso de 1Mhz y 100KHz
120 120 x = numpy.arange(-1*dataOut.nHeights/2.,dataOut.nHeights/2.)*(c/(2*deltaHeight*dataOut.nHeights*1000))
121 121 #para 1Mhz descomentar la siguiente linea
122 122 #x= x/(10000.0)
123 123 # y = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:])
124 124 # y = y.real
125 125 factor = dataOut.normFactor
126 126 data = dataOut.data_spc / factor
127 127 datadB = 10.*numpy.log10(data)
128 128 y = datadB
129 129
130 130 #thisDatetime = dataOut.datatime
131 131 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
132 132 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
133 133 xlabel = ""
134 134 #para 1Mhz descomentar la siguiente linea
135 135 #xlabel = "Frequency x 10000"
136 136 ylabel = "Intensity (dB)"
137 137
138 138 if not self.isConfig:
139 139 nplots = len(channelIndexList)
140 140
141 141 self.setup(id=id,
142 142 nplots=nplots,
143 143 wintitle=wintitle,
144 144 show=show)
145 145
146 146 if xmin == None: xmin = numpy.nanmin(x)
147 147 if xmax == None: xmax = numpy.nanmax(x)
148 148 if ymin == None: ymin = numpy.nanmin(y)
149 149 if ymax == None: ymax = numpy.nanmax(y)
150 150
151 151 self.FTP_WEI = ftp_wei
152 152 self.EXP_CODE = exp_code
153 153 self.SUB_EXP_CODE = sub_exp_code
154 154 self.PLOT_POS = plot_pos
155 155
156 156 self.isConfig = True
157 157
158 158 self.setWinTitle(title)
159 159
160 160 for i in range(len(self.axesList)):
161 161 ychannel = y[i,:]
162 162 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
163 163 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[channelIndexList[i]], numpy.max(ychannel), str_datetime)
164 164 axes = self.axesList[i]
165 165 axes.pline(x, ychannel,
166 166 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
167 167 xlabel=xlabel, ylabel=ylabel, title=title, grid='both')
168 168
169 169
170 170 self.draw()
171 171
172 172 self.save(figpath=figpath,
173 173 figfile=figfile,
174 174 save=save,
175 175 ftp=ftp,
176 176 wr_period=wr_period,
177 177 thisDatetime=thisDatetime)
178 178
179 179 return dataOut
180 180
181 181
182 182 class RTIfromSpectraHeis(Plot):
183 183
184 184 isConfig = None
185 185 __nsubplots = None
186 186
187 187 PREFIX = 'rtinoise'
188 188
189 189 def __init__(self):#, **kwargs):
190 190 Plot.__init__(self)#, **kwargs)
191 191 self.timerange = 24*60*60
192 192 self.isConfig = False
193 193 self.__nsubplots = 1
194 194
195 195 self.WIDTH = 820
196 196 self.HEIGHT = 200
197 197 self.WIDTHPROF = 120
198 198 self.HEIGHTPROF = 0
199 199 self.counter_imagwr = 0
200 200 self.xdata = None
201 201 self.ydata = None
202 202 self.figfile = None
203 203
204 204 self.PLOT_CODE = RTI_CODE
205 205
206 206 def getSubplots(self):
207 207
208 208 ncol = 1
209 209 nrow = 1
210 210
211 211 return nrow, ncol
212 212
213 213 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
214 214
215 215 self.__showprofile = showprofile
216 216 self.nplots = nplots
217 217
218 218 ncolspan = 7
219 219 colspan = 6
220 220 self.__nsubplots = 2
221 221
222 222 self.createFigure(id = id,
223 223 wintitle = wintitle,
224 224 widthplot = self.WIDTH+self.WIDTHPROF,
225 225 heightplot = self.HEIGHT+self.HEIGHTPROF,
226 226 show = show)
227 227
228 228 nrow, ncol = self.getSubplots()
229 229
230 230 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
231 231
232 232
233 233 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
234 234 xmin=None, xmax=None, ymin=None, ymax=None,
235 235 timerange=None,
236 236 save=False, figpath='./', figfile=None, ftp=False, wr_period=1, show=True,
237 237 server=None, folder=None, username=None, password=None,
238 238 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
239 239
240 240 if dataOut.flagNoData:
241 241 return dataOut
242 242
243 243
244 244 if channelList == None:
245 245 channelIndexList = dataOut.channelIndexList
246 246 channelList = dataOut.channelList
247 247 else:
248 248 channelIndexList = []
249 249 for channel in channelList:
250 250 if channel not in dataOut.channelList:
251 251 raise ValueError("Channel %d is not in dataOut.channelList")
252 252 channelIndexList.append(dataOut.channelList.index(channel))
253 253
254 254 if timerange != None:
255 255 self.timerange = timerange
256 256
257 257 x = dataOut.getTimeRange()
258 y = dataOut.getHeiRange()
258 y = dataOut.heightList
259 259
260 260 factor = dataOut.normFactor
261 261 data = dataOut.data_spc / factor
262 262 data = numpy.average(data,axis=1)
263 263 datadB = 10*numpy.log10(data)
264 264
265 265 # factor = dataOut.normFactor
266 266 # noise = dataOut.getNoise()/factor
267 267 # noisedB = 10*numpy.log10(noise)
268 268
269 269 #thisDatetime = dataOut.datatime
270 270 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
271 271 title = wintitle + " RTI: %s" %(thisDatetime.strftime("%d-%b-%Y"))
272 272 xlabel = "Local Time"
273 273 ylabel = "Intensity (dB)"
274 274
275 275 if not self.isConfig:
276 276
277 277 nplots = 1
278 278
279 279 self.setup(id=id,
280 280 nplots=nplots,
281 281 wintitle=wintitle,
282 282 showprofile=showprofile,
283 283 show=show)
284 284
285 285 self.tmin, self.tmax = self.getTimeLim(x, xmin, xmax)
286 286
287 287 if ymin == None: ymin = numpy.nanmin(datadB)
288 288 if ymax == None: ymax = numpy.nanmax(datadB)
289 289
290 290 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
291 291 self.isConfig = True
292 292 self.figfile = figfile
293 293 self.xdata = numpy.array([])
294 294 self.ydata = numpy.array([])
295 295
296 296 self.FTP_WEI = ftp_wei
297 297 self.EXP_CODE = exp_code
298 298 self.SUB_EXP_CODE = sub_exp_code
299 299 self.PLOT_POS = plot_pos
300 300
301 301 self.setWinTitle(title)
302 302
303 303
304 304 # title = "RTI %s" %(thisDatetime.strftime("%d-%b-%Y"))
305 305 title = "RTI - %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
306 306
307 307 legendlabels = ["channel %d"%idchannel for idchannel in channelList]
308 308 axes = self.axesList[0]
309 309
310 310 self.xdata = numpy.hstack((self.xdata, x[0:1]))
311 311
312 312 if len(self.ydata)==0:
313 313 self.ydata = datadB[channelIndexList].reshape(-1,1)
314 314 else:
315 315 self.ydata = numpy.hstack((self.ydata, datadB[channelIndexList].reshape(-1,1)))
316 316
317 317
318 318 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
319 319 xmin=self.tmin, xmax=self.tmax, ymin=ymin, ymax=ymax,
320 320 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='.', markersize=8, linestyle="solid", grid='both',
321 321 XAxisAsTime=True
322 322 )
323 323
324 324 self.draw()
325 325
326 326 update_figfile = False
327 327
328 328 if dataOut.ltctime >= self.tmax:
329 329 self.counter_imagwr = wr_period
330 330 self.isConfig = False
331 331 update_figfile = True
332 332
333 333 self.save(figpath=figpath,
334 334 figfile=figfile,
335 335 save=save,
336 336 ftp=ftp,
337 337 wr_period=wr_period,
338 338 thisDatetime=thisDatetime,
339 339 update_figfile=update_figfile)
340 340
341 341
342 342 return dataOut No newline at end of file
@@ -1,643 +1,641
1 1 '''
2 2 Created on Jul 9, 2014
3 3 Modified on May 10, 2020
4 4
5 5 @author: Juan C. Espinoza
6 6 '''
7 7
8 8 import os
9 9 import datetime
10 10 import numpy
11 11
12 12 from schainpy.model.graphics.jroplot_base import Plot, plt
13 13
14 14
15 15 class SpectraPlot(Plot):
16 16 '''
17 17 Plot for Spectra data
18 18 '''
19 19
20 20 CODE = 'spc'
21 21 colormap = 'jet'
22 22 plot_type = 'pcolor'
23 23
24 24 def setup(self):
25 25 self.nplots = len(self.data.channels)
26 26 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
27 27 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
28 28 self.height = 2.6 * self.nrows
29 29 self.cb_label = 'dB'
30 30 if self.showprofile:
31 31 self.width = 4 * self.ncols
32 32 else:
33 33 self.width = 3.5 * self.ncols
34 34 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
35 35 self.ylabel = 'Range [km]'
36 36
37 37 def plot(self):
38 38 if self.xaxis == "frequency":
39 39 x = self.data.xrange[0]
40 40 self.xlabel = "Frequency (kHz)"
41 41 elif self.xaxis == "time":
42 42 x = self.data.xrange[1]
43 43 self.xlabel = "Time (ms)"
44 44 else:
45 45 x = self.data.xrange[2]
46 46 self.xlabel = "Velocity (m/s)"
47 47
48 48 if self.CODE == 'spc_moments':
49 49 x = self.data.xrange[2]
50 50 self.xlabel = "Velocity (m/s)"
51 51
52 52 self.titles = []
53 53
54 54 y = self.data.heights
55 55 self.y = y
56 56 z = self.data['spc']
57 57
58 58 for n, ax in enumerate(self.axes):
59 59 noise = self.data['noise'][n][-1]
60 60 if self.CODE == 'spc_moments':
61 61 mean = self.data['moments'][n, :, 1, :][-1]
62 62 if ax.firsttime:
63 63 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
64 64 self.xmin = self.xmin if self.xmin else -self.xmax
65 65 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
66 66 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
67 67 ax.plt = ax.pcolormesh(x, y, z[n].T,
68 68 vmin=self.zmin,
69 69 vmax=self.zmax,
70 70 cmap=plt.get_cmap(self.colormap)
71 71 )
72 72
73 73 if self.showprofile:
74 74 ax.plt_profile = self.pf_axes[n].plot(
75 75 self.data['rti'][n][-1], y)[0]
76 76 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
77 77 color="k", linestyle="dashed", lw=1)[0]
78 78 if self.CODE == 'spc_moments':
79 79 ax.plt_mean = ax.plot(mean, y, color='k')[0]
80 80 else:
81 81 ax.plt.set_array(z[n].T.ravel())
82 82 if self.showprofile:
83 83 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
84 84 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
85 85 if self.CODE == 'spc_moments':
86 86 ax.plt_mean.set_data(mean, y)
87 87 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
88 88
89 89
90 90 class CrossSpectraPlot(Plot):
91 91
92 92 CODE = 'cspc'
93 93 colormap = 'jet'
94 94 plot_type = 'pcolor'
95 95 zmin_coh = None
96 96 zmax_coh = None
97 97 zmin_phase = None
98 98 zmax_phase = None
99 99
100 100 def setup(self):
101 101
102 102 self.ncols = 4
103 103 self.nrows = len(self.data.pairs)
104 104 self.nplots = self.nrows * 4
105 105 self.width = 3.1 * self.ncols
106 106 self.height = 2.6 * self.nrows
107 107 self.ylabel = 'Range [km]'
108 108 self.showprofile = False
109 109 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
110 110
111 111 def plot(self):
112 112
113 113 if self.xaxis == "frequency":
114 114 x = self.data.xrange[0]
115 115 self.xlabel = "Frequency (kHz)"
116 116 elif self.xaxis == "time":
117 117 x = self.data.xrange[1]
118 118 self.xlabel = "Time (ms)"
119 119 else:
120 120 x = self.data.xrange[2]
121 121 self.xlabel = "Velocity (m/s)"
122 122
123 123 self.titles = []
124 124
125 125 y = self.data.heights
126 126 self.y = y
127 127 nspc = self.data['spc']
128 128 spc = self.data['cspc'][0]
129 129 cspc = self.data['cspc'][1]
130 130
131 131 for n in range(self.nrows):
132 132 noise = self.data['noise'][:,-1]
133 133 pair = self.data.pairs[n]
134 134 ax = self.axes[4 * n]
135 135 if ax.firsttime:
136 136 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
137 137 self.xmin = self.xmin if self.xmin else -self.xmax
138 138 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
139 139 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
140 140 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
141 141 vmin=self.zmin,
142 142 vmax=self.zmax,
143 143 cmap=plt.get_cmap(self.colormap)
144 144 )
145 145 else:
146 146 ax.plt.set_array(nspc[pair[0]].T.ravel())
147 147 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
148 148
149 149 ax = self.axes[4 * n + 1]
150 150 if ax.firsttime:
151 151 ax.plt = ax.pcolormesh(x , y, nspc[pair[1]].T,
152 152 vmin=self.zmin,
153 153 vmax=self.zmax,
154 154 cmap=plt.get_cmap(self.colormap)
155 155 )
156 156 else:
157 157 ax.plt.set_array(nspc[pair[1]].T.ravel())
158 158 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
159 159
160 160 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
161 161 coh = numpy.abs(out)
162 162 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
163 163
164 164 ax = self.axes[4 * n + 2]
165 165 if ax.firsttime:
166 166 ax.plt = ax.pcolormesh(x, y, coh.T,
167 167 vmin=0,
168 168 vmax=1,
169 169 cmap=plt.get_cmap(self.colormap_coh)
170 170 )
171 171 else:
172 172 ax.plt.set_array(coh.T.ravel())
173 173 self.titles.append(
174 174 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
175 175
176 176 ax = self.axes[4 * n + 3]
177 177 if ax.firsttime:
178 178 ax.plt = ax.pcolormesh(x, y, phase.T,
179 179 vmin=-180,
180 180 vmax=180,
181 181 cmap=plt.get_cmap(self.colormap_phase)
182 182 )
183 183 else:
184 184 ax.plt.set_array(phase.T.ravel())
185 185 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
186 186
187 187
188 188 class RTIPlot(Plot):
189 189 '''
190 190 Plot for RTI data
191 191 '''
192 192
193 193 CODE = 'rti'
194 194 colormap = 'jet'
195 195 plot_type = 'pcolorbuffer'
196 196
197 197 def setup(self):
198 198 self.xaxis = 'time'
199 199 self.ncols = 1
200 200 self.nrows = len(self.data.channels)
201 201 self.nplots = len(self.data.channels)
202 202 self.ylabel = 'Range [km]'
203 203 self.xlabel = 'Time'
204 204 self.cb_label = 'dB'
205 205 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
206 206 self.titles = ['{} Channel {}'.format(
207 207 self.CODE.upper(), x) for x in range(self.nrows)]
208 208
209 209 def plot(self):
210 210 self.x = self.data.times
211 211 self.y = self.data.heights
212 212 self.z = self.data[self.CODE]
213 213 self.z = numpy.ma.masked_invalid(self.z)
214 214
215 215 if self.decimation is None:
216 216 x, y, z = self.fill_gaps(self.x, self.y, self.z)
217 217 else:
218 218 x, y, z = self.fill_gaps(*self.decimate())
219 219
220 220 for n, ax in enumerate(self.axes):
221 221 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
222 222 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
223 223 if ax.firsttime:
224 224 ax.plt = ax.pcolormesh(x, y, z[n].T,
225 225 vmin=self.zmin,
226 226 vmax=self.zmax,
227 227 cmap=plt.get_cmap(self.colormap)
228 228 )
229 229 if self.showprofile:
230 230 ax.plot_profile = self.pf_axes[n].plot(
231 231 self.data['rti'][n][-1], self.y)[0]
232 232 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
233 233 color="k", linestyle="dashed", lw=1)[0]
234 234 else:
235 235 ax.collections.remove(ax.collections[0])
236 236 ax.plt = ax.pcolormesh(x, y, z[n].T,
237 237 vmin=self.zmin,
238 238 vmax=self.zmax,
239 239 cmap=plt.get_cmap(self.colormap)
240 240 )
241 241 if self.showprofile:
242 242 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
243 243 ax.plot_noise.set_data(numpy.repeat(
244 244 self.data['noise'][n][-1], len(self.y)), self.y)
245 245
246 246
247 247 class CoherencePlot(RTIPlot):
248 248 '''
249 249 Plot for Coherence data
250 250 '''
251 251
252 252 CODE = 'coh'
253 253
254 254 def setup(self):
255 255 self.xaxis = 'time'
256 256 self.ncols = 1
257 257 self.nrows = len(self.data.pairs)
258 258 self.nplots = len(self.data.pairs)
259 259 self.ylabel = 'Range [km]'
260 260 self.xlabel = 'Time'
261 261 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
262 262 if self.CODE == 'coh':
263 263 self.cb_label = ''
264 264 self.titles = [
265 265 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
266 266 else:
267 267 self.cb_label = 'Degrees'
268 268 self.titles = [
269 269 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
270 270
271 271
272 272 class PhasePlot(CoherencePlot):
273 273 '''
274 274 Plot for Phase map data
275 275 '''
276 276
277 277 CODE = 'phase'
278 278 colormap = 'seismic'
279 279
280 280
281 281 class NoisePlot(Plot):
282 282 '''
283 283 Plot for noise
284 284 '''
285 285
286 286 CODE = 'noise'
287 287 plot_type = 'scatterbuffer'
288 288
289 289
290 290 def setup(self):
291 291 self.xaxis = 'time'
292 292 self.ncols = 1
293 293 self.nrows = 1
294 294 self.nplots = 1
295 295 self.ylabel = 'Intensity [dB]'
296 296 self.xlabel = 'Time'
297 297 self.titles = ['Noise']
298 298 self.colorbar = False
299 299
300 300 def plot(self):
301 301
302 302 x = self.data.times
303 303 xmin = self.data.min_time
304 304 xmax = xmin + self.xrange * 60 * 60
305 305 Y = self.data[self.CODE]
306 306
307 307 if self.axes[0].firsttime:
308 308 for ch in self.data.channels:
309 309 y = Y[ch]
310 310 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
311 311 plt.legend()
312 312 else:
313 313 for ch in self.data.channels:
314 314 y = Y[ch]
315 315 self.axes[0].lines[ch].set_data(x, y)
316 316
317 317 self.ymin = numpy.nanmin(Y) - 5
318 318 self.ymax = numpy.nanmax(Y) + 5
319 319
320 320
321 321 class PowerProfilePlot(Plot):
322 322
323 323 CODE = 'spcprofile'
324 324 plot_type = 'scatter'
325 325 buffering = False
326 326
327 327 def setup(self):
328 328
329 329 self.ncols = 1
330 330 self.nrows = 1
331 331 self.nplots = 1
332 332 self.height = 4
333 333 self.width = 3
334 334 self.ylabel = 'Range [km]'
335 335 self.xlabel = 'Intensity [dB]'
336 336 self.titles = ['Power Profile']
337 337 self.colorbar = False
338 338
339 339 def plot(self):
340 340
341 341 y = self.data.heights
342 342 self.y = y
343 343
344 344 x = self.data['spcprofile']
345 345
346 346 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
347 347 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
348 348
349 349 if self.axes[0].firsttime:
350 350 for ch in self.data.channels:
351 351 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
352 352 plt.legend()
353 353 else:
354 354 for ch in self.data.channels:
355 355 self.axes[0].lines[ch].set_data(x[ch], y)
356 356
357 357
358 358 class SpectraCutPlot(Plot):
359 359
360 360 CODE = 'spc_cut'
361 361 plot_type = 'scatter'
362 362 buffering = False
363 363
364 364 def setup(self):
365 365
366 366 self.nplots = len(self.data.channels)
367 367 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
368 368 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
369 369 self.width = 3.4 * self.ncols + 1.5
370 370 self.height = 3 * self.nrows
371 371 self.ylabel = 'Power [dB]'
372 372 self.colorbar = False
373 373 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
374 374
375 375 def plot(self):
376 376 if self.xaxis == "frequency":
377 377 x = self.data.xrange[0][1:]
378 378 self.xlabel = "Frequency (kHz)"
379 379 elif self.xaxis == "time":
380 380 x = self.data.xrange[1]
381 381 self.xlabel = "Time (ms)"
382 382 else:
383 383 x = self.data.xrange[2]
384 384 self.xlabel = "Velocity (m/s)"
385 385
386 386 self.titles = []
387 387
388 388 y = self.data.heights
389 389 #self.y = y
390 390 z = self.data['spc_cut']
391 391
392 392 if self.height_index:
393 393 index = numpy.array(self.height_index)
394 394 else:
395 395 index = numpy.arange(0, len(y), int((len(y))/9))
396 396
397 397 for n, ax in enumerate(self.axes):
398 398 if ax.firsttime:
399 399 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
400 400 self.xmin = self.xmin if self.xmin else -self.xmax
401 401 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
402 402 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
403 403 ax.plt = ax.plot(x, z[n, :, index].T)
404 404 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
405 405 self.figures[0].legend(ax.plt, labels, loc='center right')
406 406 else:
407 407 for i, line in enumerate(ax.plt):
408 408 line.set_data(x, z[n, :, i])
409 409 self.titles.append('CH {}'.format(n))
410 410
411 411
412 412 class BeaconPhase(Plot):
413 413
414 414 __isConfig = None
415 415 __nsubplots = None
416 416
417 417 PREFIX = 'beacon_phase'
418 418
419 419 def __init__(self):
420 420 Plot.__init__(self)
421 421 self.timerange = 24*60*60
422 422 self.isConfig = False
423 423 self.__nsubplots = 1
424 424 self.counter_imagwr = 0
425 425 self.WIDTH = 800
426 426 self.HEIGHT = 400
427 427 self.WIDTHPROF = 120
428 428 self.HEIGHTPROF = 0
429 429 self.xdata = None
430 430 self.ydata = None
431 431
432 432 self.PLOT_CODE = BEACON_CODE
433 433
434 434 self.FTP_WEI = None
435 435 self.EXP_CODE = None
436 436 self.SUB_EXP_CODE = None
437 437 self.PLOT_POS = None
438 438
439 439 self.filename_phase = None
440 440
441 441 self.figfile = None
442 442
443 443 self.xmin = None
444 444 self.xmax = None
445 445
446 446 def getSubplots(self):
447 447
448 448 ncol = 1
449 449 nrow = 1
450 450
451 451 return nrow, ncol
452 452
453 453 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
454 454
455 455 self.__showprofile = showprofile
456 456 self.nplots = nplots
457 457
458 458 ncolspan = 7
459 459 colspan = 6
460 460 self.__nsubplots = 2
461 461
462 462 self.createFigure(id = id,
463 463 wintitle = wintitle,
464 464 widthplot = self.WIDTH+self.WIDTHPROF,
465 465 heightplot = self.HEIGHT+self.HEIGHTPROF,
466 466 show=show)
467 467
468 468 nrow, ncol = self.getSubplots()
469 469
470 470 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
471 471
472 472 def save_phase(self, filename_phase):
473 473 f = open(filename_phase,'w+')
474 474 f.write('\n\n')
475 475 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
476 476 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
477 477 f.close()
478 478
479 479 def save_data(self, filename_phase, data, data_datetime):
480 480 f=open(filename_phase,'a')
481 481 timetuple_data = data_datetime.timetuple()
482 482 day = str(timetuple_data.tm_mday)
483 483 month = str(timetuple_data.tm_mon)
484 484 year = str(timetuple_data.tm_year)
485 485 hour = str(timetuple_data.tm_hour)
486 486 minute = str(timetuple_data.tm_min)
487 487 second = str(timetuple_data.tm_sec)
488 488 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
489 489 f.close()
490 490
491 491 def plot(self):
492 492 log.warning('TODO: Not yet implemented...')
493 493
494 494 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
495 495 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
496 496 timerange=None,
497 497 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
498 498 server=None, folder=None, username=None, password=None,
499 499 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
500 500
501 501 if dataOut.flagNoData:
502 502 return dataOut
503 503
504 504 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
505 505 return
506 506
507 507 if pairsList == None:
508 508 pairsIndexList = dataOut.pairsIndexList[:10]
509 509 else:
510 510 pairsIndexList = []
511 511 for pair in pairsList:
512 512 if pair not in dataOut.pairsList:
513 513 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
514 514 pairsIndexList.append(dataOut.pairsList.index(pair))
515 515
516 516 if pairsIndexList == []:
517 517 return
518 518
519 519 # if len(pairsIndexList) > 4:
520 520 # pairsIndexList = pairsIndexList[0:4]
521 521
522 522 hmin_index = None
523 523 hmax_index = None
524 524
525 525 if hmin != None and hmax != None:
526 526 indexes = numpy.arange(dataOut.nHeights)
527 527 hmin_list = indexes[dataOut.heightList >= hmin]
528 528 hmax_list = indexes[dataOut.heightList <= hmax]
529 529
530 530 if hmin_list.any():
531 531 hmin_index = hmin_list[0]
532 532
533 533 if hmax_list.any():
534 534 hmax_index = hmax_list[-1]+1
535 535
536 536 x = dataOut.getTimeRange()
537 #y = dataOut.getHeiRange()
538
539 537
540 538 thisDatetime = dataOut.datatime
541 539
542 540 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
543 541 xlabel = "Local Time"
544 542 ylabel = "Phase (degrees)"
545 543
546 544 update_figfile = False
547 545
548 546 nplots = len(pairsIndexList)
549 547 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
550 548 phase_beacon = numpy.zeros(len(pairsIndexList))
551 549 for i in range(nplots):
552 550 pair = dataOut.pairsList[pairsIndexList[i]]
553 551 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
554 552 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
555 553 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
556 554 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
557 555 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
558 556
559 557 if dataOut.beacon_heiIndexList:
560 558 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
561 559 else:
562 560 phase_beacon[i] = numpy.average(phase)
563 561
564 562 if not self.isConfig:
565 563
566 564 nplots = len(pairsIndexList)
567 565
568 566 self.setup(id=id,
569 567 nplots=nplots,
570 568 wintitle=wintitle,
571 569 showprofile=showprofile,
572 570 show=show)
573 571
574 572 if timerange != None:
575 573 self.timerange = timerange
576 574
577 575 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
578 576
579 577 if ymin == None: ymin = 0
580 578 if ymax == None: ymax = 360
581 579
582 580 self.FTP_WEI = ftp_wei
583 581 self.EXP_CODE = exp_code
584 582 self.SUB_EXP_CODE = sub_exp_code
585 583 self.PLOT_POS = plot_pos
586 584
587 585 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
588 586 self.isConfig = True
589 587 self.figfile = figfile
590 588 self.xdata = numpy.array([])
591 589 self.ydata = numpy.array([])
592 590
593 591 update_figfile = True
594 592
595 593 #open file beacon phase
596 594 path = '%s%03d' %(self.PREFIX, self.id)
597 595 beacon_file = os.path.join(path,'%s.txt'%self.name)
598 596 self.filename_phase = os.path.join(figpath,beacon_file)
599 597 #self.save_phase(self.filename_phase)
600 598
601 599
602 600 #store data beacon phase
603 601 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
604 602
605 603 self.setWinTitle(title)
606 604
607 605
608 606 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
609 607
610 608 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
611 609
612 610 axes = self.axesList[0]
613 611
614 612 self.xdata = numpy.hstack((self.xdata, x[0:1]))
615 613
616 614 if len(self.ydata)==0:
617 615 self.ydata = phase_beacon.reshape(-1,1)
618 616 else:
619 617 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
620 618
621 619
622 620 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
623 621 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
624 622 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
625 623 XAxisAsTime=True, grid='both'
626 624 )
627 625
628 626 self.draw()
629 627
630 628 if dataOut.ltctime >= self.xmax:
631 629 self.counter_imagwr = wr_period
632 630 self.isConfig = False
633 631 update_figfile = True
634 632
635 633 self.save(figpath=figpath,
636 634 figfile=figfile,
637 635 save=save,
638 636 ftp=ftp,
639 637 wr_period=wr_period,
640 638 thisDatetime=thisDatetime,
641 639 update_figfile=update_figfile)
642 640
643 641 return dataOut No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now