##// END OF EJS Templates
decimation a 300
José Chávez -
r1093:6f37ceb2e70a
parent child
Show More
@@ -1,939 +1,951
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 28 def figpause(interval):
28 29 backend = plt.rcParams['backend']
29 30 if backend in matplotlib.rcsetup.interactive_bk:
30 31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
31 32 if figManager is not None:
32 33 canvas = figManager.canvas
33 34 if canvas.figure.stale:
34 35 canvas.draw()
35 36 canvas.start_event_loop(interval)
36 37 return
37 38
39
38 40 class PlotData(Operation, Process):
39 41 '''
40 42 Base class for Schain plotting operations
41 43 '''
42 44
43 45 CODE = 'Figure'
44 46 colormap = 'jro'
45 47 bgcolor = 'white'
46 48 CONFLATE = False
47 49 __MAXNUMX = 80
48 50 __missing = 1E30
49 51
50 52 def __init__(self, **kwargs):
51 53
52 54 Operation.__init__(self, plot=True, **kwargs)
53 55 Process.__init__(self)
56 self.contador = 0
54 57 self.kwargs['code'] = self.CODE
55 58 self.mp = False
56 59 self.data = None
57 60 self.isConfig = False
58 61 self.figures = []
59 62 self.axes = []
60 63 self.cb_axes = []
61 64 self.localtime = kwargs.pop('localtime', True)
62 65 self.show = kwargs.get('show', True)
63 66 self.save = kwargs.get('save', False)
64 67 self.colormap = kwargs.get('colormap', self.colormap)
65 68 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
66 69 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
67 70 self.colormaps = kwargs.get('colormaps', None)
68 71 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
69 72 self.showprofile = kwargs.get('showprofile', False)
70 73 self.title = kwargs.get('wintitle', self.CODE.upper())
71 74 self.cb_label = kwargs.get('cb_label', None)
72 75 self.cb_labels = kwargs.get('cb_labels', None)
73 76 self.xaxis = kwargs.get('xaxis', 'frequency')
74 77 self.zmin = kwargs.get('zmin', None)
75 78 self.zmax = kwargs.get('zmax', None)
76 79 self.zlimits = kwargs.get('zlimits', None)
77 80 self.xmin = kwargs.get('xmin', None)
78 81 self.xmax = kwargs.get('xmax', None)
79 82 self.xrange = kwargs.get('xrange', 24)
80 83 self.ymin = kwargs.get('ymin', None)
81 84 self.ymax = kwargs.get('ymax', None)
82 85 self.xlabel = kwargs.get('xlabel', None)
83 self.__MAXNUMY = kwargs.get('decimation', 100)
86 self.__MAXNUMY = kwargs.get('decimation', 300)
84 87 self.showSNR = kwargs.get('showSNR', False)
85 88 self.oneFigure = kwargs.get('oneFigure', True)
86 89 self.width = kwargs.get('width', None)
87 90 self.height = kwargs.get('height', None)
88 91 self.colorbar = kwargs.get('colorbar', True)
89 92 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
90 93 self.titles = ['' for __ in range(16)]
91 94
92 95 def __fmtTime(self, x, pos):
93 96 '''
94 97 '''
95 98
96 99 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
97 100
98 101 def __setup(self):
99 102 '''
100 103 Common setup for all figures, here figures and axes are created
101 104 '''
102 105
103 106 self.setup()
104 107
105 108 self.time_label = 'LT' if self.localtime else 'UTC'
106 109 if self.data.localtime:
107 self.getDateTime = datetime.datetime.fromtimestamp
110 self.getDateTime = datetime.datetime.fromtimestamp
108 111 else:
109 self.getDateTime = datetime.datetime.utcfromtimestamp
112 self.getDateTime = datetime.datetime.utcfromtimestamp
110 113
111 114 if self.width is None:
112 115 self.width = 8
113 116
114 117 self.figures = []
115 118 self.axes = []
116 119 self.cb_axes = []
117 120 self.pf_axes = []
118 121 self.cmaps = []
119 122
120 123 size = '15%' if self.ncols == 1 else '30%'
121 124 pad = '4%' if self.ncols == 1 else '8%'
122 125
123 126 if self.oneFigure:
124 127 if self.height is None:
125 128 self.height = 1.4 * self.nrows + 1
126 129 fig = plt.figure(figsize=(self.width, self.height),
127 130 edgecolor='k',
128 131 facecolor='w')
129 132 self.figures.append(fig)
130 133 for n in range(self.nplots):
131 134 ax = fig.add_subplot(self.nrows, self.ncols, n + 1)
132 135 ax.tick_params(labelsize=8)
133 136 ax.firsttime = True
134 137 ax.index = 0
135 138 ax.press = None
136 self.axes.append(ax)
139 self.axes.append(ax)
137 140 if self.showprofile:
138 141 cax = self.__add_axes(ax, size=size, pad=pad)
139 142 cax.tick_params(labelsize=8)
140 143 self.pf_axes.append(cax)
141 144 else:
142 145 if self.height is None:
143 146 self.height = 3
144 147 for n in range(self.nplots):
145 148 fig = plt.figure(figsize=(self.width, self.height),
146 149 edgecolor='k',
147 150 facecolor='w')
148 151 ax = fig.add_subplot(1, 1, 1)
149 152 ax.tick_params(labelsize=8)
150 153 ax.firsttime = True
151 154 ax.index = 0
152 155 ax.press = None
153 self.figures.append(fig)
156 self.figures.append(fig)
154 157 self.axes.append(ax)
155 158 if self.showprofile:
156 159 cax = self.__add_axes(ax, size=size, pad=pad)
157 160 cax.tick_params(labelsize=8)
158 161 self.pf_axes.append(cax)
159 162
160 163 for n in range(self.nrows):
161 164 if self.colormaps is not None:
162 165 cmap = plt.get_cmap(self.colormaps[n])
163 166 else:
164 167 cmap = plt.get_cmap(self.colormap)
165 168 cmap.set_bad(self.bgcolor, 1.)
166 169 self.cmaps.append(cmap)
167 170
168 171 for fig in self.figures:
169 172 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
170 173 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
171 174 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
172 175 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
173 176 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
174 177 if self.show:
175 178 fig.show()
176 179
177 180 def OnKeyPress(self, event):
178 181 '''
179 182 Event for pressing keys (up, down) change colormap
180 183 '''
181 184 ax = event.inaxes
182 if ax in self.axes:
185 if ax in self.axes:
183 186 if event.key == 'down':
184 187 ax.index += 1
185 188 elif event.key == 'up':
186 189 ax.index -= 1
187 190 if ax.index < 0:
188 ax.index = len(CMAPS) - 1
191 ax.index = len(CMAPS) - 1
189 192 elif ax.index == len(CMAPS):
190 193 ax.index = 0
191 cmap = CMAPS[ax.index]
194 cmap = CMAPS[ax.index]
192 195 ax.cbar.set_cmap(cmap)
193 196 ax.cbar.draw_all()
194 ax.plt.set_cmap(cmap)
197 ax.plt.set_cmap(cmap)
195 198 ax.cbar.patch.figure.canvas.draw()
196 199 self.colormap = cmap.name
197 200
198 201 def OnBtnScroll(self, event):
199 202 '''
200 203 Event for scrolling, scale figure
201 204 '''
202 205 cb_ax = event.inaxes
203 206 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
204 207 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
205 pt = ax.cbar.ax.bbox.get_points()[:,1]
208 pt = ax.cbar.ax.bbox.get_points()[:, 1]
206 209 nrm = ax.cbar.norm
207 vmin, vmax, p0, p1, pS = (nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
210 vmin, vmax, p0, p1, pS = (
211 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
208 212 scale = 2 if event.step == 1 else 0.5
209 point = vmin + (vmax - vmin) / (p1 - p0)*(pS - p0)
210 ax.cbar.norm.vmin = point - scale*(point - vmin)
211 ax.cbar.norm.vmax = point - scale*(point - vmax)
213 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
214 ax.cbar.norm.vmin = point - scale * (point - vmin)
215 ax.cbar.norm.vmax = point - scale * (point - vmax)
212 216 ax.plt.set_norm(ax.cbar.norm)
213 217 ax.cbar.draw_all()
214 218 ax.cbar.patch.figure.canvas.draw()
215 219
216 220 def onBtnPress(self, event):
217 221 '''
218 222 Event for mouse button press
219 223 '''
220 224 cb_ax = event.inaxes
221 225 if cb_ax is None:
222 226 return
223 227
224 228 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
225 229 cb_ax.press = event.x, event.y
226 230 else:
227 231 cb_ax.press = None
228 232
229 233 def onMotion(self, event):
230 234 '''
231 235 Event for move inside colorbar
232 236 '''
233 237 cb_ax = event.inaxes
234 238 if cb_ax is None:
235 239 return
236 240 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
237 241 return
238 if cb_ax.press is None:
242 if cb_ax.press is None:
239 243 return
240 244
241 245 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
242 246 xprev, yprev = cb_ax.press
243 247 dx = event.x - xprev
244 248 dy = event.y - yprev
245 cb_ax.press = event.x, event.y
249 cb_ax.press = event.x, event.y
246 250 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
247 251 perc = 0.03
248 252
249 253 if event.button == 1:
250 ax.cbar.norm.vmin -= (perc*scale)*numpy.sign(dy)
251 ax.cbar.norm.vmax -= (perc*scale)*numpy.sign(dy)
254 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
255 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
252 256 elif event.button == 3:
253 ax.cbar.norm.vmin -= (perc*scale)*numpy.sign(dy)
254 ax.cbar.norm.vmax += (perc*scale)*numpy.sign(dy)
257 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
258 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
255 259
256 260 ax.cbar.draw_all()
257 261 ax.plt.set_norm(ax.cbar.norm)
258 262 ax.cbar.patch.figure.canvas.draw()
259 263
260 264 def onBtnRelease(self, event):
261 265 '''
262 266 Event for mouse button release
263 267 '''
264 268 cb_ax = event.inaxes
265 269 if cb_ax is not None:
266 270 cb_ax.press = None
267 271
268 272 def __add_axes(self, ax, size='30%', pad='8%'):
269 273 '''
270 274 Add new axes to the given figure
271 275 '''
272 276 divider = make_axes_locatable(ax)
273 277 nax = divider.new_horizontal(size=size, pad=pad)
274 278 ax.figure.add_axes(nax)
275 279 return nax
276 280
277 281 self.setup()
278 282
279 283 def setup(self):
280 284 '''
281 285 This method should be implemented in the child class, the following
282 286 attributes should be set:
283 287
284 288 self.nrows: number of rows
285 289 self.ncols: number of cols
286 290 self.nplots: number of plots (channels or pairs)
287 291 self.ylabel: label for Y axes
288 292 self.titles: list of axes title
289 293
290 294 '''
291 295 raise(NotImplementedError, 'Implement this method in child class')
292 296
293 297 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
294 298 '''
295 299 Create a masked array for missing data
296 300 '''
297 301 if x_buffer.shape[0] < 2:
298 302 return x_buffer, y_buffer, z_buffer
299 303
300 304 deltas = x_buffer[1:] - x_buffer[0:-1]
301 305 x_median = numpy.median(deltas)
302 306
303 307 index = numpy.where(deltas > 5 * x_median)
304 308
305 309 if len(index[0]) != 0:
306 310 z_buffer[::, index[0], ::] = self.__missing
307 311 z_buffer = numpy.ma.masked_inside(z_buffer,
308 312 0.99 * self.__missing,
309 313 1.01 * self.__missing)
310 314
311 315 return x_buffer, y_buffer, z_buffer
312 316
313 317 def decimate(self):
314 318
315 319 # dx = int(len(self.x)/self.__MAXNUMX) + 1
316 320 dy = int(len(self.y) / self.__MAXNUMY) + 1
317 321
318 322 # x = self.x[::dx]
319 323 x = self.x
320 324 y = self.y[::dy]
321 325 z = self.z[::, ::, ::dy]
322 326
323 327 return x, y, z
324 328
325 329 def format(self):
326 330 '''
327 331 Set min and max values, labels, ticks and titles
328 332 '''
329 333
330 334 if self.xmin is None:
331 335 xmin = self.min_time
332 336 else:
333 337 if self.xaxis is 'time':
334 dt = self.getDateTime(self.min_time)
335 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) - datetime.datetime(1970, 1, 1)).total_seconds()
338 dt = self.getDateTime(self.min_time)
339 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
340 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=0, second=0) -
352 datetime.datetime(1970, 1, 1)).total_seconds()
347 353 if self.data.localtime:
348 354 xmax += time.timezone
349 355 else:
350 356 xmax = self.xmax
351 357
352 358 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
353 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
359 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
354 360
355 361 Y = numpy.array([10, 20, 50, 100, 200, 500, 1000, 2000])
356 i = 1 if numpy.where(ymax < Y)[0][0] < 0 else numpy.where(ymax < Y)[0][0]
357 ystep = Y[i-1]/5
362 i = 1 if numpy.where(ymax < Y)[
363 0][0] < 0 else numpy.where(ymax < Y)[0][0]
364 ystep = Y[i - 1] / 5
358 365
359 366 ystep = 200 if ymax >= 800 else 100 if ymax >= 400 else 50 if ymax >= 200 else 20
360 367
361 368 for n, ax in enumerate(self.axes):
362 369 if ax.firsttime:
363 370 ax.set_facecolor(self.bgcolor)
364 371 ax.yaxis.set_major_locator(MultipleLocator(ystep))
365 if self.xaxis is 'time':
372 if self.xaxis is 'time':
366 373 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
367 ax.xaxis.set_major_locator(LinearLocator(9))
374 ax.xaxis.set_major_locator(LinearLocator(9))
368 375 if self.xlabel is not None:
369 376 ax.set_xlabel(self.xlabel)
370 377 ax.set_ylabel(self.ylabel)
371 378 ax.firsttime = False
372 379 if self.showprofile:
373 380 self.pf_axes[n].set_ylim(ymin, ymax)
374 381 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
375 382 self.pf_axes[n].set_xlabel('dB')
376 383 self.pf_axes[n].grid(b=True, axis='x')
377 384 [tick.set_visible(False)
378 385 for tick in self.pf_axes[n].get_yticklabels()]
379 386 if self.colorbar:
380 387 ax.cbar = plt.colorbar(ax.plt, ax=ax, pad=0.02, aspect=10)
381 388 ax.cbar.ax.tick_params(labelsize=8)
382 389 ax.cbar.ax.press = None
383 390 if self.cb_label:
384 391 ax.cbar.set_label(self.cb_label, size=8)
385 392 elif self.cb_labels:
386 393 ax.cbar.set_label(self.cb_labels[n], size=8)
387 394 else:
388 395 ax.cbar = None
389 396
390 397 ax.set_title('{} - {} {}'.format(
391 self.titles[n],
392 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
393 self.time_label),
398 self.titles[n],
399 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
400 self.time_label),
394 401 size=8)
395 402 ax.set_xlim(xmin, xmax)
396 403 ax.set_ylim(ymin, ymax)
397 404
398 405 def __plot(self):
399 406 '''
400 407 '''
401 408 log.success('Plotting', self.name)
402 409
403 410 self.plot()
404 411 self.format()
405 412
406 413 for n, fig in enumerate(self.figures):
407 414 if self.nrows == 0 or self.nplots == 0:
408 415 log.warning('No data', self.name)
409 continue
410
416 continue
417
411 418 fig.tight_layout()
412 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
419 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
413 420 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
414 421 # fig.canvas.draw()
415 422
416 if self.save and self.data.ended:
423 if self.save: # and self.data.ended:
424 self.contador += 1
417 425 channels = range(self.nrows)
418 426 if self.oneFigure:
419 427 label = ''
420 428 else:
421 429 label = '_{}'.format(channels[n])
422 430 figname = os.path.join(
423 431 self.save,
424 '{}{}_{}.png'.format(
432 '{}{}_{}{}.png'.format(
425 433 self.CODE,
426 434 label,
427 self.getDateTime(self.saveTime).strftime('%y%m%d_%H%M%S')
435 self.getDateTime(self.saveTime).strftime(
436 '%y%m%d_%H%M%S'),
437 str(self.contador),
428 438 )
429 439 )
430 440 print 'Saving figure: {}'.format(figname)
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 823 CODE = 'met'
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
822 832 self.xlabel = 'Zonal Zenith Angle (deg)'
823 833 self.ylabel = 'Meridional Zenith Angle (deg)'
824 834
825 835 if self.figure is None:
826 836 self.figure = plt.figure(figsize=(self.width, self.height),
827 837 edgecolor='k',
828 838 facecolor='w')
829 839 else:
830 840 self.figure.clf()
831 841
832 842 self.ax = plt.subplot2grid(
833 843 (self.nrows, self.ncols), (0, 0), 1, 1, polar=True)
834 844 self.ax.firsttime = True
835 845
836 846 def plot(self):
837 847
838 848 arrayParameters = numpy.concatenate(
839 849 [self.data['param'][t] for t in self.times])
840 850 error = arrayParameters[:, -1]
841 851 indValid = numpy.where(error == 0)[0]
842 852 finalMeteor = arrayParameters[indValid, :]
843 853 finalAzimuth = finalMeteor[:, 3]
844 854 finalZenith = finalMeteor[:, 4]
845 855
846 856 x = finalAzimuth * numpy.pi / 180
847 857 y = finalZenith
848 858
849 859 if self.ax.firsttime:
850 860 self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0]
851 861 self.ax.set_ylim(0, 90)
852 862 self.ax.set_yticks(numpy.arange(0, 90, 20))
853 863 self.ax.set_xlabel(self.xlabel)
854 864 self.ax.set_ylabel(self.ylabel)
855 865 self.ax.yaxis.labelpad = 40
856 866 self.ax.firsttime = False
857 867 else:
858 868 self.ax.plot.set_data(x, y)
859 869
860
861 870 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
862 871 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
863 872 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
864 873 dt2,
865 874 len(x))
866 875 self.ax.set_title(title, size=8)
867 876 self.saveTime = self.max_time
868 877
869 878
870 879 class PlotParamData(PlotRTIData):
871 880 '''
872 881 Plot for data_param object
873 882 '''
874 883
875 884 CODE = 'param'
876 885 colormap = 'seismic'
877 886
878 887 def setup(self):
879 888 self.xaxis = 'time'
880 889 self.ncols = 1
881 890 self.nrows = self.data.shape(self.CODE)[0]
882 891 self.nplots = self.nrows
883 892 if self.showSNR:
884 893 self.nrows += 1
885 894 self.nplots += 1
886 895
887 896 self.ylabel = 'Height [Km]'
888 897 self.titles = self.data.parameters \
889 898 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
890 899 if self.showSNR:
891 900 self.titles.append('SNR')
892 901
893 902 def plot(self):
894 903 self.data.normalize_heights()
895 904 self.x = self.times
896 905 self.y = self.data.heights
897 906 if self.showSNR:
898 907 self.z = numpy.concatenate(
899 908 (self.data[self.CODE], self.data['snr'])
900 909 )
901 910 else:
902 911 self.z = self.data[self.CODE]
903 912
904 913 self.z = numpy.ma.masked_invalid(self.z)
905 914
906 915 for n, ax in enumerate(self.axes):
907 916
908 917 x, y, z = self.fill_gaps(*self.decimate())
909 self.zmax = self.zmax if self.zmax is not None else numpy.max(self.z[n])
910 self.zmin = self.zmin if self.zmin is not None else numpy.min(self.z[n])
911
918 self.zmax = self.zmax if self.zmax is not None else numpy.max(
919 self.z[n])
920 self.zmin = self.zmin if self.zmin is not None else numpy.min(
921 self.z[n])
922
912 923 if ax.firsttime:
913 924 if self.zlimits is not None:
914 925 self.zmin, self.zmax = self.zlimits[n]
915
916 ax.plt = ax.pcolormesh(x, y, z[n].T*self.factors[n],
926
927 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
917 928 vmin=self.zmin,
918 929 vmax=self.zmax,
919 930 cmap=self.cmaps[n]
920 931 )
921 932 else:
922 933 if self.zlimits is not None:
923 934 self.zmin, self.zmax = self.zlimits[n]
924 935 ax.collections.remove(ax.collections[0])
925 ax.plt = ax.pcolormesh(x, y, z[n].T*self.factors[n],
936 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
926 937 vmin=self.zmin,
927 938 vmax=self.zmax,
928 939 cmap=self.cmaps[n]
929 940 )
930 941
931 942 self.saveTime = self.min_time
932 943
944
933 945 class PlotOutputData(PlotParamData):
934 946 '''
935 947 Plot data_output object
936 948 '''
937 949
938 950 CODE = 'output'
939 951 colormap = 'seismic'
General Comments 0
You need to be logged in to leave comments. Login now