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