##// END OF EJS Templates
MADReader support for HDF5 (mad2 & mad3)
jespinoza -
r1065:9a4424b32cac
parent child
Show More
@@ -1,7 +1,7
1 1 '''
2 2 Created on Feb 7, 2012
3 3
4 4 @author $Author$
5 5 @version $Id$
6 6 '''
7 __version__ = "2.3"
7 __version__ = '2.3'
@@ -1,782 +1,783
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 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
19 19
20 20 d1970 = datetime.datetime(1970, 1, 1)
21 21
22 22
23 23 class PlotData(Operation, Process):
24 24 '''
25 25 Base class for Schain plotting operations
26 26 '''
27 27
28 28 CODE = 'Figure'
29 29 colormap = 'jro'
30 30 bgcolor = 'white'
31 31 CONFLATE = False
32 32 __MAXNUMX = 80
33 33 __missing = 1E30
34 34
35 35 def __init__(self, **kwargs):
36 36
37 37 Operation.__init__(self, plot=True, **kwargs)
38 38 Process.__init__(self)
39 39 self.kwargs['code'] = self.CODE
40 40 self.mp = False
41 41 self.data = None
42 42 self.isConfig = False
43 43 self.figures = []
44 44 self.axes = []
45 45 self.cb_axes = []
46 46 self.localtime = kwargs.pop('localtime', True)
47 47 self.show = kwargs.get('show', True)
48 48 self.save = kwargs.get('save', False)
49 49 self.colormap = kwargs.get('colormap', self.colormap)
50 50 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
51 51 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
52 52 self.colormaps = kwargs.get('colormaps', None)
53 53 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
54 54 self.showprofile = kwargs.get('showprofile', False)
55 55 self.title = kwargs.get('wintitle', self.CODE.upper())
56 56 self.cb_label = kwargs.get('cb_label', None)
57 57 self.cb_labels = kwargs.get('cb_labels', None)
58 58 self.xaxis = kwargs.get('xaxis', 'frequency')
59 59 self.zmin = kwargs.get('zmin', None)
60 60 self.zmax = kwargs.get('zmax', None)
61 61 self.zlimits = kwargs.get('zlimits', None)
62 62 self.xmin = kwargs.get('xmin', None)
63 63 if self.xmin is not None:
64 64 self.xmin += 5
65 65 self.xmax = kwargs.get('xmax', None)
66 66 self.xrange = kwargs.get('xrange', 24)
67 67 self.ymin = kwargs.get('ymin', None)
68 68 self.ymax = kwargs.get('ymax', None)
69 69 self.xlabel = kwargs.get('xlabel', None)
70 70 self.__MAXNUMY = kwargs.get('decimation', 100)
71 71 self.showSNR = kwargs.get('showSNR', False)
72 72 self.oneFigure = kwargs.get('oneFigure', True)
73 73 self.width = kwargs.get('width', None)
74 74 self.height = kwargs.get('height', None)
75 75 self.colorbar = kwargs.get('colorbar', True)
76 76 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
77 77 self.titles = ['' for __ in range(16)]
78 78
79 79 def __setup(self):
80 80 '''
81 81 Common setup for all figures, here figures and axes are created
82 82 '''
83 83
84 84 self.setup()
85 85
86 86 if self.width is None:
87 87 self.width = 8
88 88
89 89 self.figures = []
90 90 self.axes = []
91 91 self.cb_axes = []
92 92 self.pf_axes = []
93 93 self.cmaps = []
94 94
95 95 size = '15%' if self.ncols==1 else '30%'
96 96 pad = '4%' if self.ncols==1 else '8%'
97 97
98 98 if self.oneFigure:
99 99 if self.height is None:
100 100 self.height = 1.4*self.nrows + 1
101 101 fig = plt.figure(figsize=(self.width, self.height),
102 102 edgecolor='k',
103 103 facecolor='w')
104 104 self.figures.append(fig)
105 105 for n in range(self.nplots):
106 106 ax = fig.add_subplot(self.nrows, self.ncols, n+1)
107 107 ax.tick_params(labelsize=8)
108 108 ax.firsttime = True
109 109 self.axes.append(ax)
110 110 if self.showprofile:
111 111 cax = self.__add_axes(ax, size=size, pad=pad)
112 112 cax.tick_params(labelsize=8)
113 113 self.pf_axes.append(cax)
114 114 else:
115 115 if self.height is None:
116 116 self.height = 3
117 117 for n in range(self.nplots):
118 118 fig = plt.figure(figsize=(self.width, self.height),
119 119 edgecolor='k',
120 120 facecolor='w')
121 121 ax = fig.add_subplot(1, 1, 1)
122 122 ax.tick_params(labelsize=8)
123 123 ax.firsttime = True
124 124 self.figures.append(fig)
125 125 self.axes.append(ax)
126 126 if self.showprofile:
127 127 cax = self.__add_axes(ax, size=size, pad=pad)
128 128 cax.tick_params(labelsize=8)
129 129 self.pf_axes.append(cax)
130 130
131 131 for n in range(self.nrows):
132 132 if self.colormaps is not None:
133 133 cmap = plt.get_cmap(self.colormaps[n])
134 134 else:
135 135 cmap = plt.get_cmap(self.colormap)
136 136 cmap.set_bad(self.bgcolor, 1.)
137 137 self.cmaps.append(cmap)
138 138
139 139 def __add_axes(self, ax, size='30%', pad='8%'):
140 140 '''
141 141 Add new axes to the given figure
142 142 '''
143 143 divider = make_axes_locatable(ax)
144 144 nax = divider.new_horizontal(size=size, pad=pad)
145 145 ax.figure.add_axes(nax)
146 146 return nax
147 147
148 self.setup()
148 149
149 150 def setup(self):
150 151 '''
151 152 This method should be implemented in the child class, the following
152 153 attributes should be set:
153 154
154 155 self.nrows: number of rows
155 156 self.ncols: number of cols
156 157 self.nplots: number of plots (channels or pairs)
157 158 self.ylabel: label for Y axes
158 159 self.titles: list of axes title
159 160
160 161 '''
161 162 raise(NotImplementedError, 'Implement this method in child class')
162 163
163 164 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
164 165 '''
165 166 Create a masked array for missing data
166 167 '''
167 168 if x_buffer.shape[0] < 2:
168 169 return x_buffer, y_buffer, z_buffer
169 170
170 171 deltas = x_buffer[1:] - x_buffer[0:-1]
171 172 x_median = numpy.median(deltas)
172 173
173 174 index = numpy.where(deltas > 5*x_median)
174 175
175 176 if len(index[0]) != 0:
176 177 z_buffer[::, index[0], ::] = self.__missing
177 178 z_buffer = numpy.ma.masked_inside(z_buffer,
178 179 0.99*self.__missing,
179 180 1.01*self.__missing)
180 181
181 182 return x_buffer, y_buffer, z_buffer
182 183
183 184 def decimate(self):
184 185
185 186 # dx = int(len(self.x)/self.__MAXNUMX) + 1
186 187 dy = int(len(self.y)/self.__MAXNUMY) + 1
187 188
188 189 # x = self.x[::dx]
189 190 x = self.x
190 191 y = self.y[::dy]
191 192 z = self.z[::, ::, ::dy]
192 193
193 194 return x, y, z
194 195
195 196 def format(self):
196 197 '''
197 198 Set min and max values, labels, ticks and titles
198 199 '''
199 200
200 201 if self.xmin is None:
201 202 xmin = self.min_time
202 203 else:
203 204 if self.xaxis is 'time':
204 205 dt = datetime.datetime.fromtimestamp(self.min_time)
205 206 xmin = (datetime.datetime.combine(dt.date(),
206 207 datetime.time(int(self.xmin), 0, 0))-d1970).total_seconds()
207 208 else:
208 209 xmin = self.xmin
209 210
210 211 if self.xmax is None:
211 212 xmax = xmin+self.xrange*60*60
212 213 else:
213 214 if self.xaxis is 'time':
214 215 dt = datetime.datetime.fromtimestamp(self.min_time)
215 216 xmax = (datetime.datetime.combine(dt.date(),
216 217 datetime.time(int(self.xmax), 0, 0))-d1970).total_seconds()
217 218 else:
218 219 xmax = self.xmax
219 220
220 221 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
221 222 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
222 223
223 224 ystep = 200 if ymax>= 800 else 100 if ymax>=400 else 50 if ymax>=200 else 20
224 225
225 226 for n, ax in enumerate(self.axes):
226 227 if ax.firsttime:
227 228 ax.set_facecolor(self.bgcolor)
228 229 ax.yaxis.set_major_locator(MultipleLocator(ystep))
229 230 if self.xaxis is 'time':
230 231 ax.xaxis.set_major_formatter(FuncFormatter(func))
231 232 ax.xaxis.set_major_locator(LinearLocator(9))
232 233 if self.xlabel is not None:
233 234 ax.set_xlabel(self.xlabel)
234 235 ax.set_ylabel(self.ylabel)
235 236 ax.firsttime = False
236 237 if self.showprofile:
237 238 self.pf_axes[n].set_ylim(ymin, ymax)
238 239 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
239 240 self.pf_axes[n].set_xlabel('dB')
240 241 self.pf_axes[n].grid(b=True, axis='x')
241 242 [tick.set_visible(False) for tick in self.pf_axes[n].get_yticklabels()]
242 243 if self.colorbar:
243 244 cb = plt.colorbar(ax.plt, ax=ax, pad=0.02)
244 245 cb.ax.tick_params(labelsize=8)
245 246 if self.cb_label:
246 247 cb.set_label(self.cb_label, size=8)
247 248 elif self.cb_labels:
248 249 cb.set_label(self.cb_labels[n], size=8)
249 250
250 251 ax.set_title('{} - {} UTC'.format(
251 252 self.titles[n],
252 253 datetime.datetime.fromtimestamp(self.max_time).strftime('%H:%M:%S')),
253 254 size=8)
254 255 ax.set_xlim(xmin, xmax)
255 256 ax.set_ylim(ymin, ymax)
256 257
257 258
258 259 def __plot(self):
259 260 '''
260 261 '''
261 262 log.success('Plotting', self.name)
262 263
263 264 self.plot()
264 265 self.format()
265 266
266 267 for n, fig in enumerate(self.figures):
267 268 if self.nrows == 0 or self.nplots == 0:
268 269 log.warning('No data', self.name)
269 270 continue
270 271 if self.show:
271 272 fig.show()
272 273
273 274 fig.tight_layout()
274 275 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
275 276 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
276 277 # fig.canvas.draw()
277 278
278 279 if self.save and self.data.ended:
279 280 channels = range(self.nrows)
280 281 if self.oneFigure:
281 282 label = ''
282 283 else:
283 284 label = '_{}'.format(channels[n])
284 285 figname = os.path.join(
285 286 self.save,
286 287 '{}{}_{}.png'.format(
287 288 self.CODE,
288 289 label,
289 290 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')
290 291 )
291 292 )
292 293 print 'Saving figure: {}'.format(figname)
293 294 fig.savefig(figname)
294 295
295 296 def plot(self):
296 297 '''
297 298 '''
298 299 raise(NotImplementedError, 'Implement this method in child class')
299 300
300 301 def run(self):
301 302
302 303 log.success('Starting', self.name)
303 304
304 305 context = zmq.Context()
305 306 receiver = context.socket(zmq.SUB)
306 307 receiver.setsockopt(zmq.SUBSCRIBE, '')
307 308 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
308 309
309 310 if 'server' in self.kwargs['parent']:
310 311 receiver.connect('ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
311 312 else:
312 313 receiver.connect("ipc:///tmp/zmq.plots")
313 314
314 315 while True:
315 316 try:
316 317 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
317 318
318 319 self.min_time = self.data.times[0]
319 320 self.max_time = self.data.times[-1]
320 321
321 322 if self.isConfig is False:
322 323 self.__setup()
323 324 self.isConfig = True
324 325
325 326 self.__plot()
326 327
327 328 except zmq.Again as e:
328 329 log.log('Waiting for data...')
329 330 if self.data:
330 331 plt.pause(self.data.throttle)
331 332 else:
332 333 time.sleep(2)
333 334
334 335 def close(self):
335 336 if self.data:
336 337 self.__plot()
337 338
338
339 339 class PlotSpectraData(PlotData):
340 340 '''
341 341 Plot for Spectra data
342 342 '''
343 343
344 344 CODE = 'spc'
345 345 colormap = 'jro'
346 346
347 347 def setup(self):
348 348 self.nplots = len(self.data.channels)
349 349 self.ncols = int(numpy.sqrt(self.nplots)+ 0.9)
350 350 self.nrows = int((1.0*self.nplots/self.ncols) + 0.9)
351 351 self.width = 3.4*self.ncols
352 352 self.height = 3*self.nrows
353 353 self.cb_label = 'dB'
354 354 if self.showprofile:
355 355 self.width += 0.8*self.ncols
356 356
357 357 self.ylabel = 'Range [Km]'
358 358
359 359 def plot(self):
360 360 if self.xaxis == "frequency":
361 361 x = self.data.xrange[0]
362 362 self.xlabel = "Frequency (kHz)"
363 363 elif self.xaxis == "time":
364 364 x = self.data.xrange[1]
365 365 self.xlabel = "Time (ms)"
366 366 else:
367 367 x = self.data.xrange[2]
368 368 self.xlabel = "Velocity (m/s)"
369 369
370 370 if self.CODE == 'spc_mean':
371 371 x = self.data.xrange[2]
372 372 self.xlabel = "Velocity (m/s)"
373 373
374 374 self.titles = []
375 375
376 376 y = self.data.heights
377 377 self.y = y
378 378 z = self.data['spc']
379 379
380 380 for n, ax in enumerate(self.axes):
381 381 noise = self.data['noise'][n][-1]
382 382 if self.CODE == 'spc_mean':
383 383 mean = self.data['mean'][n][-1]
384 384 if ax.firsttime:
385 385 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
386 386 self.xmin = self.xmin if self.xmin else -self.xmax
387 387 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
388 388 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
389 389 ax.plt = ax.pcolormesh(x, y, z[n].T,
390 390 vmin=self.zmin,
391 391 vmax=self.zmax,
392 392 cmap=plt.get_cmap(self.colormap)
393 393 )
394 394
395 395 if self.showprofile:
396 396 ax.plt_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], y)[0]
397 397 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
398 398 color="k", linestyle="dashed", lw=1)[0]
399 399 if self.CODE == 'spc_mean':
400 400 ax.plt_mean = ax.plot(mean, y, color='k')[0]
401 401 else:
402 402 ax.plt.set_array(z[n].T.ravel())
403 403 if self.showprofile:
404 404 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
405 405 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
406 406 if self.CODE == 'spc_mean':
407 407 ax.plt_mean.set_data(mean, y)
408 408
409 409 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
410 410 self.saveTime = self.max_time
411 411
412 412
413 413 class PlotCrossSpectraData(PlotData):
414 414
415 415 CODE = 'cspc'
416 416 zmin_coh = None
417 417 zmax_coh = None
418 418 zmin_phase = None
419 419 zmax_phase = None
420 420
421 421 def setup(self):
422 422
423 423 self.ncols = 4
424 424 self.nrows = len(self.data.pairs)
425 425 self.nplots = self.nrows*4
426 426 self.width = 3.4*self.ncols
427 427 self.height = 3*self.nrows
428 428 self.ylabel = 'Range [Km]'
429 429 self.showprofile = False
430 430
431 431 def plot(self):
432 432
433 433 if self.xaxis == "frequency":
434 434 x = self.data.xrange[0]
435 435 self.xlabel = "Frequency (kHz)"
436 436 elif self.xaxis == "time":
437 437 x = self.data.xrange[1]
438 438 self.xlabel = "Time (ms)"
439 439 else:
440 440 x = self.data.xrange[2]
441 441 self.xlabel = "Velocity (m/s)"
442 442
443 443 self.titles = []
444 444
445 445 y = self.data.heights
446 446 self.y = y
447 447 spc = self.data['spc']
448 448 cspc = self.data['cspc']
449 449
450 450 for n in range(self.nrows):
451 451 noise = self.data['noise'][n][-1]
452 452 pair = self.data.pairs[n]
453 453 ax = self.axes[4*n]
454 454 ax3 = self.axes[4*n+3]
455 455 if ax.firsttime:
456 456 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
457 457 self.xmin = self.xmin if self.xmin else -self.xmax
458 458 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
459 459 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
460 460 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
461 461 vmin=self.zmin,
462 462 vmax=self.zmax,
463 463 cmap=plt.get_cmap(self.colormap)
464 464 )
465 465 else:
466 466 ax.plt.set_array(spc[pair[0]].T.ravel())
467 467 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
468 468
469 469 ax = self.axes[4*n+1]
470 470 if ax.firsttime:
471 471 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
472 472 vmin=self.zmin,
473 473 vmax=self.zmax,
474 474 cmap=plt.get_cmap(self.colormap)
475 475 )
476 476 else:
477 477 ax.plt.set_array(spc[pair[1]].T.ravel())
478 478 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
479 479
480 480 out = cspc[n]/numpy.sqrt(spc[pair[0]]*spc[pair[1]])
481 481 coh = numpy.abs(out)
482 482 phase = numpy.arctan2(out.imag, out.real)*180/numpy.pi
483 483
484 484 ax = self.axes[4*n+2]
485 485 if ax.firsttime:
486 486 ax.plt = ax.pcolormesh(x, y, coh.T,
487 487 vmin=0,
488 488 vmax=1,
489 489 cmap=plt.get_cmap(self.colormap_coh)
490 490 )
491 491 else:
492 492 ax.plt.set_array(coh.T.ravel())
493 493 self.titles.append('Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
494 494
495 495 ax = self.axes[4*n+3]
496 496 if ax.firsttime:
497 497 ax.plt = ax.pcolormesh(x, y, phase.T,
498 498 vmin=-180,
499 499 vmax=180,
500 500 cmap=plt.get_cmap(self.colormap_phase)
501 501 )
502 502 else:
503 503 ax.plt.set_array(phase.T.ravel())
504 504 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
505 505
506 506 self.saveTime = self.max_time
507 507
508 508
509 509 class PlotSpectraMeanData(PlotSpectraData):
510 510 '''
511 511 Plot for Spectra and Mean
512 512 '''
513 513 CODE = 'spc_mean'
514 514 colormap = 'jro'
515 515
516 516
517 517 class PlotRTIData(PlotData):
518 518 '''
519 519 Plot for RTI data
520 520 '''
521 521
522 522 CODE = 'rti'
523 523 colormap = 'jro'
524 524
525 525 def setup(self):
526 526 self.xaxis = 'time'
527 527 self.ncols = 1
528 528 self.nrows = len(self.data.channels)
529 529 self.nplots = len(self.data.channels)
530 530 self.ylabel = 'Range [Km]'
531 531 self.cb_label = 'dB'
532 532 self.titles = ['{} Channel {}'.format(self.CODE.upper(), x) for x in range(self.nrows)]
533 533
534 534 def plot(self):
535 535 self.x = self.data.times
536 536 self.y = self.data.heights
537 537 self.z = self.data[self.CODE]
538 538 self.z = numpy.ma.masked_invalid(self.z)
539 539
540 540 for n, ax in enumerate(self.axes):
541 541 x, y, z = self.fill_gaps(*self.decimate())
542 542 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
543 543 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
544 544 if ax.firsttime:
545 545 ax.plt = ax.pcolormesh(x, y, z[n].T,
546 546 vmin=self.zmin,
547 547 vmax=self.zmax,
548 548 cmap=plt.get_cmap(self.colormap)
549 549 )
550 550 if self.showprofile:
551 551 ax.plot_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], self.y)[0]
552 552 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
553 553 color="k", linestyle="dashed", lw=1)[0]
554 554 else:
555 555 ax.collections.remove(ax.collections[0])
556 556 ax.plt = ax.pcolormesh(x, y, z[n].T,
557 557 vmin=self.zmin,
558 558 vmax=self.zmax,
559 559 cmap=plt.get_cmap(self.colormap)
560 560 )
561 561 if self.showprofile:
562 562 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
563 563 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y)
564 564
565 565 self.saveTime = self.min_time
566 566
567 567
568 568 class PlotCOHData(PlotRTIData):
569 569 '''
570 570 Plot for Coherence data
571 571 '''
572 572
573 573 CODE = 'coh'
574 574
575 575 def setup(self):
576 576 self.xaxis = 'time'
577 577 self.ncols = 1
578 578 self.nrows = len(self.data.pairs)
579 579 self.nplots = len(self.data.pairs)
580 580 self.ylabel = 'Range [Km]'
581 581 if self.CODE == 'coh':
582 582 self.cb_label = ''
583 583 self.titles = ['Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
584 584 else:
585 585 self.cb_label = 'Degrees'
586 586 self.titles = ['Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
587 587
588 588
589 589 class PlotPHASEData(PlotCOHData):
590 590 '''
591 591 Plot for Phase map data
592 592 '''
593 593
594 594 CODE = 'phase'
595 595 colormap = 'seismic'
596 596
597 597
598 598 class PlotNoiseData(PlotData):
599 599 '''
600 600 Plot for noise
601 601 '''
602 602
603 603 CODE = 'noise'
604 604
605 605 def setup(self):
606 606 self.xaxis = 'time'
607 607 self.ncols = 1
608 608 self.nrows = 1
609 609 self.nplots = 1
610 610 self.ylabel = 'Intensity [dB]'
611 611 self.titles = ['Noise']
612 612 self.colorbar = False
613 613
614 614 def plot(self):
615 615
616 616 x = self.data.times
617 617 xmin = self.min_time
618 618 xmax = xmin+self.xrange*60*60
619 619 Y = self.data[self.CODE]
620 620
621 621 if self.axes[0].firsttime:
622 622 for ch in self.data.channels:
623 623 y = Y[ch]
624 624 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
625 625 plt.legend()
626 626 else:
627 627 for ch in self.data.channels:
628 628 y = Y[ch]
629 629 self.axes[0].lines[ch].set_data(x, y)
630 630
631 631 self.ymin = numpy.nanmin(Y) - 5
632 632 self.ymax = numpy.nanmax(Y) + 5
633 633 self.saveTime = self.min_time
634 634
635 635
636 636 class PlotSNRData(PlotRTIData):
637 637 '''
638 638 Plot for SNR Data
639 639 '''
640 640
641 641 CODE = 'snr'
642 642 colormap = 'jet'
643 643
644 644
645 645 class PlotDOPData(PlotRTIData):
646 646 '''
647 647 Plot for DOPPLER Data
648 648 '''
649 649
650 650 CODE = 'dop'
651 651 colormap = 'jet'
652 652
653 653
654 654 class PlotSkyMapData(PlotData):
655 655 '''
656 656 Plot for meteors detection data
657 657 '''
658 658
659 659 CODE = 'met'
660 660
661 661 def setup(self):
662 662
663 663 self.ncols = 1
664 664 self.nrows = 1
665 665 self.width = 7.2
666 666 self.height = 7.2
667 667
668 668 self.xlabel = 'Zonal Zenith Angle (deg)'
669 669 self.ylabel = 'Meridional Zenith Angle (deg)'
670 670
671 671 if self.figure is None:
672 672 self.figure = plt.figure(figsize=(self.width, self.height),
673 673 edgecolor='k',
674 674 facecolor='w')
675 675 else:
676 676 self.figure.clf()
677 677
678 678 self.ax = plt.subplot2grid((self.nrows, self.ncols), (0, 0), 1, 1, polar=True)
679 679 self.ax.firsttime = True
680 680
681 681
682 682 def plot(self):
683 683
684 684 arrayParameters = numpy.concatenate([self.data['param'][t] for t in self.data.times])
685 685 error = arrayParameters[:,-1]
686 686 indValid = numpy.where(error == 0)[0]
687 687 finalMeteor = arrayParameters[indValid,:]
688 688 finalAzimuth = finalMeteor[:,3]
689 689 finalZenith = finalMeteor[:,4]
690 690
691 691 x = finalAzimuth*numpy.pi/180
692 692 y = finalZenith
693 693
694 694 if self.ax.firsttime:
695 695 self.ax.plot = self.ax.plot(x, y, 'bo', markersize=5)[0]
696 696 self.ax.set_ylim(0,90)
697 697 self.ax.set_yticks(numpy.arange(0,90,20))
698 698 self.ax.set_xlabel(self.xlabel)
699 699 self.ax.set_ylabel(self.ylabel)
700 700 self.ax.yaxis.labelpad = 40
701 701 self.ax.firsttime = False
702 702 else:
703 703 self.ax.plot.set_data(x, y)
704 704
705 705
706 706 dt1 = datetime.datetime.fromtimestamp(self.min_time).strftime('%y/%m/%d %H:%M:%S')
707 707 dt2 = datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')
708 708 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
709 709 dt2,
710 710 len(x))
711 711 self.ax.set_title(title, size=8)
712 712
713 713 self.saveTime = self.max_time
714 714
715 715 class PlotParamData(PlotRTIData):
716 716 '''
717 717 Plot for data_param object
718 718 '''
719 719
720 720 CODE = 'param'
721 721 colormap = 'seismic'
722 722
723 723 def setup(self):
724 724 self.xaxis = 'time'
725 725 self.ncols = 1
726 726 self.nrows = self.data.shape(self.CODE)[0]
727 727 self.nplots = self.nrows
728 728 if self.showSNR:
729 729 self.nrows += 1
730 self.nplots += 1
730 731
731 732 self.ylabel = 'Height [Km]'
732 733 self.titles = self.data.parameters \
733 734 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
734 735 if self.showSNR:
735 736 self.titles.append('SNR')
736 737
737 738 def plot(self):
738 739 self.data.normalize_heights()
739 740 self.x = self.data.times
740 741 self.y = self.data.heights
741 742 if self.showSNR:
742 743 self.z = numpy.concatenate(
743 744 (self.data[self.CODE], self.data['snr'])
744 745 )
745 746 else:
746 747 self.z = self.data[self.CODE]
747 748
748 749 self.z = numpy.ma.masked_invalid(self.z)
749 750
750 751 for n, ax in enumerate(self.axes):
751 752
752 753 x, y, z = self.fill_gaps(*self.decimate())
753 754
754 755 if ax.firsttime:
755 756 if self.zlimits is not None:
756 757 self.zmin, self.zmax = self.zlimits[n]
757 758 self.zmax = self.zmax if self.zmax is not None else numpy.nanmax(abs(self.z[:-1, :]))
758 759 self.zmin = self.zmin if self.zmin is not None else -self.zmax
759 760 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
760 761 vmin=self.zmin,
761 762 vmax=self.zmax,
762 763 cmap=self.cmaps[n]
763 764 )
764 765 else:
765 766 if self.zlimits is not None:
766 767 self.zmin, self.zmax = self.zlimits[n]
767 768 ax.collections.remove(ax.collections[0])
768 769 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
769 770 vmin=self.zmin,
770 771 vmax=self.zmax,
771 772 cmap=self.cmaps[n]
772 773 )
773 774
774 775 self.saveTime = self.min_time
775 776
776 777 class PlotOuputData(PlotParamData):
777 778 '''
778 779 Plot data_output object
779 780 '''
780 781
781 782 CODE = 'output'
782 colormap = 'seismic' No newline at end of file
783 colormap = 'seismic'
@@ -1,2154 +1,2151
1 1 import os
2 2 import datetime
3 3 import numpy
4 4 import inspect
5 5 from figure import Figure, isRealtime, isTimeInHourRange
6 6 from plotting_codes import *
7 7
8 8
9 9 class FitGauPlot(Figure):
10 10
11 11 isConfig = None
12 12 __nsubplots = None
13 13
14 14 WIDTHPROF = None
15 15 HEIGHTPROF = None
16 16 PREFIX = 'fitgau'
17 17
18 18 def __init__(self, **kwargs):
19 19 Figure.__init__(self, **kwargs)
20 20 self.isConfig = False
21 21 self.__nsubplots = 1
22 22
23 23 self.WIDTH = 250
24 24 self.HEIGHT = 250
25 25 self.WIDTHPROF = 120
26 26 self.HEIGHTPROF = 0
27 27 self.counter_imagwr = 0
28 28
29 29 self.PLOT_CODE = SPEC_CODE
30 30
31 31 self.FTP_WEI = None
32 32 self.EXP_CODE = None
33 33 self.SUB_EXP_CODE = None
34 34 self.PLOT_POS = None
35 35
36 36 self.__xfilter_ena = False
37 37 self.__yfilter_ena = False
38 38
39 39 def getSubplots(self):
40 40
41 41 ncol = int(numpy.sqrt(self.nplots)+0.9)
42 42 nrow = int(self.nplots*1./ncol + 0.9)
43 43
44 44 return nrow, ncol
45 45
46 46 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
47 47
48 48 self.__showprofile = showprofile
49 49 self.nplots = nplots
50 50
51 51 ncolspan = 1
52 52 colspan = 1
53 53 if showprofile:
54 54 ncolspan = 3
55 55 colspan = 2
56 56 self.__nsubplots = 2
57 57
58 58 self.createFigure(id = id,
59 59 wintitle = wintitle,
60 60 widthplot = self.WIDTH + self.WIDTHPROF,
61 61 heightplot = self.HEIGHT + self.HEIGHTPROF,
62 62 show=show)
63 63
64 64 nrow, ncol = self.getSubplots()
65 65
66 66 counter = 0
67 67 for y in range(nrow):
68 68 for x in range(ncol):
69 69
70 70 if counter >= self.nplots:
71 71 break
72 72
73 73 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
74 74
75 75 if showprofile:
76 76 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
77 77
78 78 counter += 1
79 79
80 80 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
81 81 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
82 82 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
83 83 server=None, folder=None, username=None, password=None,
84 84 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
85 85 xaxis="frequency", colormap='jet', normFactor=None , GauSelector = 1):
86 86
87 87 """
88 88
89 89 Input:
90 90 dataOut :
91 91 id :
92 92 wintitle :
93 93 channelList :
94 94 showProfile :
95 95 xmin : None,
96 96 xmax : None,
97 97 ymin : None,
98 98 ymax : None,
99 99 zmin : None,
100 100 zmax : None
101 101 """
102 102 if realtime:
103 103 if not(isRealtime(utcdatatime = dataOut.utctime)):
104 104 print 'Skipping this plot function'
105 105 return
106 106
107 107 if channelList == None:
108 108 channelIndexList = dataOut.channelIndexList
109 109 else:
110 110 channelIndexList = []
111 111 for channel in channelList:
112 112 if channel not in dataOut.channelList:
113 113 raise ValueError, "Channel %d is not in dataOut.channelList" %channel
114 114 channelIndexList.append(dataOut.channelList.index(channel))
115 115
116 116 # if normFactor is None:
117 117 # factor = dataOut.normFactor
118 118 # else:
119 119 # factor = normFactor
120 120 if xaxis == "frequency":
121 121 x = dataOut.spc_range[0]
122 122 xlabel = "Frequency (kHz)"
123 123
124 124 elif xaxis == "time":
125 125 x = dataOut.spc_range[1]
126 126 xlabel = "Time (ms)"
127 127
128 128 else:
129 129 x = dataOut.spc_range[2]
130 130 xlabel = "Velocity (m/s)"
131 131
132 132 ylabel = "Range (Km)"
133 133
134 134 y = dataOut.getHeiRange()
135 135
136 136 z = dataOut.GauSPC[:,GauSelector,:,:] #GauSelector] #dataOut.data_spc/factor
137 137 print 'GausSPC', z[0,32,10:40]
138 138 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
139 139 zdB = 10*numpy.log10(z)
140 140
141 141 avg = numpy.average(z, axis=1)
142 142 avgdB = 10*numpy.log10(avg)
143 143
144 144 noise = dataOut.spc_noise
145 145 noisedB = 10*numpy.log10(noise)
146 146
147 147 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
148 148 title = wintitle + " Spectra"
149 149 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
150 150 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
151 151
152 152 if not self.isConfig:
153 153
154 154 nplots = len(channelIndexList)
155 155
156 156 self.setup(id=id,
157 157 nplots=nplots,
158 158 wintitle=wintitle,
159 159 showprofile=showprofile,
160 160 show=show)
161 161
162 162 if xmin == None: xmin = numpy.nanmin(x)
163 163 if xmax == None: xmax = numpy.nanmax(x)
164 164 if ymin == None: ymin = numpy.nanmin(y)
165 165 if ymax == None: ymax = numpy.nanmax(y)
166 166 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
167 167 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
168 168
169 169 self.FTP_WEI = ftp_wei
170 170 self.EXP_CODE = exp_code
171 171 self.SUB_EXP_CODE = sub_exp_code
172 172 self.PLOT_POS = plot_pos
173 173
174 174 self.isConfig = True
175 175
176 176 self.setWinTitle(title)
177 177
178 178 for i in range(self.nplots):
179 179 index = channelIndexList[i]
180 180 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
181 181 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
182 182 if len(dataOut.beam.codeList) != 0:
183 183 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
184 184
185 185 axes = self.axesList[i*self.__nsubplots]
186 186 axes.pcolor(x, y, zdB[index,:,:],
187 187 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
188 188 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
189 189 ticksize=9, cblabel='')
190 190
191 191 if self.__showprofile:
192 192 axes = self.axesList[i*self.__nsubplots +1]
193 193 axes.pline(avgdB[index,:], y,
194 194 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
195 195 xlabel='dB', ylabel='', title='',
196 196 ytick_visible=False,
197 197 grid='x')
198 198
199 199 noiseline = numpy.repeat(noisedB[index], len(y))
200 200 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
201 201
202 202 self.draw()
203 203
204 204 if figfile == None:
205 205 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
206 206 name = str_datetime
207 207 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
208 208 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
209 209 figfile = self.getFilename(name)
210 210
211 211 self.save(figpath=figpath,
212 212 figfile=figfile,
213 213 save=save,
214 214 ftp=ftp,
215 215 wr_period=wr_period,
216 216 thisDatetime=thisDatetime)
217 217
218 218
219 219
220 220 class MomentsPlot(Figure):
221 221
222 222 isConfig = None
223 223 __nsubplots = None
224 224
225 225 WIDTHPROF = None
226 226 HEIGHTPROF = None
227 227 PREFIX = 'prm'
228 228 def __init__(self, **kwargs):
229 229 Figure.__init__(self, **kwargs)
230 230 self.isConfig = False
231 231 self.__nsubplots = 1
232 232
233 233 self.WIDTH = 280
234 234 self.HEIGHT = 250
235 235 self.WIDTHPROF = 120
236 236 self.HEIGHTPROF = 0
237 237 self.counter_imagwr = 0
238 238
239 239 self.PLOT_CODE = MOMENTS_CODE
240 240
241 241 self.FTP_WEI = None
242 242 self.EXP_CODE = None
243 243 self.SUB_EXP_CODE = None
244 244 self.PLOT_POS = None
245 245
246 246 def getSubplots(self):
247 247
248 248 ncol = int(numpy.sqrt(self.nplots)+0.9)
249 249 nrow = int(self.nplots*1./ncol + 0.9)
250 250
251 251 return nrow, ncol
252 252
253 253 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
254 254
255 255 self.__showprofile = showprofile
256 256 self.nplots = nplots
257 257
258 258 ncolspan = 1
259 259 colspan = 1
260 260 if showprofile:
261 261 ncolspan = 3
262 262 colspan = 2
263 263 self.__nsubplots = 2
264 264
265 265 self.createFigure(id = id,
266 266 wintitle = wintitle,
267 267 widthplot = self.WIDTH + self.WIDTHPROF,
268 268 heightplot = self.HEIGHT + self.HEIGHTPROF,
269 269 show=show)
270 270
271 271 nrow, ncol = self.getSubplots()
272 272
273 273 counter = 0
274 274 for y in range(nrow):
275 275 for x in range(ncol):
276 276
277 277 if counter >= self.nplots:
278 278 break
279 279
280 280 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
281 281
282 282 if showprofile:
283 283 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
284 284
285 285 counter += 1
286 286
287 287 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
288 288 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
289 289 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
290 290 server=None, folder=None, username=None, password=None,
291 291 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
292 292
293 293 """
294 294
295 295 Input:
296 296 dataOut :
297 297 id :
298 298 wintitle :
299 299 channelList :
300 300 showProfile :
301 301 xmin : None,
302 302 xmax : None,
303 303 ymin : None,
304 304 ymax : None,
305 305 zmin : None,
306 306 zmax : None
307 307 """
308 308
309 309 if dataOut.flagNoData:
310 310 return None
311 311
312 312 if realtime:
313 313 if not(isRealtime(utcdatatime = dataOut.utctime)):
314 314 print 'Skipping this plot function'
315 315 return
316 316
317 317 if channelList == None:
318 318 channelIndexList = dataOut.channelIndexList
319 319 else:
320 320 channelIndexList = []
321 321 for channel in channelList:
322 322 if channel not in dataOut.channelList:
323 323 raise ValueError, "Channel %d is not in dataOut.channelList"
324 324 channelIndexList.append(dataOut.channelList.index(channel))
325 325
326 326 factor = dataOut.normFactor
327 327 x = dataOut.abscissaList
328 328 y = dataOut.heightList
329 329
330 330 z = dataOut.data_pre[channelIndexList,:,:]/factor
331 331 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
332 332 avg = numpy.average(z, axis=1)
333 333 noise = dataOut.noise/factor
334 334
335 335 zdB = 10*numpy.log10(z)
336 336 avgdB = 10*numpy.log10(avg)
337 337 noisedB = 10*numpy.log10(noise)
338 338
339 339 #thisDatetime = dataOut.datatime
340 340 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
341 341 title = wintitle + " Parameters"
342 342 xlabel = "Velocity (m/s)"
343 343 ylabel = "Range (Km)"
344 344
345 345 update_figfile = False
346 346
347 347 if not self.isConfig:
348 348
349 349 nplots = len(channelIndexList)
350 350
351 351 self.setup(id=id,
352 352 nplots=nplots,
353 353 wintitle=wintitle,
354 354 showprofile=showprofile,
355 355 show=show)
356 356
357 357 if xmin == None: xmin = numpy.nanmin(x)
358 358 if xmax == None: xmax = numpy.nanmax(x)
359 359 if ymin == None: ymin = numpy.nanmin(y)
360 360 if ymax == None: ymax = numpy.nanmax(y)
361 361 if zmin == None: zmin = numpy.nanmin(avgdB)*0.9
362 362 if zmax == None: zmax = numpy.nanmax(avgdB)*0.9
363 363
364 364 self.FTP_WEI = ftp_wei
365 365 self.EXP_CODE = exp_code
366 366 self.SUB_EXP_CODE = sub_exp_code
367 367 self.PLOT_POS = plot_pos
368 368
369 369 self.isConfig = True
370 370 update_figfile = True
371 371
372 372 self.setWinTitle(title)
373 373
374 374 for i in range(self.nplots):
375 375 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
376 376 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[i], noisedB[i], str_datetime)
377 377 axes = self.axesList[i*self.__nsubplots]
378 378 axes.pcolor(x, y, zdB[i,:,:],
379 379 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
380 380 xlabel=xlabel, ylabel=ylabel, title=title,
381 381 ticksize=9, cblabel='')
382 382 #Mean Line
383 383 mean = dataOut.data_param[i, 1, :]
384 384 axes.addpline(mean, y, idline=0, color="black", linestyle="solid", lw=1)
385 385
386 386 if self.__showprofile:
387 387 axes = self.axesList[i*self.__nsubplots +1]
388 388 axes.pline(avgdB[i], y,
389 389 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
390 390 xlabel='dB', ylabel='', title='',
391 391 ytick_visible=False,
392 392 grid='x')
393 393
394 394 noiseline = numpy.repeat(noisedB[i], len(y))
395 395 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
396 396
397 397 self.draw()
398 398
399 399 self.save(figpath=figpath,
400 400 figfile=figfile,
401 401 save=save,
402 402 ftp=ftp,
403 403 wr_period=wr_period,
404 404 thisDatetime=thisDatetime)
405 405
406 406
407 407
408 408 class SkyMapPlot(Figure):
409 409
410 410 __isConfig = None
411 411 __nsubplots = None
412 412
413 413 WIDTHPROF = None
414 414 HEIGHTPROF = None
415 415 PREFIX = 'mmap'
416 416
417 417 def __init__(self, **kwargs):
418 418 Figure.__init__(self, **kwargs)
419 419 self.isConfig = False
420 420 self.__nsubplots = 1
421 421
422 422 # self.WIDTH = 280
423 423 # self.HEIGHT = 250
424 424 self.WIDTH = 600
425 425 self.HEIGHT = 600
426 426 self.WIDTHPROF = 120
427 427 self.HEIGHTPROF = 0
428 428 self.counter_imagwr = 0
429 429
430 430 self.PLOT_CODE = MSKYMAP_CODE
431 431
432 432 self.FTP_WEI = None
433 433 self.EXP_CODE = None
434 434 self.SUB_EXP_CODE = None
435 435 self.PLOT_POS = None
436 436
437 437 def getSubplots(self):
438 438
439 439 ncol = int(numpy.sqrt(self.nplots)+0.9)
440 440 nrow = int(self.nplots*1./ncol + 0.9)
441 441
442 442 return nrow, ncol
443 443
444 444 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
445 445
446 446 self.__showprofile = showprofile
447 447 self.nplots = nplots
448 448
449 449 ncolspan = 1
450 450 colspan = 1
451 451
452 452 self.createFigure(id = id,
453 453 wintitle = wintitle,
454 454 widthplot = self.WIDTH, #+ self.WIDTHPROF,
455 455 heightplot = self.HEIGHT,# + self.HEIGHTPROF,
456 456 show=show)
457 457
458 458 nrow, ncol = 1,1
459 459 counter = 0
460 460 x = 0
461 461 y = 0
462 462 self.addAxes(1, 1, 0, 0, 1, 1, True)
463 463
464 464 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
465 465 tmin=0, tmax=24, timerange=None,
466 466 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
467 467 server=None, folder=None, username=None, password=None,
468 468 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
469 469
470 470 """
471 471
472 472 Input:
473 473 dataOut :
474 474 id :
475 475 wintitle :
476 476 channelList :
477 477 showProfile :
478 478 xmin : None,
479 479 xmax : None,
480 480 ymin : None,
481 481 ymax : None,
482 482 zmin : None,
483 483 zmax : None
484 484 """
485 485
486 486 arrayParameters = dataOut.data_param
487 487 error = arrayParameters[:,-1]
488 488 indValid = numpy.where(error == 0)[0]
489 489 finalMeteor = arrayParameters[indValid,:]
490 490 finalAzimuth = finalMeteor[:,3]
491 491 finalZenith = finalMeteor[:,4]
492 492
493 493 x = finalAzimuth*numpy.pi/180
494 494 y = finalZenith
495 495 x1 = [dataOut.ltctime, dataOut.ltctime]
496 496
497 497 #thisDatetime = dataOut.datatime
498 498 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
499 499 title = wintitle + " Parameters"
500 500 xlabel = "Zonal Zenith Angle (deg) "
501 501 ylabel = "Meridional Zenith Angle (deg)"
502 502 update_figfile = False
503 503
504 504 if not self.isConfig:
505 505
506 506 nplots = 1
507 507
508 508 self.setup(id=id,
509 509 nplots=nplots,
510 510 wintitle=wintitle,
511 511 showprofile=showprofile,
512 512 show=show)
513 513
514 514 if self.xmin is None and self.xmax is None:
515 515 self.xmin, self.xmax = self.getTimeLim(x1, tmin, tmax, timerange)
516 516
517 517 if timerange != None:
518 518 self.timerange = timerange
519 519 else:
520 520 self.timerange = self.xmax - self.xmin
521 521
522 522 self.FTP_WEI = ftp_wei
523 523 self.EXP_CODE = exp_code
524 524 self.SUB_EXP_CODE = sub_exp_code
525 525 self.PLOT_POS = plot_pos
526 526 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
527 527 self.firstdate = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
528 528 self.isConfig = True
529 529 update_figfile = True
530 530
531 531 self.setWinTitle(title)
532 532
533 533 i = 0
534 534 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
535 535
536 536 axes = self.axesList[i*self.__nsubplots]
537 537 nevents = axes.x_buffer.shape[0] + x.shape[0]
538 538 title = "Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n" %(self.firstdate,str_datetime,nevents)
539 539 axes.polar(x, y,
540 540 title=title, xlabel=xlabel, ylabel=ylabel,
541 541 ticksize=9, cblabel='')
542 542
543 543 self.draw()
544 544
545 545 self.save(figpath=figpath,
546 546 figfile=figfile,
547 547 save=save,
548 548 ftp=ftp,
549 549 wr_period=wr_period,
550 550 thisDatetime=thisDatetime,
551 551 update_figfile=update_figfile)
552 552
553 553 if dataOut.ltctime >= self.xmax:
554 554 self.isConfigmagwr = wr_period
555 555 self.isConfig = False
556 556 update_figfile = True
557 557 axes.__firsttime = True
558 558 self.xmin += self.timerange
559 559 self.xmax += self.timerange
560 560
561 561
562 562
563 563
564 564 class WindProfilerPlot(Figure):
565 565
566 566 __isConfig = None
567 567 __nsubplots = None
568 568
569 569 WIDTHPROF = None
570 570 HEIGHTPROF = None
571 571 PREFIX = 'wind'
572 572
573 573 def __init__(self, **kwargs):
574 574 Figure.__init__(self, **kwargs)
575 575 self.timerange = None
576 576 self.isConfig = False
577 577 self.__nsubplots = 1
578 578
579 579 self.WIDTH = 800
580 580 self.HEIGHT = 300
581 581 self.WIDTHPROF = 120
582 582 self.HEIGHTPROF = 0
583 583 self.counter_imagwr = 0
584 584
585 585 self.PLOT_CODE = WIND_CODE
586 586
587 587 self.FTP_WEI = None
588 588 self.EXP_CODE = None
589 589 self.SUB_EXP_CODE = None
590 590 self.PLOT_POS = None
591 591 self.tmin = None
592 592 self.tmax = None
593 593
594 594 self.xmin = None
595 595 self.xmax = None
596 596
597 597 self.figfile = None
598 598
599 599 def getSubplots(self):
600 600
601 601 ncol = 1
602 602 nrow = self.nplots
603 603
604 604 return nrow, ncol
605 605
606 606 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
607 607
608 608 self.__showprofile = showprofile
609 609 self.nplots = nplots
610 610
611 611 ncolspan = 1
612 612 colspan = 1
613 613
614 614 self.createFigure(id = id,
615 615 wintitle = wintitle,
616 616 widthplot = self.WIDTH + self.WIDTHPROF,
617 617 heightplot = self.HEIGHT + self.HEIGHTPROF,
618 618 show=show)
619 619
620 620 nrow, ncol = self.getSubplots()
621 621
622 622 counter = 0
623 623 for y in range(nrow):
624 624 if counter >= self.nplots:
625 625 break
626 626
627 627 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
628 628 counter += 1
629 629
630 630 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='False',
631 631 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
632 632 zmax_ver = None, zmin_ver = None, SNRmin = None, SNRmax = None,
633 633 timerange=None, SNRthresh = None,
634 634 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
635 635 server=None, folder=None, username=None, password=None,
636 636 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
637 637 """
638 638
639 639 Input:
640 640 dataOut :
641 641 id :
642 642 wintitle :
643 643 channelList :
644 644 showProfile :
645 645 xmin : None,
646 646 xmax : None,
647 647 ymin : None,
648 648 ymax : None,
649 649 zmin : None,
650 650 zmax : None
651 651 """
652 652
653 653 # if timerange is not None:
654 654 # self.timerange = timerange
655 655 #
656 656 # tmin = None
657 657 # tmax = None
658 658
659 659 x = dataOut.getTimeRange1(dataOut.paramInterval)
660 660 y = dataOut.heightList
661 661 z = dataOut.data_output.copy()
662 662 nplots = z.shape[0] #Number of wind dimensions estimated
663 663 nplotsw = nplots
664 664
665 665
666 666 #If there is a SNR function defined
667 667 if dataOut.data_SNR is not None:
668 668 nplots += 1
669 669 SNR = dataOut.data_SNR
670 670 SNRavg = numpy.average(SNR, axis=0)
671 671
672 672 SNRdB = 10*numpy.log10(SNR)
673 673 SNRavgdB = 10*numpy.log10(SNRavg)
674 674
675 675 if SNRthresh == None: SNRthresh = -5.0
676 676 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
677 677
678 678 for i in range(nplotsw):
679 679 z[i,ind] = numpy.nan
680 680
681 681 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
682 682 #thisDatetime = datetime.datetime.now()
683 683 title = wintitle + "Wind"
684 684 xlabel = ""
685 685 ylabel = "Height (km)"
686 686 update_figfile = False
687 687
688 688 if not self.isConfig:
689 689
690 690 self.setup(id=id,
691 691 nplots=nplots,
692 692 wintitle=wintitle,
693 693 showprofile=showprofile,
694 694 show=show)
695 695
696 696 if timerange is not None:
697 697 self.timerange = timerange
698 698
699 699 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
700 700
701 701 if ymin == None: ymin = numpy.nanmin(y)
702 702 if ymax == None: ymax = numpy.nanmax(y)
703 703
704 704 if zmax == None: zmax = numpy.nanmax(abs(z[range(2),:]))
705 705 #if numpy.isnan(zmax): zmax = 50
706 706 if zmin == None: zmin = -zmax
707 707
708 708 if nplotsw == 3:
709 709 if zmax_ver == None: zmax_ver = numpy.nanmax(abs(z[2,:]))
710 710 if zmin_ver == None: zmin_ver = -zmax_ver
711 711
712 712 if dataOut.data_SNR is not None:
713 713 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
714 714 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
715 715
716 716
717 717 self.FTP_WEI = ftp_wei
718 718 self.EXP_CODE = exp_code
719 719 self.SUB_EXP_CODE = sub_exp_code
720 720 self.PLOT_POS = plot_pos
721 721
722 722 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
723 723 self.isConfig = True
724 724 self.figfile = figfile
725 725 update_figfile = True
726 726
727 727 self.setWinTitle(title)
728 728
729 729 if ((self.xmax - x[1]) < (x[1]-x[0])):
730 730 x[1] = self.xmax
731 731
732 732 strWind = ['Zonal', 'Meridional', 'Vertical']
733 733 strCb = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
734 734 zmaxVector = [zmax, zmax, zmax_ver]
735 735 zminVector = [zmin, zmin, zmin_ver]
736 736 windFactor = [1,1,100]
737 737
738 738 for i in range(nplotsw):
739 739
740 740 title = "%s Wind: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
741 741 axes = self.axesList[i*self.__nsubplots]
742 742
743 743 z1 = z[i,:].reshape((1,-1))*windFactor[i]
744 744 #z1=numpy.ma.masked_where(z1==0.,z1)
745 745
746 746 axes.pcolorbuffer(x, y, z1,
747 747 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
748 748 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
749 749 ticksize=9, cblabel=strCb[i], cbsize="1%", colormap="seismic" )
750 750
751 751 if dataOut.data_SNR is not None:
752 752 i += 1
753 753 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
754 754 axes = self.axesList[i*self.__nsubplots]
755 755 SNRavgdB = SNRavgdB.reshape((1,-1))
756 756 axes.pcolorbuffer(x, y, SNRavgdB,
757 757 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
758 758 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
759 759 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
760 760
761 761 self.draw()
762 762
763 763 self.save(figpath=figpath,
764 764 figfile=figfile,
765 765 save=save,
766 766 ftp=ftp,
767 767 wr_period=wr_period,
768 768 thisDatetime=thisDatetime,
769 769 update_figfile=update_figfile)
770 770
771 771 if dataOut.ltctime + dataOut.paramInterval >= self.xmax:
772 772 self.counter_imagwr = wr_period
773 773 self.isConfig = False
774 774 update_figfile = True
775 775
776 776
777 777 class ParametersPlot(Figure):
778 778
779 779 __isConfig = None
780 780 __nsubplots = None
781 781
782 782 WIDTHPROF = None
783 783 HEIGHTPROF = None
784 784 PREFIX = 'param'
785 785
786 786 nplots = None
787 787 nchan = None
788 788
789 789 def __init__(self, **kwargs):
790 790 Figure.__init__(self, **kwargs)
791 791 self.timerange = None
792 792 self.isConfig = False
793 793 self.__nsubplots = 1
794 794
795 795 self.WIDTH = 800
796 796 self.HEIGHT = 180
797 797 self.WIDTHPROF = 120
798 798 self.HEIGHTPROF = 0
799 799 self.counter_imagwr = 0
800 800
801 801 self.PLOT_CODE = RTI_CODE
802 802
803 803 self.FTP_WEI = None
804 804 self.EXP_CODE = None
805 805 self.SUB_EXP_CODE = None
806 806 self.PLOT_POS = None
807 807 self.tmin = None
808 808 self.tmax = None
809 809
810 810 self.xmin = None
811 811 self.xmax = None
812 812
813 813 self.figfile = None
814 814
815 815 def getSubplots(self):
816 816
817 817 ncol = 1
818 818 nrow = self.nplots
819 819
820 820 return nrow, ncol
821 821
822 822 def setup(self, id, nplots, wintitle, show=True):
823 823
824 824 self.nplots = nplots
825 825
826 826 ncolspan = 1
827 827 colspan = 1
828 828
829 829 self.createFigure(id = id,
830 830 wintitle = wintitle,
831 831 widthplot = self.WIDTH + self.WIDTHPROF,
832 832 heightplot = self.HEIGHT + self.HEIGHTPROF,
833 833 show=show)
834 834
835 835 nrow, ncol = self.getSubplots()
836 836
837 837 counter = 0
838 838 for y in range(nrow):
839 839 for x in range(ncol):
840 840
841 841 if counter >= self.nplots:
842 842 break
843 843
844 844 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
845 845
846 846 counter += 1
847 847
848 848 def run(self, dataOut, id, wintitle="", channelList=None, paramIndex = 0, colormap="jet",
849 849 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, timerange=None,
850 850 showSNR=False, SNRthresh = -numpy.inf, SNRmin=None, SNRmax=None,
851 851 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
852 852 server=None, folder=None, username=None, password=None,
853 853 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, HEIGHT=None):
854 854 """
855 855
856 856 Input:
857 857 dataOut :
858 858 id :
859 859 wintitle :
860 860 channelList :
861 861 showProfile :
862 862 xmin : None,
863 863 xmax : None,
864 864 ymin : None,
865 865 ymax : None,
866 866 zmin : None,
867 867 zmax : None
868 868 """
869 869
870 870 if HEIGHT is not None:
871 871 self.HEIGHT = HEIGHT
872 872
873 873
874 874 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
875 875 return
876 876
877 877 if channelList == None:
878 878 channelIndexList = range(dataOut.data_param.shape[0])
879 879 else:
880 880 channelIndexList = []
881 881 for channel in channelList:
882 882 if channel not in dataOut.channelList:
883 883 raise ValueError, "Channel %d is not in dataOut.channelList"
884 884 channelIndexList.append(dataOut.channelList.index(channel))
885 885
886 886 x = dataOut.getTimeRange1(dataOut.paramInterval)
887 887 y = dataOut.getHeiRange()
888 888
889 889 if dataOut.data_param.ndim == 3:
890 890 z = dataOut.data_param[channelIndexList,paramIndex,:]
891 891 else:
892 892 z = dataOut.data_param[channelIndexList,:]
893 893
894 894 if showSNR:
895 895 #SNR data
896 896 SNRarray = dataOut.data_SNR[channelIndexList,:]
897 897 SNRdB = 10*numpy.log10(SNRarray)
898 898 ind = numpy.where(SNRdB < SNRthresh)
899 899 z[ind] = numpy.nan
900 900
901 901 thisDatetime = dataOut.datatime
902 902 # thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
903 903 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
904 904 xlabel = ""
905 905 ylabel = "Range (Km)"
906 906
907 907 update_figfile = False
908 908
909 909 if not self.isConfig:
910 910
911 911 nchan = len(channelIndexList)
912 912 self.nchan = nchan
913 913 self.plotFact = 1
914 914 nplots = nchan
915 915
916 916 if showSNR:
917 917 nplots = nchan*2
918 918 self.plotFact = 2
919 919 if SNRmin == None: SNRmin = numpy.nanmin(SNRdB)
920 920 if SNRmax == None: SNRmax = numpy.nanmax(SNRdB)
921 921
922 922 self.setup(id=id,
923 923 nplots=nplots,
924 924 wintitle=wintitle,
925 925 show=show)
926 926
927 927 if timerange != None:
928 928 self.timerange = timerange
929 929
930 930 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
931 931
932 932 if ymin == None: ymin = numpy.nanmin(y)
933 933 if ymax == None: ymax = numpy.nanmax(y)
934 934 if zmin == None: zmin = numpy.nanmin(z)
935 935 if zmax == None: zmax = numpy.nanmax(z)
936 936
937 937 self.FTP_WEI = ftp_wei
938 938 self.EXP_CODE = exp_code
939 939 self.SUB_EXP_CODE = sub_exp_code
940 940 self.PLOT_POS = plot_pos
941 941
942 942 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
943 943 self.isConfig = True
944 944 self.figfile = figfile
945 945 update_figfile = True
946 946
947 947 self.setWinTitle(title)
948 948
949 949 for i in range(self.nchan):
950 950 index = channelIndexList[i]
951 951 title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
952 952 axes = self.axesList[i*self.plotFact]
953 953 z1 = z[i,:].reshape((1,-1))
954 954 axes.pcolorbuffer(x, y, z1,
955 955 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
956 956 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
957 957 ticksize=9, cblabel='', cbsize="1%",colormap=colormap)
958 958
959 959 if showSNR:
960 960 title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
961 961 axes = self.axesList[i*self.plotFact + 1]
962 962 SNRdB1 = SNRdB[i,:].reshape((1,-1))
963 963 axes.pcolorbuffer(x, y, SNRdB1,
964 964 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
965 965 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
966 966 ticksize=9, cblabel='', cbsize="1%",colormap='jet')
967 967
968 968
969 969 self.draw()
970 970
971 971 if dataOut.ltctime >= self.xmax:
972 972 self.counter_imagwr = wr_period
973 973 self.isConfig = False
974 974 update_figfile = True
975 975
976 976 self.save(figpath=figpath,
977 977 figfile=figfile,
978 978 save=save,
979 979 ftp=ftp,
980 980 wr_period=wr_period,
981 981 thisDatetime=thisDatetime,
982 982 update_figfile=update_figfile)
983 983
984 984
985 985
986 986 class Parameters1Plot(Figure):
987 987
988 988 __isConfig = None
989 989 __nsubplots = None
990 990
991 991 WIDTHPROF = None
992 992 HEIGHTPROF = None
993 993 PREFIX = 'prm'
994 994
995 995 def __init__(self, **kwargs):
996 996 Figure.__init__(self, **kwargs)
997 997 self.timerange = 2*60*60
998 998 self.isConfig = False
999 999 self.__nsubplots = 1
1000 1000
1001 1001 self.WIDTH = 800
1002 1002 self.HEIGHT = 180
1003 1003 self.WIDTHPROF = 120
1004 1004 self.HEIGHTPROF = 0
1005 1005 self.counter_imagwr = 0
1006 1006
1007 1007 self.PLOT_CODE = PARMS_CODE
1008 1008
1009 1009 self.FTP_WEI = None
1010 1010 self.EXP_CODE = None
1011 1011 self.SUB_EXP_CODE = None
1012 1012 self.PLOT_POS = None
1013 1013 self.tmin = None
1014 1014 self.tmax = None
1015 1015
1016 1016 self.xmin = None
1017 1017 self.xmax = None
1018 1018
1019 1019 self.figfile = None
1020 1020
1021 1021 def getSubplots(self):
1022 1022
1023 1023 ncol = 1
1024 1024 nrow = self.nplots
1025 1025
1026 1026 return nrow, ncol
1027 1027
1028 1028 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1029 1029
1030 1030 self.__showprofile = showprofile
1031 1031 self.nplots = nplots
1032 1032
1033 1033 ncolspan = 1
1034 1034 colspan = 1
1035 1035
1036 1036 self.createFigure(id = id,
1037 1037 wintitle = wintitle,
1038 1038 widthplot = self.WIDTH + self.WIDTHPROF,
1039 1039 heightplot = self.HEIGHT + self.HEIGHTPROF,
1040 1040 show=show)
1041 1041
1042 1042 nrow, ncol = self.getSubplots()
1043 1043
1044 1044 counter = 0
1045 1045 for y in range(nrow):
1046 1046 for x in range(ncol):
1047 1047
1048 1048 if counter >= self.nplots:
1049 1049 break
1050 1050
1051 1051 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1052 1052
1053 1053 if showprofile:
1054 1054 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
1055 1055
1056 1056 counter += 1
1057 1057
1058 1058 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
1059 1059 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,timerange=None,
1060 1060 parameterIndex = None, onlyPositive = False,
1061 1061 SNRthresh = -numpy.inf, SNR = True, SNRmin = None, SNRmax = None, onlySNR = False,
1062 1062 DOP = True,
1063 1063 zlabel = "", parameterName = "", parameterObject = "data_param",
1064 1064 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1065 1065 server=None, folder=None, username=None, password=None,
1066 1066 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1067 1067 #print inspect.getargspec(self.run).args
1068 1068 """
1069 1069
1070 1070 Input:
1071 1071 dataOut :
1072 1072 id :
1073 1073 wintitle :
1074 1074 channelList :
1075 1075 showProfile :
1076 1076 xmin : None,
1077 1077 xmax : None,
1078 1078 ymin : None,
1079 1079 ymax : None,
1080 1080 zmin : None,
1081 1081 zmax : None
1082 1082 """
1083 1083
1084 1084 data_param = getattr(dataOut, parameterObject)
1085 1085
1086 1086 if channelList == None:
1087 1087 channelIndexList = numpy.arange(data_param.shape[0])
1088 1088 else:
1089 1089 channelIndexList = numpy.array(channelList)
1090 1090
1091 1091 nchan = len(channelIndexList) #Number of channels being plotted
1092 1092
1093 1093 if nchan < 1:
1094 1094 return
1095 1095
1096 1096 nGraphsByChannel = 0
1097 1097
1098 1098 if SNR:
1099 1099 nGraphsByChannel += 1
1100 1100 if DOP:
1101 1101 nGraphsByChannel += 1
1102 1102
1103 1103 if nGraphsByChannel < 1:
1104 1104 return
1105 1105
1106 1106 nplots = nGraphsByChannel*nchan
1107 1107
1108 1108 if timerange is not None:
1109 1109 self.timerange = timerange
1110 1110
1111 1111 #tmin = None
1112 1112 #tmax = None
1113 1113 if parameterIndex == None:
1114 1114 parameterIndex = 1
1115 1115
1116 1116 x = dataOut.getTimeRange1(dataOut.paramInterval)
1117 1117 y = dataOut.heightList
1118 z = data_param[channelIndexList,parameterIndex,:].copy()
1119 1118
1120 zRange = dataOut.abscissaList
1121 # nChannels = z.shape[0] #Number of wind dimensions estimated
1122 # thisDatetime = dataOut.datatime
1119 if dataOut.data_param.ndim == 3:
1120 z = dataOut.data_param[channelIndexList,parameterIndex,:]
1121 else:
1122 z = dataOut.data_param[channelIndexList,:]
1123 1123
1124 1124 if dataOut.data_SNR is not None:
1125 SNRarray = dataOut.data_SNR[channelIndexList,:]
1126 SNRdB = 10*numpy.log10(SNRarray)
1127 # SNRavgdB = 10*numpy.log10(SNRavg)
1128 ind = numpy.where(SNRdB < 10**(SNRthresh/10))
1129 z[ind] = numpy.nan
1125 if dataOut.data_SNR.ndim == 2:
1126 SNRavg = numpy.average(dataOut.data_SNR, axis=0)
1127 else:
1128 SNRavg = dataOut.data_SNR
1129 SNRdB = 10*numpy.log10(SNRavg)
1130 1130
1131 1131 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1132 1132 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
1133 1133 xlabel = ""
1134 ylabel = "Range (Km)"
1135
1136 if (SNR and not onlySNR): nplots = 2*nplots
1134 ylabel = "Range (Km)"
1137 1135
1138 1136 if onlyPositive:
1139 1137 colormap = "jet"
1140 1138 zmin = 0
1141 1139 else: colormap = "RdBu_r"
1142 1140
1143 1141 if not self.isConfig:
1144 1142
1145 1143 self.setup(id=id,
1146 1144 nplots=nplots,
1147 1145 wintitle=wintitle,
1148 1146 showprofile=showprofile,
1149 1147 show=show)
1150 1148
1151 1149 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1152 1150
1153 1151 if ymin == None: ymin = numpy.nanmin(y)
1154 1152 if ymax == None: ymax = numpy.nanmax(y)
1155 if zmin == None: zmin = numpy.nanmin(zRange)
1156 if zmax == None: zmax = numpy.nanmax(zRange)
1153 if zmin == None: zmin = numpy.nanmin(z)
1154 if zmax == None: zmax = numpy.nanmax(z)
1157 1155
1158 1156 if SNR:
1159 1157 if SNRmin == None: SNRmin = numpy.nanmin(SNRdB)
1160 1158 if SNRmax == None: SNRmax = numpy.nanmax(SNRdB)
1161 1159
1162 1160 self.FTP_WEI = ftp_wei
1163 1161 self.EXP_CODE = exp_code
1164 1162 self.SUB_EXP_CODE = sub_exp_code
1165 1163 self.PLOT_POS = plot_pos
1166 1164
1167 1165 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1168 1166 self.isConfig = True
1169 1167 self.figfile = figfile
1170 1168
1171 1169 self.setWinTitle(title)
1172 1170
1173 1171 if ((self.xmax - x[1]) < (x[1]-x[0])):
1174 1172 x[1] = self.xmax
1175 1173
1176 1174 for i in range(nchan):
1177 1175
1178 1176 if (SNR and not onlySNR): j = 2*i
1179 1177 else: j = i
1180 1178
1181 1179 j = nGraphsByChannel*i
1182 1180
1183 1181 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1184 1182 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
1185 1183
1186 1184 if not onlySNR:
1187 1185 axes = self.axesList[j*self.__nsubplots]
1188 1186 z1 = z[i,:].reshape((1,-1))
1189 1187 axes.pcolorbuffer(x, y, z1,
1190 1188 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1191 1189 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
1192 1190 ticksize=9, cblabel=zlabel, cbsize="1%")
1193 1191
1194 1192 if DOP:
1195 1193 title = "%s Channel %d: %s" %(parameterName, channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1196 1194
1197 1195 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1198 1196 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
1199 1197 axes = self.axesList[j]
1200 1198 z1 = z[i,:].reshape((1,-1))
1201 1199 axes.pcolorbuffer(x, y, z1,
1202 1200 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1203 1201 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
1204 1202 ticksize=9, cblabel=zlabel, cbsize="1%")
1205 1203
1206 if SNR:
1207 title = "Channel %d Signal Noise Ratio (SNR): %s" %(channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1208 axes = self.axesList[(j)*self.__nsubplots]
1209 if not onlySNR:
1210 axes = self.axesList[(j + 1)*self.__nsubplots]
1211
1212 axes = self.axesList[(j + nGraphsByChannel-1)]
1204 if SNR:
1205 title = "Channel %d Signal Noise Ratio (SNR): %s" %(channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1206 axes = self.axesList[(j)*self.__nsubplots]
1207 if not onlySNR:
1208 axes = self.axesList[(j + 1)*self.__nsubplots]
1213 1209
1214 z1 = SNRdB[i,:].reshape((1,-1))
1215 axes.pcolorbuffer(x, y, z1,
1216 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1217 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap="jet",
1218 ticksize=9, cblabel=zlabel, cbsize="1%")
1210 axes = self.axesList[(j + nGraphsByChannel-1)]
1211 z1 = SNRdB.reshape((1,-1))
1212 axes.pcolorbuffer(x, y, z1,
1213 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1214 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap="jet",
1215 ticksize=9, cblabel=zlabel, cbsize="1%")
1219 1216
1220 1217
1221 1218
1222 1219 self.draw()
1223 1220
1224 1221 if x[1] >= self.axesList[0].xmax:
1225 1222 self.counter_imagwr = wr_period
1226 1223 self.isConfig = False
1227 1224 self.figfile = None
1228 1225
1229 1226 self.save(figpath=figpath,
1230 1227 figfile=figfile,
1231 1228 save=save,
1232 1229 ftp=ftp,
1233 1230 wr_period=wr_period,
1234 1231 thisDatetime=thisDatetime,
1235 1232 update_figfile=False)
1236 1233
1237 1234 class SpectralFittingPlot(Figure):
1238 1235
1239 1236 __isConfig = None
1240 1237 __nsubplots = None
1241 1238
1242 1239 WIDTHPROF = None
1243 1240 HEIGHTPROF = None
1244 1241 PREFIX = 'prm'
1245 1242
1246 1243
1247 1244 N = None
1248 1245 ippSeconds = None
1249 1246
1250 1247 def __init__(self, **kwargs):
1251 1248 Figure.__init__(self, **kwargs)
1252 1249 self.isConfig = False
1253 1250 self.__nsubplots = 1
1254 1251
1255 1252 self.PLOT_CODE = SPECFIT_CODE
1256 1253
1257 1254 self.WIDTH = 450
1258 1255 self.HEIGHT = 250
1259 1256 self.WIDTHPROF = 0
1260 1257 self.HEIGHTPROF = 0
1261 1258
1262 1259 def getSubplots(self):
1263 1260
1264 1261 ncol = int(numpy.sqrt(self.nplots)+0.9)
1265 1262 nrow = int(self.nplots*1./ncol + 0.9)
1266 1263
1267 1264 return nrow, ncol
1268 1265
1269 1266 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
1270 1267
1271 1268 showprofile = False
1272 1269 self.__showprofile = showprofile
1273 1270 self.nplots = nplots
1274 1271
1275 1272 ncolspan = 5
1276 1273 colspan = 4
1277 1274 if showprofile:
1278 1275 ncolspan = 5
1279 1276 colspan = 4
1280 1277 self.__nsubplots = 2
1281 1278
1282 1279 self.createFigure(id = id,
1283 1280 wintitle = wintitle,
1284 1281 widthplot = self.WIDTH + self.WIDTHPROF,
1285 1282 heightplot = self.HEIGHT + self.HEIGHTPROF,
1286 1283 show=show)
1287 1284
1288 1285 nrow, ncol = self.getSubplots()
1289 1286
1290 1287 counter = 0
1291 1288 for y in range(nrow):
1292 1289 for x in range(ncol):
1293 1290
1294 1291 if counter >= self.nplots:
1295 1292 break
1296 1293
1297 1294 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1298 1295
1299 1296 if showprofile:
1300 1297 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
1301 1298
1302 1299 counter += 1
1303 1300
1304 1301 def run(self, dataOut, id, cutHeight=None, fit=False, wintitle="", channelList=None, showprofile=True,
1305 1302 xmin=None, xmax=None, ymin=None, ymax=None,
1306 1303 save=False, figpath='./', figfile=None, show=True):
1307 1304
1308 1305 """
1309 1306
1310 1307 Input:
1311 1308 dataOut :
1312 1309 id :
1313 1310 wintitle :
1314 1311 channelList :
1315 1312 showProfile :
1316 1313 xmin : None,
1317 1314 xmax : None,
1318 1315 zmin : None,
1319 1316 zmax : None
1320 1317 """
1321 1318
1322 1319 if cutHeight==None:
1323 1320 h=270
1324 1321 heightindex = numpy.abs(cutHeight - dataOut.heightList).argmin()
1325 1322 cutHeight = dataOut.heightList[heightindex]
1326 1323
1327 1324 factor = dataOut.normFactor
1328 1325 x = dataOut.abscissaList[:-1]
1329 1326 #y = dataOut.getHeiRange()
1330 1327
1331 1328 z = dataOut.data_pre[:,:,heightindex]/factor
1332 1329 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1333 1330 avg = numpy.average(z, axis=1)
1334 1331 listChannels = z.shape[0]
1335 1332
1336 1333 #Reconstruct Function
1337 1334 if fit==True:
1338 1335 groupArray = dataOut.groupList
1339 1336 listChannels = groupArray.reshape((groupArray.size))
1340 1337 listChannels.sort()
1341 1338 spcFitLine = numpy.zeros(z.shape)
1342 1339 constants = dataOut.constants
1343 1340
1344 1341 nGroups = groupArray.shape[0]
1345 1342 nChannels = groupArray.shape[1]
1346 1343 nProfiles = z.shape[1]
1347 1344
1348 1345 for f in range(nGroups):
1349 1346 groupChann = groupArray[f,:]
1350 1347 p = dataOut.data_param[f,:,heightindex]
1351 1348 # p = numpy.array([ 89.343967,0.14036615,0.17086219,18.89835291,1.58388365,1.55099167])
1352 1349 fitLineAux = dataOut.library.modelFunction(p, constants)*nProfiles
1353 1350 fitLineAux = fitLineAux.reshape((nChannels,nProfiles))
1354 1351 spcFitLine[groupChann,:] = fitLineAux
1355 1352 # spcFitLine = spcFitLine/factor
1356 1353
1357 1354 z = z[listChannels,:]
1358 1355 spcFitLine = spcFitLine[listChannels,:]
1359 1356 spcFitLinedB = 10*numpy.log10(spcFitLine)
1360 1357
1361 1358 zdB = 10*numpy.log10(z)
1362 1359 #thisDatetime = dataOut.datatime
1363 1360 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1364 1361 title = wintitle + " Doppler Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
1365 1362 xlabel = "Velocity (m/s)"
1366 1363 ylabel = "Spectrum"
1367 1364
1368 1365 if not self.isConfig:
1369 1366
1370 1367 nplots = listChannels.size
1371 1368
1372 1369 self.setup(id=id,
1373 1370 nplots=nplots,
1374 1371 wintitle=wintitle,
1375 1372 showprofile=showprofile,
1376 1373 show=show)
1377 1374
1378 1375 if xmin == None: xmin = numpy.nanmin(x)
1379 1376 if xmax == None: xmax = numpy.nanmax(x)
1380 1377 if ymin == None: ymin = numpy.nanmin(zdB)
1381 1378 if ymax == None: ymax = numpy.nanmax(zdB)+2
1382 1379
1383 1380 self.isConfig = True
1384 1381
1385 1382 self.setWinTitle(title)
1386 1383 for i in range(self.nplots):
1387 1384 # title = "Channel %d: %4.2fdB" %(dataOut.channelList[i]+1, noisedB[i])
1388 1385 title = "Height %4.1f km\nChannel %d:" %(cutHeight, listChannels[i])
1389 1386 axes = self.axesList[i*self.__nsubplots]
1390 1387 if fit == False:
1391 1388 axes.pline(x, zdB[i,:],
1392 1389 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1393 1390 xlabel=xlabel, ylabel=ylabel, title=title
1394 1391 )
1395 1392 if fit == True:
1396 1393 fitline=spcFitLinedB[i,:]
1397 1394 y=numpy.vstack([zdB[i,:],fitline] )
1398 1395 legendlabels=['Data','Fitting']
1399 1396 axes.pmultilineyaxis(x, y,
1400 1397 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1401 1398 xlabel=xlabel, ylabel=ylabel, title=title,
1402 1399 legendlabels=legendlabels, marker=None,
1403 1400 linestyle='solid', grid='both')
1404 1401
1405 1402 self.draw()
1406 1403
1407 1404 self.save(figpath=figpath,
1408 1405 figfile=figfile,
1409 1406 save=save,
1410 1407 ftp=ftp,
1411 1408 wr_period=wr_period,
1412 1409 thisDatetime=thisDatetime)
1413 1410
1414 1411
1415 1412 class EWDriftsPlot(Figure):
1416 1413
1417 1414 __isConfig = None
1418 1415 __nsubplots = None
1419 1416
1420 1417 WIDTHPROF = None
1421 1418 HEIGHTPROF = None
1422 1419 PREFIX = 'drift'
1423 1420
1424 1421 def __init__(self, **kwargs):
1425 1422 Figure.__init__(self, **kwargs)
1426 1423 self.timerange = 2*60*60
1427 1424 self.isConfig = False
1428 1425 self.__nsubplots = 1
1429 1426
1430 1427 self.WIDTH = 800
1431 1428 self.HEIGHT = 150
1432 1429 self.WIDTHPROF = 120
1433 1430 self.HEIGHTPROF = 0
1434 1431 self.counter_imagwr = 0
1435 1432
1436 1433 self.PLOT_CODE = EWDRIFT_CODE
1437 1434
1438 1435 self.FTP_WEI = None
1439 1436 self.EXP_CODE = None
1440 1437 self.SUB_EXP_CODE = None
1441 1438 self.PLOT_POS = None
1442 1439 self.tmin = None
1443 1440 self.tmax = None
1444 1441
1445 1442 self.xmin = None
1446 1443 self.xmax = None
1447 1444
1448 1445 self.figfile = None
1449 1446
1450 1447 def getSubplots(self):
1451 1448
1452 1449 ncol = 1
1453 1450 nrow = self.nplots
1454 1451
1455 1452 return nrow, ncol
1456 1453
1457 1454 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1458 1455
1459 1456 self.__showprofile = showprofile
1460 1457 self.nplots = nplots
1461 1458
1462 1459 ncolspan = 1
1463 1460 colspan = 1
1464 1461
1465 1462 self.createFigure(id = id,
1466 1463 wintitle = wintitle,
1467 1464 widthplot = self.WIDTH + self.WIDTHPROF,
1468 1465 heightplot = self.HEIGHT + self.HEIGHTPROF,
1469 1466 show=show)
1470 1467
1471 1468 nrow, ncol = self.getSubplots()
1472 1469
1473 1470 counter = 0
1474 1471 for y in range(nrow):
1475 1472 if counter >= self.nplots:
1476 1473 break
1477 1474
1478 1475 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
1479 1476 counter += 1
1480 1477
1481 1478 def run(self, dataOut, id, wintitle="", channelList=None,
1482 1479 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
1483 1480 zmaxVertical = None, zminVertical = None, zmaxZonal = None, zminZonal = None,
1484 1481 timerange=None, SNRthresh = -numpy.inf, SNRmin = None, SNRmax = None, SNR_1 = False,
1485 1482 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1486 1483 server=None, folder=None, username=None, password=None,
1487 1484 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1488 1485 """
1489 1486
1490 1487 Input:
1491 1488 dataOut :
1492 1489 id :
1493 1490 wintitle :
1494 1491 channelList :
1495 1492 showProfile :
1496 1493 xmin : None,
1497 1494 xmax : None,
1498 1495 ymin : None,
1499 1496 ymax : None,
1500 1497 zmin : None,
1501 1498 zmax : None
1502 1499 """
1503 1500
1504 1501 if timerange is not None:
1505 1502 self.timerange = timerange
1506 1503
1507 1504 tmin = None
1508 1505 tmax = None
1509 1506
1510 1507 x = dataOut.getTimeRange1(dataOut.outputInterval)
1511 1508 # y = dataOut.heightList
1512 1509 y = dataOut.heightList
1513 1510
1514 1511 z = dataOut.data_output
1515 1512 nplots = z.shape[0] #Number of wind dimensions estimated
1516 1513 nplotsw = nplots
1517 1514
1518 1515 #If there is a SNR function defined
1519 1516 if dataOut.data_SNR is not None:
1520 1517 nplots += 1
1521 1518 SNR = dataOut.data_SNR
1522 1519
1523 1520 if SNR_1:
1524 1521 SNR += 1
1525 1522
1526 1523 SNRavg = numpy.average(SNR, axis=0)
1527 1524
1528 1525 SNRdB = 10*numpy.log10(SNR)
1529 1526 SNRavgdB = 10*numpy.log10(SNRavg)
1530 1527
1531 1528 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
1532 1529
1533 1530 for i in range(nplotsw):
1534 1531 z[i,ind] = numpy.nan
1535 1532
1536 1533
1537 1534 showprofile = False
1538 1535 # thisDatetime = dataOut.datatime
1539 1536 thisDatetime = datetime.datetime.utcfromtimestamp(x[1])
1540 1537 title = wintitle + " EW Drifts"
1541 1538 xlabel = ""
1542 1539 ylabel = "Height (Km)"
1543 1540
1544 1541 if not self.isConfig:
1545 1542
1546 1543 self.setup(id=id,
1547 1544 nplots=nplots,
1548 1545 wintitle=wintitle,
1549 1546 showprofile=showprofile,
1550 1547 show=show)
1551 1548
1552 1549 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1553 1550
1554 1551 if ymin == None: ymin = numpy.nanmin(y)
1555 1552 if ymax == None: ymax = numpy.nanmax(y)
1556 1553
1557 1554 if zmaxZonal == None: zmaxZonal = numpy.nanmax(abs(z[0,:]))
1558 1555 if zminZonal == None: zminZonal = -zmaxZonal
1559 1556 if zmaxVertical == None: zmaxVertical = numpy.nanmax(abs(z[1,:]))
1560 1557 if zminVertical == None: zminVertical = -zmaxVertical
1561 1558
1562 1559 if dataOut.data_SNR is not None:
1563 1560 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
1564 1561 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
1565 1562
1566 1563 self.FTP_WEI = ftp_wei
1567 1564 self.EXP_CODE = exp_code
1568 1565 self.SUB_EXP_CODE = sub_exp_code
1569 1566 self.PLOT_POS = plot_pos
1570 1567
1571 1568 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1572 1569 self.isConfig = True
1573 1570
1574 1571
1575 1572 self.setWinTitle(title)
1576 1573
1577 1574 if ((self.xmax - x[1]) < (x[1]-x[0])):
1578 1575 x[1] = self.xmax
1579 1576
1580 1577 strWind = ['Zonal','Vertical']
1581 1578 strCb = 'Velocity (m/s)'
1582 1579 zmaxVector = [zmaxZonal, zmaxVertical]
1583 1580 zminVector = [zminZonal, zminVertical]
1584 1581
1585 1582 for i in range(nplotsw):
1586 1583
1587 1584 title = "%s Drifts: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1588 1585 axes = self.axesList[i*self.__nsubplots]
1589 1586
1590 1587 z1 = z[i,:].reshape((1,-1))
1591 1588
1592 1589 axes.pcolorbuffer(x, y, z1,
1593 1590 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
1594 1591 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1595 1592 ticksize=9, cblabel=strCb, cbsize="1%", colormap="RdBu_r")
1596 1593
1597 1594 if dataOut.data_SNR is not None:
1598 1595 i += 1
1599 1596 if SNR_1:
1600 1597 title = "Signal Noise Ratio + 1 (SNR+1): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1601 1598 else:
1602 1599 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1603 1600 axes = self.axesList[i*self.__nsubplots]
1604 1601 SNRavgdB = SNRavgdB.reshape((1,-1))
1605 1602
1606 1603 axes.pcolorbuffer(x, y, SNRavgdB,
1607 1604 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1608 1605 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1609 1606 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
1610 1607
1611 1608 self.draw()
1612 1609
1613 1610 if x[1] >= self.axesList[0].xmax:
1614 1611 self.counter_imagwr = wr_period
1615 1612 self.isConfig = False
1616 1613 self.figfile = None
1617 1614
1618 1615
1619 1616
1620 1617
1621 1618 class PhasePlot(Figure):
1622 1619
1623 1620 __isConfig = None
1624 1621 __nsubplots = None
1625 1622
1626 1623 PREFIX = 'mphase'
1627 1624
1628 1625
1629 1626 def __init__(self, **kwargs):
1630 1627 Figure.__init__(self, **kwargs)
1631 1628 self.timerange = 24*60*60
1632 1629 self.isConfig = False
1633 1630 self.__nsubplots = 1
1634 1631 self.counter_imagwr = 0
1635 1632 self.WIDTH = 600
1636 1633 self.HEIGHT = 300
1637 1634 self.WIDTHPROF = 120
1638 1635 self.HEIGHTPROF = 0
1639 1636 self.xdata = None
1640 1637 self.ydata = None
1641 1638
1642 1639 self.PLOT_CODE = MPHASE_CODE
1643 1640
1644 1641 self.FTP_WEI = None
1645 1642 self.EXP_CODE = None
1646 1643 self.SUB_EXP_CODE = None
1647 1644 self.PLOT_POS = None
1648 1645
1649 1646
1650 1647 self.filename_phase = None
1651 1648
1652 1649 self.figfile = None
1653 1650
1654 1651 def getSubplots(self):
1655 1652
1656 1653 ncol = 1
1657 1654 nrow = 1
1658 1655
1659 1656 return nrow, ncol
1660 1657
1661 1658 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1662 1659
1663 1660 self.__showprofile = showprofile
1664 1661 self.nplots = nplots
1665 1662
1666 1663 ncolspan = 7
1667 1664 colspan = 6
1668 1665 self.__nsubplots = 2
1669 1666
1670 1667 self.createFigure(id = id,
1671 1668 wintitle = wintitle,
1672 1669 widthplot = self.WIDTH+self.WIDTHPROF,
1673 1670 heightplot = self.HEIGHT+self.HEIGHTPROF,
1674 1671 show=show)
1675 1672
1676 1673 nrow, ncol = self.getSubplots()
1677 1674
1678 1675 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1679 1676
1680 1677
1681 1678 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1682 1679 xmin=None, xmax=None, ymin=None, ymax=None,
1683 1680 timerange=None,
1684 1681 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1685 1682 server=None, folder=None, username=None, password=None,
1686 1683 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1687 1684
1688 1685
1689 1686 tmin = None
1690 1687 tmax = None
1691 1688 x = dataOut.getTimeRange1(dataOut.outputInterval)
1692 1689 y = dataOut.getHeiRange()
1693 1690
1694 1691
1695 1692 #thisDatetime = dataOut.datatime
1696 1693 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
1697 1694 title = wintitle + " Phase of Beacon Signal" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1698 1695 xlabel = "Local Time"
1699 1696 ylabel = "Phase"
1700 1697
1701 1698
1702 1699 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1703 1700 phase_beacon = dataOut.data_output
1704 1701 update_figfile = False
1705 1702
1706 1703 if not self.isConfig:
1707 1704
1708 1705 self.nplots = phase_beacon.size
1709 1706
1710 1707 self.setup(id=id,
1711 1708 nplots=self.nplots,
1712 1709 wintitle=wintitle,
1713 1710 showprofile=showprofile,
1714 1711 show=show)
1715 1712
1716 1713 if timerange is not None:
1717 1714 self.timerange = timerange
1718 1715
1719 1716 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1720 1717
1721 1718 if ymin == None: ymin = numpy.nanmin(phase_beacon) - 10.0
1722 1719 if ymax == None: ymax = numpy.nanmax(phase_beacon) + 10.0
1723 1720
1724 1721 self.FTP_WEI = ftp_wei
1725 1722 self.EXP_CODE = exp_code
1726 1723 self.SUB_EXP_CODE = sub_exp_code
1727 1724 self.PLOT_POS = plot_pos
1728 1725
1729 1726 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1730 1727 self.isConfig = True
1731 1728 self.figfile = figfile
1732 1729 self.xdata = numpy.array([])
1733 1730 self.ydata = numpy.array([])
1734 1731
1735 1732 #open file beacon phase
1736 1733 path = '%s%03d' %(self.PREFIX, self.id)
1737 1734 beacon_file = os.path.join(path,'%s.txt'%self.name)
1738 1735 self.filename_phase = os.path.join(figpath,beacon_file)
1739 1736 update_figfile = True
1740 1737
1741 1738
1742 1739 #store data beacon phase
1743 1740 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1744 1741
1745 1742 self.setWinTitle(title)
1746 1743
1747 1744
1748 1745 title = "Phase Offset %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1749 1746
1750 1747 legendlabels = ["phase %d"%(chan) for chan in numpy.arange(self.nplots)]
1751 1748
1752 1749 axes = self.axesList[0]
1753 1750
1754 1751 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1755 1752
1756 1753 if len(self.ydata)==0:
1757 1754 self.ydata = phase_beacon.reshape(-1,1)
1758 1755 else:
1759 1756 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1760 1757
1761 1758
1762 1759 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1763 1760 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1764 1761 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1765 1762 XAxisAsTime=True, grid='both'
1766 1763 )
1767 1764
1768 1765 self.draw()
1769 1766
1770 1767 self.save(figpath=figpath,
1771 1768 figfile=figfile,
1772 1769 save=save,
1773 1770 ftp=ftp,
1774 1771 wr_period=wr_period,
1775 1772 thisDatetime=thisDatetime,
1776 1773 update_figfile=update_figfile)
1777 1774
1778 1775 if dataOut.ltctime + dataOut.outputInterval >= self.xmax:
1779 1776 self.counter_imagwr = wr_period
1780 1777 self.isConfig = False
1781 1778 update_figfile = True
1782 1779
1783 1780
1784 1781
1785 1782 class NSMeteorDetection1Plot(Figure):
1786 1783
1787 1784 isConfig = None
1788 1785 __nsubplots = None
1789 1786
1790 1787 WIDTHPROF = None
1791 1788 HEIGHTPROF = None
1792 1789 PREFIX = 'nsm'
1793 1790
1794 1791 zminList = None
1795 1792 zmaxList = None
1796 1793 cmapList = None
1797 1794 titleList = None
1798 1795 nPairs = None
1799 1796 nChannels = None
1800 1797 nParam = None
1801 1798
1802 1799 def __init__(self, **kwargs):
1803 1800 Figure.__init__(self, **kwargs)
1804 1801 self.isConfig = False
1805 1802 self.__nsubplots = 1
1806 1803
1807 1804 self.WIDTH = 750
1808 1805 self.HEIGHT = 250
1809 1806 self.WIDTHPROF = 120
1810 1807 self.HEIGHTPROF = 0
1811 1808 self.counter_imagwr = 0
1812 1809
1813 1810 self.PLOT_CODE = SPEC_CODE
1814 1811
1815 1812 self.FTP_WEI = None
1816 1813 self.EXP_CODE = None
1817 1814 self.SUB_EXP_CODE = None
1818 1815 self.PLOT_POS = None
1819 1816
1820 1817 self.__xfilter_ena = False
1821 1818 self.__yfilter_ena = False
1822 1819
1823 1820 def getSubplots(self):
1824 1821
1825 1822 ncol = 3
1826 1823 nrow = int(numpy.ceil(self.nplots/3.0))
1827 1824
1828 1825 return nrow, ncol
1829 1826
1830 1827 def setup(self, id, nplots, wintitle, show=True):
1831 1828
1832 1829 self.nplots = nplots
1833 1830
1834 1831 ncolspan = 1
1835 1832 colspan = 1
1836 1833
1837 1834 self.createFigure(id = id,
1838 1835 wintitle = wintitle,
1839 1836 widthplot = self.WIDTH + self.WIDTHPROF,
1840 1837 heightplot = self.HEIGHT + self.HEIGHTPROF,
1841 1838 show=show)
1842 1839
1843 1840 nrow, ncol = self.getSubplots()
1844 1841
1845 1842 counter = 0
1846 1843 for y in range(nrow):
1847 1844 for x in range(ncol):
1848 1845
1849 1846 if counter >= self.nplots:
1850 1847 break
1851 1848
1852 1849 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1853 1850
1854 1851 counter += 1
1855 1852
1856 1853 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
1857 1854 xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None,
1858 1855 vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA',
1859 1856 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1860 1857 server=None, folder=None, username=None, password=None,
1861 1858 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
1862 1859 xaxis="frequency"):
1863 1860
1864 1861 """
1865 1862
1866 1863 Input:
1867 1864 dataOut :
1868 1865 id :
1869 1866 wintitle :
1870 1867 channelList :
1871 1868 showProfile :
1872 1869 xmin : None,
1873 1870 xmax : None,
1874 1871 ymin : None,
1875 1872 ymax : None,
1876 1873 zmin : None,
1877 1874 zmax : None
1878 1875 """
1879 1876 #SEPARAR EN DOS PLOTS
1880 1877 nParam = dataOut.data_param.shape[1] - 3
1881 1878
1882 1879 utctime = dataOut.data_param[0,0]
1883 1880 tmet = dataOut.data_param[:,1].astype(int)
1884 1881 hmet = dataOut.data_param[:,2].astype(int)
1885 1882
1886 1883 x = dataOut.abscissaList
1887 1884 y = dataOut.heightList
1888 1885
1889 1886 z = numpy.zeros((nParam, y.size, x.size - 1))
1890 1887 z[:,:] = numpy.nan
1891 1888 z[:,hmet,tmet] = dataOut.data_param[:,3:].T
1892 1889 z[0,:,:] = 10*numpy.log10(z[0,:,:])
1893 1890
1894 1891 xlabel = "Time (s)"
1895 1892 ylabel = "Range (km)"
1896 1893
1897 1894 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
1898 1895
1899 1896 if not self.isConfig:
1900 1897
1901 1898 nplots = nParam
1902 1899
1903 1900 self.setup(id=id,
1904 1901 nplots=nplots,
1905 1902 wintitle=wintitle,
1906 1903 show=show)
1907 1904
1908 1905 if xmin is None: xmin = numpy.nanmin(x)
1909 1906 if xmax is None: xmax = numpy.nanmax(x)
1910 1907 if ymin is None: ymin = numpy.nanmin(y)
1911 1908 if ymax is None: ymax = numpy.nanmax(y)
1912 1909 if SNRmin is None: SNRmin = numpy.nanmin(z[0,:])
1913 1910 if SNRmax is None: SNRmax = numpy.nanmax(z[0,:])
1914 1911 if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:]))
1915 1912 if vmin is None: vmin = -vmax
1916 1913 if wmin is None: wmin = 0
1917 1914 if wmax is None: wmax = 50
1918 1915
1919 1916 pairsList = dataOut.groupList
1920 1917 self.nPairs = len(dataOut.groupList)
1921 1918
1922 1919 zminList = [SNRmin, vmin, cmin] + [pmin]*self.nPairs
1923 1920 zmaxList = [SNRmax, vmax, cmax] + [pmax]*self.nPairs
1924 1921 titleList = ["SNR","Radial Velocity","Coherence"]
1925 1922 cmapList = ["jet","RdBu_r","jet"]
1926 1923
1927 1924 for i in range(self.nPairs):
1928 1925 strAux1 = "Phase Difference "+ str(pairsList[i][0]) + str(pairsList[i][1])
1929 1926 titleList = titleList + [strAux1]
1930 1927 cmapList = cmapList + ["RdBu_r"]
1931 1928
1932 1929 self.zminList = zminList
1933 1930 self.zmaxList = zmaxList
1934 1931 self.cmapList = cmapList
1935 1932 self.titleList = titleList
1936 1933
1937 1934 self.FTP_WEI = ftp_wei
1938 1935 self.EXP_CODE = exp_code
1939 1936 self.SUB_EXP_CODE = sub_exp_code
1940 1937 self.PLOT_POS = plot_pos
1941 1938
1942 1939 self.isConfig = True
1943 1940
1944 1941 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
1945 1942
1946 1943 for i in range(nParam):
1947 1944 title = self.titleList[i] + ": " +str_datetime
1948 1945 axes = self.axesList[i]
1949 1946 axes.pcolor(x, y, z[i,:].T,
1950 1947 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i],
1951 1948 xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='')
1952 1949 self.draw()
1953 1950
1954 1951 if figfile == None:
1955 1952 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
1956 1953 name = str_datetime
1957 1954 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1958 1955 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
1959 1956 figfile = self.getFilename(name)
1960 1957
1961 1958 self.save(figpath=figpath,
1962 1959 figfile=figfile,
1963 1960 save=save,
1964 1961 ftp=ftp,
1965 1962 wr_period=wr_period,
1966 1963 thisDatetime=thisDatetime)
1967 1964
1968 1965
1969 1966 class NSMeteorDetection2Plot(Figure):
1970 1967
1971 1968 isConfig = None
1972 1969 __nsubplots = None
1973 1970
1974 1971 WIDTHPROF = None
1975 1972 HEIGHTPROF = None
1976 1973 PREFIX = 'nsm'
1977 1974
1978 1975 zminList = None
1979 1976 zmaxList = None
1980 1977 cmapList = None
1981 1978 titleList = None
1982 1979 nPairs = None
1983 1980 nChannels = None
1984 1981 nParam = None
1985 1982
1986 1983 def __init__(self, **kwargs):
1987 1984 Figure.__init__(self, **kwargs)
1988 1985 self.isConfig = False
1989 1986 self.__nsubplots = 1
1990 1987
1991 1988 self.WIDTH = 750
1992 1989 self.HEIGHT = 250
1993 1990 self.WIDTHPROF = 120
1994 1991 self.HEIGHTPROF = 0
1995 1992 self.counter_imagwr = 0
1996 1993
1997 1994 self.PLOT_CODE = SPEC_CODE
1998 1995
1999 1996 self.FTP_WEI = None
2000 1997 self.EXP_CODE = None
2001 1998 self.SUB_EXP_CODE = None
2002 1999 self.PLOT_POS = None
2003 2000
2004 2001 self.__xfilter_ena = False
2005 2002 self.__yfilter_ena = False
2006 2003
2007 2004 def getSubplots(self):
2008 2005
2009 2006 ncol = 3
2010 2007 nrow = int(numpy.ceil(self.nplots/3.0))
2011 2008
2012 2009 return nrow, ncol
2013 2010
2014 2011 def setup(self, id, nplots, wintitle, show=True):
2015 2012
2016 2013 self.nplots = nplots
2017 2014
2018 2015 ncolspan = 1
2019 2016 colspan = 1
2020 2017
2021 2018 self.createFigure(id = id,
2022 2019 wintitle = wintitle,
2023 2020 widthplot = self.WIDTH + self.WIDTHPROF,
2024 2021 heightplot = self.HEIGHT + self.HEIGHTPROF,
2025 2022 show=show)
2026 2023
2027 2024 nrow, ncol = self.getSubplots()
2028 2025
2029 2026 counter = 0
2030 2027 for y in range(nrow):
2031 2028 for x in range(ncol):
2032 2029
2033 2030 if counter >= self.nplots:
2034 2031 break
2035 2032
2036 2033 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
2037 2034
2038 2035 counter += 1
2039 2036
2040 2037 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
2041 2038 xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None,
2042 2039 vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA',
2043 2040 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
2044 2041 server=None, folder=None, username=None, password=None,
2045 2042 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
2046 2043 xaxis="frequency"):
2047 2044
2048 2045 """
2049 2046
2050 2047 Input:
2051 2048 dataOut :
2052 2049 id :
2053 2050 wintitle :
2054 2051 channelList :
2055 2052 showProfile :
2056 2053 xmin : None,
2057 2054 xmax : None,
2058 2055 ymin : None,
2059 2056 ymax : None,
2060 2057 zmin : None,
2061 2058 zmax : None
2062 2059 """
2063 2060 #Rebuild matrix
2064 2061 utctime = dataOut.data_param[0,0]
2065 2062 cmet = dataOut.data_param[:,1].astype(int)
2066 2063 tmet = dataOut.data_param[:,2].astype(int)
2067 2064 hmet = dataOut.data_param[:,3].astype(int)
2068 2065
2069 2066 nParam = 3
2070 2067 nChan = len(dataOut.groupList)
2071 2068 x = dataOut.abscissaList
2072 2069 y = dataOut.heightList
2073 2070
2074 2071 z = numpy.full((nChan, nParam, y.size, x.size - 1),numpy.nan)
2075 2072 z[cmet,:,hmet,tmet] = dataOut.data_param[:,4:]
2076 2073 z[:,0,:,:] = 10*numpy.log10(z[:,0,:,:]) #logarithmic scale
2077 2074 z = numpy.reshape(z, (nChan*nParam, y.size, x.size-1))
2078 2075
2079 2076 xlabel = "Time (s)"
2080 2077 ylabel = "Range (km)"
2081 2078
2082 2079 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
2083 2080
2084 2081 if not self.isConfig:
2085 2082
2086 2083 nplots = nParam*nChan
2087 2084
2088 2085 self.setup(id=id,
2089 2086 nplots=nplots,
2090 2087 wintitle=wintitle,
2091 2088 show=show)
2092 2089
2093 2090 if xmin is None: xmin = numpy.nanmin(x)
2094 2091 if xmax is None: xmax = numpy.nanmax(x)
2095 2092 if ymin is None: ymin = numpy.nanmin(y)
2096 2093 if ymax is None: ymax = numpy.nanmax(y)
2097 2094 if SNRmin is None: SNRmin = numpy.nanmin(z[0,:])
2098 2095 if SNRmax is None: SNRmax = numpy.nanmax(z[0,:])
2099 2096 if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:]))
2100 2097 if vmin is None: vmin = -vmax
2101 2098 if wmin is None: wmin = 0
2102 2099 if wmax is None: wmax = 50
2103 2100
2104 2101 self.nChannels = nChan
2105 2102
2106 2103 zminList = []
2107 2104 zmaxList = []
2108 2105 titleList = []
2109 2106 cmapList = []
2110 2107 for i in range(self.nChannels):
2111 2108 strAux1 = "SNR Channel "+ str(i)
2112 2109 strAux2 = "Radial Velocity Channel "+ str(i)
2113 2110 strAux3 = "Spectral Width Channel "+ str(i)
2114 2111
2115 2112 titleList = titleList + [strAux1,strAux2,strAux3]
2116 2113 cmapList = cmapList + ["jet","RdBu_r","jet"]
2117 2114 zminList = zminList + [SNRmin,vmin,wmin]
2118 2115 zmaxList = zmaxList + [SNRmax,vmax,wmax]
2119 2116
2120 2117 self.zminList = zminList
2121 2118 self.zmaxList = zmaxList
2122 2119 self.cmapList = cmapList
2123 2120 self.titleList = titleList
2124 2121
2125 2122 self.FTP_WEI = ftp_wei
2126 2123 self.EXP_CODE = exp_code
2127 2124 self.SUB_EXP_CODE = sub_exp_code
2128 2125 self.PLOT_POS = plot_pos
2129 2126
2130 2127 self.isConfig = True
2131 2128
2132 2129 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
2133 2130
2134 2131 for i in range(self.nplots):
2135 2132 title = self.titleList[i] + ": " +str_datetime
2136 2133 axes = self.axesList[i]
2137 2134 axes.pcolor(x, y, z[i,:].T,
2138 2135 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i],
2139 2136 xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='')
2140 2137 self.draw()
2141 2138
2142 2139 if figfile == None:
2143 2140 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
2144 2141 name = str_datetime
2145 2142 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
2146 2143 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
2147 2144 figfile = self.getFilename(name)
2148 2145
2149 2146 self.save(figpath=figpath,
2150 2147 figfile=figfile,
2151 2148 save=save,
2152 2149 ftp=ftp,
2153 2150 wr_period=wr_period,
2154 2151 thisDatetime=thisDatetime)
@@ -1,481 +1,481
1 1 import numpy
2 2 import datetime
3 3 import sys
4 4 import matplotlib
5 5
6 6 if 'linux' in sys.platform:
7 matplotlib.use("TKAgg")
7 matplotlib.use("GTK3Agg")
8 8
9 9 if 'darwin' in sys.platform:
10 10 matplotlib.use('TKAgg')
11 11 #Qt4Agg', 'GTK', 'GTKAgg', 'ps', 'agg', 'cairo', 'MacOSX', 'GTKCairo', 'WXAgg', 'template', 'TkAgg', 'GTK3Cairo', 'GTK3Agg', 'svg', 'WebAgg', 'CocoaAgg', 'emf', 'gdk', 'WX'
12 12 import matplotlib.pyplot
13 13
14 14 from mpl_toolkits.axes_grid1 import make_axes_locatable
15 15 from matplotlib.ticker import FuncFormatter, LinearLocator
16 16
17 17 ###########################################
18 18 #Actualizacion de las funciones del driver
19 19 ###########################################
20 20
21 21 # create jro colormap
22 22
23 23 jet_values = matplotlib.pyplot.get_cmap("jet", 100)(numpy.arange(100))[10:90]
24 24 blu_values = matplotlib.pyplot.get_cmap("seismic_r", 20)(numpy.arange(20))[10:15]
25 25 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list("jro", numpy.vstack((blu_values, jet_values)))
26 26 matplotlib.pyplot.register_cmap(cmap=ncmap)
27 27
28 28 def createFigure(id, wintitle, width, height, facecolor="w", show=True, dpi = 80):
29 29
30 30 matplotlib.pyplot.ioff()
31 31
32 32 fig = matplotlib.pyplot.figure(num=id, facecolor=facecolor, figsize=(1.0*width/dpi, 1.0*height/dpi))
33 33 fig.canvas.manager.set_window_title(wintitle)
34 34 # fig.canvas.manager.resize(width, height)
35 35 matplotlib.pyplot.ion()
36 36
37 37 if show:
38 38 matplotlib.pyplot.show()
39 39
40 40 return fig
41 41
42 42 def closeFigure(show=False, fig=None):
43 43
44 44 # matplotlib.pyplot.ioff()
45 45 # matplotlib.pyplot.pause(0)
46 46
47 47 if show:
48 48 matplotlib.pyplot.show()
49 49
50 50 if fig != None:
51 51 matplotlib.pyplot.close(fig)
52 52 # matplotlib.pyplot.pause(0)
53 53 # matplotlib.pyplot.ion()
54 54
55 55 return
56 56
57 57 matplotlib.pyplot.close("all")
58 58 # matplotlib.pyplot.pause(0)
59 59 # matplotlib.pyplot.ion()
60 60
61 61 return
62 62
63 63 def saveFigure(fig, filename):
64 64
65 65 # matplotlib.pyplot.ioff()
66 66 fig.savefig(filename, dpi=matplotlib.pyplot.gcf().dpi)
67 67 # matplotlib.pyplot.ion()
68 68
69 69 def clearFigure(fig):
70 70
71 71 fig.clf()
72 72
73 73 def setWinTitle(fig, title):
74 74
75 75 fig.canvas.manager.set_window_title(title)
76 76
77 77 def setTitle(fig, title):
78 78
79 79 fig.suptitle(title)
80 80
81 81 def createAxes(fig, nrow, ncol, xpos, ypos, colspan, rowspan, polar=False):
82 82
83 83 matplotlib.pyplot.ioff()
84 84 matplotlib.pyplot.figure(fig.number)
85 85 axes = matplotlib.pyplot.subplot2grid((nrow, ncol),
86 86 (xpos, ypos),
87 87 colspan=colspan,
88 88 rowspan=rowspan,
89 89 polar=polar)
90 90
91 91 axes.grid(True)
92 92
93 93 matplotlib.pyplot.ion()
94 94 return axes
95 95
96 96 def setAxesText(ax, text):
97 97
98 98 ax.annotate(text,
99 99 xy = (.1, .99),
100 100 xycoords = 'figure fraction',
101 101 horizontalalignment = 'left',
102 102 verticalalignment = 'top',
103 103 fontsize = 10)
104 104
105 105 def printLabels(ax, xlabel, ylabel, title):
106 106
107 107 ax.set_xlabel(xlabel, size=11)
108 108 ax.set_ylabel(ylabel, size=11)
109 109 ax.set_title(title, size=8)
110 110
111 111 def createPline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='',
112 112 ticksize=9, xtick_visible=True, ytick_visible=True,
113 113 nxticks=4, nyticks=10,
114 114 grid=None,color='blue'):
115 115
116 116 """
117 117
118 118 Input:
119 119 grid : None, 'both', 'x', 'y'
120 120 """
121 121
122 122 matplotlib.pyplot.ioff()
123 123
124 124 ax.set_xlim([xmin,xmax])
125 125 ax.set_ylim([ymin,ymax])
126 126
127 127 printLabels(ax, xlabel, ylabel, title)
128 128
129 129 ######################################################
130 130 if (xmax-xmin)<=1:
131 131 xtickspos = numpy.linspace(xmin,xmax,nxticks)
132 132 xtickspos = numpy.array([float("%.1f"%i) for i in xtickspos])
133 133 ax.set_xticks(xtickspos)
134 134 else:
135 135 xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
136 136 # xtickspos = numpy.arange(nxticks)*float(xmax-xmin)/float(nxticks) + int(xmin)
137 137 ax.set_xticks(xtickspos)
138 138
139 139 for tick in ax.get_xticklabels():
140 140 tick.set_visible(xtick_visible)
141 141
142 142 for tick in ax.xaxis.get_major_ticks():
143 143 tick.label.set_fontsize(ticksize)
144 144
145 145 ######################################################
146 146 for tick in ax.get_yticklabels():
147 147 tick.set_visible(ytick_visible)
148 148
149 149 for tick in ax.yaxis.get_major_ticks():
150 150 tick.label.set_fontsize(ticksize)
151 151
152 152 ax.plot(x, y, color=color)
153 153 iplot = ax.lines[-1]
154 154
155 155 ######################################################
156 156 if '0.' in matplotlib.__version__[0:2]:
157 157 print "The matplotlib version has to be updated to 1.1 or newer"
158 158 return iplot
159 159
160 160 if '1.0.' in matplotlib.__version__[0:4]:
161 161 print "The matplotlib version has to be updated to 1.1 or newer"
162 162 return iplot
163 163
164 164 if grid != None:
165 165 ax.grid(b=True, which='major', axis=grid)
166 166
167 167 matplotlib.pyplot.tight_layout()
168 168
169 169 matplotlib.pyplot.ion()
170 170
171 171 return iplot
172 172
173 173 def set_linedata(ax, x, y, idline):
174 174
175 175 ax.lines[idline].set_data(x,y)
176 176
177 177 def pline(iplot, x, y, xlabel='', ylabel='', title=''):
178 178
179 179 ax = iplot.get_axes()
180 180
181 181 printLabels(ax, xlabel, ylabel, title)
182 182
183 183 set_linedata(ax, x, y, idline=0)
184 184
185 185 def addpline(ax, x, y, color, linestyle, lw):
186 186
187 187 ax.plot(x,y,color=color,linestyle=linestyle,lw=lw)
188 188
189 189
190 190 def createPcolor(ax, x, y, z, xmin, xmax, ymin, ymax, zmin, zmax,
191 191 xlabel='', ylabel='', title='', ticksize = 9,
192 192 colormap='jet',cblabel='', cbsize="5%",
193 193 XAxisAsTime=False):
194 194
195 195 matplotlib.pyplot.ioff()
196 196
197 197 divider = make_axes_locatable(ax)
198 198 ax_cb = divider.new_horizontal(size=cbsize, pad=0.05)
199 199 fig = ax.get_figure()
200 200 fig.add_axes(ax_cb)
201 201
202 202 ax.set_xlim([xmin,xmax])
203 203 ax.set_ylim([ymin,ymax])
204 204
205 205 printLabels(ax, xlabel, ylabel, title)
206 206
207 207 z = numpy.ma.masked_invalid(z)
208 208 cmap=matplotlib.pyplot.get_cmap(colormap)
209 209 cmap.set_bad('white',1.)
210 210 imesh = ax.pcolormesh(x,y,z.T, vmin=zmin, vmax=zmax, cmap=cmap)
211 211 cb = matplotlib.pyplot.colorbar(imesh, cax=ax_cb)
212 212 cb.set_label(cblabel)
213 213
214 214 # for tl in ax_cb.get_yticklabels():
215 215 # tl.set_visible(True)
216 216
217 217 for tick in ax.yaxis.get_major_ticks():
218 218 tick.label.set_fontsize(ticksize)
219 219
220 220 for tick in ax.xaxis.get_major_ticks():
221 221 tick.label.set_fontsize(ticksize)
222 222
223 223 for tick in cb.ax.get_yticklabels():
224 224 tick.set_fontsize(ticksize)
225 225
226 226 ax_cb.yaxis.tick_right()
227 227
228 228 if '0.' in matplotlib.__version__[0:2]:
229 229 print "The matplotlib version has to be updated to 1.1 or newer"
230 230 return imesh
231 231
232 232 if '1.0.' in matplotlib.__version__[0:4]:
233 233 print "The matplotlib version has to be updated to 1.1 or newer"
234 234 return imesh
235 235
236 236 matplotlib.pyplot.tight_layout()
237 237
238 238 if XAxisAsTime:
239 239
240 240 func = lambda x, pos: ('%s') %(datetime.datetime.utcfromtimestamp(x).strftime("%H:%M:%S"))
241 241 ax.xaxis.set_major_formatter(FuncFormatter(func))
242 242 ax.xaxis.set_major_locator(LinearLocator(7))
243 243
244 244 ax.grid(True)
245 245 matplotlib.pyplot.ion()
246 246 return imesh
247 247
248 248 def pcolor(imesh, z, xlabel='', ylabel='', title=''):
249 249
250 250 z = numpy.ma.masked_invalid(z)
251 251
252 252 cmap=matplotlib.pyplot.get_cmap('jet')
253 253 cmap.set_bad('white',1.)
254 254
255 255 z = z.T
256 256 ax = imesh.get_axes()
257 257 printLabels(ax, xlabel, ylabel, title)
258 258 imesh.set_array(z.ravel())
259 259 ax.grid(True)
260 260
261 261
262 262 def addpcolor(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'):
263 263
264 264 printLabels(ax, xlabel, ylabel, title)
265 265 z = numpy.ma.masked_invalid(z)
266 266 cmap=matplotlib.pyplot.get_cmap(colormap)
267 267 cmap.set_bad('white',1.)
268 268 ax.pcolormesh(x,y,z.T,vmin=zmin,vmax=zmax, cmap=matplotlib.pyplot.get_cmap(colormap))
269 269 ax.grid(True)
270 270
271 271 def addpcolorbuffer(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'):
272 272
273 273 printLabels(ax, xlabel, ylabel, title)
274 274
275 275 ax.collections.remove(ax.collections[0])
276 276
277 277 z = numpy.ma.masked_invalid(z)
278 278
279 279 cmap=matplotlib.pyplot.get_cmap(colormap)
280 280 cmap.set_bad('white',1.)
281 281
282 282 ax.pcolormesh(x,y,z.T,vmin=zmin,vmax=zmax, cmap=cmap)
283 283 ax.grid(True)
284 284
285 285
286 286 def createPmultiline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None,
287 287 ticksize=9, xtick_visible=True, ytick_visible=True,
288 288 nxticks=4, nyticks=10,
289 289 grid=None):
290 290
291 291 """
292 292
293 293 Input:
294 294 grid : None, 'both', 'x', 'y'
295 295 """
296 296
297 297 matplotlib.pyplot.ioff()
298 298
299 299 lines = ax.plot(x.T, y)
300 300 leg = ax.legend(lines, legendlabels, loc='upper right')
301 301 leg.get_frame().set_alpha(0.5)
302 302 ax.set_xlim([xmin,xmax])
303 303 ax.set_ylim([ymin,ymax])
304 304 printLabels(ax, xlabel, ylabel, title)
305 305
306 306 xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
307 307 ax.set_xticks(xtickspos)
308 308
309 309 for tick in ax.get_xticklabels():
310 310 tick.set_visible(xtick_visible)
311 311
312 312 for tick in ax.xaxis.get_major_ticks():
313 313 tick.label.set_fontsize(ticksize)
314 314
315 315 for tick in ax.get_yticklabels():
316 316 tick.set_visible(ytick_visible)
317 317
318 318 for tick in ax.yaxis.get_major_ticks():
319 319 tick.label.set_fontsize(ticksize)
320 320
321 321 iplot = ax.lines[-1]
322 322
323 323 if '0.' in matplotlib.__version__[0:2]:
324 324 print "The matplotlib version has to be updated to 1.1 or newer"
325 325 return iplot
326 326
327 327 if '1.0.' in matplotlib.__version__[0:4]:
328 328 print "The matplotlib version has to be updated to 1.1 or newer"
329 329 return iplot
330 330
331 331 if grid != None:
332 332 ax.grid(b=True, which='major', axis=grid)
333 333
334 334 matplotlib.pyplot.tight_layout()
335 335
336 336 matplotlib.pyplot.ion()
337 337
338 338 return iplot
339 339
340 340
341 341 def pmultiline(iplot, x, y, xlabel='', ylabel='', title=''):
342 342
343 343 ax = iplot.get_axes()
344 344
345 345 printLabels(ax, xlabel, ylabel, title)
346 346
347 347 for i in range(len(ax.lines)):
348 348 line = ax.lines[i]
349 349 line.set_data(x[i,:],y)
350 350
351 351 def createPmultilineYAxis(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None,
352 352 ticksize=9, xtick_visible=True, ytick_visible=True,
353 353 nxticks=4, nyticks=10, marker='.', markersize=10, linestyle="None",
354 354 grid=None, XAxisAsTime=False):
355 355
356 356 """
357 357
358 358 Input:
359 359 grid : None, 'both', 'x', 'y'
360 360 """
361 361
362 362 matplotlib.pyplot.ioff()
363 363
364 364 # lines = ax.plot(x, y.T, marker=marker,markersize=markersize,linestyle=linestyle)
365 365 lines = ax.plot(x, y.T)
366 366 # leg = ax.legend(lines, legendlabels, loc=2, bbox_to_anchor=(1.01, 1.00), numpoints=1, handlelength=1.5, \
367 367 # handletextpad=0.5, borderpad=0.5, labelspacing=0.5, borderaxespad=0.)
368 368
369 369 leg = ax.legend(lines, legendlabels,
370 370 loc='upper right', bbox_to_anchor=(1.16, 1), borderaxespad=0)
371 371
372 372 for label in leg.get_texts(): label.set_fontsize(9)
373 373
374 374 ax.set_xlim([xmin,xmax])
375 375 ax.set_ylim([ymin,ymax])
376 376 printLabels(ax, xlabel, ylabel, title)
377 377
378 378 # xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
379 379 # ax.set_xticks(xtickspos)
380 380
381 381 for tick in ax.get_xticklabels():
382 382 tick.set_visible(xtick_visible)
383 383
384 384 for tick in ax.xaxis.get_major_ticks():
385 385 tick.label.set_fontsize(ticksize)
386 386
387 387 for tick in ax.get_yticklabels():
388 388 tick.set_visible(ytick_visible)
389 389
390 390 for tick in ax.yaxis.get_major_ticks():
391 391 tick.label.set_fontsize(ticksize)
392 392
393 393 iplot = ax.lines[-1]
394 394
395 395 if '0.' in matplotlib.__version__[0:2]:
396 396 print "The matplotlib version has to be updated to 1.1 or newer"
397 397 return iplot
398 398
399 399 if '1.0.' in matplotlib.__version__[0:4]:
400 400 print "The matplotlib version has to be updated to 1.1 or newer"
401 401 return iplot
402 402
403 403 if grid != None:
404 404 ax.grid(b=True, which='major', axis=grid)
405 405
406 406 matplotlib.pyplot.tight_layout()
407 407
408 408 if XAxisAsTime:
409 409
410 410 func = lambda x, pos: ('%s') %(datetime.datetime.utcfromtimestamp(x).strftime("%H:%M:%S"))
411 411 ax.xaxis.set_major_formatter(FuncFormatter(func))
412 412 ax.xaxis.set_major_locator(LinearLocator(7))
413 413
414 414 matplotlib.pyplot.ion()
415 415
416 416 return iplot
417 417
418 418 def pmultilineyaxis(iplot, x, y, xlabel='', ylabel='', title=''):
419 419
420 420 ax = iplot.get_axes()
421 421 printLabels(ax, xlabel, ylabel, title)
422 422
423 423 for i in range(len(ax.lines)):
424 424 line = ax.lines[i]
425 425 line.set_data(x,y[i,:])
426 426
427 427 def createPolar(ax, x, y,
428 428 xlabel='', ylabel='', title='', ticksize = 9,
429 429 colormap='jet',cblabel='', cbsize="5%",
430 430 XAxisAsTime=False):
431 431
432 432 matplotlib.pyplot.ioff()
433 433
434 434 ax.plot(x,y,'bo', markersize=5)
435 435 # ax.set_rmax(90)
436 436 ax.set_ylim(0,90)
437 437 ax.set_yticks(numpy.arange(0,90,20))
438 438 # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center' ,size='11')
439 439 # ax.text(0, 50, ylabel, rotation='vertical', va ='center', ha = 'left' ,size='11')
440 440 # ax.text(100, 100, 'example', ha='left', va='center', rotation='vertical')
441 441 ax.yaxis.labelpad = 230
442 442 printLabels(ax, xlabel, ylabel, title)
443 443 iplot = ax.lines[-1]
444 444
445 445 if '0.' in matplotlib.__version__[0:2]:
446 446 print "The matplotlib version has to be updated to 1.1 or newer"
447 447 return iplot
448 448
449 449 if '1.0.' in matplotlib.__version__[0:4]:
450 450 print "The matplotlib version has to be updated to 1.1 or newer"
451 451 return iplot
452 452
453 453 # if grid != None:
454 454 # ax.grid(b=True, which='major', axis=grid)
455 455
456 456 matplotlib.pyplot.tight_layout()
457 457
458 458 matplotlib.pyplot.ion()
459 459
460 460
461 461 return iplot
462 462
463 463 def polar(iplot, x, y, xlabel='', ylabel='', title=''):
464 464
465 465 ax = iplot.get_axes()
466 466
467 467 # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center',size='11')
468 468 printLabels(ax, xlabel, ylabel, title)
469 469
470 470 set_linedata(ax, x, y, idline=0)
471 471
472 472 def draw(fig):
473 473
474 474 if type(fig) == 'int':
475 475 raise ValueError, "Error drawing: Fig parameter should be a matplotlib figure object figure"
476 476
477 477 fig.canvas.draw()
478 478
479 479 def pause(interval=0.000001):
480 480
481 481 matplotlib.pyplot.pause(interval)
@@ -1,21 +1,20
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JRODataIO.py 169 2012-11-19 21:57:03Z murco $
5 5 '''
6 6
7 7 from jroIO_voltage import *
8 8 from jroIO_spectra import *
9 9 from jroIO_heispectra import *
10 10 from jroIO_usrp import *
11 11
12 12 from jroIO_kamisr import *
13 13 from jroIO_param import *
14 14 from jroIO_hf import *
15 15
16 16 from jroIO_madrigal import *
17 17
18 18 from bltrIO_param import *
19 19 from jroIO_bltr import *
20 20 from jroIO_mira35c import *
21
@@ -1,1795 +1,1807
1 1 '''
2 2 Created on Jul 2, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import sys
8 8 import glob
9 9 import time
10 10 import numpy
11 11 import fnmatch
12 12 import inspect
13 13 import time, datetime
14 14 import traceback
15 15 import zmq
16 16
17 17 try:
18 18 from gevent import sleep
19 19 except:
20 20 from time import sleep
21 21
22 22 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
23 23 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
24 24
25 25 LOCALTIME = True
26 26
27 27 def isNumber(cad):
28 28 """
29 29 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
30 30
31 31 Excepciones:
32 32 Si un determinado string no puede ser convertido a numero
33 33 Input:
34 34 str, string al cual se le analiza para determinar si convertible a un numero o no
35 35
36 36 Return:
37 37 True : si el string es uno numerico
38 38 False : no es un string numerico
39 39 """
40 40 try:
41 41 float( cad )
42 42 return True
43 43 except:
44 44 return False
45 45
46 46 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
47 47 """
48 48 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
49 49
50 50 Inputs:
51 51 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
52 52
53 53 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
54 54 segundos contados desde 01/01/1970.
55 55 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
56 56 segundos contados desde 01/01/1970.
57 57
58 58 Return:
59 59 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
60 60 fecha especificado, de lo contrario retorna False.
61 61
62 62 Excepciones:
63 63 Si el archivo no existe o no puede ser abierto
64 64 Si la cabecera no puede ser leida.
65 65
66 66 """
67 67 basicHeaderObj = BasicHeader(LOCALTIME)
68 68
69 69 try:
70 70 fp = open(filename,'rb')
71 71 except IOError:
72 72 print "The file %s can't be opened" %(filename)
73 73 return 0
74 74
75 75 sts = basicHeaderObj.read(fp)
76 76 fp.close()
77 77
78 78 if not(sts):
79 79 print "Skipping the file %s because it has not a valid header" %(filename)
80 80 return 0
81 81
82 82 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
83 83 return 0
84 84
85 85 return 1
86 86
87 87 def isTimeInRange(thisTime, startTime, endTime):
88 88
89 89 if endTime >= startTime:
90 90 if (thisTime < startTime) or (thisTime > endTime):
91 91 return 0
92 92
93 93 return 1
94 94 else:
95 95 if (thisTime < startTime) and (thisTime > endTime):
96 96 return 0
97 97
98 98 return 1
99 99
100 100 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
101 101 """
102 102 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
103 103
104 104 Inputs:
105 105 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
106 106
107 107 startDate : fecha inicial del rango seleccionado en formato datetime.date
108 108
109 109 endDate : fecha final del rango seleccionado en formato datetime.date
110 110
111 111 startTime : tiempo inicial del rango seleccionado en formato datetime.time
112 112
113 113 endTime : tiempo final del rango seleccionado en formato datetime.time
114 114
115 115 Return:
116 116 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
117 117 fecha especificado, de lo contrario retorna False.
118 118
119 119 Excepciones:
120 120 Si el archivo no existe o no puede ser abierto
121 121 Si la cabecera no puede ser leida.
122 122
123 123 """
124 124
125 125
126 126 try:
127 127 fp = open(filename,'rb')
128 128 except IOError:
129 129 print "The file %s can't be opened" %(filename)
130 130 return None
131 131
132 132 firstBasicHeaderObj = BasicHeader(LOCALTIME)
133 133 systemHeaderObj = SystemHeader()
134 134 radarControllerHeaderObj = RadarControllerHeader()
135 135 processingHeaderObj = ProcessingHeader()
136 136
137 137 lastBasicHeaderObj = BasicHeader(LOCALTIME)
138 138
139 139 sts = firstBasicHeaderObj.read(fp)
140 140
141 141 if not(sts):
142 142 print "[Reading] Skipping the file %s because it has not a valid header" %(filename)
143 143 return None
144 144
145 145 if not systemHeaderObj.read(fp):
146 146 return None
147 147
148 148 if not radarControllerHeaderObj.read(fp):
149 149 return None
150 150
151 151 if not processingHeaderObj.read(fp):
152 152 return None
153 153
154 154 filesize = os.path.getsize(filename)
155 155
156 156 offset = processingHeaderObj.blockSize + 24 #header size
157 157
158 158 if filesize <= offset:
159 159 print "[Reading] %s: This file has not enough data" %filename
160 160 return None
161 161
162 162 fp.seek(-offset, 2)
163 163
164 164 sts = lastBasicHeaderObj.read(fp)
165 165
166 166 fp.close()
167 167
168 168 thisDatetime = lastBasicHeaderObj.datatime
169 169 thisTime_last_block = thisDatetime.time()
170 170
171 171 thisDatetime = firstBasicHeaderObj.datatime
172 172 thisDate = thisDatetime.date()
173 173 thisTime_first_block = thisDatetime.time()
174 174
175 175 #General case
176 176 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
177 177 #-----------o----------------------------o-----------
178 178 # startTime endTime
179 179
180 180 if endTime >= startTime:
181 181 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
182 182 return None
183 183
184 184 return thisDatetime
185 185
186 186 #If endTime < startTime then endTime belongs to the next day
187 187
188 188
189 189 #<<<<<<<<<<<o o>>>>>>>>>>>
190 190 #-----------o----------------------------o-----------
191 191 # endTime startTime
192 192
193 193 if (thisDate == startDate) and (thisTime_last_block < startTime):
194 194 return None
195 195
196 196 if (thisDate == endDate) and (thisTime_first_block > endTime):
197 197 return None
198 198
199 199 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
200 200 return None
201 201
202 202 return thisDatetime
203 203
204 204 def isFolderInDateRange(folder, startDate=None, endDate=None):
205 205 """
206 206 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
207 207
208 208 Inputs:
209 209 folder : nombre completo del directorio.
210 210 Su formato deberia ser "/path_root/?YYYYDDD"
211 211
212 212 siendo:
213 213 YYYY : Anio (ejemplo 2015)
214 214 DDD : Dia del anio (ejemplo 305)
215 215
216 216 startDate : fecha inicial del rango seleccionado en formato datetime.date
217 217
218 218 endDate : fecha final del rango seleccionado en formato datetime.date
219 219
220 220 Return:
221 221 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
222 222 fecha especificado, de lo contrario retorna False.
223 223 Excepciones:
224 224 Si el directorio no tiene el formato adecuado
225 225 """
226 226
227 227 basename = os.path.basename(folder)
228 228
229 229 if not isRadarFolder(basename):
230 230 print "The folder %s has not the rigth format" %folder
231 231 return 0
232 232
233 233 if startDate and endDate:
234 234 thisDate = getDateFromRadarFolder(basename)
235 235
236 236 if thisDate < startDate:
237 237 return 0
238 238
239 239 if thisDate > endDate:
240 240 return 0
241 241
242 242 return 1
243 243
244 244 def isFileInDateRange(filename, startDate=None, endDate=None):
245 245 """
246 246 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
247 247
248 248 Inputs:
249 249 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
250 250
251 251 Su formato deberia ser "?YYYYDDDsss"
252 252
253 253 siendo:
254 254 YYYY : Anio (ejemplo 2015)
255 255 DDD : Dia del anio (ejemplo 305)
256 256 sss : set
257 257
258 258 startDate : fecha inicial del rango seleccionado en formato datetime.date
259 259
260 260 endDate : fecha final del rango seleccionado en formato datetime.date
261 261
262 262 Return:
263 263 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
264 264 fecha especificado, de lo contrario retorna False.
265 265 Excepciones:
266 266 Si el archivo no tiene el formato adecuado
267 267 """
268 268
269 269 basename = os.path.basename(filename)
270 270
271 271 if not isRadarFile(basename):
272 272 print "The filename %s has not the rigth format" %filename
273 273 return 0
274 274
275 275 if startDate and endDate:
276 276 thisDate = getDateFromRadarFile(basename)
277 277
278 278 if thisDate < startDate:
279 279 return 0
280 280
281 281 if thisDate > endDate:
282 282 return 0
283 283
284 284 return 1
285 285
286 286 def getFileFromSet(path, ext, set):
287 287 validFilelist = []
288 288 fileList = os.listdir(path)
289 289
290 290 # 0 1234 567 89A BCDE
291 291 # H YYYY DDD SSS .ext
292 292
293 293 for thisFile in fileList:
294 294 try:
295 295 year = int(thisFile[1:5])
296 296 doy = int(thisFile[5:8])
297 297 except:
298 298 continue
299 299
300 300 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
301 301 continue
302 302
303 303 validFilelist.append(thisFile)
304 304
305 305 myfile = fnmatch.filter(validFilelist,'*%4.4d%3.3d%3.3d*'%(year,doy,set))
306 306
307 307 if len(myfile)!= 0:
308 308 return myfile[0]
309 309 else:
310 310 filename = '*%4.4d%3.3d%3.3d%s'%(year,doy,set,ext.lower())
311 311 print 'the filename %s does not exist'%filename
312 312 print '...going to the last file: '
313 313
314 314 if validFilelist:
315 315 validFilelist = sorted( validFilelist, key=str.lower )
316 316 return validFilelist[-1]
317 317
318 318 return None
319 319
320 320 def getlastFileFromPath(path, ext):
321 321 """
322 322 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
323 323 al final de la depuracion devuelve el ultimo file de la lista que quedo.
324 324
325 325 Input:
326 326 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
327 327 ext : extension de los files contenidos en una carpeta
328 328
329 329 Return:
330 330 El ultimo file de una determinada carpeta, no se considera el path.
331 331 """
332 332 validFilelist = []
333 333 fileList = os.listdir(path)
334 334
335 335 # 0 1234 567 89A BCDE
336 336 # H YYYY DDD SSS .ext
337 337
338 338 for thisFile in fileList:
339 339
340 340 year = thisFile[1:5]
341 341 if not isNumber(year):
342 342 continue
343 343
344 344 doy = thisFile[5:8]
345 345 if not isNumber(doy):
346 346 continue
347 347
348 348 year = int(year)
349 349 doy = int(doy)
350 350
351 351 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
352 352 continue
353 353
354 354 validFilelist.append(thisFile)
355 355
356 356 if validFilelist:
357 357 validFilelist = sorted( validFilelist, key=str.lower )
358 358 return validFilelist[-1]
359 359
360 360 return None
361 361
362 362 def checkForRealPath(path, foldercounter, year, doy, set, ext):
363 363 """
364 364 Por ser Linux Case Sensitive entonces checkForRealPath encuentra el nombre correcto de un path,
365 365 Prueba por varias combinaciones de nombres entre mayusculas y minusculas para determinar
366 366 el path exacto de un determinado file.
367 367
368 368 Example :
369 369 nombre correcto del file es .../.../D2009307/P2009307367.ext
370 370
371 371 Entonces la funcion prueba con las siguientes combinaciones
372 372 .../.../y2009307367.ext
373 373 .../.../Y2009307367.ext
374 374 .../.../x2009307/y2009307367.ext
375 375 .../.../x2009307/Y2009307367.ext
376 376 .../.../X2009307/y2009307367.ext
377 377 .../.../X2009307/Y2009307367.ext
378 378 siendo para este caso, la ultima combinacion de letras, identica al file buscado
379 379
380 380 Return:
381 381 Si encuentra la cobinacion adecuada devuelve el path completo y el nombre del file
382 382 caso contrario devuelve None como path y el la ultima combinacion de nombre en mayusculas
383 383 para el filename
384 384 """
385 385 fullfilename = None
386 386 find_flag = False
387 387 filename = None
388 388
389 389 prefixDirList = [None,'d','D']
390 390 if ext.lower() == ".r": #voltage
391 391 prefixFileList = ['d','D']
392 392 elif ext.lower() == ".pdata": #spectra
393 393 prefixFileList = ['p','P']
394 394 else:
395 395 return None, filename
396 396
397 397 #barrido por las combinaciones posibles
398 398 for prefixDir in prefixDirList:
399 399 thispath = path
400 400 if prefixDir != None:
401 401 #formo el nombre del directorio xYYYYDDD (x=d o x=D)
402 402 if foldercounter == 0:
403 403 thispath = os.path.join(path, "%s%04d%03d" % ( prefixDir, year, doy ))
404 404 else:
405 405 thispath = os.path.join(path, "%s%04d%03d_%02d" % ( prefixDir, year, doy , foldercounter))
406 406 for prefixFile in prefixFileList: #barrido por las dos combinaciones posibles de "D"
407 407 filename = "%s%04d%03d%03d%s" % ( prefixFile, year, doy, set, ext ) #formo el nombre del file xYYYYDDDSSS.ext
408 408 fullfilename = os.path.join( thispath, filename ) #formo el path completo
409 409
410 410 if os.path.exists( fullfilename ): #verifico que exista
411 411 find_flag = True
412 412 break
413 413 if find_flag:
414 414 break
415 415
416 416 if not(find_flag):
417 417 return None, filename
418 418
419 419 return fullfilename, filename
420 420
421 421 def isRadarFolder(folder):
422 422 try:
423 423 year = int(folder[1:5])
424 424 doy = int(folder[5:8])
425 425 except:
426 426 return 0
427 427
428 428 return 1
429 429
430 430 def isRadarFile(file):
431 431 try:
432 432 year = int(file[1:5])
433 433 doy = int(file[5:8])
434 434 set = int(file[8:11])
435 435 except:
436 436 return 0
437 437
438 438 return 1
439 439
440 440 def getDateFromRadarFile(file):
441 441 try:
442 442 year = int(file[1:5])
443 443 doy = int(file[5:8])
444 444 set = int(file[8:11])
445 445 except:
446 446 return None
447 447
448 448 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy-1)
449 449 return thisDate
450 450
451 451 def getDateFromRadarFolder(folder):
452 452 try:
453 453 year = int(folder[1:5])
454 454 doy = int(folder[5:8])
455 455 except:
456 456 return None
457 457
458 458 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy-1)
459 459 return thisDate
460 460
461 461 class JRODataIO:
462 462
463 463 c = 3E8
464 464
465 465 isConfig = False
466 466
467 467 basicHeaderObj = None
468 468
469 469 systemHeaderObj = None
470 470
471 471 radarControllerHeaderObj = None
472 472
473 473 processingHeaderObj = None
474 474
475 475 dtype = None
476 476
477 477 pathList = []
478 478
479 479 filenameList = []
480 480
481 481 filename = None
482 482
483 483 ext = None
484 484
485 485 flagIsNewFile = 1
486 486
487 487 flagDiscontinuousBlock = 0
488 488
489 489 flagIsNewBlock = 0
490 490
491 491 fp = None
492 492
493 493 firstHeaderSize = 0
494 494
495 495 basicHeaderSize = 24
496 496
497 497 versionFile = 1103
498 498
499 499 fileSize = None
500 500
501 501 # ippSeconds = None
502 502
503 503 fileSizeByHeader = None
504 504
505 505 fileIndex = None
506 506
507 507 profileIndex = None
508 508
509 509 blockIndex = None
510 510
511 511 nTotalBlocks = None
512 512
513 513 maxTimeStep = 30
514 514
515 515 lastUTTime = None
516 516
517 517 datablock = None
518 518
519 519 dataOut = None
520 520
521 521 blocksize = None
522 522
523 523 getByBlock = False
524 524
525 525 def __init__(self):
526 526
527 527 raise NotImplementedError
528 528
529 529 def run(self):
530 530
531 531 raise NotImplementedError
532 532
533 533 def getDtypeWidth(self):
534 534
535 535 dtype_index = get_dtype_index(self.dtype)
536 536 dtype_width = get_dtype_width(dtype_index)
537 537
538 538 return dtype_width
539 539
540 540 def getAllowedArgs(self):
541 541 return inspect.getargspec(self.run).args
542 542
543 543 class JRODataReader(JRODataIO):
544 544
545 545 online = 0
546 546
547 547 realtime = 0
548 548
549 549 nReadBlocks = 0
550 550
551 551 delay = 10 #number of seconds waiting a new file
552 552
553 553 nTries = 3 #quantity tries
554 554
555 555 nFiles = 3 #number of files for searching
556 556
557 557 path = None
558 558
559 559 foldercounter = 0
560 560
561 561 flagNoMoreFiles = 0
562 562
563 563 datetimeList = []
564 564
565 565 __isFirstTimeOnline = 1
566 566
567 567 __printInfo = True
568 568
569 569 profileIndex = None
570 570
571 571 nTxs = 1
572 572
573 573 txIndex = None
574 574
575 575 #Added--------------------
576 576
577 577 selBlocksize = None
578 578
579 579 selBlocktime = None
580 580
581 581 def __init__(self):
582 582
583 583 """
584 584 This class is used to find data files
585 585
586 586 Example:
587 587 reader = JRODataReader()
588 588 fileList = reader.findDataFiles()
589 589
590 590 """
591 591 pass
592 592
593 593
594 594 def createObjByDefault(self):
595 595 """
596 596
597 597 """
598 598 raise NotImplementedError
599 599
600 600 def getBlockDimension(self):
601 601
602 602 raise NotImplementedError
603 603
604 604 def searchFilesOffLine(self,
605 605 path,
606 606 startDate=None,
607 607 endDate=None,
608 608 startTime=datetime.time(0,0,0),
609 609 endTime=datetime.time(23,59,59),
610 610 set=None,
611 611 expLabel='',
612 612 ext='.r',
613 613 cursor=None,
614 614 skip=None,
615 615 walk=True):
616 616
617 617 self.filenameList = []
618 618 self.datetimeList = []
619 619
620 620 pathList = []
621 621
622 622 dateList, pathList = self.findDatafiles(path, startDate, endDate, expLabel, ext, walk, include_path=True)
623 623
624 624 if dateList == []:
625 625 return [], []
626 626
627 627 if len(dateList) > 1:
628 628 print "[Reading] Data found for date range [%s - %s]: total days = %d" %(startDate, endDate, len(dateList))
629 629 else:
630 630 print "[Reading] Data found for date range [%s - %s]: date = %s" %(startDate, endDate, dateList[0])
631 631
632 632 filenameList = []
633 633 datetimeList = []
634 634
635 635 for thisPath in pathList:
636 636
637 637 fileList = glob.glob1(thisPath, "*%s" %ext)
638 638 fileList.sort()
639 639
640 640 skippedFileList = []
641 641
642 642 if cursor is not None and skip is not None:
643 643
644 644 if skip == 0:
645 645 skippedFileList = []
646 646 else:
647 647 skippedFileList = fileList[cursor*skip: cursor*skip + skip]
648 648
649 649 else:
650 650 skippedFileList = fileList
651 651
652 652 for file in skippedFileList:
653 653
654 654 filename = os.path.join(thisPath,file)
655 655
656 656 if not isFileInDateRange(filename, startDate, endDate):
657 657 continue
658 658
659 659 thisDatetime = isFileInTimeRange(filename, startDate, endDate, startTime, endTime)
660 660
661 661 if not(thisDatetime):
662 662 continue
663 663
664 664 filenameList.append(filename)
665 665 datetimeList.append(thisDatetime)
666 666
667 667 if not(filenameList):
668 668 print "[Reading] Time range selected invalid [%s - %s]: No *%s files in %s)" %(startTime, endTime, ext, path)
669 669 return [], []
670 670
671 671 print "[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime)
672 672 print
673 673
674 674 # for i in range(len(filenameList)):
675 675 # print "[Reading] %s -> [%s]" %(filenameList[i], datetimeList[i].ctime())
676 676
677 677 self.filenameList = filenameList
678 678 self.datetimeList = datetimeList
679 679
680 680 return pathList, filenameList
681 681
682 682 def __searchFilesOnLine(self, path, expLabel = "", ext = None, walk=True, set=None):
683 683
684 684 """
685 685 Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y
686 686 devuelve el archivo encontrado ademas de otros datos.
687 687
688 688 Input:
689 689 path : carpeta donde estan contenidos los files que contiene data
690 690
691 691 expLabel : Nombre del subexperimento (subfolder)
692 692
693 693 ext : extension de los files
694 694
695 695 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
696 696
697 697 Return:
698 698 directory : eL directorio donde esta el file encontrado
699 699 filename : el ultimo file de una determinada carpeta
700 700 year : el anho
701 701 doy : el numero de dia del anho
702 702 set : el set del archivo
703 703
704 704
705 705 """
706 706 if not os.path.isdir(path):
707 707 return None, None, None, None, None, None
708 708
709 709 dirList = []
710 710
711 711 if not walk:
712 712 fullpath = path
713 713 foldercounter = 0
714 714 else:
715 715 #Filtra solo los directorios
716 716 for thisPath in os.listdir(path):
717 717 if not os.path.isdir(os.path.join(path,thisPath)):
718 718 continue
719 719 if not isRadarFolder(thisPath):
720 720 continue
721 721
722 722 dirList.append(thisPath)
723 723
724 724 if not(dirList):
725 725 return None, None, None, None, None, None
726 726
727 727 dirList = sorted( dirList, key=str.lower )
728 728
729 729 doypath = dirList[-1]
730 730 foldercounter = int(doypath.split('_')[1]) if len(doypath.split('_'))>1 else 0
731 731 fullpath = os.path.join(path, doypath, expLabel)
732 732
733 733
734 734 print "[Reading] %s folder was found: " %(fullpath )
735 735
736 736 if set == None:
737 737 filename = getlastFileFromPath(fullpath, ext)
738 738 else:
739 739 filename = getFileFromSet(fullpath, ext, set)
740 740
741 741 if not(filename):
742 742 return None, None, None, None, None, None
743 743
744 744 print "[Reading] %s file was found" %(filename)
745 745
746 746 if not(self.__verifyFile(os.path.join(fullpath, filename))):
747 747 return None, None, None, None, None, None
748 748
749 749 year = int( filename[1:5] )
750 750 doy = int( filename[5:8] )
751 751 set = int( filename[8:11] )
752 752
753 753 return fullpath, foldercounter, filename, year, doy, set
754 754
755 755 def __setNextFileOffline(self):
756 756
757 757 idFile = self.fileIndex
758 758
759 759 while (True):
760 760 idFile += 1
761 761 if not(idFile < len(self.filenameList)):
762 762 self.flagNoMoreFiles = 1
763 763 # print "[Reading] No more Files"
764 764 return 0
765 765
766 766 filename = self.filenameList[idFile]
767 767
768 768 if not(self.__verifyFile(filename)):
769 769 continue
770 770
771 771 fileSize = os.path.getsize(filename)
772 772 fp = open(filename,'rb')
773 773 break
774 774
775 775 self.flagIsNewFile = 1
776 776 self.fileIndex = idFile
777 777 self.filename = filename
778 778 self.fileSize = fileSize
779 779 self.fp = fp
780 780
781 781 # print "[Reading] Setting the file: %s"%self.filename
782 782
783 783 return 1
784 784
785 785 def __setNextFileOnline(self):
786 786 """
787 787 Busca el siguiente file que tenga suficiente data para ser leida, dentro de un folder especifico, si
788 788 no encuentra un file valido espera un tiempo determinado y luego busca en los posibles n files
789 789 siguientes.
790 790
791 791 Affected:
792 792 self.flagIsNewFile
793 793 self.filename
794 794 self.fileSize
795 795 self.fp
796 796 self.set
797 797 self.flagNoMoreFiles
798 798
799 799 Return:
800 800 0 : si luego de una busqueda del siguiente file valido este no pudo ser encontrado
801 801 1 : si el file fue abierto con exito y esta listo a ser leido
802 802
803 803 Excepciones:
804 804 Si un determinado file no puede ser abierto
805 805 """
806 806 nFiles = 0
807 807 fileOk_flag = False
808 808 firstTime_flag = True
809 809
810 810 self.set += 1
811 811
812 812 if self.set > 999:
813 813 self.set = 0
814 814 self.foldercounter += 1
815 815
816 816 #busca el 1er file disponible
817 817 fullfilename, filename = checkForRealPath( self.path, self.foldercounter, self.year, self.doy, self.set, self.ext )
818 818 if fullfilename:
819 819 if self.__verifyFile(fullfilename, False):
820 820 fileOk_flag = True
821 821
822 822 #si no encuentra un file entonces espera y vuelve a buscar
823 823 if not(fileOk_flag):
824 824 for nFiles in range(self.nFiles+1): #busco en los siguientes self.nFiles+1 files posibles
825 825
826 826 if firstTime_flag: #si es la 1era vez entonces hace el for self.nTries veces
827 827 tries = self.nTries
828 828 else:
829 829 tries = 1 #si no es la 1era vez entonces solo lo hace una vez
830 830
831 831 for nTries in range( tries ):
832 832 if firstTime_flag:
833 833 print "\t[Reading] Waiting %0.2f sec for the next file: \"%s\" , try %03d ..." % ( self.delay, filename, nTries+1 )
834 834 sleep( self.delay )
835 835 else:
836 836 print "\t[Reading] Searching the next \"%s%04d%03d%03d%s\" file ..." % (self.optchar, self.year, self.doy, self.set, self.ext)
837 837
838 838 fullfilename, filename = checkForRealPath( self.path, self.foldercounter, self.year, self.doy, self.set, self.ext )
839 839 if fullfilename:
840 840 if self.__verifyFile(fullfilename):
841 841 fileOk_flag = True
842 842 break
843 843
844 844 if fileOk_flag:
845 845 break
846 846
847 847 firstTime_flag = False
848 848
849 849 print "\t[Reading] Skipping the file \"%s\" due to this file doesn't exist" % filename
850 850 self.set += 1
851 851
852 852 if nFiles == (self.nFiles-1): #si no encuentro el file buscado cambio de carpeta y busco en la siguiente carpeta
853 853 self.set = 0
854 854 self.doy += 1
855 855 self.foldercounter = 0
856 856
857 857 if fileOk_flag:
858 858 self.fileSize = os.path.getsize( fullfilename )
859 859 self.filename = fullfilename
860 860 self.flagIsNewFile = 1
861 861 if self.fp != None: self.fp.close()
862 862 self.fp = open(fullfilename, 'rb')
863 863 self.flagNoMoreFiles = 0
864 864 # print '[Reading] Setting the file: %s' % fullfilename
865 865 else:
866 866 self.fileSize = 0
867 867 self.filename = None
868 868 self.flagIsNewFile = 0
869 869 self.fp = None
870 870 self.flagNoMoreFiles = 1
871 871 # print '[Reading] No more files to read'
872 872
873 873 return fileOk_flag
874 874
875 875 def setNextFile(self):
876 876 if self.fp != None:
877 877 self.fp.close()
878 878
879 879 if self.online:
880 880 newFile = self.__setNextFileOnline()
881 881 else:
882 882 newFile = self.__setNextFileOffline()
883 883
884 884 if not(newFile):
885 885 print '[Reading] No more files to read'
886 886 return 0
887 887
888 888 if self.verbose:
889 889 print '[Reading] Setting the file: %s' % self.filename
890 890
891 891 self.__readFirstHeader()
892 892 self.nReadBlocks = 0
893 893 return 1
894 894
895 895 def __waitNewBlock(self):
896 896 """
897 897 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
898 898
899 899 Si el modo de lectura es OffLine siempre retorn 0
900 900 """
901 901 if not self.online:
902 902 return 0
903 903
904 904 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
905 905 return 0
906 906
907 907 currentPointer = self.fp.tell()
908 908
909 909 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
910 910
911 911 for nTries in range( self.nTries ):
912 912
913 913 self.fp.close()
914 914 self.fp = open( self.filename, 'rb' )
915 915 self.fp.seek( currentPointer )
916 916
917 917 self.fileSize = os.path.getsize( self.filename )
918 918 currentSize = self.fileSize - currentPointer
919 919
920 920 if ( currentSize >= neededSize ):
921 921 self.basicHeaderObj.read(self.fp)
922 922 return 1
923 923
924 924 if self.fileSize == self.fileSizeByHeader:
925 925 # self.flagEoF = True
926 926 return 0
927 927
928 928 print "[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries+1)
929 929 sleep( self.delay )
930 930
931 931
932 932 return 0
933 933
934 934 def waitDataBlock(self,pointer_location):
935 935
936 936 currentPointer = pointer_location
937 937
938 938 neededSize = self.processingHeaderObj.blockSize #+ self.basicHeaderSize
939 939
940 940 for nTries in range( self.nTries ):
941 941 self.fp.close()
942 942 self.fp = open( self.filename, 'rb' )
943 943 self.fp.seek( currentPointer )
944 944
945 945 self.fileSize = os.path.getsize( self.filename )
946 946 currentSize = self.fileSize - currentPointer
947 947
948 948 if ( currentSize >= neededSize ):
949 949 return 1
950 950
951 951 print "[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries+1)
952 952 sleep( self.delay )
953 953
954 954 return 0
955 955
956 956 def __jumpToLastBlock(self):
957 957
958 958 if not(self.__isFirstTimeOnline):
959 959 return
960 960
961 961 csize = self.fileSize - self.fp.tell()
962 962 blocksize = self.processingHeaderObj.blockSize
963 963
964 964 #salta el primer bloque de datos
965 965 if csize > self.processingHeaderObj.blockSize:
966 966 self.fp.seek(self.fp.tell() + blocksize)
967 967 else:
968 968 return
969 969
970 970 csize = self.fileSize - self.fp.tell()
971 971 neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize
972 972 while True:
973 973
974 974 if self.fp.tell()<self.fileSize:
975 975 self.fp.seek(self.fp.tell() + neededsize)
976 976 else:
977 977 self.fp.seek(self.fp.tell() - neededsize)
978 978 break
979 979
980 980 # csize = self.fileSize - self.fp.tell()
981 981 # neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize
982 982 # factor = int(csize/neededsize)
983 983 # if factor > 0:
984 984 # self.fp.seek(self.fp.tell() + factor*neededsize)
985 985
986 986 self.flagIsNewFile = 0
987 987 self.__isFirstTimeOnline = 0
988 988
989 989 def __setNewBlock(self):
990 990 #if self.server is None:
991 991 if self.fp == None:
992 992 return 0
993 993
994 994 # if self.online:
995 995 # self.__jumpToLastBlock()
996 996
997 997 if self.flagIsNewFile:
998 998 self.lastUTTime = self.basicHeaderObj.utc
999 999 return 1
1000 1000
1001 1001 if self.realtime:
1002 1002 self.flagDiscontinuousBlock = 1
1003 1003 if not(self.setNextFile()):
1004 1004 return 0
1005 1005 else:
1006 1006 return 1
1007 1007 #if self.server is None:
1008 1008 currentSize = self.fileSize - self.fp.tell()
1009 1009 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
1010 1010 if (currentSize >= neededSize):
1011 1011 self.basicHeaderObj.read(self.fp)
1012 1012 self.lastUTTime = self.basicHeaderObj.utc
1013 1013 return 1
1014 1014 # else:
1015 1015 # self.basicHeaderObj.read(self.zHeader)
1016 1016 # self.lastUTTime = self.basicHeaderObj.utc
1017 1017 # return 1
1018 1018 if self.__waitNewBlock():
1019 1019 self.lastUTTime = self.basicHeaderObj.utc
1020 1020 return 1
1021 1021 #if self.server is None:
1022 1022 if not(self.setNextFile()):
1023 1023 return 0
1024 1024
1025 1025 deltaTime = self.basicHeaderObj.utc - self.lastUTTime #
1026 1026 self.lastUTTime = self.basicHeaderObj.utc
1027 1027
1028 1028 self.flagDiscontinuousBlock = 0
1029 1029
1030 1030 if deltaTime > self.maxTimeStep:
1031 1031 self.flagDiscontinuousBlock = 1
1032 1032
1033 1033 return 1
1034 1034
1035 1035 def readNextBlock(self):
1036 1036
1037 1037 #Skip block out of startTime and endTime
1038 1038 while True:
1039 1039 if not(self.__setNewBlock()):
1040 1040 return 0
1041 1041
1042 1042 if not(self.readBlock()):
1043 1043 return 0
1044 1044
1045 1045 self.getBasicHeader()
1046 1046
1047 1047 if not isTimeInRange(self.dataOut.datatime.time(), self.startTime, self.endTime):
1048 1048
1049 1049 print "[Reading] Block No. %d/%d -> %s [Skipping]" %(self.nReadBlocks,
1050 1050 self.processingHeaderObj.dataBlocksPerFile,
1051 1051 self.dataOut.datatime.ctime())
1052 1052 continue
1053 1053
1054 1054 break
1055 1055
1056 1056 if self.verbose:
1057 1057 print "[Reading] Block No. %d/%d -> %s" %(self.nReadBlocks,
1058 1058 self.processingHeaderObj.dataBlocksPerFile,
1059 1059 self.dataOut.datatime.ctime())
1060 1060 return 1
1061 1061
1062 1062 def __readFirstHeader(self):
1063 1063
1064 1064 self.basicHeaderObj.read(self.fp)
1065 1065 self.systemHeaderObj.read(self.fp)
1066 1066 self.radarControllerHeaderObj.read(self.fp)
1067 1067 self.processingHeaderObj.read(self.fp)
1068 1068
1069 1069 self.firstHeaderSize = self.basicHeaderObj.size
1070 1070
1071 1071 datatype = int(numpy.log2((self.processingHeaderObj.processFlags & PROCFLAG.DATATYPE_MASK))-numpy.log2(PROCFLAG.DATATYPE_CHAR))
1072 1072 if datatype == 0:
1073 1073 datatype_str = numpy.dtype([('real','<i1'),('imag','<i1')])
1074 1074 elif datatype == 1:
1075 1075 datatype_str = numpy.dtype([('real','<i2'),('imag','<i2')])
1076 1076 elif datatype == 2:
1077 1077 datatype_str = numpy.dtype([('real','<i4'),('imag','<i4')])
1078 1078 elif datatype == 3:
1079 1079 datatype_str = numpy.dtype([('real','<i8'),('imag','<i8')])
1080 1080 elif datatype == 4:
1081 1081 datatype_str = numpy.dtype([('real','<f4'),('imag','<f4')])
1082 1082 elif datatype == 5:
1083 1083 datatype_str = numpy.dtype([('real','<f8'),('imag','<f8')])
1084 1084 else:
1085 1085 raise ValueError, 'Data type was not defined'
1086 1086
1087 1087 self.dtype = datatype_str
1088 1088 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
1089 1089 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + self.firstHeaderSize + self.basicHeaderSize*(self.processingHeaderObj.dataBlocksPerFile - 1)
1090 1090 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
1091 1091 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
1092 1092 self.getBlockDimension()
1093 1093
1094 1094 def __verifyFile(self, filename, msgFlag=True):
1095 1095
1096 1096 msg = None
1097 1097
1098 1098 try:
1099 1099 fp = open(filename, 'rb')
1100 1100 except IOError:
1101 1101
1102 1102 if msgFlag:
1103 1103 print "[Reading] File %s can't be opened" % (filename)
1104 1104
1105 1105 return False
1106 1106
1107 1107 currentPosition = fp.tell()
1108 1108 neededSize = self.processingHeaderObj.blockSize + self.firstHeaderSize
1109 1109
1110 1110 if neededSize == 0:
1111 1111 basicHeaderObj = BasicHeader(LOCALTIME)
1112 1112 systemHeaderObj = SystemHeader()
1113 1113 radarControllerHeaderObj = RadarControllerHeader()
1114 1114 processingHeaderObj = ProcessingHeader()
1115 1115
1116 1116 if not( basicHeaderObj.read(fp) ):
1117 1117 fp.close()
1118 1118 return False
1119 1119
1120 1120 if not( systemHeaderObj.read(fp) ):
1121 1121 fp.close()
1122 1122 return False
1123 1123
1124 1124 if not( radarControllerHeaderObj.read(fp) ):
1125 1125 fp.close()
1126 1126 return False
1127 1127
1128 1128 if not( processingHeaderObj.read(fp) ):
1129 1129 fp.close()
1130 1130 return False
1131 1131
1132 1132 neededSize = processingHeaderObj.blockSize + basicHeaderObj.size
1133 1133 else:
1134 1134 msg = "[Reading] Skipping the file %s due to it hasn't enough data" %filename
1135 1135
1136 1136 fp.close()
1137 1137
1138 1138 fileSize = os.path.getsize(filename)
1139 1139 currentSize = fileSize - currentPosition
1140 1140
1141 1141 if currentSize < neededSize:
1142 1142 if msgFlag and (msg != None):
1143 1143 print msg
1144 1144 return False
1145 1145
1146 1146 return True
1147 1147
1148 1148 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1149 1149
1150 1150 path_empty = True
1151 1151
1152 1152 dateList = []
1153 1153 pathList = []
1154 1154
1155 1155 multi_path = path.split(',')
1156 1156
1157 1157 if not walk:
1158 1158
1159 1159 for single_path in multi_path:
1160 1160
1161 1161 if not os.path.isdir(single_path):
1162 1162 continue
1163 1163
1164 1164 fileList = glob.glob1(single_path, "*"+ext)
1165 1165
1166 1166 if not fileList:
1167 1167 continue
1168 1168
1169 1169 path_empty = False
1170 1170
1171 1171 fileList.sort()
1172 1172
1173 1173 for thisFile in fileList:
1174 1174
1175 1175 if not os.path.isfile(os.path.join(single_path, thisFile)):
1176 1176 continue
1177 1177
1178 1178 if not isRadarFile(thisFile):
1179 1179 continue
1180 1180
1181 1181 if not isFileInDateRange(thisFile, startDate, endDate):
1182 1182 continue
1183 1183
1184 1184 thisDate = getDateFromRadarFile(thisFile)
1185 1185
1186 1186 if thisDate in dateList:
1187 1187 continue
1188 1188
1189 1189 dateList.append(thisDate)
1190 1190 pathList.append(single_path)
1191 1191
1192 1192 else:
1193 1193 for single_path in multi_path:
1194 1194
1195 1195 if not os.path.isdir(single_path):
1196 1196 continue
1197 1197
1198 1198 dirList = []
1199 1199
1200 1200 for thisPath in os.listdir(single_path):
1201 1201
1202 1202 if not os.path.isdir(os.path.join(single_path,thisPath)):
1203 1203 continue
1204 1204
1205 1205 if not isRadarFolder(thisPath):
1206 1206 continue
1207 1207
1208 1208 if not isFolderInDateRange(thisPath, startDate, endDate):
1209 1209 continue
1210 1210
1211 1211 dirList.append(thisPath)
1212 1212
1213 1213 if not dirList:
1214 1214 continue
1215 1215
1216 1216 dirList.sort()
1217 1217
1218 1218 for thisDir in dirList:
1219 1219
1220 1220 datapath = os.path.join(single_path, thisDir, expLabel)
1221 1221 fileList = glob.glob1(datapath, "*"+ext)
1222 1222
1223 1223 if not fileList:
1224 1224 continue
1225 1225
1226 1226 path_empty = False
1227 1227
1228 1228 thisDate = getDateFromRadarFolder(thisDir)
1229 1229
1230 1230 pathList.append(datapath)
1231 1231 dateList.append(thisDate)
1232 1232
1233 1233 dateList.sort()
1234 1234
1235 1235 if walk:
1236 1236 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1237 1237 else:
1238 1238 pattern_path = multi_path[0]
1239 1239
1240 1240 if path_empty:
1241 1241 print "[Reading] No *%s files in %s for %s to %s" %(ext, pattern_path, startDate, endDate)
1242 1242 else:
1243 1243 if not dateList:
1244 1244 print "[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" %(startDate, endDate, ext, path)
1245 1245
1246 1246 if include_path:
1247 1247 return dateList, pathList
1248 1248
1249 1249 return dateList
1250 1250
1251 1251 def setup(self,
1252 1252 path=None,
1253 1253 startDate=None,
1254 1254 endDate=None,
1255 1255 startTime=datetime.time(0,0,0),
1256 1256 endTime=datetime.time(23,59,59),
1257 1257 set=None,
1258 1258 expLabel = "",
1259 1259 ext = None,
1260 1260 online = False,
1261 1261 delay = 60,
1262 1262 walk = True,
1263 1263 getblock = False,
1264 1264 nTxs = 1,
1265 1265 realtime=False,
1266 1266 blocksize=None,
1267 1267 blocktime=None,
1268 1268 skip=None,
1269 1269 cursor=None,
1270 1270 warnings=True,
1271 1271 verbose=True,
1272 server=None):
1272 server=None,
1273 format=None,
1274 oneDDict=None,
1275 twoDDict=None,
1276 ind2DList=None):
1273 1277 if server is not None:
1274 1278 if 'tcp://' in server:
1275 1279 address = server
1276 1280 else:
1277 1281 address = 'ipc:///tmp/%s' % server
1278 1282 self.server = address
1279 1283 self.context = zmq.Context()
1280 1284 self.receiver = self.context.socket(zmq.PULL)
1281 1285 self.receiver.connect(self.server)
1282 1286 time.sleep(0.5)
1283 1287 print '[Starting] ReceiverData from {}'.format(self.server)
1284 1288 else:
1285 1289 self.server = None
1286 1290 if path == None:
1287 1291 raise ValueError, "[Reading] The path is not valid"
1288 1292
1289 1293 if ext == None:
1290 1294 ext = self.ext
1291 1295
1292 1296 if online:
1293 1297 print "[Reading] Searching files in online mode..."
1294 1298
1295 1299 for nTries in range( self.nTries ):
1296 1300 fullpath, foldercounter, file, year, doy, set = self.__searchFilesOnLine(path=path, expLabel=expLabel, ext=ext, walk=walk, set=set)
1297 1301
1298 1302 if fullpath:
1299 1303 break
1300 1304
1301 1305 print '[Reading] Waiting %0.2f sec for an valid file in %s: try %02d ...' % (self.delay, path, nTries+1)
1302 1306 sleep( self.delay )
1303 1307
1304 1308 if not(fullpath):
1305 1309 print "[Reading] There 'isn't any valid file in %s" % path
1306 1310 return
1307 1311
1308 1312 self.year = year
1309 1313 self.doy = doy
1310 1314 self.set = set - 1
1311 1315 self.path = path
1312 1316 self.foldercounter = foldercounter
1313 1317 last_set = None
1314 1318 else:
1315 1319 print "[Reading] Searching files in offline mode ..."
1316 1320 pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate,
1317 1321 startTime=startTime, endTime=endTime,
1318 1322 set=set, expLabel=expLabel, ext=ext,
1319 1323 walk=walk, cursor=cursor,
1320 1324 skip=skip)
1321 1325
1322 1326 if not(pathList):
1323 1327 self.fileIndex = -1
1324 1328 self.pathList = []
1325 1329 self.filenameList = []
1326 1330 return
1327 1331
1328 1332 self.fileIndex = -1
1329 1333 self.pathList = pathList
1330 1334 self.filenameList = filenameList
1331 1335 file_name = os.path.basename(filenameList[-1])
1332 1336 basename, ext = os.path.splitext(file_name)
1333 1337 last_set = int(basename[-3:])
1334 1338
1335 1339 self.online = online
1336 1340 self.realtime = realtime
1337 1341 self.delay = delay
1338 1342 ext = ext.lower()
1339 1343 self.ext = ext
1340 1344 self.getByBlock = getblock
1341 1345 self.nTxs = nTxs
1342 1346 self.startTime = startTime
1343 1347 self.endTime = endTime
1344 1348
1345 1349 #Added-----------------
1346 1350 self.selBlocksize = blocksize
1347 1351 self.selBlocktime = blocktime
1348 1352
1349 1353 # Verbose-----------
1350 1354 self.verbose = verbose
1351 1355 self.warnings = warnings
1352 1356
1353 1357 if not(self.setNextFile()):
1354 1358 if (startDate!=None) and (endDate!=None):
1355 1359 print "[Reading] No files in range: %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime())
1356 1360 elif startDate != None:
1357 1361 print "[Reading] No files in range: %s" %(datetime.datetime.combine(startDate,startTime).ctime())
1358 1362 else:
1359 1363 print "[Reading] No files"
1360 1364
1361 1365 self.fileIndex = -1
1362 1366 self.pathList = []
1363 1367 self.filenameList = []
1364 1368 return
1365 1369
1366 1370 # self.getBasicHeader()
1367 1371
1368 1372 if last_set != None:
1369 1373 self.dataOut.last_block = last_set * self.processingHeaderObj.dataBlocksPerFile + self.basicHeaderObj.dataBlock
1370 1374 return
1371 1375
1372 1376 def getBasicHeader(self):
1373 1377
1374 1378 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond/1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1375 1379
1376 1380 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1377 1381
1378 1382 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1379 1383
1380 1384 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1381 1385
1382 1386 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1383 1387
1384 1388 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1385 1389
1386 1390 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds/self.nTxs
1387 1391
1388 1392 # self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs
1389 1393
1390 1394
1391 1395 def getFirstHeader(self):
1392 1396
1393 1397 raise NotImplementedError
1394 1398
1395 1399 def getData(self):
1396 1400
1397 1401 raise NotImplementedError
1398 1402
1399 1403 def hasNotDataInBuffer(self):
1400 1404
1401 1405 raise NotImplementedError
1402 1406
1403 1407 def readBlock(self):
1404 1408
1405 1409 raise NotImplementedError
1406 1410
1407 1411 def isEndProcess(self):
1408 1412
1409 1413 return self.flagNoMoreFiles
1410 1414
1411 1415 def printReadBlocks(self):
1412 1416
1413 1417 print "[Reading] Number of read blocks per file %04d" %self.nReadBlocks
1414 1418
1415 1419 def printTotalBlocks(self):
1416 1420
1417 1421 print "[Reading] Number of read blocks %04d" %self.nTotalBlocks
1418 1422
1419 1423 def printNumberOfBlock(self):
1420 1424 'SPAM!'
1421 1425
1422 1426 # if self.flagIsNewBlock:
1423 1427 # print "[Reading] Block No. %d/%d -> %s" %(self.nReadBlocks,
1424 1428 # self.processingHeaderObj.dataBlocksPerFile,
1425 1429 # self.dataOut.datatime.ctime())
1426 1430
1427 1431 def printInfo(self):
1428 1432
1429 1433 if self.__printInfo == False:
1430 1434 return
1431 1435
1432 1436 self.basicHeaderObj.printInfo()
1433 1437 self.systemHeaderObj.printInfo()
1434 1438 self.radarControllerHeaderObj.printInfo()
1435 1439 self.processingHeaderObj.printInfo()
1436 1440
1437 1441 self.__printInfo = False
1438 1442
1439 1443 def run(self,
1440 1444 path=None,
1441 1445 startDate=None,
1442 1446 endDate=None,
1443 1447 startTime=datetime.time(0,0,0),
1444 1448 endTime=datetime.time(23,59,59),
1445 1449 set=None,
1446 1450 expLabel = "",
1447 1451 ext = None,
1448 1452 online = False,
1449 1453 delay = 60,
1450 1454 walk = True,
1451 1455 getblock = False,
1452 1456 nTxs = 1,
1453 1457 realtime=False,
1454 1458 blocksize=None,
1455 1459 blocktime=None,
1456 1460 skip=None,
1457 1461 cursor=None,
1458 1462 warnings=True,
1459 1463 server=None,
1460 verbose=True, **kwargs):
1464 verbose=True,
1465 format=None,
1466 oneDDict=None,
1467 twoDDict=None,
1468 ind2DList=None, **kwargs):
1461 1469
1462 1470 if not(self.isConfig):
1463 1471 self.setup(path=path,
1464 1472 startDate=startDate,
1465 1473 endDate=endDate,
1466 1474 startTime=startTime,
1467 1475 endTime=endTime,
1468 1476 set=set,
1469 1477 expLabel=expLabel,
1470 1478 ext=ext,
1471 1479 online=online,
1472 1480 delay=delay,
1473 1481 walk=walk,
1474 1482 getblock=getblock,
1475 1483 nTxs=nTxs,
1476 1484 realtime=realtime,
1477 1485 blocksize=blocksize,
1478 1486 blocktime=blocktime,
1479 1487 skip=skip,
1480 1488 cursor=cursor,
1481 1489 warnings=warnings,
1482 1490 server=server,
1483 verbose=verbose)
1491 verbose=verbose,
1492 format=format,
1493 oneDDict=oneDDict,
1494 twoDDict=twoDDict,
1495 ind2DList=ind2DList)
1484 1496 self.isConfig = True
1485 1497 if server is None:
1486 1498 self.getData()
1487 1499 else:
1488 1500 self.getFromServer()
1489 1501
1490 1502 class JRODataWriter(JRODataIO):
1491 1503
1492 1504 """
1493 1505 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1494 1506 de los datos siempre se realiza por bloques.
1495 1507 """
1496 1508
1497 1509 blockIndex = 0
1498 1510
1499 1511 path = None
1500 1512
1501 1513 setFile = None
1502 1514
1503 1515 profilesPerBlock = None
1504 1516
1505 1517 blocksPerFile = None
1506 1518
1507 1519 nWriteBlocks = 0
1508 1520
1509 1521 fileDate = None
1510 1522
1511 1523 def __init__(self, dataOut=None):
1512 1524 raise NotImplementedError
1513 1525
1514 1526
1515 1527 def hasAllDataInBuffer(self):
1516 1528 raise NotImplementedError
1517 1529
1518 1530
1519 1531 def setBlockDimension(self):
1520 1532 raise NotImplementedError
1521 1533
1522 1534
1523 1535 def writeBlock(self):
1524 1536 raise NotImplementedError
1525 1537
1526 1538
1527 1539 def putData(self):
1528 1540 raise NotImplementedError
1529 1541
1530 1542
1531 1543 def getProcessFlags(self):
1532 1544
1533 1545 processFlags = 0
1534 1546
1535 1547 dtype_index = get_dtype_index(self.dtype)
1536 1548 procflag_dtype = get_procflag_dtype(dtype_index)
1537 1549
1538 1550 processFlags += procflag_dtype
1539 1551
1540 1552 if self.dataOut.flagDecodeData:
1541 1553 processFlags += PROCFLAG.DECODE_DATA
1542 1554
1543 1555 if self.dataOut.flagDeflipData:
1544 1556 processFlags += PROCFLAG.DEFLIP_DATA
1545 1557
1546 1558 if self.dataOut.code is not None:
1547 1559 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1548 1560
1549 1561 if self.dataOut.nCohInt > 1:
1550 1562 processFlags += PROCFLAG.COHERENT_INTEGRATION
1551 1563
1552 1564 if self.dataOut.type == "Spectra":
1553 1565 if self.dataOut.nIncohInt > 1:
1554 1566 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1555 1567
1556 1568 if self.dataOut.data_dc is not None:
1557 1569 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1558 1570
1559 1571 if self.dataOut.flagShiftFFT:
1560 1572 processFlags += PROCFLAG.SHIFT_FFT_DATA
1561 1573
1562 1574 return processFlags
1563 1575
1564 1576 def setBasicHeader(self):
1565 1577
1566 1578 self.basicHeaderObj.size = self.basicHeaderSize #bytes
1567 1579 self.basicHeaderObj.version = self.versionFile
1568 1580 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1569 1581
1570 1582 utc = numpy.floor(self.dataOut.utctime)
1571 1583 milisecond = (self.dataOut.utctime - utc)* 1000.0
1572 1584
1573 1585 self.basicHeaderObj.utc = utc
1574 1586 self.basicHeaderObj.miliSecond = milisecond
1575 1587 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1576 1588 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1577 1589 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1578 1590
1579 1591 def setFirstHeader(self):
1580 1592 """
1581 1593 Obtiene una copia del First Header
1582 1594
1583 1595 Affected:
1584 1596
1585 1597 self.basicHeaderObj
1586 1598 self.systemHeaderObj
1587 1599 self.radarControllerHeaderObj
1588 1600 self.processingHeaderObj self.
1589 1601
1590 1602 Return:
1591 1603 None
1592 1604 """
1593 1605
1594 1606 raise NotImplementedError
1595 1607
1596 1608 def __writeFirstHeader(self):
1597 1609 """
1598 1610 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1599 1611
1600 1612 Affected:
1601 1613 __dataType
1602 1614
1603 1615 Return:
1604 1616 None
1605 1617 """
1606 1618
1607 1619 # CALCULAR PARAMETROS
1608 1620
1609 1621 sizeLongHeader = self.systemHeaderObj.size + self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1610 1622 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1611 1623
1612 1624 self.basicHeaderObj.write(self.fp)
1613 1625 self.systemHeaderObj.write(self.fp)
1614 1626 self.radarControllerHeaderObj.write(self.fp)
1615 1627 self.processingHeaderObj.write(self.fp)
1616 1628
1617 1629 def __setNewBlock(self):
1618 1630 """
1619 1631 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1620 1632
1621 1633 Return:
1622 1634 0 : si no pudo escribir nada
1623 1635 1 : Si escribio el Basic el First Header
1624 1636 """
1625 1637 if self.fp == None:
1626 1638 self.setNextFile()
1627 1639
1628 1640 if self.flagIsNewFile:
1629 1641 return 1
1630 1642
1631 1643 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1632 1644 self.basicHeaderObj.write(self.fp)
1633 1645 return 1
1634 1646
1635 1647 if not( self.setNextFile() ):
1636 1648 return 0
1637 1649
1638 1650 return 1
1639 1651
1640 1652
1641 1653 def writeNextBlock(self):
1642 1654 """
1643 1655 Selecciona el bloque siguiente de datos y los escribe en un file
1644 1656
1645 1657 Return:
1646 1658 0 : Si no hizo pudo escribir el bloque de datos
1647 1659 1 : Si no pudo escribir el bloque de datos
1648 1660 """
1649 1661 if not( self.__setNewBlock() ):
1650 1662 return 0
1651 1663
1652 1664 self.writeBlock()
1653 1665
1654 1666 print "[Writing] Block No. %d/%d" %(self.blockIndex,
1655 1667 self.processingHeaderObj.dataBlocksPerFile)
1656 1668
1657 1669 return 1
1658 1670
1659 1671 def setNextFile(self):
1660 1672 """
1661 1673 Determina el siguiente file que sera escrito
1662 1674
1663 1675 Affected:
1664 1676 self.filename
1665 1677 self.subfolder
1666 1678 self.fp
1667 1679 self.setFile
1668 1680 self.flagIsNewFile
1669 1681
1670 1682 Return:
1671 1683 0 : Si el archivo no puede ser escrito
1672 1684 1 : Si el archivo esta listo para ser escrito
1673 1685 """
1674 1686 ext = self.ext
1675 1687 path = self.path
1676 1688
1677 1689 if self.fp != None:
1678 1690 self.fp.close()
1679 1691
1680 1692 timeTuple = time.localtime( self.dataOut.utctime)
1681 1693 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
1682 1694
1683 1695 fullpath = os.path.join( path, subfolder )
1684 1696 setFile = self.setFile
1685 1697
1686 1698 if not( os.path.exists(fullpath) ):
1687 1699 os.mkdir(fullpath)
1688 1700 setFile = -1 #inicializo mi contador de seteo
1689 1701 else:
1690 1702 filesList = os.listdir( fullpath )
1691 1703 if len( filesList ) > 0:
1692 1704 filesList = sorted( filesList, key=str.lower )
1693 1705 filen = filesList[-1]
1694 1706 # el filename debera tener el siguiente formato
1695 1707 # 0 1234 567 89A BCDE (hex)
1696 1708 # x YYYY DDD SSS .ext
1697 1709 if isNumber( filen[8:11] ):
1698 1710 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
1699 1711 else:
1700 1712 setFile = -1
1701 1713 else:
1702 1714 setFile = -1 #inicializo mi contador de seteo
1703 1715
1704 1716 setFile += 1
1705 1717
1706 1718 #If this is a new day it resets some values
1707 1719 if self.dataOut.datatime.date() > self.fileDate:
1708 1720 setFile = 0
1709 1721 self.nTotalBlocks = 0
1710 1722
1711 1723 filen = '%s%4.4d%3.3d%3.3d%s' % (self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext )
1712 1724
1713 1725 filename = os.path.join( path, subfolder, filen )
1714 1726
1715 1727 fp = open( filename,'wb' )
1716 1728
1717 1729 self.blockIndex = 0
1718 1730
1719 1731 #guardando atributos
1720 1732 self.filename = filename
1721 1733 self.subfolder = subfolder
1722 1734 self.fp = fp
1723 1735 self.setFile = setFile
1724 1736 self.flagIsNewFile = 1
1725 1737 self.fileDate = self.dataOut.datatime.date()
1726 1738
1727 1739 self.setFirstHeader()
1728 1740
1729 1741 print '[Writing] Opening file: %s'%self.filename
1730 1742
1731 1743 self.__writeFirstHeader()
1732 1744
1733 1745 return 1
1734 1746
1735 1747 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1736 1748 """
1737 1749 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1738 1750
1739 1751 Inputs:
1740 1752 path : directory where data will be saved
1741 1753 profilesPerBlock : number of profiles per block
1742 1754 set : initial file set
1743 1755 datatype : An integer number that defines data type:
1744 1756 0 : int8 (1 byte)
1745 1757 1 : int16 (2 bytes)
1746 1758 2 : int32 (4 bytes)
1747 1759 3 : int64 (8 bytes)
1748 1760 4 : float32 (4 bytes)
1749 1761 5 : double64 (8 bytes)
1750 1762
1751 1763 Return:
1752 1764 0 : Si no realizo un buen seteo
1753 1765 1 : Si realizo un buen seteo
1754 1766 """
1755 1767
1756 1768 if ext == None:
1757 1769 ext = self.ext
1758 1770
1759 1771 self.ext = ext.lower()
1760 1772
1761 1773 self.path = path
1762 1774
1763 1775 if set is None:
1764 1776 self.setFile = -1
1765 1777 else:
1766 1778 self.setFile = set - 1
1767 1779
1768 1780 self.blocksPerFile = blocksPerFile
1769 1781
1770 1782 self.profilesPerBlock = profilesPerBlock
1771 1783
1772 1784 self.dataOut = dataOut
1773 1785 self.fileDate = self.dataOut.datatime.date()
1774 1786 #By default
1775 1787 self.dtype = self.dataOut.dtype
1776 1788
1777 1789 if datatype is not None:
1778 1790 self.dtype = get_numpy_dtype(datatype)
1779 1791
1780 1792 if not(self.setNextFile()):
1781 1793 print "[Writing] There isn't a next file"
1782 1794 return 0
1783 1795
1784 1796 self.setBlockDimension()
1785 1797
1786 1798 return 1
1787 1799
1788 1800 def run(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1789 1801
1790 1802 if not(self.isConfig):
1791 1803
1792 1804 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock, set=set, ext=ext, datatype=datatype, **kwargs)
1793 1805 self.isConfig = True
1794 1806
1795 1807 self.putData()
@@ -1,243 +1,580
1 1 '''
2 2 Created on Aug 1, 2017
3 3
4 4 @author: Juan C. Espinoza
5 5 '''
6 6
7 7 import os
8 8 import sys
9 9 import time
10 10 import json
11 import glob
11 12 import datetime
12 13
13 14 import numpy
15 import h5py
14 16
15 17 try:
16 18 import madrigal
17 19 import madrigal.cedar
18 20 except:
19 21 print 'You should install "madrigal library" module if you want to read/write Madrigal data'
20 22
21 from schainpy.model.proc.jroproc_base import Operation
23 from schainpy.model.io.jroIO_base import JRODataReader
24 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
22 25 from schainpy.model.data.jrodata import Parameters
26 from schainpy.utils import log
27
23 28
24 MISSING = -32767
25 29 DEF_CATALOG = {
26 30 'principleInvestigator': 'Marco Milla',
27 31 'expPurpose': None,
28 32 'expMode': None,
29 33 'cycleTime': None,
30 34 'correlativeExp': None,
31 35 'sciRemarks': None,
32 36 'instRemarks': None
33 37 }
34 38 DEF_HEADER = {
35 39 'kindatDesc': None,
36 40 'analyst': 'Jicamarca User',
37 41 'comments': None,
38 42 'history': None
39 43 }
40 44 MNEMONICS = {
41 45 10: 'jro',
42 46 11: 'jbr',
43 47 840: 'jul',
44 48 13: 'jas',
45 49 1000: 'pbr',
46 50 1001: 'hbr',
47 51 1002: 'obr',
48 52 }
49 53
54 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
55
50 56 def load_json(obj):
51 57 '''
52 58 Parse json as string instead of unicode
53 59 '''
54 60
55 61 if isinstance(obj, str):
56 obj = json.loads(obj)
62 iterable = json.loads(obj)
63
64 if isinstance(iterable, dict):
65 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, unicode) else v
66 for k, v in iterable.items()}
67 elif isinstance(iterable, (list, tuple)):
68 return [str(v) if isinstance(v, unicode) else v for v in iterable]
69
70 return iterable
71
72
73 class MADReader(JRODataReader, ProcessingUnit):
74
75 def __init__(self, **kwargs):
76
77 ProcessingUnit.__init__(self, **kwargs)
78
79 self.dataOut = Parameters()
80 self.counter_records = 0
81 self.nrecords = None
82 self.flagNoMoreFiles = 0
83 self.isConfig = False
84 self.filename = None
85 self.intervals = set()
86
87 def setup(self,
88 path=None,
89 startDate=None,
90 endDate=None,
91 format=None,
92 startTime=datetime.time(0, 0, 0),
93 endTime=datetime.time(23, 59, 59),
94 **kwargs):
95
96 self.started = True
97 self.path = path
98 self.startDate = startDate
99 self.endDate = endDate
100 self.startTime = startTime
101 self.endTime = endTime
102 self.datatime = datetime.datetime(1900,1,1)
103 self.oneDDict = load_json(kwargs.get('oneDDict',
104 "{\"GDLATR\":\"lat\", \"GDLONR\":\"lon\"}"))
105 self.twoDDict = load_json(kwargs.get('twoDDict',
106 "{\"GDALT\": \"heightList\"}"))
107 self.ind2DList = load_json(kwargs.get('ind2DList',
108 "[\"GDALT\"]"))
109 if self.path is None:
110 raise ValueError, 'The path is not valid'
111
112 if format is None:
113 raise ValueError, 'The format is not valid choose simple or hdf5'
114 elif format.lower() in ('simple', 'txt'):
115 self.ext = '.txt'
116 elif format.lower() in ('cedar',):
117 self.ext = '.001'
118 else:
119 self.ext = '.hdf5'
120
121 self.search_files(self.path)
122 self.fileId = 0
123
124 if not self.fileList:
125 raise Warning, 'There is no files matching these date in the folder: {}. \n Check startDate and endDate'.format(path)
126
127 self.setNextFile()
128
129 def search_files(self, path):
130 '''
131 Searching for madrigal files in path
132 Creating a list of files to procces included in [startDate,endDate]
133
134 Input:
135 path - Path to find files
136 '''
137
138 print 'Searching files {} in {} '.format(self.ext, path)
139 foldercounter = 0
140 fileList0 = glob.glob1(path, '*{}'.format(self.ext))
141 fileList0.sort()
142
143 self.fileList = []
144 self.dateFileList = []
57 145
58 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, unicode) else v
59 for k, v in obj.items()}
146 startDate = self.startDate - datetime.timedelta(1)
147 endDate = self.endDate + datetime.timedelta(1)
148
149 for thisFile in fileList0:
150 year = thisFile[3:7]
151 if not year.isdigit():
152 continue
153
154 month = thisFile[7:9]
155 if not month.isdigit():
156 continue
157
158 day = thisFile[9:11]
159 if not day.isdigit():
160 continue
161
162 year, month, day = int(year), int(month), int(day)
163 dateFile = datetime.date(year, month, day)
164
165 if (startDate > dateFile) or (endDate < dateFile):
166 continue
167
168 self.fileList.append(thisFile)
169 self.dateFileList.append(dateFile)
170
171 return
172
173 def parseHeader(self):
174 '''
175 '''
176
177 self.output = {}
178 self.version = '2'
179 s_parameters = None
180 if self.ext == '.txt':
181 self.parameters = [s.strip().lower() for s in self.fp.readline().strip().split(' ') if s]
182 elif self.ext == '.hdf5':
183 metadata = self.fp['Metadata']
184 data = self.fp['Data']['Array Layout']
185 if 'Independent Spatial Parameters' in metadata:
186 s_parameters = [s[0].lower() for s in metadata['Independent Spatial Parameters']]
187 self.version = '3'
188 one = [s[0].lower() for s in data['1D Parameters']['Data Parameters']]
189 one_d = [1 for s in one]
190 two = [s[0].lower() for s in data['2D Parameters']['Data Parameters']]
191 two_d = [2 for s in two]
192 self.parameters = one + two
193 self.parameters_d = one_d + two_d
194
195 log.success('Parameters found: {}'.format(','.join(self.parameters)),
196 'MADReader')
197 if s_parameters:
198 log.success('Spatial parameters: {}'.format(','.join(s_parameters)),
199 'MADReader')
200
201 for param in self.oneDDict.keys():
202 if param.lower() not in self.parameters:
203 print('\x1b[33m[Warning]\x1b[0m Parameter \x1b[1;32m{}\x1b[0m not found will be ignored'.format(
204 param
205 ))
206 self.oneDDict.pop(param, None)
207
208 for param, value in self.twoDDict.items():
209 if param.lower() not in self.parameters:
210 print('\x1b[33m[Warning]\x1b[0m Parameter \x1b[1;32m{}\x1b[0m not found will be ignored'.format(
211 param
212 ))
213 self.twoDDict.pop(param, None)
214 continue
215 if isinstance(value, list):
216 if value[0] not in self.output:
217 self.output[value[0]] = []
218 self.output[value[0]].append(None)
219
220 def parseData(self):
221 '''
222 '''
223
224 if self.ext == '.txt':
225 self.data = numpy.genfromtxt(self.fp, missing_values=('missing'))
226 self.nrecords = self.data.shape[0]
227 self.ranges = numpy.unique(self.data[:,self.parameters.index(self.ind2DList[0].lower())])
228 elif self.ext == '.hdf5':
229 self.data = self.fp['Data']['Array Layout']
230 self.nrecords = len(self.data['timestamps'].value)
231 self.ranges = self.data['range'].value
232
233 def setNextFile(self):
234 '''
235 '''
236
237 file_id = self.fileId
238
239 if file_id == len(self.fileList):
240 print '\nNo more files in the folder'
241 print 'Total number of file(s) read : {}'.format(self.fileId)
242 self.flagNoMoreFiles = 1
243 return 0
244
245 print('\x1b[32m[Info]\x1b[0m Opening: {}'.format(
246 self.fileList[file_id]
247 ))
248 filename = os.path.join(self.path, self.fileList[file_id])
249
250 if self.filename is not None:
251 self.fp.close()
252
253 self.filename = filename
254 self.filedate = self.dateFileList[file_id]
255
256 if self.ext=='.hdf5':
257 self.fp = h5py.File(self.filename, 'r')
258 else:
259 self.fp = open(self.filename, 'rb')
260
261 self.parseHeader()
262 self.parseData()
263 self.sizeOfFile = os.path.getsize(self.filename)
264 self.counter_records = 0
265 self.flagIsNewFile = 0
266 self.fileId += 1
267
268 return 1
269
270 def readNextBlock(self):
271
272 while True:
273
274 if self.flagIsNewFile:
275 if not self.setNextFile():
276 return 0
277
278 self.readBlock()
279
280 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
281 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
282 print "\x1b[32m[Reading]\x1b[0m Record No. %d/%d -> %s \x1b[33m[Skipping]\x1b[0m" %(
283 self.counter_records,
284 self.nrecords,
285 self.datatime.ctime())
286 continue
287 break
288
289 print "\x1b[32m[Reading]\x1b[0m Record No. %d/%d -> %s" %(
290 self.counter_records,
291 self.nrecords,
292 self.datatime.ctime())
293
294 return 1
295
296 def readBlock(self):
297 '''
298 '''
299 dum = []
300 if self.ext == '.txt':
301 dt = self.data[self.counter_records][:6].astype(int)
302 self.datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
303 while True:
304 dt = self.data[self.counter_records][:6].astype(int)
305 datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
306 if datatime == self.datatime:
307 dum.append(self.data[self.counter_records])
308 self.counter_records += 1
309 if self.counter_records == self.nrecords:
310 self.flagIsNewFile = True
311 break
312 continue
313 self.intervals.add((datatime-self.datatime).seconds)
314 break
315 elif self.ext == '.hdf5':
316 datatime = datetime.datetime.utcfromtimestamp(
317 self.data['timestamps'][self.counter_records])
318 nHeights = len(self.ranges)
319 for n, param in enumerate(self.parameters):
320 if self.parameters_d[n] == 1:
321 dum.append(numpy.ones(nHeights)*self.data['1D Parameters'][param][self.counter_records])
322 else:
323 if self.version == '2':
324 dum.append(self.data['2D Parameters'][param][self.counter_records])
325 else:
326 tmp = self.data['2D Parameters'][param].value.T
327 dum.append(tmp[self.counter_records])
328 self.intervals.add((datatime-self.datatime).seconds)
329 self.datatime = datatime
330 self.counter_records += 1
331 if self.counter_records == self.nrecords:
332 self.flagIsNewFile = True
333
334 self.buffer = numpy.array(dum)
335 return
336
337 def set_output(self):
338 '''
339 Storing data from buffer to dataOut object
340 '''
341
342 parameters = [None for __ in self.parameters]
343
344 for param, attr in self.oneDDict.items():
345 x = self.parameters.index(param.lower())
346 setattr(self.dataOut, attr, self.buffer[0][x])
347
348 for param, value in self.twoDDict.items():
349 x = self.parameters.index(param.lower())
350 if self.ext == '.txt':
351 y = self.parameters.index(self.ind2DList[0].lower())
352 ranges = self.buffer[:,y]
353 if self.ranges.size == ranges.size:
354 continue
355 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
356 dummy = numpy.zeros(self.ranges.shape) + numpy.nan
357 dummy[index] = self.buffer[:,x]
358 else:
359
360 dummy = self.buffer[x]
361
362 if isinstance(value, str):
363 if value not in self.ind2DList:
364 setattr(self.dataOut, value, dummy.reshape(1,-1))
365 elif isinstance(value, list):
366 self.output[value[0]][value[1]] = dummy
367 parameters[value[1]] = param
368
369 for key, value in self.output.items():
370 setattr(self.dataOut, key, numpy.array(value))
371
372 self.dataOut.parameters = [s for s in parameters if s]
373 self.dataOut.heightList = self.ranges
374 self.dataOut.utctime = (self.datatime - UT1970).total_seconds()
375 self.dataOut.utctimeInit = self.dataOut.utctime
376 self.dataOut.paramInterval = min(self.intervals)
377 self.dataOut.useLocalTime = False
378 self.dataOut.flagNoData = False
379 self.dataOut.started = self.started
380
381 def getData(self):
382 '''
383 Storing data from databuffer to dataOut object
384 '''
385 if self.flagNoMoreFiles:
386 self.dataOut.flagNoData = True
387 print 'No file left to process'
388 return 0
389
390 if not self.readNextBlock():
391 self.dataOut.flagNoData = True
392 return 0
393
394 self.set_output()
395
396 return 1
60 397
61 398
62 399 class MAD2Writer(Operation):
400
401 missing = -32767
402 ext = '.dat'
63 403
64 404 def __init__(self, **kwargs):
65 405
66 406 Operation.__init__(self, **kwargs)
67 407 self.dataOut = Parameters()
68 408 self.path = None
69 409 self.dataOut = None
70 self.ext = '.dat'
71
72 return
73 410
74 def run(self, dataOut, path, oneDList, twoDParam='', twoDList='{}', metadata='{}', **kwargs):
411 def run(self, dataOut, path, oneDDict, ind2DList='[]', twoDDict='{}', metadata='{}', **kwargs):
75 412 '''
76 413 Inputs:
77 414 path - path where files will be created
78 oneDList - json of one-dimensional parameters in record where keys
415 oneDDict - json of one-dimensional parameters in record where keys
79 416 are Madrigal codes (integers or mnemonics) and values the corresponding
80 417 dataOut attribute e.g: {
81 418 'gdlatr': 'lat',
82 419 'gdlonr': 'lon',
83 420 'gdlat2':'lat',
84 421 'glon2':'lon'}
85 twoDParam - independent parameter to get the number of rows e.g:
86 heighList
87 twoDList - json of two-dimensional parameters in record where keys
422 ind2DList - list of independent spatial two-dimensional parameters e.g:
423 ['heighList']
424 twoDDict - json of two-dimensional parameters in record where keys
88 425 are Madrigal codes (integers or mnemonics) and values the corresponding
89 426 dataOut attribute if multidimensional array specify as tupple
90 427 ('attr', pos) e.g: {
91 428 'gdalt': 'heightList',
92 429 'vn1p2': ('data_output', 0),
93 430 'vn2p2': ('data_output', 1),
94 431 'vn3': ('data_output', 2),
95 432 'snl': ('data_SNR', 'db')
96 433 }
97 434 metadata - json of madrigal metadata (kinst, kindat, catalog and header)
98 435 '''
99 436 if not self.isConfig:
100 self.setup(dataOut, path, oneDList, twoDParam, twoDList, metadata, **kwargs)
437 self.setup(dataOut, path, oneDDict, ind2DList, twoDDict, metadata, **kwargs)
101 438 self.isConfig = True
102 439
103 440 self.putData()
104 441 return
105 442
106 def setup(self, dataOut, path, oneDList, twoDParam, twoDList, metadata, **kwargs):
443 def setup(self, dataOut, path, oneDDict, ind2DList, twoDDict, metadata, **kwargs):
107 444 '''
108 445 Configure Operation
109 446 '''
110 447
111 448 self.dataOut = dataOut
112 449 self.nmodes = self.dataOut.nmodes
113 450 self.path = path
114 451 self.blocks = kwargs.get('blocks', None)
115 452 self.counter = 0
116 self.oneDList = load_json(oneDList)
117 self.twoDList = load_json(twoDList)
118 self.twoDParam = twoDParam
453 self.oneDDict = load_json(oneDDict)
454 self.twoDDict = load_json(twoDDict)
455 self.ind2DList = load_json(ind2DList)
119 456 meta = load_json(metadata)
120 457 self.kinst = meta.get('kinst')
121 458 self.kindat = meta.get('kindat')
122 459 self.catalog = meta.get('catalog', DEF_CATALOG)
123 460 self.header = meta.get('header', DEF_HEADER)
124 461
125 462 return
126 463
127 464 def setFile(self):
128 465 '''
129 466 Create new cedar file object
130 467 '''
131 468
132 469 self.mnemonic = MNEMONICS[self.kinst] #TODO get mnemonic from madrigal
133 470 date = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
134 471
135 472 filename = '%s%s_%s%s' % (self.mnemonic,
136 473 date.strftime('%Y%m%d_%H%M%S'),
137 474 self.dataOut.mode,
138 475 self.ext)
139 476
140 477 self.fullname = os.path.join(self.path, filename)
141 478
142 479 if os.path.isfile(self.fullname) :
143 480 print "Destination path '%s' already exists. Previous file deleted. " %self.fullname
144 481 os.remove(self.fullname)
145 482
146 483 try:
147 484 print '[Writing] creating file : %s' % (self.fullname)
148 485 self.cedarObj = madrigal.cedar.MadrigalCedarFile(self.fullname, True)
149 486 except ValueError, e:
150 487 print '[Error]: Impossible to create a cedar object with "madrigal.cedar.MadrigalCedarFile" '
151 488 return
152 489
153 490 return 1
154 491
155 492 def writeBlock(self):
156 493 '''
157 Add data records to cedar file taking data from oneDList and twoDList
494 Add data records to cedar file taking data from oneDDict and twoDDict
158 495 attributes.
159 496 Allowed parameters in: parcodes.tab
160 497 '''
161 498
162 499 startTime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
163 500 endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
164 nrows = len(getattr(self.dataOut, self.twoDParam))
501 nrows = len(getattr(self.dataOut, self.ind2DList))
165 502
166 503 rec = madrigal.cedar.MadrigalDataRecord(
167 504 self.kinst,
168 505 self.kindat,
169 506 startTime.year,
170 507 startTime.month,
171 508 startTime.day,
172 509 startTime.hour,
173 510 startTime.minute,
174 511 startTime.second,
175 512 startTime.microsecond/10000,
176 513 endTime.year,
177 514 endTime.month,
178 515 endTime.day,
179 516 endTime.hour,
180 517 endTime.minute,
181 518 endTime.second,
182 519 endTime.microsecond/10000,
183 self.oneDList.keys(),
184 self.twoDList.keys(),
520 self.oneDDict.keys(),
521 self.twoDDict.keys(),
185 522 nrows
186 523 )
187 524
188 525 # Setting 1d values
189 for key in self.oneDList:
190 rec.set1D(key, getattr(self.dataOut, self.oneDList[key]))
526 for key in self.oneDDict:
527 rec.set1D(key, getattr(self.dataOut, self.oneDDict[key]))
191 528
192 529 # Setting 2d values
193 530 invalid = numpy.isnan(self.dataOut.data_output)
194 self.dataOut.data_output[invalid] = MISSING
531 self.dataOut.data_output[invalid] = self.missing
195 532 out = {}
196 for key, value in self.twoDList.items():
533 for key, value in self.twoDDict.items():
197 534 if isinstance(value, str):
198 535 out[key] = getattr(self.dataOut, value)
199 536 elif isinstance(value, tuple):
200 537 attr, x = value
201 538 if isinstance(x, (int, float)):
202 539 out[key] = getattr(self.dataOut, attr)[int(x)]
203 540 elif x.lower()=='db':
204 541 tmp = getattr(self.dataOut, attr)
205 542 SNRavg = numpy.average(tmp, axis=0)
206 543 out[key] = 10*numpy.log10(SNRavg)
207 544
208 545 for n in range(nrows):
209 546 for key in out:
210 547 rec.set2D(key, n, out[key][n])
211 548
212 549 self.cedarObj.append(rec)
213 550 self.cedarObj.dump()
214 551 print '[Writing] Record No. {} (mode {}).'.format(
215 552 self.counter,
216 553 self.dataOut.mode
217 554 )
218 555
219 556 def setHeader(self):
220 557 '''
221 558 Create an add catalog and header to cedar file
222 559 '''
223 560
224 561 header = madrigal.cedar.CatalogHeaderCreator(self.fullname)
225 562 header.createCatalog(**self.catalog)
226 563 header.createHeader(**self.header)
227 564 header.write()
228 565
229 566 def putData(self):
230 567
231 568 if self.dataOut.flagNoData:
232 569 return 0
233 570
234 571 if self.counter == 0:
235 572 self.setFile()
236 573
237 574 if self.counter <= self.dataOut.nrecords:
238 575 self.writeBlock()
239 576 self.counter += 1
240 577
241 578 if self.counter == self.dataOut.nrecords or self.counter == self.blocks:
242 579 self.setHeader()
243 580 self.counter = 0
@@ -1,707 +1,698
1 1 '''
2 2 Created on Jul 2, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import numpy
7 7
8 8 from jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
9 9 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
10 10 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
11 11 from schainpy.model.data.jrodata import Spectra
12 12
13 13 class SpectraReader(JRODataReader, ProcessingUnit):
14 14
15 15 """
16 16 Esta clase permite leer datos de espectros desde archivos procesados (.pdata). La lectura
17 17 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones)
18 18 son almacenados en tres buffer's para el Self Spectra, el Cross Spectra y el DC Channel.
19 19
20 20 paresCanalesIguales * alturas * perfiles (Self Spectra)
21 21 paresCanalesDiferentes * alturas * perfiles (Cross Spectra)
22 22 canales * alturas (DC Channels)
23 23
24 24
25 25 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
26 26 RadarControllerHeader y Spectra. Los tres primeros se usan para almacenar informacion de la
27 27 cabecera de datos (metadata), y el cuarto (Spectra) para obtener y almacenar un bloque de
28 28 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
29 29
30 30 Example:
31 31 dpath = "/home/myuser/data"
32 32
33 33 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
34 34
35 35 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
36 36
37 37 readerObj = SpectraReader()
38 38
39 39 readerObj.setup(dpath, startTime, endTime)
40 40
41 41 while(True):
42 42
43 43 readerObj.getData()
44 44
45 45 print readerObj.data_spc
46 46
47 47 print readerObj.data_cspc
48 48
49 49 print readerObj.data_dc
50 50
51 51 if readerObj.flagNoMoreFiles:
52 52 break
53 53
54 54 """
55 55
56 56 pts2read_SelfSpectra = 0
57 57
58 58 pts2read_CrossSpectra = 0
59 59
60 60 pts2read_DCchannels = 0
61 61
62 62 ext = ".pdata"
63 63
64 64 optchar = "P"
65 65
66 66 dataOut = None
67 67
68 68 nRdChannels = None
69 69
70 70 nRdPairs = None
71 71
72 72 rdPairList = []
73 73
74 74 def __init__(self, **kwargs):
75 75 """
76 76 Inicializador de la clase SpectraReader para la lectura de datos de espectros.
77 77
78 78 Inputs:
79 79
80 80 dataOut : Objeto de la clase Spectra. Este objeto sera utilizado para
81 81 almacenar un perfil de datos cada vez que se haga un requerimiento
82 82 (getData). El perfil sera obtenido a partir del buffer de datos,
83 83 si el buffer esta vacio se hara un nuevo proceso de lectura de un
84 84 bloque de datos.
85 85 Si este parametro no es pasado se creara uno internamente.
86 86
87 87
88 88 Affected:
89 89
90 90 self.dataOut
91 91
92 92 Return : None
93 93 """
94 94
95 95
96 96 #Eliminar de la base la herencia
97 97 ProcessingUnit.__init__(self, **kwargs)
98 98
99 99 # self.isConfig = False
100 100
101 101 self.pts2read_SelfSpectra = 0
102 102
103 103 self.pts2read_CrossSpectra = 0
104 104
105 105 self.pts2read_DCchannels = 0
106 106
107 107 self.datablock = None
108 108
109 109 self.utc = None
110 110
111 111 self.ext = ".pdata"
112 112
113 113 self.optchar = "P"
114 114
115 115 self.basicHeaderObj = BasicHeader(LOCALTIME)
116 116
117 117 self.systemHeaderObj = SystemHeader()
118 118
119 119 self.radarControllerHeaderObj = RadarControllerHeader()
120 120
121 121 self.processingHeaderObj = ProcessingHeader()
122 122
123 123 self.online = 0
124 124
125 125 self.fp = None
126 126
127 127 self.idFile = None
128 128
129 129 self.dtype = None
130 130
131 131 self.fileSizeByHeader = None
132 132
133 133 self.filenameList = []
134 134
135 135 self.filename = None
136 136
137 137 self.fileSize = None
138 138
139 139 self.firstHeaderSize = 0
140 140
141 141 self.basicHeaderSize = 24
142 142
143 143 self.pathList = []
144 144
145 145 self.lastUTTime = 0
146 146
147 147 self.maxTimeStep = 30
148 148
149 149 self.flagNoMoreFiles = 0
150 150
151 151 self.set = 0
152 152
153 153 self.path = None
154 154
155 155 self.delay = 60 #seconds
156 156
157 157 self.nTries = 3 #quantity tries
158 158
159 159 self.nFiles = 3 #number of files for searching
160 160
161 161 self.nReadBlocks = 0
162 162
163 163 self.flagIsNewFile = 1
164 164
165 165 self.__isFirstTimeOnline = 1
166 166
167 167 # self.ippSeconds = 0
168 168
169 169 self.flagDiscontinuousBlock = 0
170 170
171 171 self.flagIsNewBlock = 0
172 172
173 173 self.nTotalBlocks = 0
174 174
175 175 self.blocksize = 0
176 176
177 177 self.dataOut = self.createObjByDefault()
178 178
179 179 self.profileIndex = 1 #Always
180 180
181 181
182 182 def createObjByDefault(self):
183 183
184 184 dataObj = Spectra()
185 185
186 186 return dataObj
187 187
188 188 def __hasNotDataInBuffer(self):
189 189 return 1
190 190
191 191
192 192 def getBlockDimension(self):
193 193 """
194 194 Obtiene la cantidad de puntos a leer por cada bloque de datos
195 195
196 196 Affected:
197 197 self.nRdChannels
198 198 self.nRdPairs
199 199 self.pts2read_SelfSpectra
200 200 self.pts2read_CrossSpectra
201 201 self.pts2read_DCchannels
202 202 self.blocksize
203 203 self.dataOut.nChannels
204 204 self.dataOut.nPairs
205 205
206 206 Return:
207 207 None
208 208 """
209 209 self.nRdChannels = 0
210 210 self.nRdPairs = 0
211 211 self.rdPairList = []
212 212
213 213 for i in range(0, self.processingHeaderObj.totalSpectra*2, 2):
214 214 if self.processingHeaderObj.spectraComb[i] == self.processingHeaderObj.spectraComb[i+1]:
215 215 self.nRdChannels = self.nRdChannels + 1 #par de canales iguales
216 216
217 217 else:
218 218 self.nRdPairs = self.nRdPairs + 1 #par de canales diferentes
219 219 self.rdPairList.append((self.processingHeaderObj.spectraComb[i], self.processingHeaderObj.spectraComb[i+1]))
220 220
221 221 pts2read = self.processingHeaderObj.nHeights * self.processingHeaderObj.profilesPerBlock
222 222
223 223 self.pts2read_SelfSpectra = int(self.nRdChannels * pts2read)
224 224 self.blocksize = self.pts2read_SelfSpectra
225 225
226 226 if self.processingHeaderObj.flag_cspc:
227 227 self.pts2read_CrossSpectra = int(self.nRdPairs * pts2read)
228 228 self.blocksize += self.pts2read_CrossSpectra
229 229
230 230 if self.processingHeaderObj.flag_dc:
231 231 self.pts2read_DCchannels = int(self.systemHeaderObj.nChannels * self.processingHeaderObj.nHeights)
232 232 self.blocksize += self.pts2read_DCchannels
233 233
234 234 # self.blocksize = self.pts2read_SelfSpectra + self.pts2read_CrossSpectra + self.pts2read_DCchannels
235 235
236 236
237 237 def readBlock(self):
238 238 """
239 239 Lee el bloque de datos desde la posicion actual del puntero del archivo
240 240 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
241 241 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
242 242 es seteado a 0
243 243
244 244 Return: None
245 245
246 246 Variables afectadas:
247 247
248 248
249 249 self.flagIsNewFile
250 250 self.flagIsNewBlock
251 251 self.nTotalBlocks
252 252 self.data_spc
253 253 self.data_cspc
254 254 self.data_dc
255 255
256 256 Exceptions:
257 257 Si un bloque leido no es un bloque valido
258 258 """
259 print ' ======================================================== '
260 print ' '
261 print ' '
262 print self.processingHeaderObj.totalSpectra, 'TotalSpectra', type(self.processingHeaderObj.totalSpectra)
263 print self.processingHeaderObj.spectraComb, 'SpectraComb', type(self.processingHeaderObj.spectraComb)
264 print ' '
265 print ' '
266 print ' ======================================================== '
267
268 259
269 260 blockOk_flag = False
270 261 fpointer = self.fp.tell()
271 262
272 263 spc = numpy.fromfile( self.fp, self.dtype[0], self.pts2read_SelfSpectra )
273 264 spc = spc.reshape( (self.nRdChannels, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) ) #transforma a un arreglo 3D
274 265
275 266 if self.processingHeaderObj.flag_cspc:
276 267 cspc = numpy.fromfile( self.fp, self.dtype, self.pts2read_CrossSpectra )
277 268 cspc = cspc.reshape( (self.nRdPairs, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) ) #transforma a un arreglo 3D
278 269
279 270 if self.processingHeaderObj.flag_dc:
280 271 dc = numpy.fromfile( self.fp, self.dtype, self.pts2read_DCchannels ) #int(self.processingHeaderObj.nHeights*self.systemHeaderObj.nChannels) )
281 272 dc = dc.reshape( (self.systemHeaderObj.nChannels, self.processingHeaderObj.nHeights) ) #transforma a un arreglo 2D
282 273
283 274
284 275 if not(self.processingHeaderObj.shif_fft):
285 276 #desplaza a la derecha en el eje 2 determinadas posiciones
286 277 shift = int(self.processingHeaderObj.profilesPerBlock/2)
287 278 spc = numpy.roll( spc, shift , axis=2 )
288 279
289 280 if self.processingHeaderObj.flag_cspc:
290 281 #desplaza a la derecha en el eje 2 determinadas posiciones
291 282 cspc = numpy.roll( cspc, shift, axis=2 )
292 283
293 284 #Dimensions : nChannels, nProfiles, nSamples
294 285 spc = numpy.transpose( spc, (0,2,1) )
295 286 self.data_spc = spc
296 287
297 288 if self.processingHeaderObj.flag_cspc:
298 289
299 290 cspc = numpy.transpose( cspc, (0,2,1) )
300 291 self.data_cspc = cspc['real'] + cspc['imag']*1j
301 292 else:
302 293 self.data_cspc = None
303 294
304 295
305 296 if self.processingHeaderObj.flag_dc:
306 297 self.data_dc = dc['real'] + dc['imag']*1j
307 298 else:
308 299 self.data_dc = None
309 300
310 301 self.flagIsNewFile = 0
311 302 self.flagIsNewBlock = 1
312 303
313 304 self.nTotalBlocks += 1
314 305 self.nReadBlocks += 1
315 306
316 307 return 1
317 308
318 309 def getFirstHeader(self):
319 310
320 311 self.getBasicHeader()
321 312
322 313 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
323 314
324 315 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
325 316
326 317 # self.dataOut.ippSeconds = self.ippSeconds
327 318
328 319 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt * self.processingHeaderObj.nIncohInt * self.processingHeaderObj.profilesPerBlock
329 320
330 321 self.dataOut.dtype = self.dtype
331 322
332 323 # self.dataOut.nPairs = self.nPairs
333 324
334 325 self.dataOut.pairsList = self.rdPairList
335 326
336 327 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
337 328
338 329 self.dataOut.nFFTPoints = self.processingHeaderObj.profilesPerBlock
339 330
340 331 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
341 332
342 333 self.dataOut.nIncohInt = self.processingHeaderObj.nIncohInt
343 334
344 335 xf = self.processingHeaderObj.firstHeight + self.processingHeaderObj.nHeights*self.processingHeaderObj.deltaHeight
345 336
346 337 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.firstHeight, xf, self.processingHeaderObj.deltaHeight)
347 338
348 339 self.dataOut.channelList = range(self.systemHeaderObj.nChannels)
349 340
350 341 self.dataOut.flagShiftFFT = True #Data is always shifted
351 342
352 343 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode #asumo q la data no esta decodificada
353 344
354 345 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip #asumo q la data esta sin flip
355 346
356 347 def getData(self):
357 348 """
358 349 First method to execute before "RUN" is called.
359 350
360 351 Copia el buffer de lectura a la clase "Spectra",
361 352 con todos los parametros asociados a este (metadata). cuando no hay datos en el buffer de
362 353 lectura es necesario hacer una nueva lectura de los bloques de datos usando "readNextBlock"
363 354
364 355 Return:
365 356 0 : Si no hay mas archivos disponibles
366 357 1 : Si hizo una buena copia del buffer
367 358
368 359 Affected:
369 360 self.dataOut
370 361
371 362 self.flagDiscontinuousBlock
372 363 self.flagIsNewBlock
373 364 """
374 365
375 366 if self.flagNoMoreFiles:
376 367 self.dataOut.flagNoData = True
377 368 print 'Process finished'
378 369 return 0
379 370
380 371 self.flagDiscontinuousBlock = 0
381 372 self.flagIsNewBlock = 0
382 373
383 374 if self.__hasNotDataInBuffer():
384 375
385 376 if not( self.readNextBlock() ):
386 377 self.dataOut.flagNoData = True
387 378 return 0
388 379
389 380
390 381 #data es un numpy array de 3 dmensiones (perfiles, alturas y canales)
391 382
392 383 if self.data_spc is None:
393 384 self.dataOut.flagNoData = True
394 385 return 0
395 386
396 387 self.getBasicHeader()
397 388
398 389 self.getFirstHeader()
399 390
400 391 self.dataOut.data_spc = self.data_spc
401 392
402 393 self.dataOut.data_cspc = self.data_cspc
403 394
404 395 self.dataOut.data_dc = self.data_dc
405 396
406 397 self.dataOut.flagNoData = False
407 398
408 399 self.dataOut.realtime = self.online
409 400
410 401 return self.dataOut.data_spc
411 402
412 403 class SpectraWriter(JRODataWriter, Operation):
413 404
414 405 """
415 406 Esta clase permite escribir datos de espectros a archivos procesados (.pdata). La escritura
416 407 de los datos siempre se realiza por bloques.
417 408 """
418 409
419 410 ext = ".pdata"
420 411
421 412 optchar = "P"
422 413
423 414 shape_spc_Buffer = None
424 415
425 416 shape_cspc_Buffer = None
426 417
427 418 shape_dc_Buffer = None
428 419
429 420 data_spc = None
430 421
431 422 data_cspc = None
432 423
433 424 data_dc = None
434 425
435 426 # dataOut = None
436 427
437 428 def __init__(self):
438 429 """
439 430 Inicializador de la clase SpectraWriter para la escritura de datos de espectros.
440 431
441 432 Affected:
442 433
443 434 self.dataOut
444 435 self.basicHeaderObj
445 436 self.systemHeaderObj
446 437 self.radarControllerHeaderObj
447 438 self.processingHeaderObj
448 439
449 440 Return: None
450 441 """
451 442
452 443 Operation.__init__(self)
453 444
454 445 self.isConfig = False
455 446
456 447 self.nTotalBlocks = 0
457 448
458 449 self.data_spc = None
459 450
460 451 self.data_cspc = None
461 452
462 453
463 454 self.data_dc = None
464 455
465 456 self.fp = None
466 457
467 458 self.flagIsNewFile = 1
468 459
469 460 self.nTotalBlocks = 0
470 461
471 462 self.flagIsNewBlock = 0
472 463
473 464 self.setFile = None
474 465
475 466 self.dtype = None
476 467
477 468 self.path = None
478 469
479 470 self.noMoreFiles = 0
480 471
481 472 self.filename = None
482 473
483 474 self.basicHeaderObj = BasicHeader(LOCALTIME)
484 475
485 476 self.systemHeaderObj = SystemHeader()
486 477
487 478 self.radarControllerHeaderObj = RadarControllerHeader()
488 479
489 480 self.processingHeaderObj = ProcessingHeader()
490 481
491 482
492 483 def hasAllDataInBuffer(self):
493 484 return 1
494 485
495 486
496 487
497 488 def setBlockDimension(self):
498 489 """
499 490 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
500 491
501 492 Affected:
502 493 self.shape_spc_Buffer
503 494 self.shape_cspc_Buffer
504 495 self.shape_dc_Buffer
505 496
506 497 Return: None
507 498 """
508 499 self.shape_spc_Buffer = (self.dataOut.nChannels,
509 500 self.processingHeaderObj.nHeights,
510 501 self.processingHeaderObj.profilesPerBlock)
511 502
512 503 self.shape_cspc_Buffer = (self.dataOut.nPairs,
513 504 self.processingHeaderObj.nHeights,
514 505 self.processingHeaderObj.profilesPerBlock)
515 506
516 507 self.shape_dc_Buffer = (self.dataOut.nChannels,
517 508 self.processingHeaderObj.nHeights)
518 509
519 510
520 511 def writeBlock(self):
521 512 """
522 513 Escribe el buffer en el file designado
523 514
524 515
525 516 Affected:
526 517 self.data_spc
527 518 self.data_cspc
528 519 self.data_dc
529 520 self.flagIsNewFile
530 521 self.flagIsNewBlock
531 522 self.nTotalBlocks
532 523 self.nWriteBlocks
533 524
534 525 Return: None
535 526 """
536 527
537 528 spc = numpy.transpose( self.data_spc, (0,2,1) )
538 529 if not( self.processingHeaderObj.shif_fft ):
539 530 spc = numpy.roll( spc, self.processingHeaderObj.profilesPerBlock/2, axis=2 ) #desplaza a la derecha en el eje 2 determinadas posiciones
540 531 data = spc.reshape((-1))
541 532 data = data.astype(self.dtype[0])
542 533 data.tofile(self.fp)
543 534
544 535 if self.data_cspc is not None:
545 536 data = numpy.zeros( self.shape_cspc_Buffer, self.dtype )
546 537 cspc = numpy.transpose( self.data_cspc, (0,2,1) )
547 538 if not( self.processingHeaderObj.shif_fft ):
548 539 cspc = numpy.roll( cspc, self.processingHeaderObj.profilesPerBlock/2, axis=2 ) #desplaza a la derecha en el eje 2 determinadas posiciones
549 540 data['real'] = cspc.real
550 541 data['imag'] = cspc.imag
551 542 data = data.reshape((-1))
552 543 data.tofile(self.fp)
553 544
554 545
555 546 if self.data_dc is not None:
556 547 data = numpy.zeros( self.shape_dc_Buffer, self.dtype )
557 548 dc = self.data_dc
558 549 data['real'] = dc.real
559 550 data['imag'] = dc.imag
560 551 data = data.reshape((-1))
561 552 data.tofile(self.fp)
562 553
563 554 # self.data_spc.fill(0)
564 555 #
565 556 # if self.data_dc is not None:
566 557 # self.data_dc.fill(0)
567 558 #
568 559 # if self.data_cspc is not None:
569 560 # self.data_cspc.fill(0)
570 561
571 562
572 563 self.flagIsNewFile = 0
573 564 self.flagIsNewBlock = 1
574 565 self.nTotalBlocks += 1
575 566 self.nWriteBlocks += 1
576 567 self.blockIndex += 1
577 568
578 569 # print "[Writing] Block = %d04" %self.blockIndex
579 570
580 571 def putData(self):
581 572 """
582 573 Setea un bloque de datos y luego los escribe en un file
583 574
584 575
585 576 Affected:
586 577 self.data_spc
587 578 self.data_cspc
588 579 self.data_dc
589 580
590 581 Return:
591 582 0 : Si no hay data o no hay mas files que puedan escribirse
592 583 1 : Si se escribio la data de un bloque en un file
593 584 """
594 585
595 586 if self.dataOut.flagNoData:
596 587 return 0
597 588
598 589 self.flagIsNewBlock = 0
599 590
600 591 if self.dataOut.flagDiscontinuousBlock:
601 592 self.data_spc.fill(0)
602 593 self.data_cspc.fill(0)
603 594 self.data_dc.fill(0)
604 595 self.setNextFile()
605 596
606 597 if self.flagIsNewFile == 0:
607 598 self.setBasicHeader()
608 599
609 600 self.data_spc = self.dataOut.data_spc.copy()
610 601
611 602 if self.dataOut.data_cspc is not None:
612 603 self.data_cspc = self.dataOut.data_cspc.copy()
613 604
614 605 if self.dataOut.data_dc is not None:
615 606 self.data_dc = self.dataOut.data_dc.copy()
616 607
617 608 # #self.processingHeaderObj.dataBlocksPerFile)
618 609 if self.hasAllDataInBuffer():
619 610 # self.setFirstHeader()
620 611 self.writeNextBlock()
621 612
622 613 return 1
623 614
624 615
625 616 def __getBlockSize(self):
626 617 '''
627 618 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Spectra
628 619 '''
629 620
630 621 dtype_width = self.getDtypeWidth()
631 622
632 623 pts2write = self.dataOut.nHeights * self.dataOut.nFFTPoints
633 624
634 625 pts2write_SelfSpectra = int(self.dataOut.nChannels * pts2write)
635 626 blocksize = (pts2write_SelfSpectra*dtype_width)
636 627
637 628 if self.dataOut.data_cspc is not None:
638 629 pts2write_CrossSpectra = int(self.dataOut.nPairs * pts2write)
639 630 blocksize += (pts2write_CrossSpectra*dtype_width*2)
640 631
641 632 if self.dataOut.data_dc is not None:
642 633 pts2write_DCchannels = int(self.dataOut.nChannels * self.dataOut.nHeights)
643 634 blocksize += (pts2write_DCchannels*dtype_width*2)
644 635
645 636 # blocksize = blocksize #* datatypeValue * 2 #CORREGIR ESTO
646 637
647 638 return blocksize
648 639
649 640 def setFirstHeader(self):
650 641
651 642 """
652 643 Obtiene una copia del First Header
653 644
654 645 Affected:
655 646 self.systemHeaderObj
656 647 self.radarControllerHeaderObj
657 648 self.dtype
658 649
659 650 Return:
660 651 None
661 652 """
662 653
663 654 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
664 655 self.systemHeaderObj.nChannels = self.dataOut.nChannels
665 656 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
666 657
667 658 self.processingHeaderObj.dtype = 1 # Spectra
668 659 self.processingHeaderObj.blockSize = self.__getBlockSize()
669 660 self.processingHeaderObj.profilesPerBlock = self.dataOut.nFFTPoints
670 661 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
671 662 self.processingHeaderObj.nWindows = 1 #podria ser 1 o self.dataOut.processingHeaderObj.nWindows
672 663 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt# Se requiere para determinar el valor de timeInterval
673 664 self.processingHeaderObj.nIncohInt = self.dataOut.nIncohInt
674 665 self.processingHeaderObj.totalSpectra = self.dataOut.nPairs + self.dataOut.nChannels
675 666 self.processingHeaderObj.shif_fft = self.dataOut.flagShiftFFT
676 667
677 668
678 669 if self.processingHeaderObj.totalSpectra > 0:
679 670 channelList = []
680 671 for channel in range(self.dataOut.nChannels):
681 672 channelList.append(channel)
682 673 channelList.append(channel)
683 674
684 675 pairsList = []
685 676 if self.dataOut.nPairs > 0:
686 677 for pair in self.dataOut.pairsList:
687 678 pairsList.append(pair[0])
688 679 pairsList.append(pair[1])
689 680
690 681 spectraComb = channelList + pairsList
691 682 spectraComb = numpy.array(spectraComb, dtype="u1")
692 683 self.processingHeaderObj.spectraComb = spectraComb
693 684
694 685 if self.dataOut.code is not None:
695 686 self.processingHeaderObj.code = self.dataOut.code
696 687 self.processingHeaderObj.nCode = self.dataOut.nCode
697 688 self.processingHeaderObj.nBaud = self.dataOut.nBaud
698 689
699 690 if self.processingHeaderObj.nWindows != 0:
700 691 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
701 692 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
702 693 self.processingHeaderObj.nHeights = self.dataOut.nHeights
703 694 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
704 695
705 696 self.processingHeaderObj.processFlags = self.getProcessFlags()
706 697
707 698 self.setBasicHeader()
@@ -1,4042 +1,4045
1 1 import numpy
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 4 import scipy
5 5 import re
6 6 import datetime
7 7 import copy
8 8 import sys
9 9 import importlib
10 10 import itertools
11 11 from multiprocessing import Pool, TimeoutError
12 12 from multiprocessing.pool import ThreadPool
13 13 import copy_reg
14 14 import cPickle
15 15 import types
16 16 from functools import partial
17 17 import time
18 18 #from sklearn.cluster import KMeans
19 19
20 20 import matplotlib.pyplot as plt
21 21
22 22 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
23 23 from jroproc_base import ProcessingUnit, Operation
24 24 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
25 25 from scipy import asarray as ar,exp
26 26 from scipy.optimize import curve_fit
27 27
28 28 import warnings
29 29 from numpy import NaN
30 30 from scipy.optimize.optimize import OptimizeWarning
31 31 warnings.filterwarnings('ignore')
32 32
33 33
34 34 SPEED_OF_LIGHT = 299792458
35 35
36 36
37 37 '''solving pickling issue'''
38 38
39 39 def _pickle_method(method):
40 40 func_name = method.im_func.__name__
41 41 obj = method.im_self
42 42 cls = method.im_class
43 43 return _unpickle_method, (func_name, obj, cls)
44 44
45 45 def _unpickle_method(func_name, obj, cls):
46 46 for cls in cls.mro():
47 47 try:
48 48 func = cls.__dict__[func_name]
49 49 except KeyError:
50 50 pass
51 51 else:
52 52 break
53 53 return func.__get__(obj, cls)
54 54
55 55 class ParametersProc(ProcessingUnit):
56 56
57 57 nSeconds = None
58 58
59 59 def __init__(self):
60 60 ProcessingUnit.__init__(self)
61 61
62 62 # self.objectDict = {}
63 63 self.buffer = None
64 64 self.firstdatatime = None
65 65 self.profIndex = 0
66 66 self.dataOut = Parameters()
67 67
68 68 def __updateObjFromInput(self):
69 69
70 70 self.dataOut.inputUnit = self.dataIn.type
71 71
72 72 self.dataOut.timeZone = self.dataIn.timeZone
73 73 self.dataOut.dstFlag = self.dataIn.dstFlag
74 74 self.dataOut.errorCount = self.dataIn.errorCount
75 75 self.dataOut.useLocalTime = self.dataIn.useLocalTime
76 76
77 77 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
78 78 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
79 79 self.dataOut.channelList = self.dataIn.channelList
80 80 self.dataOut.heightList = self.dataIn.heightList
81 81 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
82 82 # self.dataOut.nHeights = self.dataIn.nHeights
83 83 # self.dataOut.nChannels = self.dataIn.nChannels
84 84 self.dataOut.nBaud = self.dataIn.nBaud
85 85 self.dataOut.nCode = self.dataIn.nCode
86 86 self.dataOut.code = self.dataIn.code
87 87 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
88 88 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
89 89 # self.dataOut.utctime = self.firstdatatime
90 90 self.dataOut.utctime = self.dataIn.utctime
91 91 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
92 92 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
93 93 self.dataOut.nCohInt = self.dataIn.nCohInt
94 94 # self.dataOut.nIncohInt = 1
95 95 self.dataOut.ippSeconds = self.dataIn.ippSeconds
96 96 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
97 97 self.dataOut.timeInterval1 = self.dataIn.timeInterval
98 98 self.dataOut.heightList = self.dataIn.getHeiRange()
99 99 self.dataOut.frequency = self.dataIn.frequency
100 100 # self.dataOut.noise = self.dataIn.noise
101 101
102 102 def run(self):
103 103
104 104 #---------------------- Voltage Data ---------------------------
105 105
106 106 if self.dataIn.type == "Voltage":
107 107
108 108 self.__updateObjFromInput()
109 109 self.dataOut.data_pre = self.dataIn.data.copy()
110 110 self.dataOut.flagNoData = False
111 111 self.dataOut.utctimeInit = self.dataIn.utctime
112 112 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
113 113 return
114 114
115 115 #---------------------- Spectra Data ---------------------------
116 116
117 117 if self.dataIn.type == "Spectra":
118 118
119 119 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
120 120 self.dataOut.data_spc = self.dataIn.data_spc
121 121 self.dataOut.data_cspc = self.dataIn.data_cspc
122 122 self.dataOut.nProfiles = self.dataIn.nProfiles
123 123 self.dataOut.nIncohInt = self.dataIn.nIncohInt
124 124 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
125 125 self.dataOut.ippFactor = self.dataIn.ippFactor
126 126 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
127 127 self.dataOut.spc_noise = self.dataIn.getNoise()
128 128 self.dataOut.spc_range = (self.dataIn.getFreqRange(1)/1000. , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
129 129 self.dataOut.pairsList = self.dataIn.pairsList
130 130 self.dataOut.groupList = self.dataIn.pairsList
131 131 self.dataOut.flagNoData = False
132 132
133 133 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
134 134 self.dataOut.ChanDist = self.dataIn.ChanDist
135 135 else: self.dataOut.ChanDist = None
136 136
137 137 if hasattr(self.dataIn, 'VelRange'): #Velocities range
138 138 self.dataOut.VelRange = self.dataIn.VelRange
139 139 else: self.dataOut.VelRange = None
140 140
141 141 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
142 142 self.dataOut.RadarConst = self.dataIn.RadarConst
143 143
144 144 if hasattr(self.dataIn, 'NPW'): #NPW
145 145 self.dataOut.NPW = self.dataIn.NPW
146 146
147 147 if hasattr(self.dataIn, 'COFA'): #COFA
148 148 self.dataOut.COFA = self.dataIn.COFA
149 149
150 150
151 151
152 152 #---------------------- Correlation Data ---------------------------
153 153
154 154 if self.dataIn.type == "Correlation":
155 155 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
156 156
157 157 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
158 158 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
159 159 self.dataOut.groupList = (acf_pairs, ccf_pairs)
160 160
161 161 self.dataOut.abscissaList = self.dataIn.lagRange
162 162 self.dataOut.noise = self.dataIn.noise
163 163 self.dataOut.data_SNR = self.dataIn.SNR
164 164 self.dataOut.flagNoData = False
165 165 self.dataOut.nAvg = self.dataIn.nAvg
166 166
167 167 #---------------------- Parameters Data ---------------------------
168 168
169 169 if self.dataIn.type == "Parameters":
170 170 self.dataOut.copy(self.dataIn)
171 171 self.dataOut.flagNoData = False
172 172
173 173 return True
174 174
175 175 self.__updateObjFromInput()
176 176 self.dataOut.utctimeInit = self.dataIn.utctime
177 177 self.dataOut.paramInterval = self.dataIn.timeInterval
178 178
179 179 return
180 180
181 181
182 182 def target(tups):
183 183
184 184 obj, args = tups
185 185 #print 'TARGETTT', obj, args
186 186 return obj.FitGau(args)
187 187
188 188 class GaussianFit(Operation):
189 189
190 190 '''
191 191 Function that fit of one and two generalized gaussians (gg) based
192 192 on the PSD shape across an "power band" identified from a cumsum of
193 193 the measured spectrum - noise.
194 194
195 195 Input:
196 196 self.dataOut.data_pre : SelfSpectra
197 197
198 198 Output:
199 199 self.dataOut.GauSPC : SPC_ch1, SPC_ch2
200 200
201 201 '''
202 202 def __init__(self, **kwargs):
203 203 Operation.__init__(self, **kwargs)
204 204 self.i=0
205 205
206 206
207 207 def run(self, dataOut, num_intg=7, pnoise=1., vel_arr=None, SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
208 208 """This routine will find a couple of generalized Gaussians to a power spectrum
209 209 input: spc
210 210 output:
211 211 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
212 212 """
213 213
214 214 self.spc = dataOut.data_pre[0].copy()
215 215
216 216
217 217 print 'SelfSpectra Shape', numpy.asarray(self.spc).shape
218 218
219 219
220 220 #plt.figure(50)
221 221 #plt.subplot(121)
222 222 #plt.plot(self.spc,'k',label='spc(66)')
223 223 #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
224 224 #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
225 225 #plt.plot(xFrec,FitGauss,'yo:',label='fit')
226 226 #plt.legend()
227 227 #plt.title('DATOS A ALTURA DE 7500 METROS')
228 228 #plt.show()
229 229
230 230 self.Num_Hei = self.spc.shape[2]
231 231 #self.Num_Bin = len(self.spc)
232 232 self.Num_Bin = self.spc.shape[1]
233 233 self.Num_Chn = self.spc.shape[0]
234 234
235 235 Vrange = dataOut.abscissaList
236 236
237 237 #print 'self.spc2', numpy.asarray(self.spc).shape
238 238
239 239 GauSPC = numpy.empty([2,self.Num_Bin,self.Num_Hei])
240 240 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
241 241 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
242 242 SPC_ch1[:] = numpy.NaN
243 243 SPC_ch2[:] = numpy.NaN
244 244
245 245
246 246 start_time = time.time()
247 247
248 248 noise_ = dataOut.spc_noise[0].copy()
249 249
250 250
251 251
252 252 pool = Pool(processes=self.Num_Chn)
253 253 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
254 254 objs = [self for __ in range(self.Num_Chn)]
255 255 attrs = zip(objs, args)
256 256 gauSPC = pool.map(target, attrs)
257 257 dataOut.GauSPC = numpy.asarray(gauSPC)
258 258 # ret = []
259 259 # for n in range(self.Num_Chn):
260 260 # self.FitGau(args[n])
261 261 # dataOut.GauSPC = ret
262 262
263 263
264 264
265 265 # for ch in range(self.Num_Chn):
266 266 #
267 267 # for ht in range(self.Num_Hei):
268 268 # #print (numpy.asarray(self.spc).shape)
269 269 # spc = numpy.asarray(self.spc)[ch,:,ht]
270 270 #
271 271 # #############################################
272 272 # # normalizing spc and noise
273 273 # # This part differs from gg1
274 274 # spc_norm_max = max(spc)
275 275 # spc = spc / spc_norm_max
276 276 # pnoise = pnoise / spc_norm_max
277 277 # #############################################
278 278 #
279 279 # if abs(vel_arr[0])<15.0: # this switch is for spectra collected with different length IPP's
280 280 # fatspectra=1.0
281 281 # else:
282 282 # fatspectra=0.5
283 283 #
284 284 # wnoise = noise_ / spc_norm_max
285 285 # #print 'wnoise', noise_, dataOut.spc_noise[0], wnoise
286 286 # #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
287 287 # #if wnoise>1.1*pnoise: # to be tested later
288 288 # # wnoise=pnoise
289 289 # noisebl=wnoise*0.9; noisebh=wnoise*1.1
290 290 # spc=spc-wnoise
291 291 #
292 292 # minx=numpy.argmin(spc)
293 293 # spcs=numpy.roll(spc,-minx)
294 294 # cum=numpy.cumsum(spcs)
295 295 # tot_noise=wnoise * self.Num_Bin #64;
296 296 # #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
297 297 # #snr=tot_signal/tot_noise
298 298 # #snr=cum[-1]/tot_noise
299 299 #
300 300 # #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
301 301 #
302 302 # snr = sum(spcs)/tot_noise
303 303 # snrdB=10.*numpy.log10(snr)
304 304 #
305 305 # #if snrdB < -9 :
306 306 # # snrdB = numpy.NaN
307 307 # # continue
308 308 #
309 309 # #print 'snr',snrdB # , sum(spcs) , tot_noise
310 310 #
311 311 #
312 312 # #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
313 313 # # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
314 314 #
315 315 # cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
316 316 # cumlo=cummax*epsi;
317 317 # cumhi=cummax*(1-epsi)
318 318 # powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
319 319 #
320 320 # #if len(powerindex)==1:
321 321 # ##return [numpy.mod(powerindex[0]+minx,64),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
322 322 # #return [numpy.mod(powerindex[0]+minx, self.Num_Bin ),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
323 323 # #elif len(powerindex)<4*fatspectra:
324 324 # #return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
325 325 #
326 326 # if len(powerindex) < 1:# case for powerindex 0
327 327 # continue
328 328 # powerlo=powerindex[0]
329 329 # powerhi=powerindex[-1]
330 330 # powerwidth=powerhi-powerlo
331 331 #
332 332 # firstpeak=powerlo+powerwidth/10.# first gaussian energy location
333 333 # secondpeak=powerhi-powerwidth/10.#second gaussian energy location
334 334 # midpeak=(firstpeak+secondpeak)/2.
335 335 # firstamp=spcs[int(firstpeak)]
336 336 # secondamp=spcs[int(secondpeak)]
337 337 # midamp=spcs[int(midpeak)]
338 338 # #x=numpy.spc.shape[1]
339 339 #
340 340 # #x=numpy.arange(64)
341 341 # x=numpy.arange( self.Num_Bin )
342 342 # y_data=spc+wnoise
343 343 #
344 344 # # single gaussian
345 345 # #shift0=numpy.mod(midpeak+minx,64)
346 346 # shift0=numpy.mod(midpeak+minx, self.Num_Bin )
347 347 # width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
348 348 # power0=2.
349 349 # amplitude0=midamp
350 350 # state0=[shift0,width0,amplitude0,power0,wnoise]
351 351 # #bnds=((0,63),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
352 352 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
353 353 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(0.1,0.5))
354 354 # # bnds = range of fft, power width, amplitude, power, noise
355 355 # lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
356 356 #
357 357 # chiSq1=lsq1[1];
358 358 # jack1= self.y_jacobian1(x,lsq1[0])
359 359 #
360 360 #
361 361 # try:
362 362 # sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
363 363 # except:
364 364 # std1=32.; sigmas1=numpy.ones(5)
365 365 # else:
366 366 # std1=sigmas1[0]
367 367 #
368 368 #
369 369 # if fatspectra<1.0 and powerwidth<4:
370 370 # choice=0
371 371 # Amplitude0=lsq1[0][2]
372 372 # shift0=lsq1[0][0]
373 373 # width0=lsq1[0][1]
374 374 # p0=lsq1[0][3]
375 375 # Amplitude1=0.
376 376 # shift1=0.
377 377 # width1=0.
378 378 # p1=0.
379 379 # noise=lsq1[0][4]
380 380 # #return (numpy.array([shift0,width0,Amplitude0,p0]),
381 381 # # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
382 382 #
383 383 # # two gaussians
384 384 # #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
385 385 # shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
386 386 # shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
387 387 # width0=powerwidth/6.;
388 388 # width1=width0
389 389 # power0=2.;
390 390 # power1=power0
391 391 # amplitude0=firstamp;
392 392 # amplitude1=secondamp
393 393 # state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
394 394 # #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
395 395 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
396 396 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
397 397 #
398 398 # lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
399 399 #
400 400 #
401 401 # chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
402 402 #
403 403 #
404 404 # try:
405 405 # sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
406 406 # except:
407 407 # std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
408 408 # else:
409 409 # std2a=sigmas2[0]; std2b=sigmas2[4]
410 410 #
411 411 #
412 412 #
413 413 # oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
414 414 #
415 415 # if snrdB>-9: # when SNR is strong pick the peak with least shift (LOS velocity) error
416 416 # if oneG:
417 417 # choice=0
418 418 # else:
419 419 # w1=lsq2[0][1]; w2=lsq2[0][5]
420 420 # a1=lsq2[0][2]; a2=lsq2[0][6]
421 421 # p1=lsq2[0][3]; p2=lsq2[0][7]
422 422 # s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1; s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
423 423 # gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
424 424 #
425 425 # if gp1>gp2:
426 426 # if a1>0.7*a2:
427 427 # choice=1
428 428 # else:
429 429 # choice=2
430 430 # elif gp2>gp1:
431 431 # if a2>0.7*a1:
432 432 # choice=2
433 433 # else:
434 434 # choice=1
435 435 # else:
436 436 # choice=numpy.argmax([a1,a2])+1
437 437 # #else:
438 438 # #choice=argmin([std2a,std2b])+1
439 439 #
440 440 # else: # with low SNR go to the most energetic peak
441 441 # choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
442 442 #
443 443 # #print 'choice',choice
444 444 #
445 445 # if choice==0: # pick the single gaussian fit
446 446 # Amplitude0=lsq1[0][2]
447 447 # shift0=lsq1[0][0]
448 448 # width0=lsq1[0][1]
449 449 # p0=lsq1[0][3]
450 450 # Amplitude1=0.
451 451 # shift1=0.
452 452 # width1=0.
453 453 # p1=0.
454 454 # noise=lsq1[0][4]
455 455 # elif choice==1: # take the first one of the 2 gaussians fitted
456 456 # Amplitude0 = lsq2[0][2]
457 457 # shift0 = lsq2[0][0]
458 458 # width0 = lsq2[0][1]
459 459 # p0 = lsq2[0][3]
460 460 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
461 461 # shift1 = lsq2[0][4] # This is 0 in gg1
462 462 # width1 = lsq2[0][5] # This is 0 in gg1
463 463 # p1 = lsq2[0][7] # This is 0 in gg1
464 464 # noise = lsq2[0][8]
465 465 # else: # the second one
466 466 # Amplitude0 = lsq2[0][6]
467 467 # shift0 = lsq2[0][4]
468 468 # width0 = lsq2[0][5]
469 469 # p0 = lsq2[0][7]
470 470 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
471 471 # shift1 = lsq2[0][0] # This is 0 in gg1
472 472 # width1 = lsq2[0][1] # This is 0 in gg1
473 473 # p1 = lsq2[0][3] # This is 0 in gg1
474 474 # noise = lsq2[0][8]
475 475 #
476 476 # #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
477 477 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
478 478 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
479 479 # #print 'SPC_ch1.shape',SPC_ch1.shape
480 480 # #print 'SPC_ch2.shape',SPC_ch2.shape
481 481 # #dataOut.data_param = SPC_ch1
482 482 # GauSPC[0] = SPC_ch1
483 483 # GauSPC[1] = SPC_ch2
484 484
485 485 # #plt.gcf().clear()
486 486 # plt.figure(50+self.i)
487 487 # self.i=self.i+1
488 488 # #plt.subplot(121)
489 489 # plt.plot(self.spc,'k')#,label='spc(66)')
490 490 # plt.plot(SPC_ch1[ch,ht],'b')#,label='gg1')
491 491 # #plt.plot(SPC_ch2,'r')#,label='gg2')
492 492 # #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
493 493 # #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
494 494 # #plt.plot(xFrec,FitGauss,'yo:',label='fit')
495 495 # plt.legend()
496 496 # plt.title('DATOS A ALTURA DE 7500 METROS')
497 497 # plt.show()
498 498 # print 'shift0', shift0
499 499 # print 'Amplitude0', Amplitude0
500 500 # print 'width0', width0
501 501 # print 'p0', p0
502 502 # print '========================'
503 503 # print 'shift1', shift1
504 504 # print 'Amplitude1', Amplitude1
505 505 # print 'width1', width1
506 506 # print 'p1', p1
507 507 # print 'noise', noise
508 508 # print 's_noise', wnoise
509 509
510 510 print '========================================================'
511 511 print 'total_time: ', time.time()-start_time
512 512
513 513 # re-normalizing spc and noise
514 514 # This part differs from gg1
515 515
516 516
517 517
518 518 ''' Parameters:
519 519 1. Amplitude
520 520 2. Shift
521 521 3. Width
522 522 4. Power
523 523 '''
524 524
525 525
526 526 ###############################################################################
527 527 def FitGau(self, X):
528 528
529 529 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
530 530 #print 'VARSSSS', ch, pnoise, noise, num_intg
531 531
532 532 #print 'HEIGHTS', self.Num_Hei
533 533
534 534 GauSPC = []
535 535 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
536 536 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
537 537 SPC_ch1[:] = 0#numpy.NaN
538 538 SPC_ch2[:] = 0#numpy.NaN
539 539
540 540
541 541
542 542 for ht in range(self.Num_Hei):
543 543 #print (numpy.asarray(self.spc).shape)
544 544
545 545 #print 'TTTTT', ch , ht
546 546 #print self.spc.shape
547 547
548 548
549 549 spc = numpy.asarray(self.spc)[ch,:,ht]
550 550
551 551 #############################################
552 552 # normalizing spc and noise
553 553 # This part differs from gg1
554 554 spc_norm_max = max(spc)
555 555 spc = spc / spc_norm_max
556 556 pnoise = pnoise / spc_norm_max
557 557 #############################################
558 558
559 559 fatspectra=1.0
560 560
561 561 wnoise = noise_ / spc_norm_max
562 562 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
563 563 #if wnoise>1.1*pnoise: # to be tested later
564 564 # wnoise=pnoise
565 565 noisebl=wnoise*0.9; noisebh=wnoise*1.1
566 566 spc=spc-wnoise
567 567 # print 'wnoise', noise_[0], spc_norm_max, wnoise
568 568 minx=numpy.argmin(spc)
569 569 spcs=numpy.roll(spc,-minx)
570 570 cum=numpy.cumsum(spcs)
571 571 tot_noise=wnoise * self.Num_Bin #64;
572 572 #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
573 573 #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
574 574 #snr=tot_signal/tot_noise
575 575 #snr=cum[-1]/tot_noise
576 576 snr = sum(spcs)/tot_noise
577 577 snrdB=10.*numpy.log10(snr)
578 578
579 579 if snrdB < SNRlimit :
580 580 snr = numpy.NaN
581 581 SPC_ch1[:,ht] = 0#numpy.NaN
582 582 SPC_ch1[:,ht] = 0#numpy.NaN
583 583 GauSPC = (SPC_ch1,SPC_ch2)
584 584 continue
585 585 #print 'snr',snrdB #, sum(spcs) , tot_noise
586 586
587 587
588 588
589 589 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
590 590 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
591 591
592 592 cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
593 593 cumlo=cummax*epsi;
594 594 cumhi=cummax*(1-epsi)
595 595 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
596 596
597 597
598 598 if len(powerindex) < 1:# case for powerindex 0
599 599 continue
600 600 powerlo=powerindex[0]
601 601 powerhi=powerindex[-1]
602 602 powerwidth=powerhi-powerlo
603 603
604 604 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
605 605 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
606 606 midpeak=(firstpeak+secondpeak)/2.
607 607 firstamp=spcs[int(firstpeak)]
608 608 secondamp=spcs[int(secondpeak)]
609 609 midamp=spcs[int(midpeak)]
610 610
611 611 x=numpy.arange( self.Num_Bin )
612 612 y_data=spc+wnoise
613 613
614 614 # single gaussian
615 615 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
616 616 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
617 617 power0=2.
618 618 amplitude0=midamp
619 619 state0=[shift0,width0,amplitude0,power0,wnoise]
620 620 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
621 621 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
622 622
623 623 chiSq1=lsq1[1];
624 624 jack1= self.y_jacobian1(x,lsq1[0])
625 625
626 626
627 627 try:
628 628 sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
629 629 except:
630 630 std1=32.; sigmas1=numpy.ones(5)
631 631 else:
632 632 std1=sigmas1[0]
633 633
634 634
635 635 if fatspectra<1.0 and powerwidth<4:
636 636 choice=0
637 637 Amplitude0=lsq1[0][2]
638 638 shift0=lsq1[0][0]
639 639 width0=lsq1[0][1]
640 640 p0=lsq1[0][3]
641 641 Amplitude1=0.
642 642 shift1=0.
643 643 width1=0.
644 644 p1=0.
645 645 noise=lsq1[0][4]
646 646 #return (numpy.array([shift0,width0,Amplitude0,p0]),
647 647 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
648 648
649 649 # two gaussians
650 650 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
651 651 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
652 652 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
653 653 width0=powerwidth/6.;
654 654 width1=width0
655 655 power0=2.;
656 656 power1=power0
657 657 amplitude0=firstamp;
658 658 amplitude1=secondamp
659 659 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
660 660 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
661 661 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
662 662 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
663 663
664 664 lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
665 665
666 666
667 667 chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
668 668
669 669
670 670 try:
671 671 sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
672 672 except:
673 673 std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
674 674 else:
675 675 std2a=sigmas2[0]; std2b=sigmas2[4]
676 676
677 677
678 678
679 679 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
680 680
681 681 if snrdB>-6: # when SNR is strong pick the peak with least shift (LOS velocity) error
682 682 if oneG:
683 683 choice=0
684 684 else:
685 685 w1=lsq2[0][1]; w2=lsq2[0][5]
686 686 a1=lsq2[0][2]; a2=lsq2[0][6]
687 687 p1=lsq2[0][3]; p2=lsq2[0][7]
688 688 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
689 689 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
690 690 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
691 691
692 692 if gp1>gp2:
693 693 if a1>0.7*a2:
694 694 choice=1
695 695 else:
696 696 choice=2
697 697 elif gp2>gp1:
698 698 if a2>0.7*a1:
699 699 choice=2
700 700 else:
701 701 choice=1
702 702 else:
703 703 choice=numpy.argmax([a1,a2])+1
704 704 #else:
705 705 #choice=argmin([std2a,std2b])+1
706 706
707 707 else: # with low SNR go to the most energetic peak
708 708 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
709 709
710 710
711 711 shift0=lsq2[0][0]; vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
712 712 shift1=lsq2[0][4]; vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
713 713
714 714 max_vel = 20
715 715
716 716 #first peak will be 0, second peak will be 1
717 717 if vel0 > 0 and vel0 < max_vel : #first peak is in the correct range
718 718 shift0=lsq2[0][0]
719 719 width0=lsq2[0][1]
720 720 Amplitude0=lsq2[0][2]
721 721 p0=lsq2[0][3]
722 722
723 723 shift1=lsq2[0][4]
724 724 width1=lsq2[0][5]
725 725 Amplitude1=lsq2[0][6]
726 726 p1=lsq2[0][7]
727 727 noise=lsq2[0][8]
728 728 else:
729 729 shift1=lsq2[0][0]
730 730 width1=lsq2[0][1]
731 731 Amplitude1=lsq2[0][2]
732 732 p1=lsq2[0][3]
733 733
734 734 shift0=lsq2[0][4]
735 735 width0=lsq2[0][5]
736 736 Amplitude0=lsq2[0][6]
737 737 p0=lsq2[0][7]
738 738 noise=lsq2[0][8]
739 739
740 740 if Amplitude0<0.1: # in case the peak is noise
741 741 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
742 742 if Amplitude1<0.1:
743 743 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
744 744
745 745
746 746 # if choice==0: # pick the single gaussian fit
747 747 # Amplitude0=lsq1[0][2]
748 748 # shift0=lsq1[0][0]
749 749 # width0=lsq1[0][1]
750 750 # p0=lsq1[0][3]
751 751 # Amplitude1=0.
752 752 # shift1=0.
753 753 # width1=0.
754 754 # p1=0.
755 755 # noise=lsq1[0][4]
756 756 # elif choice==1: # take the first one of the 2 gaussians fitted
757 757 # Amplitude0 = lsq2[0][2]
758 758 # shift0 = lsq2[0][0]
759 759 # width0 = lsq2[0][1]
760 760 # p0 = lsq2[0][3]
761 761 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
762 762 # shift1 = lsq2[0][4] # This is 0 in gg1
763 763 # width1 = lsq2[0][5] # This is 0 in gg1
764 764 # p1 = lsq2[0][7] # This is 0 in gg1
765 765 # noise = lsq2[0][8]
766 766 # else: # the second one
767 767 # Amplitude0 = lsq2[0][6]
768 768 # shift0 = lsq2[0][4]
769 769 # width0 = lsq2[0][5]
770 770 # p0 = lsq2[0][7]
771 771 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
772 772 # shift1 = lsq2[0][0] # This is 0 in gg1
773 773 # width1 = lsq2[0][1] # This is 0 in gg1
774 774 # p1 = lsq2[0][3] # This is 0 in gg1
775 775 # noise = lsq2[0][8]
776 776
777 777 #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
778 778 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
779 779 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
780 780 #print 'SPC_ch1.shape',SPC_ch1.shape
781 781 #print 'SPC_ch2.shape',SPC_ch2.shape
782 782 #dataOut.data_param = SPC_ch1
783 783 GauSPC = (SPC_ch1,SPC_ch2)
784 784 #GauSPC[1] = SPC_ch2
785 785
786 786 # print 'shift0', shift0
787 787 # print 'Amplitude0', Amplitude0
788 788 # print 'width0', width0
789 789 # print 'p0', p0
790 790 # print '========================'
791 791 # print 'shift1', shift1
792 792 # print 'Amplitude1', Amplitude1
793 793 # print 'width1', width1
794 794 # print 'p1', p1
795 795 # print 'noise', noise
796 796 # print 's_noise', wnoise
797 797
798 798 return GauSPC
799 799
800 800
801 801 def y_jacobian1(self,x,state): # This function is for further analysis of generalized Gaussians, it is not too importan for the signal discrimination.
802 802 y_model=self.y_model1(x,state)
803 803 s0,w0,a0,p0,n=state
804 804 e0=((x-s0)/w0)**2;
805 805
806 806 e0u=((x-s0-self.Num_Bin)/w0)**2;
807 807
808 808 e0d=((x-s0+self.Num_Bin)/w0)**2
809 809 m0=numpy.exp(-0.5*e0**(p0/2.));
810 810 m0u=numpy.exp(-0.5*e0u**(p0/2.));
811 811 m0d=numpy.exp(-0.5*e0d**(p0/2.))
812 812 JA=m0+m0u+m0d
813 813 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
814 814
815 815 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
816 816
817 817 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
818 818 jack1=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,1./y_model])
819 819 return jack1.T
820 820
821 821 def y_jacobian2(self,x,state):
822 822 y_model=self.y_model2(x,state)
823 823 s0,w0,a0,p0,s1,w1,a1,p1,n=state
824 824 e0=((x-s0)/w0)**2;
825 825
826 826 e0u=((x-s0- self.Num_Bin )/w0)**2;
827 827
828 828 e0d=((x-s0+ self.Num_Bin )/w0)**2
829 829 e1=((x-s1)/w1)**2;
830 830
831 831 e1u=((x-s1- self.Num_Bin )/w1)**2;
832 832
833 833 e1d=((x-s1+ self.Num_Bin )/w1)**2
834 834 m0=numpy.exp(-0.5*e0**(p0/2.));
835 835 m0u=numpy.exp(-0.5*e0u**(p0/2.));
836 836 m0d=numpy.exp(-0.5*e0d**(p0/2.))
837 837 m1=numpy.exp(-0.5*e1**(p1/2.));
838 838 m1u=numpy.exp(-0.5*e1u**(p1/2.));
839 839 m1d=numpy.exp(-0.5*e1d**(p1/2.))
840 840 JA=m0+m0u+m0d
841 841 JA1=m1+m1u+m1d
842 842 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
843 843 JP1=(-1/4.)*a1*m1*e1**(p1/2.)*numpy.log(e1)+(-1/4.)*a1*m1u*e1u**(p1/2.)*numpy.log(e1u)+(-1/4.)*a1*m1d*e1d**(p1/2.)*numpy.log(e1d)
844 844
845 845 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
846 846
847 847 JS1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)
848 848
849 849 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
850 850
851 851 JW1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)**2+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)**2+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)**2
852 852 jack2=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,JS1/y_model,JW1/y_model,JA1/y_model,JP1/y_model,1./y_model])
853 853 return jack2.T
854 854
855 855 def y_model1(self,x,state):
856 856 shift0,width0,amplitude0,power0,noise=state
857 857 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
858 858
859 859 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
860 860
861 861 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
862 862 return model0+model0u+model0d+noise
863 863
864 864 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
865 865 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
866 866 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
867 867
868 868 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
869 869
870 870 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
871 871 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
872 872
873 873 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
874 874
875 875 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
876 876 return model0+model0u+model0d+model1+model1u+model1d+noise
877 877
878 878 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
879 879
880 880 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
881 881
882 882 def misfit2(self,state,y_data,x,num_intg):
883 883 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
884 884
885 885
886 886 class PrecipitationProc(Operation):
887 887
888 888 '''
889 889 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
890 890
891 891 Input:
892 892 self.dataOut.data_pre : SelfSpectra
893 893
894 894 Output:
895 895
896 896 self.dataOut.data_output : Reflectivity factor, rainfall Rate
897 897
898 898
899 899 Parameters affected:
900 900 '''
901 901
902 902
903 903 def run(self, dataOut, radar=None, Pt=None, Gt=None, Gr=None, Lambda=None, aL=None,
904 904 tauW=None, ThetaT=None, ThetaR=None, Km = 0.93, Altitude=None):
905 905
906 906 self.spc = dataOut.data_pre[0].copy()
907 907 self.Num_Hei = self.spc.shape[2]
908 908 self.Num_Bin = self.spc.shape[1]
909 909 self.Num_Chn = self.spc.shape[0]
910 910
911 911 Velrange = dataOut.abscissaList
912 912
913 913 if radar == "MIRA35C" :
914 914
915 915 Ze = self.dBZeMODE2(dataOut)
916 916
917 917 else:
918 918
919 919 self.Pt = Pt
920 920 self.Gt = Gt
921 921 self.Gr = Gr
922 922 self.Lambda = Lambda
923 923 self.aL = aL
924 924 self.tauW = tauW
925 925 self.ThetaT = ThetaT
926 926 self.ThetaR = ThetaR
927 927
928 928 RadarConstant = GetRadarConstant()
929 929 SPCmean = numpy.mean(self.spc,0)
930 930 ETA = numpy.zeros(self.Num_Hei)
931 931 Pr = numpy.sum(SPCmean,0)
932 932
933 933 #for R in range(self.Num_Hei):
934 934 # ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
935 935
936 936 D_range = numpy.zeros(self.Num_Hei)
937 937 EqSec = numpy.zeros(self.Num_Hei)
938 938 del_V = numpy.zeros(self.Num_Hei)
939 939
940 940 for R in range(self.Num_Hei):
941 941 ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
942 942
943 943 h = R + Altitude #Range from ground to radar pulse altitude
944 944 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
945 945
946 946 D_range[R] = numpy.log( (9.65 - (Velrange[R]/del_V[R])) / 10.3 ) / -0.6 #Range of Diameter of drops related to velocity
947 947 SIGMA[R] = numpy.pi**5 / Lambda**4 * Km * D_range[R]**6 #Equivalent Section of drops (sigma)
948 948
949 949 N_dist[R] = ETA[R] / SIGMA[R]
950 950
951 951 Ze = (ETA * Lambda**4) / (numpy.pi * Km)
952 952 Z = numpy.sum( N_dist * D_range**6 )
953 953 RR = 6*10**-4*numpy.pi * numpy.sum( D_range**3 * N_dist * Velrange ) #Rainfall rate
954 954
955 955
956 956 RR = (Ze/200)**(1/1.6)
957 957 dBRR = 10*numpy.log10(RR)
958 958
959 959 dBZe = 10*numpy.log10(Ze)
960 960 dataOut.data_output = Ze
961 961 dataOut.data_param = numpy.ones([2,self.Num_Hei])
962 962 dataOut.channelList = [0,1]
963 963 print 'channelList', dataOut.channelList
964 964 dataOut.data_param[0]=dBZe
965 965 dataOut.data_param[1]=dBRR
966 966 print 'RR SHAPE', dBRR.shape
967 967 print 'Ze SHAPE', dBZe.shape
968 968 print 'dataOut.data_param SHAPE', dataOut.data_param.shape
969 969
970 970
971 971 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
972 972
973 973 NPW = dataOut.NPW
974 974 COFA = dataOut.COFA
975 975
976 976 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
977 977 RadarConst = dataOut.RadarConst
978 978 #frequency = 34.85*10**9
979 979
980 980 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
981 981 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
982 982
983 983 ETA = numpy.sum(SNR,1)
984 984 print 'ETA' , ETA
985 985 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
986 986
987 987 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
988 988
989 989 for r in range(self.Num_Hei):
990 990
991 991 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
992 992 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
993 993
994 994 return Ze
995 995
996 996 def GetRadarConstant(self):
997 997
998 998 """
999 999 Constants:
1000 1000
1001 1001 Pt: Transmission Power dB
1002 1002 Gt: Transmission Gain dB
1003 1003 Gr: Reception Gain dB
1004 1004 Lambda: Wavelenght m
1005 1005 aL: Attenuation loses dB
1006 1006 tauW: Width of transmission pulse s
1007 1007 ThetaT: Transmission antenna bean angle rad
1008 1008 ThetaR: Reception antenna beam angle rad
1009 1009
1010 1010 """
1011 1011 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1012 1012 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1013 1013 RadarConstant = Numerator / Denominator
1014 1014
1015 1015 return RadarConstant
1016 1016
1017 1017
1018 1018
1019 1019 class FullSpectralAnalysis(Operation):
1020 1020
1021 1021 """
1022 1022 Function that implements Full Spectral Analisys technique.
1023 1023
1024 1024 Input:
1025 1025 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
1026 1026 self.dataOut.groupList : Pairlist of channels
1027 1027 self.dataOut.ChanDist : Physical distance between receivers
1028 1028
1029 1029
1030 1030 Output:
1031 1031
1032 1032 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
1033 1033
1034 1034
1035 1035 Parameters affected: Winds, height range, SNR
1036 1036
1037 1037 """
1038 1038 def run(self, dataOut, E01=None, E02=None, E12=None, N01=None, N02=None, N12=None, SNRlimit=7):
1039 1039
1040 1040 spc = dataOut.data_pre[0].copy()
1041 1041 cspc = dataOut.data_pre[1].copy()
1042 1042
1043 1043 nChannel = spc.shape[0]
1044 1044 nProfiles = spc.shape[1]
1045 1045 nHeights = spc.shape[2]
1046 1046
1047 1047 pairsList = dataOut.groupList
1048 1048 if dataOut.ChanDist is not None :
1049 1049 ChanDist = dataOut.ChanDist
1050 1050 else:
1051 1051 ChanDist = numpy.array([[E01, N01],[E02,N02],[E12,N12]])
1052 1052
1053 1053 #print 'ChanDist', ChanDist
1054 1054
1055 1055 if dataOut.VelRange is not None:
1056 1056 VelRange= dataOut.VelRange
1057 1057 else:
1058 1058 VelRange= dataOut.abscissaList
1059 1059
1060 1060 ySamples=numpy.ones([nChannel,nProfiles])
1061 1061 phase=numpy.ones([nChannel,nProfiles])
1062 1062 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
1063 1063 coherence=numpy.ones([nChannel,nProfiles])
1064 1064 PhaseSlope=numpy.ones(nChannel)
1065 1065 PhaseInter=numpy.ones(nChannel)
1066 1066 dataSNR = dataOut.data_SNR
1067 1067
1068 1068
1069 1069
1070 1070 data = dataOut.data_pre
1071 1071 noise = dataOut.noise
1072 1072 print 'noise',noise
1073 1073 #SNRdB = 10*numpy.log10(dataOut.data_SNR)
1074 1074
1075 1075 FirstMoment = numpy.average(dataOut.data_param[:,1,:],0)
1076 1076 #SNRdBMean = []
1077 1077
1078 1078
1079 1079 #for j in range(nHeights):
1080 1080 # FirstMoment = numpy.append(FirstMoment,numpy.mean([dataOut.data_param[0,1,j],dataOut.data_param[1,1,j],dataOut.data_param[2,1,j]]))
1081 1081 # SNRdBMean = numpy.append(SNRdBMean,numpy.mean([SNRdB[0,j],SNRdB[1,j],SNRdB[2,j]]))
1082 1082
1083 1083 data_output=numpy.ones([3,spc.shape[2]])*numpy.NaN
1084 1084
1085 1085 velocityX=[]
1086 1086 velocityY=[]
1087 1087 velocityV=[]
1088 1088
1089 1089 dbSNR = 10*numpy.log10(dataSNR)
1090 1090 dbSNR = numpy.average(dbSNR,0)
1091 1091 for Height in range(nHeights):
1092 1092
1093 1093 [Vzon,Vmer,Vver, GaussCenter]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR[Height], SNRlimit)
1094 1094
1095 1095 if abs(Vzon)<100. and abs(Vzon)> 0.:
1096 1096 velocityX=numpy.append(velocityX, Vzon)#Vmag
1097 1097
1098 1098 else:
1099 1099 print 'Vzon',Vzon
1100 1100 velocityX=numpy.append(velocityX, numpy.NaN)
1101 1101
1102 1102 if abs(Vmer)<100. and abs(Vmer) > 0.:
1103 1103 velocityY=numpy.append(velocityY, Vmer)#Vang
1104 1104
1105 1105 else:
1106 1106 print 'Vmer',Vmer
1107 1107 velocityY=numpy.append(velocityY, numpy.NaN)
1108 1108
1109 1109 if dbSNR[Height] > SNRlimit:
1110 1110 velocityV=numpy.append(velocityV, FirstMoment[Height])
1111 1111 else:
1112 1112 velocityV=numpy.append(velocityV, numpy.NaN)
1113 1113 #FirstMoment[Height]= numpy.NaN
1114 1114 # if SNRdBMean[Height] <12:
1115 1115 # FirstMoment[Height] = numpy.NaN
1116 1116 # velocityX[Height] = numpy.NaN
1117 1117 # velocityY[Height] = numpy.NaN
1118 1118
1119 1119
1120 1120 data_output[0]=numpy.array(velocityX)
1121 1121 data_output[1]=numpy.array(velocityY)
1122 1122 data_output[2]=-velocityV#FirstMoment
1123 1123
1124 1124 print ' '
1125 1125 #print 'FirstMoment'
1126 1126 #print FirstMoment
1127 1127 print 'velocityX',data_output[0]
1128 1128 print ' '
1129 1129 print 'velocityY',data_output[1]
1130 1130 #print numpy.array(velocityY)
1131 1131 print ' '
1132 1132 #print 'SNR'
1133 1133 #print 10*numpy.log10(dataOut.data_SNR)
1134 1134 #print numpy.shape(10*numpy.log10(dataOut.data_SNR))
1135 1135 print ' '
1136 1136
1137 1137
1138 1138 dataOut.data_output=data_output
1139 1139 return
1140 1140
1141 1141
1142 1142 def moving_average(self,x, N=2):
1143 1143 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1144 1144
1145 1145 def gaus(self,xSamples,a,x0,sigma):
1146 1146 return a*numpy.exp(-(xSamples-x0)**2/(2*sigma**2))
1147 1147
1148 1148 def Find(self,x,value):
1149 1149 for index in range(len(x)):
1150 1150 if x[index]==value:
1151 1151 return index
1152 1152
1153 1153 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR, SNRlimit):
1154 1154
1155 1155 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
1156 1156 phase=numpy.ones([spc.shape[0],spc.shape[1]])
1157 1157 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
1158 1158 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
1159 1159 PhaseSlope=numpy.ones(spc.shape[0])
1160 1160 PhaseInter=numpy.ones(spc.shape[0])
1161 1161 xFrec=VelRange
1162 1162
1163 1163 '''Getting Eij and Nij'''
1164 1164
1165 1165 E01=ChanDist[0][0]
1166 1166 N01=ChanDist[0][1]
1167 1167
1168 1168 E02=ChanDist[1][0]
1169 1169 N02=ChanDist[1][1]
1170 1170
1171 1171 E12=ChanDist[2][0]
1172 1172 N12=ChanDist[2][1]
1173 1173
1174 1174 z = spc.copy()
1175 1175 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1176 1176
1177 1177 for i in range(spc.shape[0]):
1178 1178
1179 1179 '''****** Line of Data SPC ******'''
1180 1180 zline=z[i,:,Height]
1181 1181
1182 1182 '''****** SPC is normalized ******'''
1183 1183 FactNorm= (zline.copy()-noise[i]) / numpy.sum(zline.copy())
1184 1184 FactNorm= FactNorm/numpy.sum(FactNorm)
1185 1185
1186 1186 SmoothSPC=self.moving_average(FactNorm,N=3)
1187 1187
1188 1188 xSamples = ar(range(len(SmoothSPC)))
1189 1189 ySamples[i] = SmoothSPC
1190 1190
1191 1191 #dbSNR=10*numpy.log10(dataSNR)
1192 1192 print ' '
1193 1193 print ' '
1194 1194 print ' '
1195 1195
1196 1196 #print 'dataSNR', dbSNR.shape, dbSNR[0,40:120]
1197 1197 print 'SmoothSPC', SmoothSPC.shape, SmoothSPC[0:20]
1198 1198 print 'noise',noise
1199 1199 print 'zline',zline.shape, zline[0:20]
1200 1200 print 'FactNorm',FactNorm.shape, FactNorm[0:20]
1201 1201 print 'FactNorm suma', numpy.sum(FactNorm)
1202 1202
1203 1203 for i in range(spc.shape[0]):
1204 1204
1205 1205 '''****** Line of Data CSPC ******'''
1206 1206 cspcLine=cspc[i,:,Height].copy()
1207 1207
1208 1208 '''****** CSPC is normalized ******'''
1209 1209 chan_index0 = pairsList[i][0]
1210 1210 chan_index1 = pairsList[i][1]
1211 1211 CSPCFactor= abs(numpy.sum(ySamples[chan_index0]) * numpy.sum(ySamples[chan_index1])) #
1212 1212
1213 1213 CSPCNorm = (cspcLine.copy() -noise[i]) / numpy.sqrt(CSPCFactor)
1214 1214
1215 1215 CSPCSamples[i] = CSPCNorm
1216 1216 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
1217 1217
1218 1218 coherence[i]= self.moving_average(coherence[i],N=2)
1219 1219
1220 1220 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
1221 1221
1222 1222 print 'cspcLine', cspcLine.shape, cspcLine[0:20]
1223 1223 print 'CSPCFactor', CSPCFactor#, CSPCFactor[0:20]
1224 1224 print numpy.sum(ySamples[chan_index0]), numpy.sum(ySamples[chan_index1]), -noise[i]
1225 1225 print 'CSPCNorm', CSPCNorm.shape, CSPCNorm[0:20]
1226 1226 print 'CSPCNorm suma', numpy.sum(CSPCNorm)
1227 1227 print 'CSPCSamples', CSPCSamples.shape, CSPCSamples[0,0:20]
1228 1228
1229 1229 '''****** Getting fij width ******'''
1230 1230
1231 1231 yMean=[]
1232 1232 yMean2=[]
1233 1233
1234 1234 for j in range(len(ySamples[1])):
1235 1235 yMean=numpy.append(yMean,numpy.mean([ySamples[0,j],ySamples[1,j],ySamples[2,j]]))
1236 1236
1237 1237 '''******* Getting fitting Gaussian ******'''
1238 1238 meanGauss=sum(xSamples*yMean) / len(xSamples)
1239 1239 sigma=sum(yMean*(xSamples-meanGauss)**2) / len(xSamples)
1240 1240
1241 1241 print '****************************'
1242 1242 print 'len(xSamples): ',len(xSamples)
1243 1243 print 'yMean: ', yMean.shape, yMean[0:20]
1244 1244 print 'ySamples', ySamples.shape, ySamples[0,0:20]
1245 1245 print 'xSamples: ',xSamples.shape, xSamples[0:20]
1246 1246
1247 1247 print 'meanGauss',meanGauss
1248 1248 print 'sigma',sigma
1249 1249
1250 1250 #if (abs(meanGauss/sigma**2) > 0.0001) : #0.000000001):
1251 1251 if dbSNR > SNRlimit :
1252 1252 try:
1253 1253 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=[1,meanGauss,sigma])
1254 1254
1255 1255 if numpy.amax(popt)>numpy.amax(yMean)*0.3:
1256 1256 FitGauss=self.gaus(xSamples,*popt)
1257 1257
1258 1258 else:
1259 1259 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1260 1260 print 'Verificador: Dentro', Height
1261 1261 except :#RuntimeError:
1262 1262 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1263 1263
1264 1264
1265 1265 else:
1266 1266 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1267 1267
1268 1268 Maximun=numpy.amax(yMean)
1269 1269 eMinus1=Maximun*numpy.exp(-1)#*0.8
1270 1270
1271 1271 HWpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1)))
1272 1272 HalfWidth= xFrec[HWpos]
1273 1273 GCpos=self.Find(FitGauss, numpy.amax(FitGauss))
1274 1274 Vpos=self.Find(FactNorm, numpy.amax(FactNorm))
1275 1275
1276 1276 #Vpos=FirstMoment[]
1277 1277
1278 1278 '''****** Getting Fij ******'''
1279 1279
1280 1280 GaussCenter=xFrec[GCpos]
1281 1281 if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0):
1282 1282 Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001
1283 1283 else:
1284 1284 Fij=abs(GaussCenter-HalfWidth)+0.0000001
1285 1285
1286 1286 '''****** Getting Frecuency range of significant data ******'''
1287 1287
1288 1288 Rangpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10)))
1289 1289
1290 1290 if Rangpos<GCpos:
1291 1291 Range=numpy.array([Rangpos,2*GCpos-Rangpos])
1292 1292 elif Rangpos< ( len(xFrec)- len(xFrec)*0.1):
1293 1293 Range=numpy.array([2*GCpos-Rangpos,Rangpos])
1294 1294 else:
1295 1295 Range = numpy.array([0,0])
1296 1296
1297 1297 print ' '
1298 1298 print 'GCpos',GCpos, ( len(xFrec)- len(xFrec)*0.1)
1299 1299 print 'Rangpos',Rangpos
1300 1300 print 'RANGE: ', Range
1301 1301 FrecRange=xFrec[Range[0]:Range[1]]
1302 1302
1303 1303 '''****** Getting SCPC Slope ******'''
1304 1304
1305 1305 for i in range(spc.shape[0]):
1306 1306
1307 1307 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.5:
1308 1308 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1309 1309
1310 1310 print 'FrecRange', len(FrecRange) , FrecRange
1311 1311 print 'PhaseRange', len(PhaseRange), PhaseRange
1312 1312 print ' '
1313 1313 if len(FrecRange) == len(PhaseRange):
1314 1314 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange,PhaseRange)
1315 1315 PhaseSlope[i]=slope
1316 1316 PhaseInter[i]=intercept
1317 1317 else:
1318 1318 PhaseSlope[i]=0
1319 1319 PhaseInter[i]=0
1320 1320 else:
1321 1321 PhaseSlope[i]=0
1322 1322 PhaseInter[i]=0
1323 1323
1324 1324 '''Getting constant C'''
1325 1325 cC=(Fij*numpy.pi)**2
1326 1326
1327 1327 '''****** Getting constants F and G ******'''
1328 1328 MijEijNij=numpy.array([[E02,N02], [E12,N12]])
1329 1329 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1330 1330 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1331 1331 MijResults=numpy.array([MijResult0,MijResult1])
1332 1332 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1333 1333
1334 1334 '''****** Getting constants A, B and H ******'''
1335 1335 W01=numpy.amax(coherence[0])
1336 1336 W02=numpy.amax(coherence[1])
1337 1337 W12=numpy.amax(coherence[2])
1338 1338
1339 1339 WijResult0=((cF*E01+cG*N01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1340 1340 WijResult1=((cF*E02+cG*N02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1341 1341 WijResult2=((cF*E12+cG*N12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1342 1342
1343 1343 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1344 1344
1345 1345 WijEijNij=numpy.array([ [E01**2, N01**2, 2*E01*N01] , [E02**2, N02**2, 2*E02*N02] , [E12**2, N12**2, 2*E12*N12] ])
1346 1346 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1347 1347
1348 1348 VxVy=numpy.array([[cA,cH],[cH,cB]])
1349 1349
1350 1350 VxVyResults=numpy.array([-cF,-cG])
1351 1351 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1352 1352
1353 1353 Vzon = Vy
1354 1354 Vmer = Vx
1355 1355 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1356 1356 Vang=numpy.arctan2(Vmer,Vzon)
1357 1357 Vver=xFrec[Vpos]
1358 1358 print 'vzon y vmer', Vzon, Vmer
1359 1359 return Vzon, Vmer, Vver, GaussCenter
1360 1360
1361 1361 class SpectralMoments(Operation):
1362 1362
1363 1363 '''
1364 1364 Function SpectralMoments()
1365 1365
1366 1366 Calculates moments (power, mean, standard deviation) and SNR of the signal
1367 1367
1368 1368 Type of dataIn: Spectra
1369 1369
1370 1370 Configuration Parameters:
1371 1371
1372 1372 dirCosx : Cosine director in X axis
1373 1373 dirCosy : Cosine director in Y axis
1374 1374
1375 1375 elevation :
1376 1376 azimuth :
1377 1377
1378 1378 Input:
1379 1379 channelList : simple channel list to select e.g. [2,3,7]
1380 1380 self.dataOut.data_pre : Spectral data
1381 1381 self.dataOut.abscissaList : List of frequencies
1382 1382 self.dataOut.noise : Noise level per channel
1383 1383
1384 1384 Affected:
1385 1385 self.dataOut.data_param : Parameters per channel
1386 1386 self.dataOut.data_SNR : SNR per channel
1387 1387
1388 1388 '''
1389 1389
1390 1390 def run(self, dataOut):
1391 1391
1392 1392 #dataOut.data_pre = dataOut.data_pre[0]
1393 1393 data = dataOut.data_pre[0]
1394 1394 absc = dataOut.abscissaList[:-1]
1395 1395 noise = dataOut.noise
1396 1396 nChannel = data.shape[0]
1397 1397 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1398 1398
1399 1399 for ind in range(nChannel):
1400 1400 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1401 1401
1402 1402 dataOut.data_param = data_param[:,1:,:]
1403 1403 dataOut.data_SNR = data_param[:,0]
1404 dataOut.data_DOP = data_param[:,1]
1405 dataOut.data_MEAN = data_param[:,2]
1406 dataOut.data_STD = data_param[:,3]
1404 1407 return
1405 1408
1406 1409 def __calculateMoments(self, oldspec, oldfreq, n0,
1407 1410 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1408 1411
1409 1412 if (nicoh == None): nicoh = 1
1410 1413 if (graph == None): graph = 0
1411 1414 if (smooth == None): smooth = 0
1412 1415 elif (self.smooth < 3): smooth = 0
1413 1416
1414 1417 if (type1 == None): type1 = 0
1415 1418 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
1416 1419 if (snrth == None): snrth = -3
1417 1420 if (dc == None): dc = 0
1418 1421 if (aliasing == None): aliasing = 0
1419 1422 if (oldfd == None): oldfd = 0
1420 1423 if (wwauto == None): wwauto = 0
1421 1424
1422 1425 if (n0 < 1.e-20): n0 = 1.e-20
1423 1426
1424 1427 freq = oldfreq
1425 1428 vec_power = numpy.zeros(oldspec.shape[1])
1426 1429 vec_fd = numpy.zeros(oldspec.shape[1])
1427 1430 vec_w = numpy.zeros(oldspec.shape[1])
1428 1431 vec_snr = numpy.zeros(oldspec.shape[1])
1429 1432
1430 1433 for ind in range(oldspec.shape[1]):
1431 1434
1432 1435 spec = oldspec[:,ind]
1433 1436 aux = spec*fwindow
1434 1437 max_spec = aux.max()
1435 1438 m = list(aux).index(max_spec)
1436 1439
1437 1440 #Smooth
1438 1441 if (smooth == 0): spec2 = spec
1439 1442 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1440 1443
1441 1444 # Calculo de Momentos
1442 1445 bb = spec2[range(m,spec2.size)]
1443 1446 bb = (bb<n0).nonzero()
1444 1447 bb = bb[0]
1445 1448
1446 1449 ss = spec2[range(0,m + 1)]
1447 1450 ss = (ss<n0).nonzero()
1448 1451 ss = ss[0]
1449 1452
1450 1453 if (bb.size == 0):
1451 1454 bb0 = spec.size - 1 - m
1452 1455 else:
1453 1456 bb0 = bb[0] - 1
1454 1457 if (bb0 < 0):
1455 1458 bb0 = 0
1456 1459
1457 1460 if (ss.size == 0): ss1 = 1
1458 1461 else: ss1 = max(ss) + 1
1459 1462
1460 1463 if (ss1 > m): ss1 = m
1461 1464
1462 1465 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
1463 1466 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1464 1467 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1465 1468 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1466 1469 snr = (spec2.mean()-n0)/n0
1467 1470
1468 1471 if (snr < 1.e-20) :
1469 1472 snr = 1.e-20
1470 1473
1471 1474 vec_power[ind] = power
1472 1475 vec_fd[ind] = fd
1473 1476 vec_w[ind] = w
1474 1477 vec_snr[ind] = snr
1475 1478
1476 1479 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1477 1480 return moments
1478 1481
1479 1482 #------------------ Get SA Parameters --------------------------
1480 1483
1481 1484 def GetSAParameters(self):
1482 1485 #SA en frecuencia
1483 1486 pairslist = self.dataOut.groupList
1484 1487 num_pairs = len(pairslist)
1485 1488
1486 1489 vel = self.dataOut.abscissaList
1487 1490 spectra = self.dataOut.data_pre
1488 1491 cspectra = self.dataIn.data_cspc
1489 1492 delta_v = vel[1] - vel[0]
1490 1493
1491 1494 #Calculating the power spectrum
1492 1495 spc_pow = numpy.sum(spectra, 3)*delta_v
1493 1496 #Normalizing Spectra
1494 1497 norm_spectra = spectra/spc_pow
1495 1498 #Calculating the norm_spectra at peak
1496 1499 max_spectra = numpy.max(norm_spectra, 3)
1497 1500
1498 1501 #Normalizing Cross Spectra
1499 1502 norm_cspectra = numpy.zeros(cspectra.shape)
1500 1503
1501 1504 for i in range(num_chan):
1502 1505 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1503 1506
1504 1507 max_cspectra = numpy.max(norm_cspectra,2)
1505 1508 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1506 1509
1507 1510 for i in range(num_pairs):
1508 1511 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1509 1512 #------------------- Get Lags ----------------------------------
1510 1513
1511 1514 class SALags(Operation):
1512 1515 '''
1513 1516 Function GetMoments()
1514 1517
1515 1518 Input:
1516 1519 self.dataOut.data_pre
1517 1520 self.dataOut.abscissaList
1518 1521 self.dataOut.noise
1519 1522 self.dataOut.normFactor
1520 1523 self.dataOut.data_SNR
1521 1524 self.dataOut.groupList
1522 1525 self.dataOut.nChannels
1523 1526
1524 1527 Affected:
1525 1528 self.dataOut.data_param
1526 1529
1527 1530 '''
1528 1531 def run(self, dataOut):
1529 1532 data_acf = dataOut.data_pre[0]
1530 1533 data_ccf = dataOut.data_pre[1]
1531 1534 normFactor_acf = dataOut.normFactor[0]
1532 1535 normFactor_ccf = dataOut.normFactor[1]
1533 1536 pairs_acf = dataOut.groupList[0]
1534 1537 pairs_ccf = dataOut.groupList[1]
1535 1538
1536 1539 nHeights = dataOut.nHeights
1537 1540 absc = dataOut.abscissaList
1538 1541 noise = dataOut.noise
1539 1542 SNR = dataOut.data_SNR
1540 1543 nChannels = dataOut.nChannels
1541 1544 # pairsList = dataOut.groupList
1542 1545 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1543 1546
1544 1547 for l in range(len(pairs_acf)):
1545 1548 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1546 1549
1547 1550 for l in range(len(pairs_ccf)):
1548 1551 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1549 1552
1550 1553 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1551 1554 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1552 1555 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1553 1556 return
1554 1557
1555 1558 # def __getPairsAutoCorr(self, pairsList, nChannels):
1556 1559 #
1557 1560 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1558 1561 #
1559 1562 # for l in range(len(pairsList)):
1560 1563 # firstChannel = pairsList[l][0]
1561 1564 # secondChannel = pairsList[l][1]
1562 1565 #
1563 1566 # #Obteniendo pares de Autocorrelacion
1564 1567 # if firstChannel == secondChannel:
1565 1568 # pairsAutoCorr[firstChannel] = int(l)
1566 1569 #
1567 1570 # pairsAutoCorr = pairsAutoCorr.astype(int)
1568 1571 #
1569 1572 # pairsCrossCorr = range(len(pairsList))
1570 1573 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1571 1574 #
1572 1575 # return pairsAutoCorr, pairsCrossCorr
1573 1576
1574 1577 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1575 1578
1576 1579 lag0 = data_acf.shape[1]/2
1577 1580 #Funcion de Autocorrelacion
1578 1581 mean_acf = stats.nanmean(data_acf, axis = 0)
1579 1582
1580 1583 #Obtencion Indice de TauCross
1581 1584 ind_ccf = data_ccf.argmax(axis = 1)
1582 1585 #Obtencion Indice de TauAuto
1583 1586 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1584 1587 ccf_lag0 = data_ccf[:,lag0,:]
1585 1588
1586 1589 for i in range(ccf_lag0.shape[0]):
1587 1590 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1588 1591
1589 1592 #Obtencion de TauCross y TauAuto
1590 1593 tau_ccf = lagRange[ind_ccf]
1591 1594 tau_acf = lagRange[ind_acf]
1592 1595
1593 1596 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1594 1597
1595 1598 tau_ccf[Nan1,Nan2] = numpy.nan
1596 1599 tau_acf[Nan1,Nan2] = numpy.nan
1597 1600 tau = numpy.vstack((tau_ccf,tau_acf))
1598 1601
1599 1602 return tau
1600 1603
1601 1604 def __calculateLag1Phase(self, data, lagTRange):
1602 1605 data1 = stats.nanmean(data, axis = 0)
1603 1606 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1604 1607
1605 1608 phase = numpy.angle(data1[lag1,:])
1606 1609
1607 1610 return phase
1608 1611
1609 1612 class SpectralFitting(Operation):
1610 1613 '''
1611 1614 Function GetMoments()
1612 1615
1613 1616 Input:
1614 1617 Output:
1615 1618 Variables modified:
1616 1619 '''
1617 1620
1618 1621 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1619 1622
1620 1623
1621 1624 if path != None:
1622 1625 sys.path.append(path)
1623 1626 self.dataOut.library = importlib.import_module(file)
1624 1627
1625 1628 #To be inserted as a parameter
1626 1629 groupArray = numpy.array(groupList)
1627 1630 # groupArray = numpy.array([[0,1],[2,3]])
1628 1631 self.dataOut.groupList = groupArray
1629 1632
1630 1633 nGroups = groupArray.shape[0]
1631 1634 nChannels = self.dataIn.nChannels
1632 1635 nHeights=self.dataIn.heightList.size
1633 1636
1634 1637 #Parameters Array
1635 1638 self.dataOut.data_param = None
1636 1639
1637 1640 #Set constants
1638 1641 constants = self.dataOut.library.setConstants(self.dataIn)
1639 1642 self.dataOut.constants = constants
1640 1643 M = self.dataIn.normFactor
1641 1644 N = self.dataIn.nFFTPoints
1642 1645 ippSeconds = self.dataIn.ippSeconds
1643 1646 K = self.dataIn.nIncohInt
1644 1647 pairsArray = numpy.array(self.dataIn.pairsList)
1645 1648
1646 1649 #List of possible combinations
1647 1650 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1648 1651 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1649 1652
1650 1653 if getSNR:
1651 1654 listChannels = groupArray.reshape((groupArray.size))
1652 1655 listChannels.sort()
1653 1656 noise = self.dataIn.getNoise()
1654 1657 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1655 1658
1656 1659 for i in range(nGroups):
1657 1660 coord = groupArray[i,:]
1658 1661
1659 1662 #Input data array
1660 1663 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1661 1664 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1662 1665
1663 1666 #Cross Spectra data array for Covariance Matrixes
1664 1667 ind = 0
1665 1668 for pairs in listComb:
1666 1669 pairsSel = numpy.array([coord[x],coord[y]])
1667 1670 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1668 1671 ind += 1
1669 1672 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1670 1673 dataCross = dataCross**2/K
1671 1674
1672 1675 for h in range(nHeights):
1673 1676 # print self.dataOut.heightList[h]
1674 1677
1675 1678 #Input
1676 1679 d = data[:,h]
1677 1680
1678 1681 #Covariance Matrix
1679 1682 D = numpy.diag(d**2/K)
1680 1683 ind = 0
1681 1684 for pairs in listComb:
1682 1685 #Coordinates in Covariance Matrix
1683 1686 x = pairs[0]
1684 1687 y = pairs[1]
1685 1688 #Channel Index
1686 1689 S12 = dataCross[ind,:,h]
1687 1690 D12 = numpy.diag(S12)
1688 1691 #Completing Covariance Matrix with Cross Spectras
1689 1692 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1690 1693 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1691 1694 ind += 1
1692 1695 Dinv=numpy.linalg.inv(D)
1693 1696 L=numpy.linalg.cholesky(Dinv)
1694 1697 LT=L.T
1695 1698
1696 1699 dp = numpy.dot(LT,d)
1697 1700
1698 1701 #Initial values
1699 1702 data_spc = self.dataIn.data_spc[coord,:,h]
1700 1703
1701 1704 if (h>0)and(error1[3]<5):
1702 1705 p0 = self.dataOut.data_param[i,:,h-1]
1703 1706 else:
1704 1707 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1705 1708
1706 1709 try:
1707 1710 #Least Squares
1708 1711 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1709 1712 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1710 1713 #Chi square error
1711 1714 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1712 1715 #Error with Jacobian
1713 1716 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1714 1717 except:
1715 1718 minp = p0*numpy.nan
1716 1719 error0 = numpy.nan
1717 1720 error1 = p0*numpy.nan
1718 1721
1719 1722 #Save
1720 1723 if self.dataOut.data_param == None:
1721 1724 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1722 1725 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1723 1726
1724 1727 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1725 1728 self.dataOut.data_param[i,:,h] = minp
1726 1729 return
1727 1730
1728 1731 def __residFunction(self, p, dp, LT, constants):
1729 1732
1730 1733 fm = self.dataOut.library.modelFunction(p, constants)
1731 1734 fmp=numpy.dot(LT,fm)
1732 1735
1733 1736 return dp-fmp
1734 1737
1735 1738 def __getSNR(self, z, noise):
1736 1739
1737 1740 avg = numpy.average(z, axis=1)
1738 1741 SNR = (avg.T-noise)/noise
1739 1742 SNR = SNR.T
1740 1743 return SNR
1741 1744
1742 1745 def __chisq(p,chindex,hindex):
1743 1746 #similar to Resid but calculates CHI**2
1744 1747 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1745 1748 dp=numpy.dot(LT,d)
1746 1749 fmp=numpy.dot(LT,fm)
1747 1750 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1748 1751 return chisq
1749 1752
1750 1753 class WindProfiler(Operation):
1751 1754
1752 1755 __isConfig = False
1753 1756
1754 1757 __initime = None
1755 1758 __lastdatatime = None
1756 1759 __integrationtime = None
1757 1760
1758 1761 __buffer = None
1759 1762
1760 1763 __dataReady = False
1761 1764
1762 1765 __firstdata = None
1763 1766
1764 1767 n = None
1765 1768
1766 1769 def __init__(self):
1767 1770 Operation.__init__(self)
1768 1771
1769 1772 def __calculateCosDir(self, elev, azim):
1770 1773 zen = (90 - elev)*numpy.pi/180
1771 1774 azim = azim*numpy.pi/180
1772 1775 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1773 1776 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1774 1777
1775 1778 signX = numpy.sign(numpy.cos(azim))
1776 1779 signY = numpy.sign(numpy.sin(azim))
1777 1780
1778 1781 cosDirX = numpy.copysign(cosDirX, signX)
1779 1782 cosDirY = numpy.copysign(cosDirY, signY)
1780 1783 return cosDirX, cosDirY
1781 1784
1782 1785 def __calculateAngles(self, theta_x, theta_y, azimuth):
1783 1786
1784 1787 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1785 1788 zenith_arr = numpy.arccos(dir_cosw)
1786 1789 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1787 1790
1788 1791 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1789 1792 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1790 1793
1791 1794 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1792 1795
1793 1796 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1794 1797
1795 1798 #
1796 1799 if horOnly:
1797 1800 A = numpy.c_[dir_cosu,dir_cosv]
1798 1801 else:
1799 1802 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1800 1803 A = numpy.asmatrix(A)
1801 1804 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1802 1805
1803 1806 return A1
1804 1807
1805 1808 def __correctValues(self, heiRang, phi, velRadial, SNR):
1806 1809 listPhi = phi.tolist()
1807 1810 maxid = listPhi.index(max(listPhi))
1808 1811 minid = listPhi.index(min(listPhi))
1809 1812
1810 1813 rango = range(len(phi))
1811 1814 # rango = numpy.delete(rango,maxid)
1812 1815
1813 1816 heiRang1 = heiRang*math.cos(phi[maxid])
1814 1817 heiRangAux = heiRang*math.cos(phi[minid])
1815 1818 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1816 1819 heiRang1 = numpy.delete(heiRang1,indOut)
1817 1820
1818 1821 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1819 1822 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1820 1823
1821 1824 for i in rango:
1822 1825 x = heiRang*math.cos(phi[i])
1823 1826 y1 = velRadial[i,:]
1824 1827 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1825 1828
1826 1829 x1 = heiRang1
1827 1830 y11 = f1(x1)
1828 1831
1829 1832 y2 = SNR[i,:]
1830 1833 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1831 1834 y21 = f2(x1)
1832 1835
1833 1836 velRadial1[i,:] = y11
1834 1837 SNR1[i,:] = y21
1835 1838
1836 1839 return heiRang1, velRadial1, SNR1
1837 1840
1838 1841 def __calculateVelUVW(self, A, velRadial):
1839 1842
1840 1843 #Operacion Matricial
1841 1844 # velUVW = numpy.zeros((velRadial.shape[1],3))
1842 1845 # for ind in range(velRadial.shape[1]):
1843 1846 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1844 1847 # velUVW = velUVW.transpose()
1845 1848 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1846 1849 velUVW[:,:] = numpy.dot(A,velRadial)
1847 1850
1848 1851
1849 1852 return velUVW
1850 1853
1851 1854 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1852 1855
1853 1856 def techniqueDBS(self, kwargs):
1854 1857 """
1855 1858 Function that implements Doppler Beam Swinging (DBS) technique.
1856 1859
1857 1860 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1858 1861 Direction correction (if necessary), Ranges and SNR
1859 1862
1860 1863 Output: Winds estimation (Zonal, Meridional and Vertical)
1861 1864
1862 1865 Parameters affected: Winds, height range, SNR
1863 1866 """
1864 1867 velRadial0 = kwargs['velRadial']
1865 1868 heiRang = kwargs['heightList']
1866 1869 SNR0 = kwargs['SNR']
1867 1870
1868 1871 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
1869 1872 theta_x = numpy.array(kwargs['dirCosx'])
1870 1873 theta_y = numpy.array(kwargs['dirCosy'])
1871 1874 else:
1872 1875 elev = numpy.array(kwargs['elevation'])
1873 1876 azim = numpy.array(kwargs['azimuth'])
1874 1877 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1875 1878 azimuth = kwargs['correctAzimuth']
1876 1879 if kwargs.has_key('horizontalOnly'):
1877 1880 horizontalOnly = kwargs['horizontalOnly']
1878 1881 else: horizontalOnly = False
1879 1882 if kwargs.has_key('correctFactor'):
1880 1883 correctFactor = kwargs['correctFactor']
1881 1884 else: correctFactor = 1
1882 1885 if kwargs.has_key('channelList'):
1883 1886 channelList = kwargs['channelList']
1884 1887 if len(channelList) == 2:
1885 1888 horizontalOnly = True
1886 1889 arrayChannel = numpy.array(channelList)
1887 1890 param = param[arrayChannel,:,:]
1888 1891 theta_x = theta_x[arrayChannel]
1889 1892 theta_y = theta_y[arrayChannel]
1890 1893
1891 1894 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1892 1895 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1893 1896 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1894 1897
1895 1898 #Calculo de Componentes de la velocidad con DBS
1896 1899 winds = self.__calculateVelUVW(A,velRadial1)
1897 1900
1898 1901 return winds, heiRang1, SNR1
1899 1902
1900 1903 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1901 1904
1902 1905 nPairs = len(pairs_ccf)
1903 1906 posx = numpy.asarray(posx)
1904 1907 posy = numpy.asarray(posy)
1905 1908
1906 1909 #Rotacion Inversa para alinear con el azimuth
1907 1910 if azimuth!= None:
1908 1911 azimuth = azimuth*math.pi/180
1909 1912 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1910 1913 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1911 1914 else:
1912 1915 posx1 = posx
1913 1916 posy1 = posy
1914 1917
1915 1918 #Calculo de Distancias
1916 1919 distx = numpy.zeros(nPairs)
1917 1920 disty = numpy.zeros(nPairs)
1918 1921 dist = numpy.zeros(nPairs)
1919 1922 ang = numpy.zeros(nPairs)
1920 1923
1921 1924 for i in range(nPairs):
1922 1925 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1923 1926 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1924 1927 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1925 1928 ang[i] = numpy.arctan2(disty[i],distx[i])
1926 1929
1927 1930 return distx, disty, dist, ang
1928 1931 #Calculo de Matrices
1929 1932 # nPairs = len(pairs)
1930 1933 # ang1 = numpy.zeros((nPairs, 2, 1))
1931 1934 # dist1 = numpy.zeros((nPairs, 2, 1))
1932 1935 #
1933 1936 # for j in range(nPairs):
1934 1937 # dist1[j,0,0] = dist[pairs[j][0]]
1935 1938 # dist1[j,1,0] = dist[pairs[j][1]]
1936 1939 # ang1[j,0,0] = ang[pairs[j][0]]
1937 1940 # ang1[j,1,0] = ang[pairs[j][1]]
1938 1941 #
1939 1942 # return distx,disty, dist1,ang1
1940 1943
1941 1944
1942 1945 def __calculateVelVer(self, phase, lagTRange, _lambda):
1943 1946
1944 1947 Ts = lagTRange[1] - lagTRange[0]
1945 1948 velW = -_lambda*phase/(4*math.pi*Ts)
1946 1949
1947 1950 return velW
1948 1951
1949 1952 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1950 1953 nPairs = tau1.shape[0]
1951 1954 nHeights = tau1.shape[1]
1952 1955 vel = numpy.zeros((nPairs,3,nHeights))
1953 1956 dist1 = numpy.reshape(dist, (dist.size,1))
1954 1957
1955 1958 angCos = numpy.cos(ang)
1956 1959 angSin = numpy.sin(ang)
1957 1960
1958 1961 vel0 = dist1*tau1/(2*tau2**2)
1959 1962 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1960 1963 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1961 1964
1962 1965 ind = numpy.where(numpy.isinf(vel))
1963 1966 vel[ind] = numpy.nan
1964 1967
1965 1968 return vel
1966 1969
1967 1970 # def __getPairsAutoCorr(self, pairsList, nChannels):
1968 1971 #
1969 1972 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1970 1973 #
1971 1974 # for l in range(len(pairsList)):
1972 1975 # firstChannel = pairsList[l][0]
1973 1976 # secondChannel = pairsList[l][1]
1974 1977 #
1975 1978 # #Obteniendo pares de Autocorrelacion
1976 1979 # if firstChannel == secondChannel:
1977 1980 # pairsAutoCorr[firstChannel] = int(l)
1978 1981 #
1979 1982 # pairsAutoCorr = pairsAutoCorr.astype(int)
1980 1983 #
1981 1984 # pairsCrossCorr = range(len(pairsList))
1982 1985 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1983 1986 #
1984 1987 # return pairsAutoCorr, pairsCrossCorr
1985 1988
1986 1989 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1987 1990 def techniqueSA(self, kwargs):
1988 1991
1989 1992 """
1990 1993 Function that implements Spaced Antenna (SA) technique.
1991 1994
1992 1995 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1993 1996 Direction correction (if necessary), Ranges and SNR
1994 1997
1995 1998 Output: Winds estimation (Zonal, Meridional and Vertical)
1996 1999
1997 2000 Parameters affected: Winds
1998 2001 """
1999 2002 position_x = kwargs['positionX']
2000 2003 position_y = kwargs['positionY']
2001 2004 azimuth = kwargs['azimuth']
2002 2005
2003 2006 if kwargs.has_key('correctFactor'):
2004 2007 correctFactor = kwargs['correctFactor']
2005 2008 else:
2006 2009 correctFactor = 1
2007 2010
2008 2011 groupList = kwargs['groupList']
2009 2012 pairs_ccf = groupList[1]
2010 2013 tau = kwargs['tau']
2011 2014 _lambda = kwargs['_lambda']
2012 2015
2013 2016 #Cross Correlation pairs obtained
2014 2017 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
2015 2018 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
2016 2019 # pairsSelArray = numpy.array(pairsSelected)
2017 2020 # pairs = []
2018 2021 #
2019 2022 # #Wind estimation pairs obtained
2020 2023 # for i in range(pairsSelArray.shape[0]/2):
2021 2024 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
2022 2025 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
2023 2026 # pairs.append((ind1,ind2))
2024 2027
2025 2028 indtau = tau.shape[0]/2
2026 2029 tau1 = tau[:indtau,:]
2027 2030 tau2 = tau[indtau:-1,:]
2028 2031 # tau1 = tau1[pairs,:]
2029 2032 # tau2 = tau2[pairs,:]
2030 2033 phase1 = tau[-1,:]
2031 2034
2032 2035 #---------------------------------------------------------------------
2033 2036 #Metodo Directo
2034 2037 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
2035 2038 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
2036 2039 winds = stats.nanmean(winds, axis=0)
2037 2040 #---------------------------------------------------------------------
2038 2041 #Metodo General
2039 2042 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
2040 2043 # #Calculo Coeficientes de Funcion de Correlacion
2041 2044 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
2042 2045 # #Calculo de Velocidades
2043 2046 # winds = self.calculateVelUV(F,G,A,B,H)
2044 2047
2045 2048 #---------------------------------------------------------------------
2046 2049 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
2047 2050 winds = correctFactor*winds
2048 2051 return winds
2049 2052
2050 2053 def __checkTime(self, currentTime, paramInterval, outputInterval):
2051 2054
2052 2055 dataTime = currentTime + paramInterval
2053 2056 deltaTime = dataTime - self.__initime
2054 2057
2055 2058 if deltaTime >= outputInterval or deltaTime < 0:
2056 2059 self.__dataReady = True
2057 2060 return
2058 2061
2059 2062 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
2060 2063 '''
2061 2064 Function that implements winds estimation technique with detected meteors.
2062 2065
2063 2066 Input: Detected meteors, Minimum meteor quantity to wind estimation
2064 2067
2065 2068 Output: Winds estimation (Zonal and Meridional)
2066 2069
2067 2070 Parameters affected: Winds
2068 2071 '''
2069 2072 # print arrayMeteor.shape
2070 2073 #Settings
2071 2074 nInt = (heightMax - heightMin)/2
2072 2075 # print nInt
2073 2076 nInt = int(nInt)
2074 2077 # print nInt
2075 2078 winds = numpy.zeros((2,nInt))*numpy.nan
2076 2079
2077 2080 #Filter errors
2078 2081 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
2079 2082 finalMeteor = arrayMeteor[error,:]
2080 2083
2081 2084 #Meteor Histogram
2082 2085 finalHeights = finalMeteor[:,2]
2083 2086 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
2084 2087 nMeteorsPerI = hist[0]
2085 2088 heightPerI = hist[1]
2086 2089
2087 2090 #Sort of meteors
2088 2091 indSort = finalHeights.argsort()
2089 2092 finalMeteor2 = finalMeteor[indSort,:]
2090 2093
2091 2094 # Calculating winds
2092 2095 ind1 = 0
2093 2096 ind2 = 0
2094 2097
2095 2098 for i in range(nInt):
2096 2099 nMet = nMeteorsPerI[i]
2097 2100 ind1 = ind2
2098 2101 ind2 = ind1 + nMet
2099 2102
2100 2103 meteorAux = finalMeteor2[ind1:ind2,:]
2101 2104
2102 2105 if meteorAux.shape[0] >= meteorThresh:
2103 2106 vel = meteorAux[:, 6]
2104 2107 zen = meteorAux[:, 4]*numpy.pi/180
2105 2108 azim = meteorAux[:, 3]*numpy.pi/180
2106 2109
2107 2110 n = numpy.cos(zen)
2108 2111 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
2109 2112 # l = m*numpy.tan(azim)
2110 2113 l = numpy.sin(zen)*numpy.sin(azim)
2111 2114 m = numpy.sin(zen)*numpy.cos(azim)
2112 2115
2113 2116 A = numpy.vstack((l, m)).transpose()
2114 2117 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
2115 2118 windsAux = numpy.dot(A1, vel)
2116 2119
2117 2120 winds[0,i] = windsAux[0]
2118 2121 winds[1,i] = windsAux[1]
2119 2122
2120 2123 return winds, heightPerI[:-1]
2121 2124
2122 2125 def techniqueNSM_SA(self, **kwargs):
2123 2126 metArray = kwargs['metArray']
2124 2127 heightList = kwargs['heightList']
2125 2128 timeList = kwargs['timeList']
2126 2129
2127 2130 rx_location = kwargs['rx_location']
2128 2131 groupList = kwargs['groupList']
2129 2132 azimuth = kwargs['azimuth']
2130 2133 dfactor = kwargs['dfactor']
2131 2134 k = kwargs['k']
2132 2135
2133 2136 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2134 2137 d = dist*dfactor
2135 2138 #Phase calculation
2136 2139 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2137 2140
2138 2141 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2139 2142
2140 2143 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2141 2144 azimuth1 = azimuth1*numpy.pi/180
2142 2145
2143 2146 for i in range(heightList.size):
2144 2147 h = heightList[i]
2145 2148 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2146 2149 metHeight = metArray1[indH,:]
2147 2150 if metHeight.shape[0] >= 2:
2148 2151 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2149 2152 iazim = metHeight[:,1].astype(int)
2150 2153 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2151 2154 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2152 2155 A = numpy.asmatrix(A)
2153 2156 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2154 2157 velHor = numpy.dot(A1,velAux)
2155 2158
2156 2159 velEst[i,:] = numpy.squeeze(velHor)
2157 2160 return velEst
2158 2161
2159 2162 def __getPhaseSlope(self, metArray, heightList, timeList):
2160 2163 meteorList = []
2161 2164 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2162 2165 #Putting back together the meteor matrix
2163 2166 utctime = metArray[:,0]
2164 2167 uniqueTime = numpy.unique(utctime)
2165 2168
2166 2169 phaseDerThresh = 0.5
2167 2170 ippSeconds = timeList[1] - timeList[0]
2168 2171 sec = numpy.where(timeList>1)[0][0]
2169 2172 nPairs = metArray.shape[1] - 6
2170 2173 nHeights = len(heightList)
2171 2174
2172 2175 for t in uniqueTime:
2173 2176 metArray1 = metArray[utctime==t,:]
2174 2177 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2175 2178 tmet = metArray1[:,1].astype(int)
2176 2179 hmet = metArray1[:,2].astype(int)
2177 2180
2178 2181 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2179 2182 metPhase[:,:] = numpy.nan
2180 2183 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2181 2184
2182 2185 #Delete short trails
2183 2186 metBool = ~numpy.isnan(metPhase[0,:,:])
2184 2187 heightVect = numpy.sum(metBool, axis = 1)
2185 2188 metBool[heightVect<sec,:] = False
2186 2189 metPhase[:,heightVect<sec,:] = numpy.nan
2187 2190
2188 2191 #Derivative
2189 2192 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2190 2193 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2191 2194 metPhase[phDerAux] = numpy.nan
2192 2195
2193 2196 #--------------------------METEOR DETECTION -----------------------------------------
2194 2197 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2195 2198
2196 2199 for p in numpy.arange(nPairs):
2197 2200 phase = metPhase[p,:,:]
2198 2201 phDer = metDer[p,:,:]
2199 2202
2200 2203 for h in indMet:
2201 2204 height = heightList[h]
2202 2205 phase1 = phase[h,:] #82
2203 2206 phDer1 = phDer[h,:]
2204 2207
2205 2208 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2206 2209
2207 2210 indValid = numpy.where(~numpy.isnan(phase1))[0]
2208 2211 initMet = indValid[0]
2209 2212 endMet = 0
2210 2213
2211 2214 for i in range(len(indValid)-1):
2212 2215
2213 2216 #Time difference
2214 2217 inow = indValid[i]
2215 2218 inext = indValid[i+1]
2216 2219 idiff = inext - inow
2217 2220 #Phase difference
2218 2221 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2219 2222
2220 2223 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2221 2224 sizeTrail = inow - initMet + 1
2222 2225 if sizeTrail>3*sec: #Too short meteors
2223 2226 x = numpy.arange(initMet,inow+1)*ippSeconds
2224 2227 y = phase1[initMet:inow+1]
2225 2228 ynnan = ~numpy.isnan(y)
2226 2229 x = x[ynnan]
2227 2230 y = y[ynnan]
2228 2231 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2229 2232 ylin = x*slope + intercept
2230 2233 rsq = r_value**2
2231 2234 if rsq > 0.5:
2232 2235 vel = slope#*height*1000/(k*d)
2233 2236 estAux = numpy.array([utctime,p,height, vel, rsq])
2234 2237 meteorList.append(estAux)
2235 2238 initMet = inext
2236 2239 metArray2 = numpy.array(meteorList)
2237 2240
2238 2241 return metArray2
2239 2242
2240 2243 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2241 2244
2242 2245 azimuth1 = numpy.zeros(len(pairslist))
2243 2246 dist = numpy.zeros(len(pairslist))
2244 2247
2245 2248 for i in range(len(rx_location)):
2246 2249 ch0 = pairslist[i][0]
2247 2250 ch1 = pairslist[i][1]
2248 2251
2249 2252 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2250 2253 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2251 2254 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2252 2255 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2253 2256
2254 2257 azimuth1 -= azimuth0
2255 2258 return azimuth1, dist
2256 2259
2257 2260 def techniqueNSM_DBS(self, **kwargs):
2258 2261 metArray = kwargs['metArray']
2259 2262 heightList = kwargs['heightList']
2260 2263 timeList = kwargs['timeList']
2261 2264 azimuth = kwargs['azimuth']
2262 2265 theta_x = numpy.array(kwargs['theta_x'])
2263 2266 theta_y = numpy.array(kwargs['theta_y'])
2264 2267
2265 2268 utctime = metArray[:,0]
2266 2269 cmet = metArray[:,1].astype(int)
2267 2270 hmet = metArray[:,3].astype(int)
2268 2271 SNRmet = metArray[:,4]
2269 2272 vmet = metArray[:,5]
2270 2273 spcmet = metArray[:,6]
2271 2274
2272 2275 nChan = numpy.max(cmet) + 1
2273 2276 nHeights = len(heightList)
2274 2277
2275 2278 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2276 2279 hmet = heightList[hmet]
2277 2280 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2278 2281
2279 2282 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2280 2283
2281 2284 for i in range(nHeights - 1):
2282 2285 hmin = heightList[i]
2283 2286 hmax = heightList[i + 1]
2284 2287
2285 2288 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2286 2289 indthisH = numpy.where(thisH)
2287 2290
2288 2291 if numpy.size(indthisH) > 3:
2289 2292
2290 2293 vel_aux = vmet[thisH]
2291 2294 chan_aux = cmet[thisH]
2292 2295 cosu_aux = dir_cosu[chan_aux]
2293 2296 cosv_aux = dir_cosv[chan_aux]
2294 2297 cosw_aux = dir_cosw[chan_aux]
2295 2298
2296 2299 nch = numpy.size(numpy.unique(chan_aux))
2297 2300 if nch > 1:
2298 2301 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2299 2302 velEst[i,:] = numpy.dot(A,vel_aux)
2300 2303
2301 2304 return velEst
2302 2305
2303 2306 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2304 2307
2305 2308 param = dataOut.data_param
2306 2309 if dataOut.abscissaList != None:
2307 2310 absc = dataOut.abscissaList[:-1]
2308 2311 # noise = dataOut.noise
2309 2312 heightList = dataOut.heightList
2310 2313 SNR = dataOut.data_SNR
2311 2314
2312 2315 if technique == 'DBS':
2313 2316
2314 2317 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2315 2318 kwargs['heightList'] = heightList
2316 2319 kwargs['SNR'] = SNR
2317 2320
2318 2321 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2319 2322 dataOut.utctimeInit = dataOut.utctime
2320 2323 dataOut.outputInterval = dataOut.paramInterval
2321 2324
2322 2325 elif technique == 'SA':
2323 2326
2324 2327 #Parameters
2325 2328 # position_x = kwargs['positionX']
2326 2329 # position_y = kwargs['positionY']
2327 2330 # azimuth = kwargs['azimuth']
2328 2331 #
2329 2332 # if kwargs.has_key('crosspairsList'):
2330 2333 # pairs = kwargs['crosspairsList']
2331 2334 # else:
2332 2335 # pairs = None
2333 2336 #
2334 2337 # if kwargs.has_key('correctFactor'):
2335 2338 # correctFactor = kwargs['correctFactor']
2336 2339 # else:
2337 2340 # correctFactor = 1
2338 2341
2339 2342 # tau = dataOut.data_param
2340 2343 # _lambda = dataOut.C/dataOut.frequency
2341 2344 # pairsList = dataOut.groupList
2342 2345 # nChannels = dataOut.nChannels
2343 2346
2344 2347 kwargs['groupList'] = dataOut.groupList
2345 2348 kwargs['tau'] = dataOut.data_param
2346 2349 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2347 2350 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2348 2351 dataOut.data_output = self.techniqueSA(kwargs)
2349 2352 dataOut.utctimeInit = dataOut.utctime
2350 2353 dataOut.outputInterval = dataOut.timeInterval
2351 2354
2352 2355 elif technique == 'Meteors':
2353 2356 dataOut.flagNoData = True
2354 2357 self.__dataReady = False
2355 2358
2356 2359 if kwargs.has_key('nHours'):
2357 2360 nHours = kwargs['nHours']
2358 2361 else:
2359 2362 nHours = 1
2360 2363
2361 2364 if kwargs.has_key('meteorsPerBin'):
2362 2365 meteorThresh = kwargs['meteorsPerBin']
2363 2366 else:
2364 2367 meteorThresh = 6
2365 2368
2366 2369 if kwargs.has_key('hmin'):
2367 2370 hmin = kwargs['hmin']
2368 2371 else: hmin = 70
2369 2372 if kwargs.has_key('hmax'):
2370 2373 hmax = kwargs['hmax']
2371 2374 else: hmax = 110
2372 2375
2373 2376 dataOut.outputInterval = nHours*3600
2374 2377
2375 2378 if self.__isConfig == False:
2376 2379 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2377 2380 #Get Initial LTC time
2378 2381 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2379 2382 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2380 2383
2381 2384 self.__isConfig = True
2382 2385
2383 2386 if self.__buffer == None:
2384 2387 self.__buffer = dataOut.data_param
2385 2388 self.__firstdata = copy.copy(dataOut)
2386 2389
2387 2390 else:
2388 2391 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2389 2392
2390 2393 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2391 2394
2392 2395 if self.__dataReady:
2393 2396 dataOut.utctimeInit = self.__initime
2394 2397
2395 2398 self.__initime += dataOut.outputInterval #to erase time offset
2396 2399
2397 2400 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2398 2401 dataOut.flagNoData = False
2399 2402 self.__buffer = None
2400 2403
2401 2404 elif technique == 'Meteors1':
2402 2405 dataOut.flagNoData = True
2403 2406 self.__dataReady = False
2404 2407
2405 2408 if kwargs.has_key('nMins'):
2406 2409 nMins = kwargs['nMins']
2407 2410 else: nMins = 20
2408 2411 if kwargs.has_key('rx_location'):
2409 2412 rx_location = kwargs['rx_location']
2410 2413 else: rx_location = [(0,1),(1,1),(1,0)]
2411 2414 if kwargs.has_key('azimuth'):
2412 2415 azimuth = kwargs['azimuth']
2413 2416 else: azimuth = 51.06
2414 2417 if kwargs.has_key('dfactor'):
2415 2418 dfactor = kwargs['dfactor']
2416 2419 if kwargs.has_key('mode'):
2417 2420 mode = kwargs['mode']
2418 2421 if kwargs.has_key('theta_x'):
2419 2422 theta_x = kwargs['theta_x']
2420 2423 if kwargs.has_key('theta_y'):
2421 2424 theta_y = kwargs['theta_y']
2422 2425 else: mode = 'SA'
2423 2426
2424 2427 #Borrar luego esto
2425 2428 if dataOut.groupList == None:
2426 2429 dataOut.groupList = [(0,1),(0,2),(1,2)]
2427 2430 groupList = dataOut.groupList
2428 2431 C = 3e8
2429 2432 freq = 50e6
2430 2433 lamb = C/freq
2431 2434 k = 2*numpy.pi/lamb
2432 2435
2433 2436 timeList = dataOut.abscissaList
2434 2437 heightList = dataOut.heightList
2435 2438
2436 2439 if self.__isConfig == False:
2437 2440 dataOut.outputInterval = nMins*60
2438 2441 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2439 2442 #Get Initial LTC time
2440 2443 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2441 2444 minuteAux = initime.minute
2442 2445 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2443 2446 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2444 2447
2445 2448 self.__isConfig = True
2446 2449
2447 2450 if self.__buffer == None:
2448 2451 self.__buffer = dataOut.data_param
2449 2452 self.__firstdata = copy.copy(dataOut)
2450 2453
2451 2454 else:
2452 2455 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2453 2456
2454 2457 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2455 2458
2456 2459 if self.__dataReady:
2457 2460 dataOut.utctimeInit = self.__initime
2458 2461 self.__initime += dataOut.outputInterval #to erase time offset
2459 2462
2460 2463 metArray = self.__buffer
2461 2464 if mode == 'SA':
2462 2465 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2463 2466 elif mode == 'DBS':
2464 2467 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2465 2468 dataOut.data_output = dataOut.data_output.T
2466 2469 dataOut.flagNoData = False
2467 2470 self.__buffer = None
2468 2471
2469 2472 return
2470 2473
2471 2474 class EWDriftsEstimation(Operation):
2472 2475
2473 2476 def __init__(self):
2474 2477 Operation.__init__(self)
2475 2478
2476 2479 def __correctValues(self, heiRang, phi, velRadial, SNR):
2477 2480 listPhi = phi.tolist()
2478 2481 maxid = listPhi.index(max(listPhi))
2479 2482 minid = listPhi.index(min(listPhi))
2480 2483
2481 2484 rango = range(len(phi))
2482 2485 # rango = numpy.delete(rango,maxid)
2483 2486
2484 2487 heiRang1 = heiRang*math.cos(phi[maxid])
2485 2488 heiRangAux = heiRang*math.cos(phi[minid])
2486 2489 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2487 2490 heiRang1 = numpy.delete(heiRang1,indOut)
2488 2491
2489 2492 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2490 2493 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2491 2494
2492 2495 for i in rango:
2493 2496 x = heiRang*math.cos(phi[i])
2494 2497 y1 = velRadial[i,:]
2495 2498 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2496 2499
2497 2500 x1 = heiRang1
2498 2501 y11 = f1(x1)
2499 2502
2500 2503 y2 = SNR[i,:]
2501 2504 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2502 2505 y21 = f2(x1)
2503 2506
2504 2507 velRadial1[i,:] = y11
2505 2508 SNR1[i,:] = y21
2506 2509
2507 2510 return heiRang1, velRadial1, SNR1
2508 2511
2509 2512 def run(self, dataOut, zenith, zenithCorrection):
2510 2513 heiRang = dataOut.heightList
2511 2514 velRadial = dataOut.data_param[:,3,:]
2512 2515 SNR = dataOut.data_SNR
2513 2516
2514 2517 zenith = numpy.array(zenith)
2515 2518 zenith -= zenithCorrection
2516 2519 zenith *= numpy.pi/180
2517 2520
2518 2521 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2519 2522
2520 2523 alp = zenith[0]
2521 2524 bet = zenith[1]
2522 2525
2523 2526 w_w = velRadial1[0,:]
2524 2527 w_e = velRadial1[1,:]
2525 2528
2526 2529 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2527 2530 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2528 2531
2529 2532 winds = numpy.vstack((u,w))
2530 2533
2531 2534 dataOut.heightList = heiRang1
2532 2535 dataOut.data_output = winds
2533 2536 dataOut.data_SNR = SNR1
2534 2537
2535 2538 dataOut.utctimeInit = dataOut.utctime
2536 2539 dataOut.outputInterval = dataOut.timeInterval
2537 2540 return
2538 2541
2539 2542 #--------------- Non Specular Meteor ----------------
2540 2543
2541 2544 class NonSpecularMeteorDetection(Operation):
2542 2545
2543 2546 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2544 2547 data_acf = dataOut.data_pre[0]
2545 2548 data_ccf = dataOut.data_pre[1]
2546 2549 pairsList = dataOut.groupList[1]
2547 2550
2548 2551 lamb = dataOut.C/dataOut.frequency
2549 2552 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2550 2553 paramInterval = dataOut.paramInterval
2551 2554
2552 2555 nChannels = data_acf.shape[0]
2553 2556 nLags = data_acf.shape[1]
2554 2557 nProfiles = data_acf.shape[2]
2555 2558 nHeights = dataOut.nHeights
2556 2559 nCohInt = dataOut.nCohInt
2557 2560 sec = numpy.round(nProfiles/dataOut.paramInterval)
2558 2561 heightList = dataOut.heightList
2559 2562 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2560 2563 utctime = dataOut.utctime
2561 2564
2562 2565 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2563 2566
2564 2567 #------------------------ SNR --------------------------------------
2565 2568 power = data_acf[:,0,:,:].real
2566 2569 noise = numpy.zeros(nChannels)
2567 2570 SNR = numpy.zeros(power.shape)
2568 2571 for i in range(nChannels):
2569 2572 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2570 2573 SNR[i] = (power[i]-noise[i])/noise[i]
2571 2574 SNRm = numpy.nanmean(SNR, axis = 0)
2572 2575 SNRdB = 10*numpy.log10(SNR)
2573 2576
2574 2577 if mode == 'SA':
2575 2578 dataOut.groupList = dataOut.groupList[1]
2576 2579 nPairs = data_ccf.shape[0]
2577 2580 #---------------------- Coherence and Phase --------------------------
2578 2581 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2579 2582 # phase1 = numpy.copy(phase)
2580 2583 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2581 2584
2582 2585 for p in range(nPairs):
2583 2586 ch0 = pairsList[p][0]
2584 2587 ch1 = pairsList[p][1]
2585 2588 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2586 2589 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2587 2590 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2588 2591 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2589 2592 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2590 2593 coh = numpy.nanmax(coh1, axis = 0)
2591 2594 # struc = numpy.ones((5,1))
2592 2595 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2593 2596 #---------------------- Radial Velocity ----------------------------
2594 2597 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2595 2598 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2596 2599
2597 2600 if allData:
2598 2601 boolMetFin = ~numpy.isnan(SNRm)
2599 2602 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2600 2603 else:
2601 2604 #------------------------ Meteor mask ---------------------------------
2602 2605 # #SNR mask
2603 2606 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2604 2607 #
2605 2608 # #Erase small objects
2606 2609 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2607 2610 #
2608 2611 # auxEEJ = numpy.sum(boolMet1,axis=0)
2609 2612 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2610 2613 # indEEJ = numpy.where(indOver)[0]
2611 2614 # indNEEJ = numpy.where(~indOver)[0]
2612 2615 #
2613 2616 # boolMetFin = boolMet1
2614 2617 #
2615 2618 # if indEEJ.size > 0:
2616 2619 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2617 2620 #
2618 2621 # boolMet2 = coh > cohThresh
2619 2622 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2620 2623 #
2621 2624 # #Final Meteor mask
2622 2625 # boolMetFin = boolMet1|boolMet2
2623 2626
2624 2627 #Coherence mask
2625 2628 boolMet1 = coh > 0.75
2626 2629 struc = numpy.ones((30,1))
2627 2630 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2628 2631
2629 2632 #Derivative mask
2630 2633 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2631 2634 boolMet2 = derPhase < 0.2
2632 2635 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2633 2636 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2634 2637 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2635 2638 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2636 2639 # #Final mask
2637 2640 # boolMetFin = boolMet2
2638 2641 boolMetFin = boolMet1&boolMet2
2639 2642 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2640 2643 #Creating data_param
2641 2644 coordMet = numpy.where(boolMetFin)
2642 2645
2643 2646 tmet = coordMet[0]
2644 2647 hmet = coordMet[1]
2645 2648
2646 2649 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2647 2650 data_param[:,0] = utctime
2648 2651 data_param[:,1] = tmet
2649 2652 data_param[:,2] = hmet
2650 2653 data_param[:,3] = SNRm[tmet,hmet]
2651 2654 data_param[:,4] = velRad[tmet,hmet]
2652 2655 data_param[:,5] = coh[tmet,hmet]
2653 2656 data_param[:,6:] = phase[:,tmet,hmet].T
2654 2657
2655 2658 elif mode == 'DBS':
2656 2659 dataOut.groupList = numpy.arange(nChannels)
2657 2660
2658 2661 #Radial Velocities
2659 2662 phase = numpy.angle(data_acf[:,1,:,:])
2660 2663 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2661 2664 velRad = phase*lamb/(4*numpy.pi*tSamp)
2662 2665
2663 2666 #Spectral width
2664 2667 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2665 2668 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2666 2669 acf1 = data_acf[:,1,:,:]
2667 2670 acf2 = data_acf[:,2,:,:]
2668 2671
2669 2672 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2670 2673 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2671 2674 if allData:
2672 2675 boolMetFin = ~numpy.isnan(SNRdB)
2673 2676 else:
2674 2677 #SNR
2675 2678 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2676 2679 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2677 2680
2678 2681 #Radial velocity
2679 2682 boolMet2 = numpy.abs(velRad) < 20
2680 2683 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2681 2684
2682 2685 #Spectral Width
2683 2686 boolMet3 = spcWidth < 30
2684 2687 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2685 2688 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2686 2689 boolMetFin = boolMet1&boolMet2&boolMet3
2687 2690
2688 2691 #Creating data_param
2689 2692 coordMet = numpy.where(boolMetFin)
2690 2693
2691 2694 cmet = coordMet[0]
2692 2695 tmet = coordMet[1]
2693 2696 hmet = coordMet[2]
2694 2697
2695 2698 data_param = numpy.zeros((tmet.size, 7))
2696 2699 data_param[:,0] = utctime
2697 2700 data_param[:,1] = cmet
2698 2701 data_param[:,2] = tmet
2699 2702 data_param[:,3] = hmet
2700 2703 data_param[:,4] = SNR[cmet,tmet,hmet].T
2701 2704 data_param[:,5] = velRad[cmet,tmet,hmet].T
2702 2705 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2703 2706
2704 2707 # self.dataOut.data_param = data_int
2705 2708 if len(data_param) == 0:
2706 2709 dataOut.flagNoData = True
2707 2710 else:
2708 2711 dataOut.data_param = data_param
2709 2712
2710 2713 def __erase_small(self, binArray, threshX, threshY):
2711 2714 labarray, numfeat = ndimage.measurements.label(binArray)
2712 2715 binArray1 = numpy.copy(binArray)
2713 2716
2714 2717 for i in range(1,numfeat + 1):
2715 2718 auxBin = (labarray==i)
2716 2719 auxSize = auxBin.sum()
2717 2720
2718 2721 x,y = numpy.where(auxBin)
2719 2722 widthX = x.max() - x.min()
2720 2723 widthY = y.max() - y.min()
2721 2724
2722 2725 #width X: 3 seg -> 12.5*3
2723 2726 #width Y:
2724 2727
2725 2728 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2726 2729 binArray1[auxBin] = False
2727 2730
2728 2731 return binArray1
2729 2732
2730 2733 #--------------- Specular Meteor ----------------
2731 2734
2732 2735 class SMDetection(Operation):
2733 2736 '''
2734 2737 Function DetectMeteors()
2735 2738 Project developed with paper:
2736 2739 HOLDSWORTH ET AL. 2004
2737 2740
2738 2741 Input:
2739 2742 self.dataOut.data_pre
2740 2743
2741 2744 centerReceiverIndex: From the channels, which is the center receiver
2742 2745
2743 2746 hei_ref: Height reference for the Beacon signal extraction
2744 2747 tauindex:
2745 2748 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2746 2749
2747 2750 cohDetection: Whether to user Coherent detection or not
2748 2751 cohDet_timeStep: Coherent Detection calculation time step
2749 2752 cohDet_thresh: Coherent Detection phase threshold to correct phases
2750 2753
2751 2754 noise_timeStep: Noise calculation time step
2752 2755 noise_multiple: Noise multiple to define signal threshold
2753 2756
2754 2757 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2755 2758 multDet_rangeLimit: Multiple Detection Removal range limit in km
2756 2759
2757 2760 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2758 2761 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2759 2762
2760 2763 hmin: Minimum Height of the meteor to use it in the further wind estimations
2761 2764 hmax: Maximum Height of the meteor to use it in the further wind estimations
2762 2765 azimuth: Azimuth angle correction
2763 2766
2764 2767 Affected:
2765 2768 self.dataOut.data_param
2766 2769
2767 2770 Rejection Criteria (Errors):
2768 2771 0: No error; analysis OK
2769 2772 1: SNR < SNR threshold
2770 2773 2: angle of arrival (AOA) ambiguously determined
2771 2774 3: AOA estimate not feasible
2772 2775 4: Large difference in AOAs obtained from different antenna baselines
2773 2776 5: echo at start or end of time series
2774 2777 6: echo less than 5 examples long; too short for analysis
2775 2778 7: echo rise exceeds 0.3s
2776 2779 8: echo decay time less than twice rise time
2777 2780 9: large power level before echo
2778 2781 10: large power level after echo
2779 2782 11: poor fit to amplitude for estimation of decay time
2780 2783 12: poor fit to CCF phase variation for estimation of radial drift velocity
2781 2784 13: height unresolvable echo: not valid height within 70 to 110 km
2782 2785 14: height ambiguous echo: more then one possible height within 70 to 110 km
2783 2786 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2784 2787 16: oscilatory echo, indicating event most likely not an underdense echo
2785 2788
2786 2789 17: phase difference in meteor Reestimation
2787 2790
2788 2791 Data Storage:
2789 2792 Meteors for Wind Estimation (8):
2790 2793 Utc Time | Range Height
2791 2794 Azimuth Zenith errorCosDir
2792 2795 VelRad errorVelRad
2793 2796 Phase0 Phase1 Phase2 Phase3
2794 2797 TypeError
2795 2798
2796 2799 '''
2797 2800
2798 2801 def run(self, dataOut, hei_ref = None, tauindex = 0,
2799 2802 phaseOffsets = None,
2800 2803 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2801 2804 noise_timeStep = 4, noise_multiple = 4,
2802 2805 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2803 2806 phaseThresh = 20, SNRThresh = 5,
2804 2807 hmin = 50, hmax=150, azimuth = 0,
2805 2808 channelPositions = None) :
2806 2809
2807 2810
2808 2811 #Getting Pairslist
2809 2812 if channelPositions == None:
2810 2813 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2811 2814 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2812 2815 meteorOps = SMOperations()
2813 2816 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2814 2817 heiRang = dataOut.getHeiRange()
2815 2818 #Get Beacon signal - No Beacon signal anymore
2816 2819 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2817 2820 #
2818 2821 # if hei_ref != None:
2819 2822 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2820 2823 #
2821 2824
2822 2825
2823 2826 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2824 2827 # see if the user put in pre defined phase shifts
2825 2828 voltsPShift = dataOut.data_pre.copy()
2826 2829
2827 2830 # if predefinedPhaseShifts != None:
2828 2831 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2829 2832 #
2830 2833 # # elif beaconPhaseShifts:
2831 2834 # # #get hardware phase shifts using beacon signal
2832 2835 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2833 2836 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2834 2837 #
2835 2838 # else:
2836 2839 # hardwarePhaseShifts = numpy.zeros(5)
2837 2840 #
2838 2841 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2839 2842 # for i in range(self.dataOut.data_pre.shape[0]):
2840 2843 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2841 2844
2842 2845 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2843 2846
2844 2847 #Remove DC
2845 2848 voltsDC = numpy.mean(voltsPShift,1)
2846 2849 voltsDC = numpy.mean(voltsDC,1)
2847 2850 for i in range(voltsDC.shape[0]):
2848 2851 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2849 2852
2850 2853 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2851 2854 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2852 2855
2853 2856 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2854 2857 #Coherent Detection
2855 2858 if cohDetection:
2856 2859 #use coherent detection to get the net power
2857 2860 cohDet_thresh = cohDet_thresh*numpy.pi/180
2858 2861 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2859 2862
2860 2863 #Non-coherent detection!
2861 2864 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2862 2865 #********** END OF COH/NON-COH POWER CALCULATION**********************
2863 2866
2864 2867 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2865 2868 #Get noise
2866 2869 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2867 2870 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2868 2871 #Get signal threshold
2869 2872 signalThresh = noise_multiple*noise
2870 2873 #Meteor echoes detection
2871 2874 listMeteors = self.__findMeteors(powerNet, signalThresh)
2872 2875 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2873 2876
2874 2877 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2875 2878 #Parameters
2876 2879 heiRange = dataOut.getHeiRange()
2877 2880 rangeInterval = heiRange[1] - heiRange[0]
2878 2881 rangeLimit = multDet_rangeLimit/rangeInterval
2879 2882 timeLimit = multDet_timeLimit/dataOut.timeInterval
2880 2883 #Multiple detection removals
2881 2884 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2882 2885 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2883 2886
2884 2887 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2885 2888 #Parameters
2886 2889 phaseThresh = phaseThresh*numpy.pi/180
2887 2890 thresh = [phaseThresh, noise_multiple, SNRThresh]
2888 2891 #Meteor reestimation (Errors N 1, 6, 12, 17)
2889 2892 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2890 2893 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2891 2894 #Estimation of decay times (Errors N 7, 8, 11)
2892 2895 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2893 2896 #******************* END OF METEOR REESTIMATION *******************
2894 2897
2895 2898 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2896 2899 #Calculating Radial Velocity (Error N 15)
2897 2900 radialStdThresh = 10
2898 2901 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2899 2902
2900 2903 if len(listMeteors4) > 0:
2901 2904 #Setting New Array
2902 2905 date = dataOut.utctime
2903 2906 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2904 2907
2905 2908 #Correcting phase offset
2906 2909 if phaseOffsets != None:
2907 2910 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2908 2911 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2909 2912
2910 2913 #Second Pairslist
2911 2914 pairsList = []
2912 2915 pairx = (0,1)
2913 2916 pairy = (2,3)
2914 2917 pairsList.append(pairx)
2915 2918 pairsList.append(pairy)
2916 2919
2917 2920 jph = numpy.array([0,0,0,0])
2918 2921 h = (hmin,hmax)
2919 2922 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2920 2923
2921 2924 # #Calculate AOA (Error N 3, 4)
2922 2925 # #JONES ET AL. 1998
2923 2926 # error = arrayParameters[:,-1]
2924 2927 # AOAthresh = numpy.pi/8
2925 2928 # phases = -arrayParameters[:,9:13]
2926 2929 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2927 2930 #
2928 2931 # #Calculate Heights (Error N 13 and 14)
2929 2932 # error = arrayParameters[:,-1]
2930 2933 # Ranges = arrayParameters[:,2]
2931 2934 # zenith = arrayParameters[:,5]
2932 2935 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2933 2936 # error = arrayParameters[:,-1]
2934 2937 #********************* END OF PARAMETERS CALCULATION **************************
2935 2938
2936 2939 #***************************+ PASS DATA TO NEXT STEP **********************
2937 2940 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2938 2941 dataOut.data_param = arrayParameters
2939 2942
2940 2943 if arrayParameters == None:
2941 2944 dataOut.flagNoData = True
2942 2945 else:
2943 2946 dataOut.flagNoData = True
2944 2947
2945 2948 return
2946 2949
2947 2950 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2948 2951
2949 2952 minIndex = min(newheis[0])
2950 2953 maxIndex = max(newheis[0])
2951 2954
2952 2955 voltage = voltage0[:,:,minIndex:maxIndex+1]
2953 2956 nLength = voltage.shape[1]/n
2954 2957 nMin = 0
2955 2958 nMax = 0
2956 2959 phaseOffset = numpy.zeros((len(pairslist),n))
2957 2960
2958 2961 for i in range(n):
2959 2962 nMax += nLength
2960 2963 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2961 2964 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2962 2965 phaseOffset[:,i] = phaseCCF.transpose()
2963 2966 nMin = nMax
2964 2967 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2965 2968
2966 2969 #Remove Outliers
2967 2970 factor = 2
2968 2971 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2969 2972 dw = numpy.std(wt,axis = 1)
2970 2973 dw = dw.reshape((dw.size,1))
2971 2974 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2972 2975 phaseOffset[ind] = numpy.nan
2973 2976 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2974 2977
2975 2978 return phaseOffset
2976 2979
2977 2980 def __shiftPhase(self, data, phaseShift):
2978 2981 #this will shift the phase of a complex number
2979 2982 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2980 2983 return dataShifted
2981 2984
2982 2985 def __estimatePhaseDifference(self, array, pairslist):
2983 2986 nChannel = array.shape[0]
2984 2987 nHeights = array.shape[2]
2985 2988 numPairs = len(pairslist)
2986 2989 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2987 2990 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2988 2991
2989 2992 #Correct phases
2990 2993 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2991 2994 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2992 2995
2993 2996 if indDer[0].shape[0] > 0:
2994 2997 for i in range(indDer[0].shape[0]):
2995 2998 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2996 2999 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2997 3000
2998 3001 # for j in range(numSides):
2999 3002 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
3000 3003 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
3001 3004 #
3002 3005 #Linear
3003 3006 phaseInt = numpy.zeros((numPairs,1))
3004 3007 angAllCCF = phaseCCF[:,[0,1,3,4],0]
3005 3008 for j in range(numPairs):
3006 3009 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
3007 3010 phaseInt[j] = fit[1]
3008 3011 #Phase Differences
3009 3012 phaseDiff = phaseInt - phaseCCF[:,2,:]
3010 3013 phaseArrival = phaseInt.reshape(phaseInt.size)
3011 3014
3012 3015 #Dealias
3013 3016 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
3014 3017 # indAlias = numpy.where(phaseArrival > numpy.pi)
3015 3018 # phaseArrival[indAlias] -= 2*numpy.pi
3016 3019 # indAlias = numpy.where(phaseArrival < -numpy.pi)
3017 3020 # phaseArrival[indAlias] += 2*numpy.pi
3018 3021
3019 3022 return phaseDiff, phaseArrival
3020 3023
3021 3024 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
3022 3025 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
3023 3026 #find the phase shifts of each channel over 1 second intervals
3024 3027 #only look at ranges below the beacon signal
3025 3028 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
3026 3029 numBlocks = int(volts.shape[1]/numProfPerBlock)
3027 3030 numHeights = volts.shape[2]
3028 3031 nChannel = volts.shape[0]
3029 3032 voltsCohDet = volts.copy()
3030 3033
3031 3034 pairsarray = numpy.array(pairslist)
3032 3035 indSides = pairsarray[:,1]
3033 3036 # indSides = numpy.array(range(nChannel))
3034 3037 # indSides = numpy.delete(indSides, indCenter)
3035 3038 #
3036 3039 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
3037 3040 listBlocks = numpy.array_split(volts, numBlocks, 1)
3038 3041
3039 3042 startInd = 0
3040 3043 endInd = 0
3041 3044
3042 3045 for i in range(numBlocks):
3043 3046 startInd = endInd
3044 3047 endInd = endInd + listBlocks[i].shape[1]
3045 3048
3046 3049 arrayBlock = listBlocks[i]
3047 3050 # arrayBlockCenter = listCenter[i]
3048 3051
3049 3052 #Estimate the Phase Difference
3050 3053 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
3051 3054 #Phase Difference RMS
3052 3055 arrayPhaseRMS = numpy.abs(phaseDiff)
3053 3056 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
3054 3057 indPhase = numpy.where(phaseRMSaux==4)
3055 3058 #Shifting
3056 3059 if indPhase[0].shape[0] > 0:
3057 3060 for j in range(indSides.size):
3058 3061 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
3059 3062 voltsCohDet[:,startInd:endInd,:] = arrayBlock
3060 3063
3061 3064 return voltsCohDet
3062 3065
3063 3066 def __calculateCCF(self, volts, pairslist ,laglist):
3064 3067
3065 3068 nHeights = volts.shape[2]
3066 3069 nPoints = volts.shape[1]
3067 3070 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
3068 3071
3069 3072 for i in range(len(pairslist)):
3070 3073 volts1 = volts[pairslist[i][0]]
3071 3074 volts2 = volts[pairslist[i][1]]
3072 3075
3073 3076 for t in range(len(laglist)):
3074 3077 idxT = laglist[t]
3075 3078 if idxT >= 0:
3076 3079 vStacked = numpy.vstack((volts2[idxT:,:],
3077 3080 numpy.zeros((idxT, nHeights),dtype='complex')))
3078 3081 else:
3079 3082 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
3080 3083 volts2[:(nPoints + idxT),:]))
3081 3084 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
3082 3085
3083 3086 vStacked = None
3084 3087 return voltsCCF
3085 3088
3086 3089 def __getNoise(self, power, timeSegment, timeInterval):
3087 3090 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
3088 3091 numBlocks = int(power.shape[0]/numProfPerBlock)
3089 3092 numHeights = power.shape[1]
3090 3093
3091 3094 listPower = numpy.array_split(power, numBlocks, 0)
3092 3095 noise = numpy.zeros((power.shape[0], power.shape[1]))
3093 3096 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
3094 3097
3095 3098 startInd = 0
3096 3099 endInd = 0
3097 3100
3098 3101 for i in range(numBlocks): #split por canal
3099 3102 startInd = endInd
3100 3103 endInd = endInd + listPower[i].shape[0]
3101 3104
3102 3105 arrayBlock = listPower[i]
3103 3106 noiseAux = numpy.mean(arrayBlock, 0)
3104 3107 # noiseAux = numpy.median(noiseAux)
3105 3108 # noiseAux = numpy.mean(arrayBlock)
3106 3109 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
3107 3110
3108 3111 noiseAux1 = numpy.mean(arrayBlock)
3109 3112 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
3110 3113
3111 3114 return noise, noise1
3112 3115
3113 3116 def __findMeteors(self, power, thresh):
3114 3117 nProf = power.shape[0]
3115 3118 nHeights = power.shape[1]
3116 3119 listMeteors = []
3117 3120
3118 3121 for i in range(nHeights):
3119 3122 powerAux = power[:,i]
3120 3123 threshAux = thresh[:,i]
3121 3124
3122 3125 indUPthresh = numpy.where(powerAux > threshAux)[0]
3123 3126 indDNthresh = numpy.where(powerAux <= threshAux)[0]
3124 3127
3125 3128 j = 0
3126 3129
3127 3130 while (j < indUPthresh.size - 2):
3128 3131 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
3129 3132 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3130 3133 indDNthresh = indDNthresh[indDNAux]
3131 3134
3132 3135 if (indDNthresh.size > 0):
3133 3136 indEnd = indDNthresh[0] - 1
3134 3137 indInit = indUPthresh[j]
3135 3138
3136 3139 meteor = powerAux[indInit:indEnd + 1]
3137 3140 indPeak = meteor.argmax() + indInit
3138 3141 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3139 3142
3140 3143 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3141 3144 j = numpy.where(indUPthresh == indEnd)[0] + 1
3142 3145 else: j+=1
3143 3146 else: j+=1
3144 3147
3145 3148 return listMeteors
3146 3149
3147 3150 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3148 3151
3149 3152 arrayMeteors = numpy.asarray(listMeteors)
3150 3153 listMeteors1 = []
3151 3154
3152 3155 while arrayMeteors.shape[0] > 0:
3153 3156 FLAs = arrayMeteors[:,4]
3154 3157 maxFLA = FLAs.argmax()
3155 3158 listMeteors1.append(arrayMeteors[maxFLA,:])
3156 3159
3157 3160 MeteorInitTime = arrayMeteors[maxFLA,1]
3158 3161 MeteorEndTime = arrayMeteors[maxFLA,3]
3159 3162 MeteorHeight = arrayMeteors[maxFLA,0]
3160 3163
3161 3164 #Check neighborhood
3162 3165 maxHeightIndex = MeteorHeight + rangeLimit
3163 3166 minHeightIndex = MeteorHeight - rangeLimit
3164 3167 minTimeIndex = MeteorInitTime - timeLimit
3165 3168 maxTimeIndex = MeteorEndTime + timeLimit
3166 3169
3167 3170 #Check Heights
3168 3171 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3169 3172 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3170 3173 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3171 3174
3172 3175 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3173 3176
3174 3177 return listMeteors1
3175 3178
3176 3179 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3177 3180 numHeights = volts.shape[2]
3178 3181 nChannel = volts.shape[0]
3179 3182
3180 3183 thresholdPhase = thresh[0]
3181 3184 thresholdNoise = thresh[1]
3182 3185 thresholdDB = float(thresh[2])
3183 3186
3184 3187 thresholdDB1 = 10**(thresholdDB/10)
3185 3188 pairsarray = numpy.array(pairslist)
3186 3189 indSides = pairsarray[:,1]
3187 3190
3188 3191 pairslist1 = list(pairslist)
3189 3192 pairslist1.append((0,1))
3190 3193 pairslist1.append((3,4))
3191 3194
3192 3195 listMeteors1 = []
3193 3196 listPowerSeries = []
3194 3197 listVoltageSeries = []
3195 3198 #volts has the war data
3196 3199
3197 3200 if frequency == 30e6:
3198 3201 timeLag = 45*10**-3
3199 3202 else:
3200 3203 timeLag = 15*10**-3
3201 3204 lag = numpy.ceil(timeLag/timeInterval)
3202 3205
3203 3206 for i in range(len(listMeteors)):
3204 3207
3205 3208 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3206 3209 meteorAux = numpy.zeros(16)
3207 3210
3208 3211 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3209 3212 mHeight = listMeteors[i][0]
3210 3213 mStart = listMeteors[i][1]
3211 3214 mPeak = listMeteors[i][2]
3212 3215 mEnd = listMeteors[i][3]
3213 3216
3214 3217 #get the volt data between the start and end times of the meteor
3215 3218 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3216 3219 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3217 3220
3218 3221 #3.6. Phase Difference estimation
3219 3222 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3220 3223
3221 3224 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3222 3225 #meteorVolts0.- all Channels, all Profiles
3223 3226 meteorVolts0 = volts[:,:,mHeight]
3224 3227 meteorThresh = noise[:,mHeight]*thresholdNoise
3225 3228 meteorNoise = noise[:,mHeight]
3226 3229 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3227 3230 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3228 3231
3229 3232 #Times reestimation
3230 3233 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3231 3234 if mStart1.size > 0:
3232 3235 mStart1 = mStart1[-1] + 1
3233 3236
3234 3237 else:
3235 3238 mStart1 = mPeak
3236 3239
3237 3240 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3238 3241 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3239 3242 if mEndDecayTime1.size == 0:
3240 3243 mEndDecayTime1 = powerNet0.size
3241 3244 else:
3242 3245 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3243 3246 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3244 3247
3245 3248 #meteorVolts1.- all Channels, from start to end
3246 3249 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3247 3250 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3248 3251 if meteorVolts2.shape[1] == 0:
3249 3252 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3250 3253 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3251 3254 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3252 3255 ##################### END PARAMETERS REESTIMATION #########################
3253 3256
3254 3257 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3255 3258 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3256 3259 if meteorVolts2.shape[1] > 0:
3257 3260 #Phase Difference re-estimation
3258 3261 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3259 3262 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3260 3263 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3261 3264 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3262 3265 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3263 3266
3264 3267 #Phase Difference RMS
3265 3268 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3266 3269 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3267 3270 #Data from Meteor
3268 3271 mPeak1 = powerNet1.argmax() + mStart1
3269 3272 mPeakPower1 = powerNet1.max()
3270 3273 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3271 3274 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3272 3275 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3273 3276 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3274 3277 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3275 3278 #Vectorize
3276 3279 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3277 3280 meteorAux[7:11] = phaseDiffint[0:4]
3278 3281
3279 3282 #Rejection Criterions
3280 3283 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3281 3284 meteorAux[-1] = 17
3282 3285 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3283 3286 meteorAux[-1] = 1
3284 3287
3285 3288
3286 3289 else:
3287 3290 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3288 3291 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3289 3292 PowerSeries = 0
3290 3293
3291 3294 listMeteors1.append(meteorAux)
3292 3295 listPowerSeries.append(PowerSeries)
3293 3296 listVoltageSeries.append(meteorVolts1)
3294 3297
3295 3298 return listMeteors1, listPowerSeries, listVoltageSeries
3296 3299
3297 3300 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3298 3301
3299 3302 threshError = 10
3300 3303 #Depending if it is 30 or 50 MHz
3301 3304 if frequency == 30e6:
3302 3305 timeLag = 45*10**-3
3303 3306 else:
3304 3307 timeLag = 15*10**-3
3305 3308 lag = numpy.ceil(timeLag/timeInterval)
3306 3309
3307 3310 listMeteors1 = []
3308 3311
3309 3312 for i in range(len(listMeteors)):
3310 3313 meteorPower = listPower[i]
3311 3314 meteorAux = listMeteors[i]
3312 3315
3313 3316 if meteorAux[-1] == 0:
3314 3317
3315 3318 try:
3316 3319 indmax = meteorPower.argmax()
3317 3320 indlag = indmax + lag
3318 3321
3319 3322 y = meteorPower[indlag:]
3320 3323 x = numpy.arange(0, y.size)*timeLag
3321 3324
3322 3325 #first guess
3323 3326 a = y[0]
3324 3327 tau = timeLag
3325 3328 #exponential fit
3326 3329 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3327 3330 y1 = self.__exponential_function(x, *popt)
3328 3331 #error estimation
3329 3332 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3330 3333
3331 3334 decayTime = popt[1]
3332 3335 riseTime = indmax*timeInterval
3333 3336 meteorAux[11:13] = [decayTime, error]
3334 3337
3335 3338 #Table items 7, 8 and 11
3336 3339 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3337 3340 meteorAux[-1] = 7
3338 3341 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3339 3342 meteorAux[-1] = 8
3340 3343 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3341 3344 meteorAux[-1] = 11
3342 3345
3343 3346
3344 3347 except:
3345 3348 meteorAux[-1] = 11
3346 3349
3347 3350
3348 3351 listMeteors1.append(meteorAux)
3349 3352
3350 3353 return listMeteors1
3351 3354
3352 3355 #Exponential Function
3353 3356
3354 3357 def __exponential_function(self, x, a, tau):
3355 3358 y = a*numpy.exp(-x/tau)
3356 3359 return y
3357 3360
3358 3361 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3359 3362
3360 3363 pairslist1 = list(pairslist)
3361 3364 pairslist1.append((0,1))
3362 3365 pairslist1.append((3,4))
3363 3366 numPairs = len(pairslist1)
3364 3367 #Time Lag
3365 3368 timeLag = 45*10**-3
3366 3369 c = 3e8
3367 3370 lag = numpy.ceil(timeLag/timeInterval)
3368 3371 freq = 30e6
3369 3372
3370 3373 listMeteors1 = []
3371 3374
3372 3375 for i in range(len(listMeteors)):
3373 3376 meteorAux = listMeteors[i]
3374 3377 if meteorAux[-1] == 0:
3375 3378 mStart = listMeteors[i][1]
3376 3379 mPeak = listMeteors[i][2]
3377 3380 mLag = mPeak - mStart + lag
3378 3381
3379 3382 #get the volt data between the start and end times of the meteor
3380 3383 meteorVolts = listVolts[i]
3381 3384 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3382 3385
3383 3386 #Get CCF
3384 3387 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3385 3388
3386 3389 #Method 2
3387 3390 slopes = numpy.zeros(numPairs)
3388 3391 time = numpy.array([-2,-1,1,2])*timeInterval
3389 3392 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3390 3393
3391 3394 #Correct phases
3392 3395 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3393 3396 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3394 3397
3395 3398 if indDer[0].shape[0] > 0:
3396 3399 for i in range(indDer[0].shape[0]):
3397 3400 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3398 3401 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3399 3402
3400 3403 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3401 3404 for j in range(numPairs):
3402 3405 fit = stats.linregress(time, angAllCCF[j,:])
3403 3406 slopes[j] = fit[0]
3404 3407
3405 3408 #Remove Outlier
3406 3409 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3407 3410 # slopes = numpy.delete(slopes,indOut)
3408 3411 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3409 3412 # slopes = numpy.delete(slopes,indOut)
3410 3413
3411 3414 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3412 3415 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3413 3416 meteorAux[-2] = radialError
3414 3417 meteorAux[-3] = radialVelocity
3415 3418
3416 3419 #Setting Error
3417 3420 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3418 3421 if numpy.abs(radialVelocity) > 200:
3419 3422 meteorAux[-1] = 15
3420 3423 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3421 3424 elif radialError > radialStdThresh:
3422 3425 meteorAux[-1] = 12
3423 3426
3424 3427 listMeteors1.append(meteorAux)
3425 3428 return listMeteors1
3426 3429
3427 3430 def __setNewArrays(self, listMeteors, date, heiRang):
3428 3431
3429 3432 #New arrays
3430 3433 arrayMeteors = numpy.array(listMeteors)
3431 3434 arrayParameters = numpy.zeros((len(listMeteors), 13))
3432 3435
3433 3436 #Date inclusion
3434 3437 # date = re.findall(r'\((.*?)\)', date)
3435 3438 # date = date[0].split(',')
3436 3439 # date = map(int, date)
3437 3440 #
3438 3441 # if len(date)<6:
3439 3442 # date.append(0)
3440 3443 #
3441 3444 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3442 3445 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3443 3446 arrayDate = numpy.tile(date, (len(listMeteors)))
3444 3447
3445 3448 #Meteor array
3446 3449 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3447 3450 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3448 3451
3449 3452 #Parameters Array
3450 3453 arrayParameters[:,0] = arrayDate #Date
3451 3454 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3452 3455 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3453 3456 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3454 3457 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3455 3458
3456 3459
3457 3460 return arrayParameters
3458 3461
3459 3462 class CorrectSMPhases(Operation):
3460 3463
3461 3464 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3462 3465
3463 3466 arrayParameters = dataOut.data_param
3464 3467 pairsList = []
3465 3468 pairx = (0,1)
3466 3469 pairy = (2,3)
3467 3470 pairsList.append(pairx)
3468 3471 pairsList.append(pairy)
3469 3472 jph = numpy.zeros(4)
3470 3473
3471 3474 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3472 3475 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3473 3476 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3474 3477
3475 3478 meteorOps = SMOperations()
3476 3479 if channelPositions == None:
3477 3480 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3478 3481 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3479 3482
3480 3483 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3481 3484 h = (hmin,hmax)
3482 3485
3483 3486 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3484 3487
3485 3488 dataOut.data_param = arrayParameters
3486 3489 return
3487 3490
3488 3491 class SMPhaseCalibration(Operation):
3489 3492
3490 3493 __buffer = None
3491 3494
3492 3495 __initime = None
3493 3496
3494 3497 __dataReady = False
3495 3498
3496 3499 __isConfig = False
3497 3500
3498 3501 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3499 3502
3500 3503 dataTime = currentTime + paramInterval
3501 3504 deltaTime = dataTime - initTime
3502 3505
3503 3506 if deltaTime >= outputInterval or deltaTime < 0:
3504 3507 return True
3505 3508
3506 3509 return False
3507 3510
3508 3511 def __getGammas(self, pairs, d, phases):
3509 3512 gammas = numpy.zeros(2)
3510 3513
3511 3514 for i in range(len(pairs)):
3512 3515
3513 3516 pairi = pairs[i]
3514 3517
3515 3518 phip3 = phases[:,pairi[0]]
3516 3519 d3 = d[pairi[0]]
3517 3520 phip2 = phases[:,pairi[1]]
3518 3521 d2 = d[pairi[1]]
3519 3522 #Calculating gamma
3520 3523 # jdcos = alp1/(k*d1)
3521 3524 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3522 3525 jgamma = -phip2*d3/d2 - phip3
3523 3526 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3524 3527 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3525 3528 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3526 3529
3527 3530 #Revised distribution
3528 3531 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3529 3532
3530 3533 #Histogram
3531 3534 nBins = 64
3532 3535 rmin = -0.5*numpy.pi
3533 3536 rmax = 0.5*numpy.pi
3534 3537 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3535 3538
3536 3539 meteorsY = phaseHisto[0]
3537 3540 phasesX = phaseHisto[1][:-1]
3538 3541 width = phasesX[1] - phasesX[0]
3539 3542 phasesX += width/2
3540 3543
3541 3544 #Gaussian aproximation
3542 3545 bpeak = meteorsY.argmax()
3543 3546 peak = meteorsY.max()
3544 3547 jmin = bpeak - 5
3545 3548 jmax = bpeak + 5 + 1
3546 3549
3547 3550 if jmin<0:
3548 3551 jmin = 0
3549 3552 jmax = 6
3550 3553 elif jmax > meteorsY.size:
3551 3554 jmin = meteorsY.size - 6
3552 3555 jmax = meteorsY.size
3553 3556
3554 3557 x0 = numpy.array([peak,bpeak,50])
3555 3558 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3556 3559
3557 3560 #Gammas
3558 3561 gammas[i] = coeff[0][1]
3559 3562
3560 3563 return gammas
3561 3564
3562 3565 def __residualFunction(self, coeffs, y, t):
3563 3566
3564 3567 return y - self.__gauss_function(t, coeffs)
3565 3568
3566 3569 def __gauss_function(self, t, coeffs):
3567 3570
3568 3571 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3569 3572
3570 3573 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3571 3574 meteorOps = SMOperations()
3572 3575 nchan = 4
3573 3576 pairx = pairsList[0] #x es 0
3574 3577 pairy = pairsList[1] #y es 1
3575 3578 center_xangle = 0
3576 3579 center_yangle = 0
3577 3580 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3578 3581 ntimes = len(range_angle)
3579 3582
3580 3583 nstepsx = 20
3581 3584 nstepsy = 20
3582 3585
3583 3586 for iz in range(ntimes):
3584 3587 min_xangle = -range_angle[iz]/2 + center_xangle
3585 3588 max_xangle = range_angle[iz]/2 + center_xangle
3586 3589 min_yangle = -range_angle[iz]/2 + center_yangle
3587 3590 max_yangle = range_angle[iz]/2 + center_yangle
3588 3591
3589 3592 inc_x = (max_xangle-min_xangle)/nstepsx
3590 3593 inc_y = (max_yangle-min_yangle)/nstepsy
3591 3594
3592 3595 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3593 3596 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3594 3597 penalty = numpy.zeros((nstepsx,nstepsy))
3595 3598 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3596 3599 jph = numpy.zeros(nchan)
3597 3600
3598 3601 # Iterations looking for the offset
3599 3602 for iy in range(int(nstepsy)):
3600 3603 for ix in range(int(nstepsx)):
3601 3604 d3 = d[pairsList[1][0]]
3602 3605 d2 = d[pairsList[1][1]]
3603 3606 d5 = d[pairsList[0][0]]
3604 3607 d4 = d[pairsList[0][1]]
3605 3608
3606 3609 alp2 = alpha_y[iy] #gamma 1
3607 3610 alp4 = alpha_x[ix] #gamma 0
3608 3611
3609 3612 alp3 = -alp2*d3/d2 - gammas[1]
3610 3613 alp5 = -alp4*d5/d4 - gammas[0]
3611 3614 # jph[pairy[1]] = alpha_y[iy]
3612 3615 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3613 3616
3614 3617 # jph[pairx[1]] = alpha_x[ix]
3615 3618 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3616 3619 jph[pairsList[0][1]] = alp4
3617 3620 jph[pairsList[0][0]] = alp5
3618 3621 jph[pairsList[1][0]] = alp3
3619 3622 jph[pairsList[1][1]] = alp2
3620 3623 jph_array[:,ix,iy] = jph
3621 3624 # d = [2.0,2.5,2.5,2.0]
3622 3625 #falta chequear si va a leer bien los meteoros
3623 3626 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3624 3627 error = meteorsArray1[:,-1]
3625 3628 ind1 = numpy.where(error==0)[0]
3626 3629 penalty[ix,iy] = ind1.size
3627 3630
3628 3631 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3629 3632 phOffset = jph_array[:,i,j]
3630 3633
3631 3634 center_xangle = phOffset[pairx[1]]
3632 3635 center_yangle = phOffset[pairy[1]]
3633 3636
3634 3637 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3635 3638 phOffset = phOffset*180/numpy.pi
3636 3639 return phOffset
3637 3640
3638 3641
3639 3642 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3640 3643
3641 3644 dataOut.flagNoData = True
3642 3645 self.__dataReady = False
3643 3646 dataOut.outputInterval = nHours*3600
3644 3647
3645 3648 if self.__isConfig == False:
3646 3649 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3647 3650 #Get Initial LTC time
3648 3651 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3649 3652 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3650 3653
3651 3654 self.__isConfig = True
3652 3655
3653 3656 if self.__buffer == None:
3654 3657 self.__buffer = dataOut.data_param.copy()
3655 3658
3656 3659 else:
3657 3660 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3658 3661
3659 3662 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3660 3663
3661 3664 if self.__dataReady:
3662 3665 dataOut.utctimeInit = self.__initime
3663 3666 self.__initime += dataOut.outputInterval #to erase time offset
3664 3667
3665 3668 freq = dataOut.frequency
3666 3669 c = dataOut.C #m/s
3667 3670 lamb = c/freq
3668 3671 k = 2*numpy.pi/lamb
3669 3672 azimuth = 0
3670 3673 h = (hmin, hmax)
3671 3674 # pairs = ((0,1),(2,3)) #Estrella
3672 3675 # pairs = ((1,0),(2,3)) #T
3673 3676
3674 3677 if channelPositions is None:
3675 3678 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3676 3679 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3677 3680 meteorOps = SMOperations()
3678 3681 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3679 3682
3680 3683 #Checking correct order of pairs
3681 3684 pairs = []
3682 3685 if distances[1] > distances[0]:
3683 3686 pairs.append((1,0))
3684 3687 else:
3685 3688 pairs.append((0,1))
3686 3689
3687 3690 if distances[3] > distances[2]:
3688 3691 pairs.append((3,2))
3689 3692 else:
3690 3693 pairs.append((2,3))
3691 3694 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3692 3695
3693 3696 meteorsArray = self.__buffer
3694 3697 error = meteorsArray[:,-1]
3695 3698 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3696 3699 ind1 = numpy.where(boolError)[0]
3697 3700 meteorsArray = meteorsArray[ind1,:]
3698 3701 meteorsArray[:,-1] = 0
3699 3702 phases = meteorsArray[:,8:12]
3700 3703
3701 3704 #Calculate Gammas
3702 3705 gammas = self.__getGammas(pairs, distances, phases)
3703 3706 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3704 3707 #Calculate Phases
3705 3708 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3706 3709 phasesOff = phasesOff.reshape((1,phasesOff.size))
3707 3710 dataOut.data_output = -phasesOff
3708 3711 dataOut.flagNoData = False
3709 3712 self.__buffer = None
3710 3713
3711 3714
3712 3715 return
3713 3716
3714 3717 class SMOperations():
3715 3718
3716 3719 def __init__(self):
3717 3720
3718 3721 return
3719 3722
3720 3723 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3721 3724
3722 3725 arrayParameters = arrayParameters0.copy()
3723 3726 hmin = h[0]
3724 3727 hmax = h[1]
3725 3728
3726 3729 #Calculate AOA (Error N 3, 4)
3727 3730 #JONES ET AL. 1998
3728 3731 AOAthresh = numpy.pi/8
3729 3732 error = arrayParameters[:,-1]
3730 3733 phases = -arrayParameters[:,8:12] + jph
3731 3734 # phases = numpy.unwrap(phases)
3732 3735 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3733 3736
3734 3737 #Calculate Heights (Error N 13 and 14)
3735 3738 error = arrayParameters[:,-1]
3736 3739 Ranges = arrayParameters[:,1]
3737 3740 zenith = arrayParameters[:,4]
3738 3741 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3739 3742
3740 3743 #----------------------- Get Final data ------------------------------------
3741 3744 # error = arrayParameters[:,-1]
3742 3745 # ind1 = numpy.where(error==0)[0]
3743 3746 # arrayParameters = arrayParameters[ind1,:]
3744 3747
3745 3748 return arrayParameters
3746 3749
3747 3750 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3748 3751
3749 3752 arrayAOA = numpy.zeros((phases.shape[0],3))
3750 3753 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3751 3754
3752 3755 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3753 3756 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3754 3757 arrayAOA[:,2] = cosDirError
3755 3758
3756 3759 azimuthAngle = arrayAOA[:,0]
3757 3760 zenithAngle = arrayAOA[:,1]
3758 3761
3759 3762 #Setting Error
3760 3763 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3761 3764 error[indError] = 0
3762 3765 #Number 3: AOA not fesible
3763 3766 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3764 3767 error[indInvalid] = 3
3765 3768 #Number 4: Large difference in AOAs obtained from different antenna baselines
3766 3769 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3767 3770 error[indInvalid] = 4
3768 3771 return arrayAOA, error
3769 3772
3770 3773 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3771 3774
3772 3775 #Initializing some variables
3773 3776 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3774 3777 ang_aux = ang_aux.reshape(1,ang_aux.size)
3775 3778
3776 3779 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3777 3780 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3778 3781
3779 3782
3780 3783 for i in range(2):
3781 3784 ph0 = arrayPhase[:,pairsList[i][0]]
3782 3785 ph1 = arrayPhase[:,pairsList[i][1]]
3783 3786 d0 = distances[pairsList[i][0]]
3784 3787 d1 = distances[pairsList[i][1]]
3785 3788
3786 3789 ph0_aux = ph0 + ph1
3787 3790 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3788 3791 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3789 3792 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3790 3793 #First Estimation
3791 3794 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3792 3795
3793 3796 #Most-Accurate Second Estimation
3794 3797 phi1_aux = ph0 - ph1
3795 3798 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3796 3799 #Direction Cosine 1
3797 3800 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3798 3801
3799 3802 #Searching the correct Direction Cosine
3800 3803 cosdir0_aux = cosdir0[:,i]
3801 3804 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3802 3805 #Minimum Distance
3803 3806 cosDiff = (cosdir1 - cosdir0_aux)**2
3804 3807 indcos = cosDiff.argmin(axis = 1)
3805 3808 #Saving Value obtained
3806 3809 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3807 3810
3808 3811 return cosdir0, cosdir
3809 3812
3810 3813 def __calculateAOA(self, cosdir, azimuth):
3811 3814 cosdirX = cosdir[:,0]
3812 3815 cosdirY = cosdir[:,1]
3813 3816
3814 3817 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3815 3818 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3816 3819 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3817 3820
3818 3821 return angles
3819 3822
3820 3823 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3821 3824
3822 3825 Ramb = 375 #Ramb = c/(2*PRF)
3823 3826 Re = 6371 #Earth Radius
3824 3827 heights = numpy.zeros(Ranges.shape)
3825 3828
3826 3829 R_aux = numpy.array([0,1,2])*Ramb
3827 3830 R_aux = R_aux.reshape(1,R_aux.size)
3828 3831
3829 3832 Ranges = Ranges.reshape(Ranges.size,1)
3830 3833
3831 3834 Ri = Ranges + R_aux
3832 3835 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3833 3836
3834 3837 #Check if there is a height between 70 and 110 km
3835 3838 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3836 3839 ind_h = numpy.where(h_bool == 1)[0]
3837 3840
3838 3841 hCorr = hi[ind_h, :]
3839 3842 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3840 3843
3841 3844 hCorr = hi[ind_hCorr][:len(ind_h)]
3842 3845 heights[ind_h] = hCorr
3843 3846
3844 3847 #Setting Error
3845 3848 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3846 3849 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3847 3850 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3848 3851 error[indError] = 0
3849 3852 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3850 3853 error[indInvalid2] = 14
3851 3854 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3852 3855 error[indInvalid1] = 13
3853 3856
3854 3857 return heights, error
3855 3858
3856 3859 def getPhasePairs(self, channelPositions):
3857 3860 chanPos = numpy.array(channelPositions)
3858 3861 listOper = list(itertools.combinations(range(5),2))
3859 3862
3860 3863 distances = numpy.zeros(4)
3861 3864 axisX = []
3862 3865 axisY = []
3863 3866 distX = numpy.zeros(3)
3864 3867 distY = numpy.zeros(3)
3865 3868 ix = 0
3866 3869 iy = 0
3867 3870
3868 3871 pairX = numpy.zeros((2,2))
3869 3872 pairY = numpy.zeros((2,2))
3870 3873
3871 3874 for i in range(len(listOper)):
3872 3875 pairi = listOper[i]
3873 3876
3874 3877 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3875 3878
3876 3879 if posDif[0] == 0:
3877 3880 axisY.append(pairi)
3878 3881 distY[iy] = posDif[1]
3879 3882 iy += 1
3880 3883 elif posDif[1] == 0:
3881 3884 axisX.append(pairi)
3882 3885 distX[ix] = posDif[0]
3883 3886 ix += 1
3884 3887
3885 3888 for i in range(2):
3886 3889 if i==0:
3887 3890 dist0 = distX
3888 3891 axis0 = axisX
3889 3892 else:
3890 3893 dist0 = distY
3891 3894 axis0 = axisY
3892 3895
3893 3896 side = numpy.argsort(dist0)[:-1]
3894 3897 axis0 = numpy.array(axis0)[side,:]
3895 3898 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3896 3899 axis1 = numpy.unique(numpy.reshape(axis0,4))
3897 3900 side = axis1[axis1 != chanC]
3898 3901 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3899 3902 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3900 3903 if diff1<0:
3901 3904 chan2 = side[0]
3902 3905 d2 = numpy.abs(diff1)
3903 3906 chan1 = side[1]
3904 3907 d1 = numpy.abs(diff2)
3905 3908 else:
3906 3909 chan2 = side[1]
3907 3910 d2 = numpy.abs(diff2)
3908 3911 chan1 = side[0]
3909 3912 d1 = numpy.abs(diff1)
3910 3913
3911 3914 if i==0:
3912 3915 chanCX = chanC
3913 3916 chan1X = chan1
3914 3917 chan2X = chan2
3915 3918 distances[0:2] = numpy.array([d1,d2])
3916 3919 else:
3917 3920 chanCY = chanC
3918 3921 chan1Y = chan1
3919 3922 chan2Y = chan2
3920 3923 distances[2:4] = numpy.array([d1,d2])
3921 3924 # axisXsides = numpy.reshape(axisX[ix,:],4)
3922 3925 #
3923 3926 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3924 3927 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3925 3928 #
3926 3929 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3927 3930 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3928 3931 # channel25X = int(pairX[0,ind25X])
3929 3932 # channel20X = int(pairX[1,ind20X])
3930 3933 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3931 3934 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3932 3935 # channel25Y = int(pairY[0,ind25Y])
3933 3936 # channel20Y = int(pairY[1,ind20Y])
3934 3937
3935 3938 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3936 3939 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3937 3940
3938 3941 return pairslist, distances
3939 3942 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3940 3943 #
3941 3944 # arrayAOA = numpy.zeros((phases.shape[0],3))
3942 3945 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3943 3946 #
3944 3947 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3945 3948 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3946 3949 # arrayAOA[:,2] = cosDirError
3947 3950 #
3948 3951 # azimuthAngle = arrayAOA[:,0]
3949 3952 # zenithAngle = arrayAOA[:,1]
3950 3953 #
3951 3954 # #Setting Error
3952 3955 # #Number 3: AOA not fesible
3953 3956 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3954 3957 # error[indInvalid] = 3
3955 3958 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3956 3959 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3957 3960 # error[indInvalid] = 4
3958 3961 # return arrayAOA, error
3959 3962 #
3960 3963 # def __getDirectionCosines(self, arrayPhase, pairsList):
3961 3964 #
3962 3965 # #Initializing some variables
3963 3966 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3964 3967 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3965 3968 #
3966 3969 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3967 3970 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3968 3971 #
3969 3972 #
3970 3973 # for i in range(2):
3971 3974 # #First Estimation
3972 3975 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3973 3976 # #Dealias
3974 3977 # indcsi = numpy.where(phi0_aux > numpy.pi)
3975 3978 # phi0_aux[indcsi] -= 2*numpy.pi
3976 3979 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3977 3980 # phi0_aux[indcsi] += 2*numpy.pi
3978 3981 # #Direction Cosine 0
3979 3982 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3980 3983 #
3981 3984 # #Most-Accurate Second Estimation
3982 3985 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3983 3986 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3984 3987 # #Direction Cosine 1
3985 3988 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3986 3989 #
3987 3990 # #Searching the correct Direction Cosine
3988 3991 # cosdir0_aux = cosdir0[:,i]
3989 3992 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3990 3993 # #Minimum Distance
3991 3994 # cosDiff = (cosdir1 - cosdir0_aux)**2
3992 3995 # indcos = cosDiff.argmin(axis = 1)
3993 3996 # #Saving Value obtained
3994 3997 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3995 3998 #
3996 3999 # return cosdir0, cosdir
3997 4000 #
3998 4001 # def __calculateAOA(self, cosdir, azimuth):
3999 4002 # cosdirX = cosdir[:,0]
4000 4003 # cosdirY = cosdir[:,1]
4001 4004 #
4002 4005 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
4003 4006 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
4004 4007 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
4005 4008 #
4006 4009 # return angles
4007 4010 #
4008 4011 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
4009 4012 #
4010 4013 # Ramb = 375 #Ramb = c/(2*PRF)
4011 4014 # Re = 6371 #Earth Radius
4012 4015 # heights = numpy.zeros(Ranges.shape)
4013 4016 #
4014 4017 # R_aux = numpy.array([0,1,2])*Ramb
4015 4018 # R_aux = R_aux.reshape(1,R_aux.size)
4016 4019 #
4017 4020 # Ranges = Ranges.reshape(Ranges.size,1)
4018 4021 #
4019 4022 # Ri = Ranges + R_aux
4020 4023 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
4021 4024 #
4022 4025 # #Check if there is a height between 70 and 110 km
4023 4026 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
4024 4027 # ind_h = numpy.where(h_bool == 1)[0]
4025 4028 #
4026 4029 # hCorr = hi[ind_h, :]
4027 4030 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
4028 4031 #
4029 4032 # hCorr = hi[ind_hCorr]
4030 4033 # heights[ind_h] = hCorr
4031 4034 #
4032 4035 # #Setting Error
4033 4036 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
4034 4037 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
4035 4038 #
4036 4039 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
4037 4040 # error[indInvalid2] = 14
4038 4041 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
4039 4042 # error[indInvalid1] = 13
4040 4043 #
4041 4044 # return heights, error
4042 4045 No newline at end of file
@@ -1,604 +1,607
1 1 '''
2 2 @author: Juan C. Espinoza
3 3 '''
4 4
5 5 import time
6 6 import json
7 7 import numpy
8 8 import paho.mqtt.client as mqtt
9 9 import zmq
10 10 import datetime
11 11 from zmq.utils.monitor import recv_monitor_message
12 12 from functools import wraps
13 13 from threading import Thread
14 14 from multiprocessing import Process
15 15
16 16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 17 from schainpy.model.data.jrodata import JROData
18 18 from schainpy.utils import log
19 19
20 20 MAXNUMX = 100
21 21 MAXNUMY = 100
22 22
23 23 class PrettyFloat(float):
24 24 def __repr__(self):
25 25 return '%.2f' % self
26 26
27 27 def roundFloats(obj):
28 28 if isinstance(obj, list):
29 29 return map(roundFloats, obj)
30 30 elif isinstance(obj, float):
31 31 return round(obj, 2)
32 32
33 33 def decimate(z, MAXNUMY):
34 34 dy = int(len(z[0])/MAXNUMY) + 1
35 35
36 36 return z[::, ::dy]
37 37
38 38 class throttle(object):
39 39 '''
40 40 Decorator that prevents a function from being called more than once every
41 41 time period.
42 42 To create a function that cannot be called more than once a minute, but
43 43 will sleep until it can be called:
44 44 @throttle(minutes=1)
45 45 def foo():
46 46 pass
47 47
48 48 for i in range(10):
49 49 foo()
50 50 print "This function has run %s times." % i
51 51 '''
52 52
53 53 def __init__(self, seconds=0, minutes=0, hours=0):
54 54 self.throttle_period = datetime.timedelta(
55 55 seconds=seconds, minutes=minutes, hours=hours
56 56 )
57 57
58 58 self.time_of_last_call = datetime.datetime.min
59 59
60 60 def __call__(self, fn):
61 61 @wraps(fn)
62 62 def wrapper(*args, **kwargs):
63 63 now = datetime.datetime.now()
64 64 time_since_last_call = now - self.time_of_last_call
65 65 time_left = self.throttle_period - time_since_last_call
66 66
67 67 if time_left > datetime.timedelta(seconds=0):
68 68 return
69 69
70 70 self.time_of_last_call = datetime.datetime.now()
71 71 return fn(*args, **kwargs)
72 72
73 73 return wrapper
74 74
75 75 class Data(object):
76 76 '''
77 77 Object to hold data to be plotted
78 78 '''
79 79
80 80 def __init__(self, plottypes, throttle_value):
81 81 self.plottypes = plottypes
82 82 self.throttle = throttle_value
83 83 self.ended = False
84 84 self.__times = []
85 85
86 86 def __str__(self):
87 87 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
88 88 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
89 89
90 90 def __len__(self):
91 91 return len(self.__times)
92 92
93 93 def __getitem__(self, key):
94 94 if key not in self.data:
95 95 raise KeyError(log.error('Missing key: {}'.format(key)))
96 96
97 97 if 'spc' in key:
98 98 ret = self.data[key]
99 99 else:
100 100 ret = numpy.array([self.data[key][x] for x in self.times])
101 101 if ret.ndim > 1:
102 102 ret = numpy.swapaxes(ret, 0, 1)
103 103 return ret
104 104
105 105 def setup(self):
106 106 '''
107 107 Configure object
108 108 '''
109 109
110 110 self.ended = False
111 111 self.data = {}
112 112 self.__times = []
113 113 self.__heights = []
114 114 self.__all_heights = set()
115 115 for plot in self.plottypes:
116 if 'snr' in plot:
117 plot = 'snr'
116 118 self.data[plot] = {}
117 119
118 120 def shape(self, key):
119 121 '''
120 122 Get the shape of the one-element data for the given key
121 123 '''
122 124
123 125 if len(self.data[key]):
124 126 if 'spc' in key:
125 127 return self.data[key].shape
126 128 return self.data[key][self.__times[0]].shape
127 129 return (0,)
128 130
129 131 def update(self, dataOut):
130 132 '''
131 133 Update data object with new dataOut
132 134 '''
133 135
134 136 tm = dataOut.utctime
135 137 if tm in self.__times:
136 138 return
137 139
138 140 self.parameters = getattr(dataOut, 'parameters', [])
139 141 self.pairs = dataOut.pairsList
140 142 self.channels = dataOut.channelList
141 self.xrange = (dataOut.getFreqRange(1)/1000. , dataOut.getAcfRange(1) , dataOut.getVelRange(1))
142 143 self.interval = dataOut.getTimeInterval()
144 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
145 self.xrange = (dataOut.getFreqRange(1)/1000. , dataOut.getAcfRange(1) , dataOut.getVelRange(1))
143 146 self.__heights.append(dataOut.heightList)
144 147 self.__all_heights.update(dataOut.heightList)
145 148 self.__times.append(tm)
146 149
147 150 for plot in self.plottypes:
148 151 if plot == 'spc':
149 152 z = dataOut.data_spc/dataOut.normFactor
150 153 self.data[plot] = 10*numpy.log10(z)
151 154 if plot == 'cspc':
152 155 self.data[plot] = dataOut.data_cspc
153 156 if plot == 'noise':
154 157 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
155 158 if plot == 'rti':
156 159 self.data[plot][tm] = dataOut.getPower()
157 160 if plot == 'snr_db':
158 161 self.data['snr'][tm] = dataOut.data_SNR
159 162 if plot == 'snr':
160 163 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
161 164 if plot == 'dop':
162 165 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
163 166 if plot == 'mean':
164 167 self.data[plot][tm] = dataOut.data_MEAN
165 168 if plot == 'std':
166 169 self.data[plot][tm] = dataOut.data_STD
167 170 if plot == 'coh':
168 171 self.data[plot][tm] = dataOut.getCoherence()
169 172 if plot == 'phase':
170 173 self.data[plot][tm] = dataOut.getCoherence(phase=True)
171 174 if plot == 'output':
172 175 self.data[plot][tm] = dataOut.data_output
173 176 if plot == 'param':
174 177 self.data[plot][tm] = dataOut.data_param
175 178
176 179 def normalize_heights(self):
177 180 '''
178 181 Ensure same-dimension of the data for different heighList
179 182 '''
180 183
181 184 H = numpy.array(list(self.__all_heights))
182 185 H.sort()
183 186 for key in self.data:
184 187 shape = self.shape(key)[:-1] + H.shape
185 188 for tm, obj in self.data[key].items():
186 189 h = self.__heights[self.__times.index(tm)]
187 190 if H.size == h.size:
188 191 continue
189 192 index = numpy.where(numpy.in1d(H, h))[0]
190 193 dummy = numpy.zeros(shape) + numpy.nan
191 194 if len(shape) == 2:
192 195 dummy[:, index] = obj
193 196 else:
194 197 dummy[index] = obj
195 198 self.data[key][tm] = dummy
196 199
197 200 self.__heights = [H for tm in self.__times]
198 201
199 202 def jsonify(self, decimate=False):
200 203 '''
201 204 Convert data to json
202 205 '''
203 206
204 207 ret = {}
205 208 tm = self.times[-1]
206 209
207 210 for key, value in self.data:
208 211 if key in ('spc', 'cspc'):
209 212 ret[key] = roundFloats(self.data[key].to_list())
210 213 else:
211 214 ret[key] = roundFloats(self.data[key][tm].to_list())
212 215
213 216 ret['timestamp'] = tm
214 217 ret['interval'] = self.interval
215 218
216 219 @property
217 220 def times(self):
218 221 '''
219 222 Return the list of times of the current data
220 223 '''
221 224
222 225 ret = numpy.array(self.__times)
223 226 ret.sort()
224 227 return ret
225 228
226 229 @property
227 230 def heights(self):
228 231 '''
229 232 Return the list of heights of the current data
230 233 '''
231 234
232 235 return numpy.array(self.__heights[-1])
233 236
234 237 class PublishData(Operation):
235 238 '''
236 239 Operation to send data over zmq.
237 240 '''
238 241
239 242 def __init__(self, **kwargs):
240 243 """Inicio."""
241 244 Operation.__init__(self, **kwargs)
242 245 self.isConfig = False
243 246 self.client = None
244 247 self.zeromq = None
245 248 self.mqtt = None
246 249
247 250 def on_disconnect(self, client, userdata, rc):
248 251 if rc != 0:
249 252 log.warning('Unexpected disconnection.')
250 253 self.connect()
251 254
252 255 def connect(self):
253 256 log.warning('trying to connect')
254 257 try:
255 258 self.client.connect(
256 259 host=self.host,
257 260 port=self.port,
258 261 keepalive=60*10,
259 262 bind_address='')
260 263 self.client.loop_start()
261 264 # self.client.publish(
262 265 # self.topic + 'SETUP',
263 266 # json.dumps(setup),
264 267 # retain=True
265 268 # )
266 269 except:
267 270 log.error('MQTT Conection error.')
268 271 self.client = False
269 272
270 273 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
271 274 self.counter = 0
272 275 self.topic = kwargs.get('topic', 'schain')
273 276 self.delay = kwargs.get('delay', 0)
274 277 self.plottype = kwargs.get('plottype', 'spectra')
275 278 self.host = kwargs.get('host', "10.10.10.82")
276 279 self.port = kwargs.get('port', 3000)
277 280 self.clientId = clientId
278 281 self.cnt = 0
279 282 self.zeromq = zeromq
280 283 self.mqtt = kwargs.get('plottype', 0)
281 284 self.client = None
282 285 self.verbose = verbose
283 286 setup = []
284 287 if mqtt is 1:
285 288 self.client = mqtt.Client(
286 289 client_id=self.clientId + self.topic + 'SCHAIN',
287 290 clean_session=True)
288 291 self.client.on_disconnect = self.on_disconnect
289 292 self.connect()
290 293 for plot in self.plottype:
291 294 setup.append({
292 295 'plot': plot,
293 296 'topic': self.topic + plot,
294 297 'title': getattr(self, plot + '_' + 'title', False),
295 298 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
296 299 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
297 300 'xrange': getattr(self, plot + '_' + 'xrange', False),
298 301 'yrange': getattr(self, plot + '_' + 'yrange', False),
299 302 'zrange': getattr(self, plot + '_' + 'zrange', False),
300 303 })
301 304 if zeromq is 1:
302 305 context = zmq.Context()
303 306 self.zmq_socket = context.socket(zmq.PUSH)
304 307 server = kwargs.get('server', 'zmq.pipe')
305 308
306 309 if 'tcp://' in server:
307 310 address = server
308 311 else:
309 312 address = 'ipc:///tmp/%s' % server
310 313
311 314 self.zmq_socket.connect(address)
312 315 time.sleep(1)
313 316
314 317
315 318 def publish_data(self):
316 319 self.dataOut.finished = False
317 320 if self.mqtt is 1:
318 321 yData = self.dataOut.heightList[:2].tolist()
319 322 if self.plottype == 'spectra':
320 323 data = getattr(self.dataOut, 'data_spc')
321 324 z = data/self.dataOut.normFactor
322 325 zdB = 10*numpy.log10(z)
323 326 xlen, ylen = zdB[0].shape
324 327 dx = int(xlen/MAXNUMX) + 1
325 328 dy = int(ylen/MAXNUMY) + 1
326 329 Z = [0 for i in self.dataOut.channelList]
327 330 for i in self.dataOut.channelList:
328 331 Z[i] = zdB[i][::dx, ::dy].tolist()
329 332 payload = {
330 333 'timestamp': self.dataOut.utctime,
331 334 'data': roundFloats(Z),
332 335 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
333 336 'interval': self.dataOut.getTimeInterval(),
334 337 'type': self.plottype,
335 338 'yData': yData
336 339 }
337 340
338 341 elif self.plottype in ('rti', 'power'):
339 342 data = getattr(self.dataOut, 'data_spc')
340 343 z = data/self.dataOut.normFactor
341 344 avg = numpy.average(z, axis=1)
342 345 avgdB = 10*numpy.log10(avg)
343 346 xlen, ylen = z[0].shape
344 347 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
345 348 AVG = [0 for i in self.dataOut.channelList]
346 349 for i in self.dataOut.channelList:
347 350 AVG[i] = avgdB[i][::dy].tolist()
348 351 payload = {
349 352 'timestamp': self.dataOut.utctime,
350 353 'data': roundFloats(AVG),
351 354 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
352 355 'interval': self.dataOut.getTimeInterval(),
353 356 'type': self.plottype,
354 357 'yData': yData
355 358 }
356 359 elif self.plottype == 'noise':
357 360 noise = self.dataOut.getNoise()/self.dataOut.normFactor
358 361 noisedB = 10*numpy.log10(noise)
359 362 payload = {
360 363 'timestamp': self.dataOut.utctime,
361 364 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
362 365 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
363 366 'interval': self.dataOut.getTimeInterval(),
364 367 'type': self.plottype,
365 368 'yData': yData
366 369 }
367 370 elif self.plottype == 'snr':
368 371 data = getattr(self.dataOut, 'data_SNR')
369 372 avgdB = 10*numpy.log10(data)
370 373
371 374 ylen = data[0].size
372 375 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
373 376 AVG = [0 for i in self.dataOut.channelList]
374 377 for i in self.dataOut.channelList:
375 378 AVG[i] = avgdB[i][::dy].tolist()
376 379 payload = {
377 380 'timestamp': self.dataOut.utctime,
378 381 'data': roundFloats(AVG),
379 382 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
380 383 'type': self.plottype,
381 384 'yData': yData
382 385 }
383 386 else:
384 387 print "Tipo de grafico invalido"
385 388 payload = {
386 389 'data': 'None',
387 390 'timestamp': 'None',
388 391 'type': None
389 392 }
390 393
391 394 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
392 395
393 396 if self.zeromq is 1:
394 397 if self.verbose:
395 398 log.log(
396 399 '{} - {}'.format(self.dataOut.type, self.dataOut.datatime),
397 400 'Sending'
398 401 )
399 402 self.zmq_socket.send_pyobj(self.dataOut)
400 403
401 404 def run(self, dataOut, **kwargs):
402 405 self.dataOut = dataOut
403 406 if not self.isConfig:
404 407 self.setup(**kwargs)
405 408 self.isConfig = True
406 409
407 410 self.publish_data()
408 411 time.sleep(self.delay)
409 412
410 413 def close(self):
411 414 if self.zeromq is 1:
412 415 self.dataOut.finished = True
413 416 self.zmq_socket.send_pyobj(self.dataOut)
414 417 time.sleep(0.1)
415 418 self.zmq_socket.close()
416 419 if self.client:
417 420 self.client.loop_stop()
418 421 self.client.disconnect()
419 422
420 423
421 424 class ReceiverData(ProcessingUnit):
422 425
423 426 def __init__(self, **kwargs):
424 427
425 428 ProcessingUnit.__init__(self, **kwargs)
426 429
427 430 self.isConfig = False
428 431 server = kwargs.get('server', 'zmq.pipe')
429 432 if 'tcp://' in server:
430 433 address = server
431 434 else:
432 435 address = 'ipc:///tmp/%s' % server
433 436
434 437 self.address = address
435 438 self.dataOut = JROData()
436 439
437 440 def setup(self):
438 441
439 442 self.context = zmq.Context()
440 443 self.receiver = self.context.socket(zmq.PULL)
441 444 self.receiver.bind(self.address)
442 445 time.sleep(0.5)
443 446 log.success('ReceiverData from {}'.format(self.address))
444 447
445 448
446 449 def run(self):
447 450
448 451 if not self.isConfig:
449 452 self.setup()
450 453 self.isConfig = True
451 454
452 455 self.dataOut = self.receiver.recv_pyobj()
453 456 log.log('{} - {}'.format(self.dataOut.type,
454 457 self.dataOut.datatime.ctime(),),
455 458 'Receiving')
456 459
457 460
458 461 class PlotterReceiver(ProcessingUnit, Process):
459 462
460 463 throttle_value = 5
461 464
462 465 def __init__(self, **kwargs):
463 466
464 467 ProcessingUnit.__init__(self, **kwargs)
465 468 Process.__init__(self)
466 469 self.mp = False
467 470 self.isConfig = False
468 471 self.isWebConfig = False
469 472 self.connections = 0
470 473 server = kwargs.get('server', 'zmq.pipe')
471 474 plot_server = kwargs.get('plot_server', 'zmq.web')
472 475 if 'tcp://' in server:
473 476 address = server
474 477 else:
475 478 address = 'ipc:///tmp/%s' % server
476 479
477 480 if 'tcp://' in plot_server:
478 481 plot_address = plot_server
479 482 else:
480 483 plot_address = 'ipc:///tmp/%s' % plot_server
481 484
482 485 self.address = address
483 486 self.plot_address = plot_address
484 487 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
485 488 self.realtime = kwargs.get('realtime', False)
486 489 self.throttle_value = kwargs.get('throttle', 5)
487 490 self.sendData = self.initThrottle(self.throttle_value)
488 491 self.dates = []
489 492 self.setup()
490 493
491 494 def setup(self):
492 495
493 496 self.data = Data(self.plottypes, self.throttle_value)
494 497 self.isConfig = True
495 498
496 499 def event_monitor(self, monitor):
497 500
498 501 events = {}
499 502
500 503 for name in dir(zmq):
501 504 if name.startswith('EVENT_'):
502 505 value = getattr(zmq, name)
503 506 events[value] = name
504 507
505 508 while monitor.poll():
506 509 evt = recv_monitor_message(monitor)
507 510 if evt['event'] == 32:
508 511 self.connections += 1
509 512 if evt['event'] == 512:
510 513 pass
511 514
512 515 evt.update({'description': events[evt['event']]})
513 516
514 517 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
515 518 break
516 519 monitor.close()
517 520 print('event monitor thread done!')
518 521
519 522 def initThrottle(self, throttle_value):
520 523
521 524 @throttle(seconds=throttle_value)
522 525 def sendDataThrottled(fn_sender, data):
523 526 fn_sender(data)
524 527
525 528 return sendDataThrottled
526 529
527 530 def send(self, data):
528 531 log.success('Sending {}'.format(data), self.name)
529 532 self.sender.send_pyobj(data)
530 533
531 534 def run(self):
532 535
533 536 log.success(
534 537 'Starting from {}'.format(self.address),
535 538 self.name
536 539 )
537 540
538 541 self.context = zmq.Context()
539 542 self.receiver = self.context.socket(zmq.PULL)
540 543 self.receiver.bind(self.address)
541 544 monitor = self.receiver.get_monitor_socket()
542 545 self.sender = self.context.socket(zmq.PUB)
543 546 if self.realtime:
544 547 self.sender_web = self.context.socket(zmq.PUB)
545 548 self.sender_web.connect(self.plot_address)
546 549 time.sleep(1)
547 550
548 551 if 'server' in self.kwargs:
549 552 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
550 553 else:
551 554 self.sender.bind("ipc:///tmp/zmq.plots")
552 555
553 556 time.sleep(2)
554 557
555 558 t = Thread(target=self.event_monitor, args=(monitor,))
556 559 t.start()
557 560
558 561 while True:
559 562 dataOut = self.receiver.recv_pyobj()
560 563 dt = datetime.datetime.fromtimestamp(dataOut.utctime).date()
561 564 sended = False
562 565 if dt not in self.dates:
563 566 if self.data:
564 567 self.data.ended = True
565 568 self.send(self.data)
566 569 sended = True
567 570 self.data.setup()
568 571 self.dates.append(dt)
569 572
570 573 self.data.update(dataOut)
571 574
572 575 if dataOut.finished is True:
573 576 self.connections -= 1
574 577 if self.connections == 0 and dt in self.dates:
575 578 self.data.ended = True
576 579 self.send(self.data)
577 580 self.data.setup()
578 581 else:
579 582 if self.realtime:
580 583 self.send(self.data)
581 584 # self.sender_web.send_string(self.data.jsonify())
582 585 else:
583 586 if not sended:
584 587 self.sendData(self.send, self.data)
585 588
586 589 return
587 590
588 591 def sendToWeb(self):
589 592
590 593 if not self.isWebConfig:
591 594 context = zmq.Context()
592 595 sender_web_config = context.socket(zmq.PUB)
593 596 if 'tcp://' in self.plot_address:
594 597 dum, address, port = self.plot_address.split(':')
595 598 conf_address = '{}:{}:{}'.format(dum, address, int(port)+1)
596 599 else:
597 600 conf_address = self.plot_address + '.config'
598 601 sender_web_config.bind(conf_address)
599 602 time.sleep(1)
600 603 for kwargs in self.operationKwargs.values():
601 604 if 'plot' in kwargs:
602 605 log.success('[Sending] Config data to web for {}'.format(kwargs['code'].upper()))
603 606 sender_web_config.send_string(json.dumps(kwargs))
604 607 self.isWebConfig = True No newline at end of file
@@ -1,34 +0,0
1 from schainpy.controller import Project
2
3 desc = "A schain project"
4
5 controller = Project()
6 controller.setup(id='191', name="project", description=desc)
7
8 readUnitConf = controller.addReadUnit(datatype='VoltageReader',
9 path="/home/nanosat/schain/schainpy",
10 startDate="1970/01/01",
11 endDate="2017/12/31",
12 startTime="00:00:00",
13 endTime="23:59:59",
14 online=0,
15 verbose=1,
16 walk=1,
17 )
18
19 procUnitConf1 = controller.addProcUnit(datatype='VoltageProc', inputId=readUnitConf.getId())
20
21 opObj11 = procUnitConf1.addOperation(name='ProfileSelector', optype='other')
22 opObj11.addParameter(name='profileRangeList', value='120,183', format='intlist')
23
24 opObj11 = procUnitConf1.addOperation(name='RTIPlot', optype='other')
25 opObj11.addParameter(name='wintitle', value='Jicamarca Radio Observatory', format='str')
26 opObj11.addParameter(name='showprofile', value='0', format='int')
27 opObj11.addParameter(name='xmin', value='0', format='int')
28 opObj11.addParameter(name='xmax', value='24', format='int')
29 opObj11.addParameter(name='figpath', value="/home/nanosat/schain/schainpy/figs", format='str')
30 opObj11.addParameter(name='wr_period', value='5', format='int')
31 opObj11.addParameter(name='exp_code', value='22', format='int')
32
33
34 controller.start()
General Comments 0
You need to be logged in to leave comments. Login now