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