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