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