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