##// END OF EJS Templates
Skip plotting if an error raise
jespinoza -
r1121:14c0870adb40
parent child
Show More
@@ -1,962 +1,965
1 1
2 2 import os
3 3 import time
4 4 import glob
5 5 import datetime
6 6 from multiprocessing import Process
7 7
8 8 import zmq
9 9 import numpy
10 10 import matplotlib
11 11 import matplotlib.pyplot as plt
12 12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
14 14
15 15 from schainpy.model.proc.jroproc_base import Operation
16 16 from schainpy.utils import log
17 17
18 18 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
19 19 blu_values = matplotlib.pyplot.get_cmap(
20 20 'seismic_r', 20)(numpy.arange(20))[10:15]
21 21 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
22 22 'jro', numpy.vstack((blu_values, jet_values)))
23 23 matplotlib.pyplot.register_cmap(cmap=ncmap)
24 24
25 25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
26 26
27 27
28 28 def figpause(interval):
29 29 backend = plt.rcParams['backend']
30 30 if backend in matplotlib.rcsetup.interactive_bk:
31 31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
32 32 if figManager is not None:
33 33 canvas = figManager.canvas
34 34 if canvas.figure.stale:
35 35 canvas.draw()
36 36 canvas.start_event_loop(interval)
37 37 return
38 38
39 39
40 40 class PlotData(Operation, Process):
41 41 '''
42 42 Base class for Schain plotting operations
43 43 '''
44 44
45 45 CODE = 'Figure'
46 46 colormap = 'jro'
47 47 bgcolor = 'white'
48 48 CONFLATE = False
49 49 __missing = 1E30
50 50
51 51 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
52 52 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
53 53 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
54 54 'showprofile', 'decimation']
55 55
56 56 def __init__(self, **kwargs):
57 57
58 58 Operation.__init__(self, plot=True, **kwargs)
59 59 Process.__init__(self)
60 60
61 61 self.kwargs['code'] = self.CODE
62 62 self.mp = False
63 63 self.data = None
64 64 self.isConfig = False
65 65 self.figures = []
66 66 self.axes = []
67 67 self.cb_axes = []
68 68 self.localtime = kwargs.pop('localtime', True)
69 69 self.show = kwargs.get('show', True)
70 70 self.save = kwargs.get('save', False)
71 71 self.colormap = kwargs.get('colormap', self.colormap)
72 72 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
73 73 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
74 74 self.colormaps = kwargs.get('colormaps', None)
75 75 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
76 76 self.showprofile = kwargs.get('showprofile', False)
77 77 self.title = kwargs.get('wintitle', self.CODE.upper())
78 78 self.cb_label = kwargs.get('cb_label', None)
79 79 self.cb_labels = kwargs.get('cb_labels', None)
80 80 self.xaxis = kwargs.get('xaxis', 'frequency')
81 81 self.zmin = kwargs.get('zmin', None)
82 82 self.zmax = kwargs.get('zmax', None)
83 83 self.zlimits = kwargs.get('zlimits', None)
84 84 self.xmin = kwargs.get('xmin', None)
85 85 self.xmax = kwargs.get('xmax', None)
86 86 self.xrange = kwargs.get('xrange', 24)
87 87 self.ymin = kwargs.get('ymin', None)
88 88 self.ymax = kwargs.get('ymax', None)
89 89 self.xlabel = kwargs.get('xlabel', None)
90 90 self.decimation = kwargs.get('decimation', None)
91 91 self.showSNR = kwargs.get('showSNR', False)
92 92 self.oneFigure = kwargs.get('oneFigure', True)
93 93 self.width = kwargs.get('width', None)
94 94 self.height = kwargs.get('height', None)
95 95 self.colorbar = kwargs.get('colorbar', True)
96 96 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
97 97 self.titles = kwargs.get('titles', [])
98 98 self.polar = False
99 99
100 100 def __fmtTime(self, x, pos):
101 101 '''
102 102 '''
103 103
104 104 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
105 105
106 106 def __setup(self):
107 107 '''
108 108 Common setup for all figures, here figures and axes are created
109 109 '''
110 110
111 111 if self.CODE not in self.data:
112 112 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
113 113 self.name))
114 114
115 115 self.setup()
116 116
117 117 self.time_label = 'LT' if self.localtime else 'UTC'
118 118 if self.data.localtime:
119 119 self.getDateTime = datetime.datetime.fromtimestamp
120 120 else:
121 121 self.getDateTime = datetime.datetime.utcfromtimestamp
122 122
123 123 if self.width is None:
124 124 self.width = 8
125 125
126 126 self.figures = []
127 127 self.axes = []
128 128 self.cb_axes = []
129 129 self.pf_axes = []
130 130 self.cmaps = []
131 131
132 132 size = '15%' if self.ncols == 1 else '30%'
133 133 pad = '4%' if self.ncols == 1 else '8%'
134 134
135 135 if self.oneFigure:
136 136 if self.height is None:
137 137 self.height = 1.4 * self.nrows + 1
138 138 fig = plt.figure(figsize=(self.width, self.height),
139 139 edgecolor='k',
140 140 facecolor='w')
141 141 self.figures.append(fig)
142 142 for n in range(self.nplots):
143 143 ax = fig.add_subplot(self.nrows, self.ncols,
144 144 n + 1, polar=self.polar)
145 145 ax.tick_params(labelsize=8)
146 146 ax.firsttime = True
147 147 ax.index = 0
148 148 ax.press = None
149 149 self.axes.append(ax)
150 150 if self.showprofile:
151 151 cax = self.__add_axes(ax, size=size, pad=pad)
152 152 cax.tick_params(labelsize=8)
153 153 self.pf_axes.append(cax)
154 154 else:
155 155 if self.height is None:
156 156 self.height = 3
157 157 for n in range(self.nplots):
158 158 fig = plt.figure(figsize=(self.width, self.height),
159 159 edgecolor='k',
160 160 facecolor='w')
161 161 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
162 162 ax.tick_params(labelsize=8)
163 163 ax.firsttime = True
164 164 ax.index = 0
165 165 ax.press = None
166 166 self.figures.append(fig)
167 167 self.axes.append(ax)
168 168 if self.showprofile:
169 169 cax = self.__add_axes(ax, size=size, pad=pad)
170 170 cax.tick_params(labelsize=8)
171 171 self.pf_axes.append(cax)
172 172
173 173 for n in range(self.nrows):
174 174 if self.colormaps is not None:
175 175 cmap = plt.get_cmap(self.colormaps[n])
176 176 else:
177 177 cmap = plt.get_cmap(self.colormap)
178 178 cmap.set_bad(self.bgcolor, 1.)
179 179 self.cmaps.append(cmap)
180 180
181 181 for fig in self.figures:
182 182 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
183 183 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
184 184 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
185 185 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
186 186 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
187 187 if self.show:
188 188 fig.show()
189 189
190 190 def OnKeyPress(self, event):
191 191 '''
192 192 Event for pressing keys (up, down) change colormap
193 193 '''
194 194 ax = event.inaxes
195 195 if ax in self.axes:
196 196 if event.key == 'down':
197 197 ax.index += 1
198 198 elif event.key == 'up':
199 199 ax.index -= 1
200 200 if ax.index < 0:
201 201 ax.index = len(CMAPS) - 1
202 202 elif ax.index == len(CMAPS):
203 203 ax.index = 0
204 204 cmap = CMAPS[ax.index]
205 205 ax.cbar.set_cmap(cmap)
206 206 ax.cbar.draw_all()
207 207 ax.plt.set_cmap(cmap)
208 208 ax.cbar.patch.figure.canvas.draw()
209 209 self.colormap = cmap.name
210 210
211 211 def OnBtnScroll(self, event):
212 212 '''
213 213 Event for scrolling, scale figure
214 214 '''
215 215 cb_ax = event.inaxes
216 216 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
217 217 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
218 218 pt = ax.cbar.ax.bbox.get_points()[:, 1]
219 219 nrm = ax.cbar.norm
220 220 vmin, vmax, p0, p1, pS = (
221 221 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
222 222 scale = 2 if event.step == 1 else 0.5
223 223 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
224 224 ax.cbar.norm.vmin = point - scale * (point - vmin)
225 225 ax.cbar.norm.vmax = point - scale * (point - vmax)
226 226 ax.plt.set_norm(ax.cbar.norm)
227 227 ax.cbar.draw_all()
228 228 ax.cbar.patch.figure.canvas.draw()
229 229
230 230 def onBtnPress(self, event):
231 231 '''
232 232 Event for mouse button press
233 233 '''
234 234 cb_ax = event.inaxes
235 235 if cb_ax is None:
236 236 return
237 237
238 238 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
239 239 cb_ax.press = event.x, event.y
240 240 else:
241 241 cb_ax.press = None
242 242
243 243 def onMotion(self, event):
244 244 '''
245 245 Event for move inside colorbar
246 246 '''
247 247 cb_ax = event.inaxes
248 248 if cb_ax is None:
249 249 return
250 250 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
251 251 return
252 252 if cb_ax.press is None:
253 253 return
254 254
255 255 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
256 256 xprev, yprev = cb_ax.press
257 257 dx = event.x - xprev
258 258 dy = event.y - yprev
259 259 cb_ax.press = event.x, event.y
260 260 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
261 261 perc = 0.03
262 262
263 263 if event.button == 1:
264 264 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
265 265 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
266 266 elif event.button == 3:
267 267 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
268 268 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
269 269
270 270 ax.cbar.draw_all()
271 271 ax.plt.set_norm(ax.cbar.norm)
272 272 ax.cbar.patch.figure.canvas.draw()
273 273
274 274 def onBtnRelease(self, event):
275 275 '''
276 276 Event for mouse button release
277 277 '''
278 278 cb_ax = event.inaxes
279 279 if cb_ax is not None:
280 280 cb_ax.press = None
281 281
282 282 def __add_axes(self, ax, size='30%', pad='8%'):
283 283 '''
284 284 Add new axes to the given figure
285 285 '''
286 286 divider = make_axes_locatable(ax)
287 287 nax = divider.new_horizontal(size=size, pad=pad)
288 288 ax.figure.add_axes(nax)
289 289 return nax
290 290
291 291 self.setup()
292 292
293 293 def setup(self):
294 294 '''
295 295 This method should be implemented in the child class, the following
296 296 attributes should be set:
297 297
298 298 self.nrows: number of rows
299 299 self.ncols: number of cols
300 300 self.nplots: number of plots (channels or pairs)
301 301 self.ylabel: label for Y axes
302 302 self.titles: list of axes title
303 303
304 304 '''
305 305 raise(NotImplementedError, 'Implement this method in child class')
306 306
307 307 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
308 308 '''
309 309 Create a masked array for missing data
310 310 '''
311 311 if x_buffer.shape[0] < 2:
312 312 return x_buffer, y_buffer, z_buffer
313 313
314 314 deltas = x_buffer[1:] - x_buffer[0:-1]
315 315 x_median = numpy.median(deltas)
316 316
317 317 index = numpy.where(deltas > 5 * x_median)
318 318
319 319 if len(index[0]) != 0:
320 320 z_buffer[::, index[0], ::] = self.__missing
321 321 z_buffer = numpy.ma.masked_inside(z_buffer,
322 322 0.99 * self.__missing,
323 323 1.01 * self.__missing)
324 324
325 325 return x_buffer, y_buffer, z_buffer
326 326
327 327 def decimate(self):
328 328
329 329 # dx = int(len(self.x)/self.__MAXNUMX) + 1
330 330 dy = int(len(self.y) / self.decimation) + 1
331 331
332 332 # x = self.x[::dx]
333 333 x = self.x
334 334 y = self.y[::dy]
335 335 z = self.z[::, ::, ::dy]
336 336
337 337 return x, y, z
338 338
339 339 def format(self):
340 340 '''
341 341 Set min and max values, labels, ticks and titles
342 342 '''
343 343
344 344 if self.xmin is None:
345 345 xmin = self.min_time
346 346 else:
347 347 if self.xaxis is 'time':
348 348 dt = self.getDateTime(self.min_time)
349 349 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
350 350 datetime.datetime(1970, 1, 1)).total_seconds()
351 351 if self.data.localtime:
352 352 xmin += time.timezone
353 353 else:
354 354 xmin = self.xmin
355 355
356 356 if self.xmax is None:
357 357 xmax = xmin + self.xrange * 60 * 60
358 358 else:
359 359 if self.xaxis is 'time':
360 360 dt = self.getDateTime(self.max_time)
361 361 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
362 362 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
363 363 if self.data.localtime:
364 364 xmax += time.timezone
365 365 else:
366 366 xmax = self.xmax
367 367
368 368 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
369 369 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
370 370
371 371 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000])
372 372 i = 1 if numpy.where(ymax-ymin < Y)[0][0] < 0 else numpy.where(ymax-ymin < Y)[0][0]
373 373 ystep = Y[i] / 5
374 374
375 375 for n, ax in enumerate(self.axes):
376 376 if ax.firsttime:
377 377 ax.set_facecolor(self.bgcolor)
378 378 ax.yaxis.set_major_locator(MultipleLocator(ystep))
379 379 if self.xaxis is 'time':
380 380 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
381 381 ax.xaxis.set_major_locator(LinearLocator(9))
382 382 if self.xlabel is not None:
383 383 ax.set_xlabel(self.xlabel)
384 384 ax.set_ylabel(self.ylabel)
385 385 ax.firsttime = False
386 386 if self.showprofile:
387 387 self.pf_axes[n].set_ylim(ymin, ymax)
388 388 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
389 389 self.pf_axes[n].set_xlabel('dB')
390 390 self.pf_axes[n].grid(b=True, axis='x')
391 391 [tick.set_visible(False)
392 392 for tick in self.pf_axes[n].get_yticklabels()]
393 393 if self.colorbar:
394 394 ax.cbar = plt.colorbar(
395 395 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
396 396 ax.cbar.ax.tick_params(labelsize=8)
397 397 ax.cbar.ax.press = None
398 398 if self.cb_label:
399 399 ax.cbar.set_label(self.cb_label, size=8)
400 400 elif self.cb_labels:
401 401 ax.cbar.set_label(self.cb_labels[n], size=8)
402 402 else:
403 403 ax.cbar = None
404 404
405 405 if not self.polar:
406 406 ax.set_xlim(xmin, xmax)
407 407 ax.set_ylim(ymin, ymax)
408 408 ax.set_title('{} - {} {}'.format(
409 409 self.titles[n],
410 410 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
411 411 self.time_label),
412 412 size=8)
413 413 else:
414 414 ax.set_title('{}'.format(self.titles[n]), size=8)
415 415 ax.set_ylim(0, 90)
416 416 ax.set_yticks(numpy.arange(0, 90, 20))
417 417 ax.yaxis.labelpad = 40
418 418
419 419 def __plot(self):
420 420 '''
421 421 '''
422 422 log.success('Plotting', self.name)
423 423
424 self.plot()
425 self.format()
424 try:
425 self.plot()
426 self.format()
427 except:
428 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
426 429
427 430 for n, fig in enumerate(self.figures):
428 431 if self.nrows == 0 or self.nplots == 0:
429 432 log.warning('No data', self.name)
430 433 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
431 434 fig.canvas.manager.set_window_title(self.CODE)
432 435 continue
433 436
434 437 fig.tight_layout()
435 438 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
436 439 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
437 440 fig.canvas.draw()
438 441
439 442 if self.save and self.data.ended:
440 443 channels = range(self.nrows)
441 444 if self.oneFigure:
442 445 label = ''
443 446 else:
444 447 label = '_{}'.format(channels[n])
445 448 figname = os.path.join(
446 449 self.save,
447 450 '{}{}_{}.png'.format(
448 451 self.CODE,
449 452 label,
450 453 self.getDateTime(self.saveTime).strftime(
451 454 '%y%m%d_%H%M%S'),
452 455 )
453 456 )
454 457 log.log('Saving figure: {}'.format(figname), self.name)
455 458 fig.savefig(figname)
456 459
457 460 def plot(self):
458 461 '''
459 462 '''
460 463 raise(NotImplementedError, 'Implement this method in child class')
461 464
462 465 def run(self):
463 466
464 467 log.success('Starting', self.name)
465 468
466 469 context = zmq.Context()
467 470 receiver = context.socket(zmq.SUB)
468 471 receiver.setsockopt(zmq.SUBSCRIBE, '')
469 472 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
470 473
471 474 if 'server' in self.kwargs['parent']:
472 475 receiver.connect(
473 476 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
474 477 else:
475 478 receiver.connect("ipc:///tmp/zmq.plots")
476 479
477 480 while True:
478 481 try:
479 482 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
480 483 if self.data.localtime and self.localtime:
481 484 self.times = self.data.times
482 485 elif self.data.localtime and not self.localtime:
483 486 self.times = self.data.times + time.timezone
484 487 elif not self.data.localtime and self.localtime:
485 488 self.times = self.data.times - time.timezone
486 489 else:
487 490 self.times = self.data.times
488 491
489 492 self.min_time = self.times[0]
490 493 self.max_time = self.times[-1]
491 494
492 495 if self.isConfig is False:
493 496 self.__setup()
494 497 self.isConfig = True
495 498
496 499 self.__plot()
497 500
498 501 except zmq.Again as e:
499 502 log.log('Waiting for data...')
500 503 if self.data:
501 504 figpause(self.data.throttle)
502 505 else:
503 506 time.sleep(2)
504 507
505 508 def close(self):
506 509 if self.data:
507 510 self.__plot()
508 511
509 512
510 513 class PlotSpectraData(PlotData):
511 514 '''
512 515 Plot for Spectra data
513 516 '''
514 517
515 518 CODE = 'spc'
516 519 colormap = 'jro'
517 520
518 521 def setup(self):
519 522 self.nplots = len(self.data.channels)
520 523 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
521 524 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
522 525 self.width = 3.4 * self.ncols
523 526 self.height = 3 * self.nrows
524 527 self.cb_label = 'dB'
525 528 if self.showprofile:
526 529 self.width += 0.8 * self.ncols
527 530
528 531 self.ylabel = 'Range [Km]'
529 532
530 533 def plot(self):
531 534 if self.xaxis == "frequency":
532 535 x = self.data.xrange[0]
533 536 self.xlabel = "Frequency (kHz)"
534 537 elif self.xaxis == "time":
535 538 x = self.data.xrange[1]
536 539 self.xlabel = "Time (ms)"
537 540 else:
538 541 x = self.data.xrange[2]
539 542 self.xlabel = "Velocity (m/s)"
540 543
541 544 if self.CODE == 'spc_mean':
542 545 x = self.data.xrange[2]
543 546 self.xlabel = "Velocity (m/s)"
544 547
545 548 self.titles = []
546 549
547 550 y = self.data.heights
548 551 self.y = y
549 552 z = self.data['spc']
550 553
551 554 for n, ax in enumerate(self.axes):
552 555 noise = self.data['noise'][n][-1]
553 556 if self.CODE == 'spc_mean':
554 557 mean = self.data['mean'][n][-1]
555 558 if ax.firsttime:
556 559 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
557 560 self.xmin = self.xmin if self.xmin else -self.xmax
558 561 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
559 562 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
560 563 ax.plt = ax.pcolormesh(x, y, z[n].T,
561 564 vmin=self.zmin,
562 565 vmax=self.zmax,
563 566 cmap=plt.get_cmap(self.colormap)
564 567 )
565 568
566 569 if self.showprofile:
567 570 ax.plt_profile = self.pf_axes[n].plot(
568 571 self.data['rti'][n][-1], y)[0]
569 572 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
570 573 color="k", linestyle="dashed", lw=1)[0]
571 574 if self.CODE == 'spc_mean':
572 575 ax.plt_mean = ax.plot(mean, y, color='k')[0]
573 576 else:
574 577 ax.plt.set_array(z[n].T.ravel())
575 578 if self.showprofile:
576 579 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
577 580 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
578 581 if self.CODE == 'spc_mean':
579 582 ax.plt_mean.set_data(mean, y)
580 583
581 584 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
582 585 self.saveTime = self.max_time
583 586
584 587
585 588 class PlotCrossSpectraData(PlotData):
586 589
587 590 CODE = 'cspc'
588 591 zmin_coh = None
589 592 zmax_coh = None
590 593 zmin_phase = None
591 594 zmax_phase = None
592 595
593 596 def setup(self):
594 597
595 598 self.ncols = 4
596 599 self.nrows = len(self.data.pairs)
597 600 self.nplots = self.nrows * 4
598 601 self.width = 3.4 * self.ncols
599 602 self.height = 3 * self.nrows
600 603 self.ylabel = 'Range [Km]'
601 604 self.showprofile = False
602 605
603 606 def plot(self):
604 607
605 608 if self.xaxis == "frequency":
606 609 x = self.data.xrange[0]
607 610 self.xlabel = "Frequency (kHz)"
608 611 elif self.xaxis == "time":
609 612 x = self.data.xrange[1]
610 613 self.xlabel = "Time (ms)"
611 614 else:
612 615 x = self.data.xrange[2]
613 616 self.xlabel = "Velocity (m/s)"
614 617
615 618 self.titles = []
616 619
617 620 y = self.data.heights
618 621 self.y = y
619 622 spc = self.data['spc']
620 623 cspc = self.data['cspc']
621 624
622 625 for n in range(self.nrows):
623 626 noise = self.data['noise'][n][-1]
624 627 pair = self.data.pairs[n]
625 628 ax = self.axes[4 * n]
626 629 ax3 = self.axes[4 * n + 3]
627 630 if ax.firsttime:
628 631 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
629 632 self.xmin = self.xmin if self.xmin else -self.xmax
630 633 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
631 634 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
632 635 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
633 636 vmin=self.zmin,
634 637 vmax=self.zmax,
635 638 cmap=plt.get_cmap(self.colormap)
636 639 )
637 640 else:
638 641 ax.plt.set_array(spc[pair[0]].T.ravel())
639 642 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
640 643
641 644 ax = self.axes[4 * n + 1]
642 645 if ax.firsttime:
643 646 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
644 647 vmin=self.zmin,
645 648 vmax=self.zmax,
646 649 cmap=plt.get_cmap(self.colormap)
647 650 )
648 651 else:
649 652 ax.plt.set_array(spc[pair[1]].T.ravel())
650 653 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
651 654
652 655 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
653 656 coh = numpy.abs(out)
654 657 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
655 658
656 659 ax = self.axes[4 * n + 2]
657 660 if ax.firsttime:
658 661 ax.plt = ax.pcolormesh(x, y, coh.T,
659 662 vmin=0,
660 663 vmax=1,
661 664 cmap=plt.get_cmap(self.colormap_coh)
662 665 )
663 666 else:
664 667 ax.plt.set_array(coh.T.ravel())
665 668 self.titles.append(
666 669 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
667 670
668 671 ax = self.axes[4 * n + 3]
669 672 if ax.firsttime:
670 673 ax.plt = ax.pcolormesh(x, y, phase.T,
671 674 vmin=-180,
672 675 vmax=180,
673 676 cmap=plt.get_cmap(self.colormap_phase)
674 677 )
675 678 else:
676 679 ax.plt.set_array(phase.T.ravel())
677 680 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
678 681
679 682 self.saveTime = self.max_time
680 683
681 684
682 685 class PlotSpectraMeanData(PlotSpectraData):
683 686 '''
684 687 Plot for Spectra and Mean
685 688 '''
686 689 CODE = 'spc_mean'
687 690 colormap = 'jro'
688 691
689 692
690 693 class PlotRTIData(PlotData):
691 694 '''
692 695 Plot for RTI data
693 696 '''
694 697
695 698 CODE = 'rti'
696 699 colormap = 'jro'
697 700
698 701 def setup(self):
699 702 self.xaxis = 'time'
700 703 self.ncols = 1
701 704 self.nrows = len(self.data.channels)
702 705 self.nplots = len(self.data.channels)
703 706 self.ylabel = 'Range [Km]'
704 707 self.cb_label = 'dB'
705 708 self.titles = ['{} Channel {}'.format(
706 709 self.CODE.upper(), x) for x in range(self.nrows)]
707 710
708 711 def plot(self):
709 712 self.x = self.times
710 713 self.y = self.data.heights
711 714 self.z = self.data[self.CODE]
712 715 self.z = numpy.ma.masked_invalid(self.z)
713 716
714 717 if self.decimation is None:
715 718 x, y, z = self.fill_gaps(self.x, self.y, self.z)
716 719 else:
717 720 x, y, z = self.fill_gaps(*self.decimate())
718 721
719 722 for n, ax in enumerate(self.axes):
720 723 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
721 724 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
722 725 if ax.firsttime:
723 726 ax.plt = ax.pcolormesh(x, y, z[n].T,
724 727 vmin=self.zmin,
725 728 vmax=self.zmax,
726 729 cmap=plt.get_cmap(self.colormap)
727 730 )
728 731 if self.showprofile:
729 732 ax.plot_profile = self.pf_axes[n].plot(
730 733 self.data['rti'][n][-1], self.y)[0]
731 734 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
732 735 color="k", linestyle="dashed", lw=1)[0]
733 736 else:
734 737 ax.collections.remove(ax.collections[0])
735 738 ax.plt = ax.pcolormesh(x, y, z[n].T,
736 739 vmin=self.zmin,
737 740 vmax=self.zmax,
738 741 cmap=plt.get_cmap(self.colormap)
739 742 )
740 743 if self.showprofile:
741 744 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
742 745 ax.plot_noise.set_data(numpy.repeat(
743 746 self.data['noise'][n][-1], len(self.y)), self.y)
744 747
745 748 self.saveTime = self.min_time
746 749
747 750
748 751 class PlotCOHData(PlotRTIData):
749 752 '''
750 753 Plot for Coherence data
751 754 '''
752 755
753 756 CODE = 'coh'
754 757
755 758 def setup(self):
756 759 self.xaxis = 'time'
757 760 self.ncols = 1
758 761 self.nrows = len(self.data.pairs)
759 762 self.nplots = len(self.data.pairs)
760 763 self.ylabel = 'Range [Km]'
761 764 if self.CODE == 'coh':
762 765 self.cb_label = ''
763 766 self.titles = [
764 767 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
765 768 else:
766 769 self.cb_label = 'Degrees'
767 770 self.titles = [
768 771 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
769 772
770 773
771 774 class PlotPHASEData(PlotCOHData):
772 775 '''
773 776 Plot for Phase map data
774 777 '''
775 778
776 779 CODE = 'phase'
777 780 colormap = 'seismic'
778 781
779 782
780 783 class PlotNoiseData(PlotData):
781 784 '''
782 785 Plot for noise
783 786 '''
784 787
785 788 CODE = 'noise'
786 789
787 790 def setup(self):
788 791 self.xaxis = 'time'
789 792 self.ncols = 1
790 793 self.nrows = 1
791 794 self.nplots = 1
792 795 self.ylabel = 'Intensity [dB]'
793 796 self.titles = ['Noise']
794 797 self.colorbar = False
795 798
796 799 def plot(self):
797 800
798 801 x = self.times
799 802 xmin = self.min_time
800 803 xmax = xmin + self.xrange * 60 * 60
801 804 Y = self.data[self.CODE]
802 805
803 806 if self.axes[0].firsttime:
804 807 for ch in self.data.channels:
805 808 y = Y[ch]
806 809 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
807 810 plt.legend()
808 811 else:
809 812 for ch in self.data.channels:
810 813 y = Y[ch]
811 814 self.axes[0].lines[ch].set_data(x, y)
812 815
813 816 self.ymin = numpy.nanmin(Y) - 5
814 817 self.ymax = numpy.nanmax(Y) + 5
815 818 self.saveTime = self.min_time
816 819
817 820
818 821 class PlotSNRData(PlotRTIData):
819 822 '''
820 823 Plot for SNR Data
821 824 '''
822 825
823 826 CODE = 'snr'
824 827 colormap = 'jet'
825 828
826 829
827 830 class PlotDOPData(PlotRTIData):
828 831 '''
829 832 Plot for DOPPLER Data
830 833 '''
831 834
832 835 CODE = 'dop'
833 836 colormap = 'jet'
834 837
835 838
836 839 class PlotSkyMapData(PlotData):
837 840 '''
838 841 Plot for meteors detection data
839 842 '''
840 843
841 844 CODE = 'param'
842 845
843 846 def setup(self):
844 847
845 848 self.ncols = 1
846 849 self.nrows = 1
847 850 self.width = 7.2
848 851 self.height = 7.2
849 852 self.nplots = 1
850 853 self.xlabel = 'Zonal Zenith Angle (deg)'
851 854 self.ylabel = 'Meridional Zenith Angle (deg)'
852 855 self.polar = True
853 856 self.ymin = -180
854 857 self.ymax = 180
855 858 self.colorbar = False
856 859
857 860 def plot(self):
858 861
859 862 arrayParameters = numpy.concatenate(self.data['param'])
860 863 error = arrayParameters[:, -1]
861 864 indValid = numpy.where(error == 0)[0]
862 865 finalMeteor = arrayParameters[indValid, :]
863 866 finalAzimuth = finalMeteor[:, 3]
864 867 finalZenith = finalMeteor[:, 4]
865 868
866 869 x = finalAzimuth * numpy.pi / 180
867 870 y = finalZenith
868 871
869 872 ax = self.axes[0]
870 873
871 874 if ax.firsttime:
872 875 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
873 876 else:
874 877 ax.plot.set_data(x, y)
875 878
876 879 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
877 880 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
878 881 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
879 882 dt2,
880 883 len(x))
881 884 self.titles[0] = title
882 885 self.saveTime = self.max_time
883 886
884 887
885 888 class PlotParamData(PlotRTIData):
886 889 '''
887 890 Plot for data_param object
888 891 '''
889 892
890 893 CODE = 'param'
891 894 colormap = 'seismic'
892 895
893 896 def setup(self):
894 897 self.xaxis = 'time'
895 898 self.ncols = 1
896 899 self.nrows = self.data.shape(self.CODE)[0]
897 900 self.nplots = self.nrows
898 901 if self.showSNR:
899 902 self.nrows += 1
900 903 self.nplots += 1
901 904
902 905 self.ylabel = 'Height [Km]'
903 906 if not self.titles:
904 907 self.titles = self.data.parameters \
905 908 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
906 909 if self.showSNR:
907 910 self.titles.append('SNR')
908 911
909 912 def plot(self):
910 913 self.data.normalize_heights()
911 914 self.x = self.times
912 915 self.y = self.data.heights
913 916 if self.showSNR:
914 917 self.z = numpy.concatenate(
915 918 (self.data[self.CODE], self.data['snr'])
916 919 )
917 920 else:
918 921 self.z = self.data[self.CODE]
919 922
920 923 self.z = numpy.ma.masked_invalid(self.z)
921 924
922 925 if self.decimation is None:
923 926 x, y, z = self.fill_gaps(self.x, self.y, self.z)
924 927 else:
925 928 x, y, z = self.fill_gaps(*self.decimate())
926 929
927 930 for n, ax in enumerate(self.axes):
928 931
929 932 self.zmax = self.zmax if self.zmax is not None else numpy.max(
930 933 self.z[n])
931 934 self.zmin = self.zmin if self.zmin is not None else numpy.min(
932 935 self.z[n])
933 936
934 937 if ax.firsttime:
935 938 if self.zlimits is not None:
936 939 self.zmin, self.zmax = self.zlimits[n]
937 940
938 941 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
939 942 vmin=self.zmin,
940 943 vmax=self.zmax,
941 944 cmap=self.cmaps[n]
942 945 )
943 946 else:
944 947 if self.zlimits is not None:
945 948 self.zmin, self.zmax = self.zlimits[n]
946 949 ax.collections.remove(ax.collections[0])
947 950 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
948 951 vmin=self.zmin,
949 952 vmax=self.zmax,
950 953 cmap=self.cmaps[n]
951 954 )
952 955
953 956 self.saveTime = self.min_time
954 957
955 958
956 959 class PlotOutputData(PlotParamData):
957 960 '''
958 961 Plot data_output object
959 962 '''
960 963
961 964 CODE = 'output'
962 965 colormap = 'seismic'
General Comments 0
You need to be logged in to leave comments. Login now